Skip to main content
ClaudeWave
Install in Claude Code
Copy
git clone --depth 1 https://github.com/jazzyalex/agent-sessions /tmp/plans && cp -r /tmp/plans/docs/superpowers/plans/2026-07-09-handover- ~/.claude/skills/plans
Then start a new Claude Code session; the skill loads automatically.

2026-07-09-handover-skill.md

# Handover Skill Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Ship a global `/handover` skill + a global Stop hook that append dated, structured entries to a per-repo `RepoHandover.md`, so archived-session context is recoverable without grepping.

**Architecture:** Develop three testable shell artifacts + one skill markdown in the repo under `tools/handover/` (source of truth, versioned, TDD-tested following the existing `tools/test_*.sh` pattern), then an idempotent `install.sh` deploys them to the global `~/.claude/` (skill → `~/.claude/skills/handover/`, hook → `~/.claude/hooks/`, Stop-hook wiring merged into `~/.claude/settings.json`). "Test in `tools/handover/` first, install to `~/.claude/` last" honors the repo's test-before-production rule.

**Tech Stack:** Bash (`#!/usr/bin/env bash`, `set -euo pipefail`), `jq` (`/usr/bin/jq`), Claude Code skills + hooks (`Stop` event), plain-shell test scripts.

## Global Constraints

- Spec: `docs/superpowers/specs/2026-07-09-handover-skill-design.md` (authoritative for format + behavior).
- Test style: plain `bash` scripts under `tools/`, named `tools/test_handover_*.sh`, using `set -euo pipefail` and `pass()`/`fail()` helpers with `PASSED`/`FAILED` counters (match `tools/test_smoke.sh`).
- All hermetic tests must NOT touch the real `~/.claude/` — override `HOME` and `TMPDIR` to temp dirs.
- The skill and hook **never run `git commit`** — they write files only; the user commits (repo rule).
- Entry key block is exactly: line 1 `## <DATE> <TIME> · <slug> · <title>`, line 2 `status: <value>`, line 3 `branch: <text>`. `status` ∈ `in-progress | blocked | done | superseded-by:<YYYY-MM-DD>`. Not YAML.
- Newest-first: new entries are **prepended** to `RepoHandover.md`.
- Stop hook offers **at most once per session** (session-id sentinel), soft offer only (never `decision:"block"`).
- Commit messages: Conventional Commits, no "Generated with Claude Code" footer, no Co-Authored-By. Trailers `Tool:`/`Model:`/`Why:` optional per repo convention. Do NOT commit unless the executing operator confirms (repo rule); plan commit steps stage only their own task's paths.

---

## File Structure

Source of truth (repo, versioned, tested):
- Create `tools/handover/handover-lint.sh` — validates the newest entry's key block. Test oracle + reusable by the skill.
- Create `tools/handover/handover-offer.sh` — the `Stop` hook: gates + soft offer.
- Create `tools/handover/install.sh` — idempotent global installer.
- Create `tools/handover/SKILL.md` — the `/handover` skill (drafting/format/write/supersede/pointer logic).
- Create `tools/test_handover_lint.sh` — tests for the validator.
- Create `tools/test_handover_hook.sh` — tests for the hook (gate matrix).
- Create `tools/test_handover_install.sh` — tests for the installer (fake `HOME`).

Deployed (global, created by installer at execution time):
- `~/.claude/skills/handover/SKILL.md`
- `~/.claude/hooks/handover-offer.sh`
- `~/.claude/settings.json` (`Stop` hook entry merged in)

---

## Task 1: Format validator (`handover-lint.sh`)

Locks the entry-format contract as executable spec. The validator checks the **newest** (topmost) entry's 3-line key block. Later tasks (the skill) use it as an acceptance oracle.

**Files:**
- Create: `tools/handover/handover-lint.sh`
- Test: `tools/test_handover_lint.sh`

**Interfaces:**
- Consumes: nothing.
- Produces: CLI `handover-lint.sh <path-to-RepoHandover.md>` → exit `0` if the topmost entry's key block is valid, exit `1` + a one-line reason on stderr otherwise. Empty/missing file → exit `1`.

- [ ] **Step 1: Write the failing test**

Create `tools/test_handover_lint.sh`:

```bash
#!/usr/bin/env bash
set -euo pipefail

LINT="$(dirname "$0")/handover/handover-lint.sh"
WORK="$(mktemp -d)"
trap 'rm -rf "$WORK"' EXIT
PASSED=0; FAILED=0
pass() { echo "✓ $1"; PASSED=$((PASSED+1)); }
fail() { echo "✗ $1"; FAILED=$((FAILED+1)); }

# assert_exit <expected-code> <file> <label>
assert_exit() {
  local want="$1" file="$2" label="$3" got=0
  bash "$LINT" "$file" >/dev/null 2>&1 || got=$?
  if [ "$got" = "$want" ]; then pass "$label"; else fail "$label (want exit $want, got $got)"; fi
}

# Valid entry
cat > "$WORK/good.md" <<'EOF'
## 2026-07-09 14:32 · runway-auth · AS-owned OAuth (P2)
status: in-progress
branch: main @ 9ade2753 (dirty: 2 files)

**State in one line:** next is P2.
EOF
assert_exit 0 "$WORK/good.md" "valid entry passes"

# superseded-by status is valid
cat > "$WORK/superseded.md" <<'EOF'
## 2026-07-09 14:32 · runway-auth · title
status: superseded-by:2026-07-10
branch: main @ abc1234 (clean)
EOF
assert_exit 0 "$WORK/superseded.md" "superseded-by status passes"

# Bad status value
cat > "$WORK/badstatus.md" <<'EOF'
## 2026-07-09 14:32 · slug · title
status: wip
branch: main @ abc1234
EOF
assert_exit 1 "$WORK/badstatus.md" "invalid status fails"

# Missing branch line
cat > "$WORK/nobranch.md" <<'EOF'
## 2026-07-09 14:32 · slug · title
status: done
**State:** x
EOF
assert_exit 1 "$WORK/nobranch.md" "missing branch line fails"

# Heading without timestamp
cat > "$WORK/badhead.md" <<'EOF'
## runway-auth notes
status: done
branch: main
EOF
assert_exit 1 "$WORK/badhead.md" "heading without timestamp fails"

# Empty file
: > "$WORK/empty.md"
assert_exit 1 "$WORK/empty.md" "empty file fails"

# Missing file
assert_exit 1 "$WORK/does-not-exist.md" "missing file fails"

echo "----"; echo "PASSED=$PASSED FAILED=$FAILED"
[ "$FAILED" = 0 ]
```

- [ ] **Step 2: Run the test to verify it fails**

Run: `bash tools/test_handover_lint.sh`
Expected: FAIL — script errors because `tools/handover/handover-lint.sh` does not exist yet.

- [ ] **Step 3: Write the validator**

Create `tools/handover/handover-lint.sh`:

```bash
#!/usr/bin/env bash
# Validate the newest (topmost) entry's key block in
deploySkill

Use when shipping a release of Agent Sessions — bumping version, updating CHANGELOG, building, signing, notarizing, publishing appcast, and creating a GitHub release.

add-agent-supportSkill

Create and ship AgentSessions support for a new or changed local AI agent/provider. Use when adding, reviewing, testing, documenting, or marketing a provider integration, session parser, transcript source, support-matrix entry, verified-version bump, or provider UI surface; drives the full loop from pre-support research through binary install, real session capture, fixture redaction, parser/discovery/search/UI integration, QA, review/fix loops, support records, PR/release notes, and conservative marketing claims.

agent-session-format-checkSkill

Verify agent session format compatibility for Agent Sessions. Use when any agent CLI updates, when monitoring flags drift, or when bumping max verified versions (fixtures + docs + tests). Covers session schema, usage/limits tracking, storage backends, and discovery path contracts for all supported agents.

agent-support-matrixSkill

Maintain Agent Sessions agent support matrix and JSON/JSONL parsing compatibility. Use when checking upstream agent releases for session format changes, updating max verified versions in docs/agent-support/agent-support-matrix.yml, or updating docs/agent-json-tracking.md and fixtures/tests.

sc-skillSkill

Capture deterministic macOS screenshots for testing, docs, release notes, and marketing assets. Use when asked to automate app screenshots, batch-generate screenshot sets, standardize window sizing/composition, or choose between Peekaboo and native macOS screenshot tooling.

release-notesSkill

Use when writing or curating the user-facing release copy for an Agent Sessions release — README "What's New", GitHub release notes, Sparkle release notes, or website/launch copy. Not for the internal CHANGELOG, which stays a full development history.

handoverSkill

Use when wrapping up or capturing the current state of a coding session — writes a short, dated entry to the repo's RepoHandover.md so a future agent or you can resume without grepping archived sessions. Triggers on "handover", "hand off", "write handover", "capture state", "checkpoint this session".