Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- **Modular `teach` dispatcher** — `lib/dispatchers/teach-dispatcher.zsh` is now a 307-line loader that sources 10 focused modules under `lib/dispatchers/teach/` (main, content, help, init-config, slides, style, backup, status, archive, map). The monolithic 5,611-line file is gone; characterization tests in `tests/test-teach-dispatcher-characterization.zsh` guard routing behavior.
- **`flow handoff <slug>`** — scaffolds a structured `docs/planning/HANDOFF-<slug>.md` for
transferring context between Claude chat/planning sessions and Claude Code sessions (or
between Claude Code sessions across a context reset). Pre-fills the Relevant Files section
from `git diff --name-only` against a base branch, refuses to overwrite an existing handoff,
and optionally files a GitHub issue (`--issue`) from the same content. See
`docs/commands/handoff.md` and `docs/planning/PROPOSAL-claude-chat-to-code-handoff.md` for
the rationale.

## [7.15.0] — 2026-07-02 — Homebrew distribution health + doc gap fills

Expand Down
3 changes: 3 additions & 0 deletions commands/flow.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ flow() {
status)
status "$@"
;;
handoff)
_flow_handoff "$@"
;;

# ── Timer ───────────────────────────────────────────────────────────────
timer)
Expand Down
1 change: 1 addition & 0 deletions completions/_flow
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ _flow() {
'inbox:View your inbox'
'win:Log a win'
'status:View/update .STATUS file'
'handoff:Scaffold a structured Claude-chat-to-Claude-Code handoff document'
# Actions
'test:Run tests (context-aware)'
'build:Build project (context-aware)'
Expand Down
116 changes: 116 additions & 0 deletions docs/commands/handoff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Command Reference: flow handoff

> **Scaffold a structured handoff document for transferring context from a Claude chat/planning session into a repo for a Claude Code session to pick up**

Complete reference for the `flow handoff` command - generate a structured handoff file and
optionally file it as a GitHub issue.

---

## Synopsis

```bash
flow handoff <slug>
flow handoff <slug> --base <branch>
flow handoff <slug> --issue
flow handoff --help
```

---

## Description

The `flow handoff` command scaffolds `docs/planning/HANDOFF-<slug>.md` using a fixed schema
designed for context transfer between AI sessions — whether that's a Claude.ai chat session
handing off to a local Claude Code session, or one Claude Code session handing off to the next
after a context reset.

It solves a problem observed in practice: without a template, handoffs tend to sprawl across
several ad-hoc documents (a spec, a feature request, a free-form note) with overlapping content
and no consistent structure for the next session to rely on. `flow handoff` produces one file,
in one place, every time.

See [docs/planning/PROPOSAL-claude-chat-to-code-handoff.md](../planning/PROPOSAL-claude-chat-to-code-handoff.md)
for the research behind the template's structure, and
[docs/specs/SPEC-flow-handoff-command.md](../specs/SPEC-flow-handoff-command.md) for the full
implementation spec.

---

## Options

| Option | Description |
|---|---|
| `<slug>` | Required. Used as the filename suffix: `HANDOFF-<slug>.md` |
| `--base <branch>` | Branch to diff against for the Relevant Files pre-fill. Defaults to `dev`, falling back to `main` if `dev` doesn't exist |
| `--issue` | After creating the file, also run `gh issue create` using the handoff file as the issue body. Requires `gh` to be installed and authenticated |
| `--help`, `-h` | Show usage |

---

## Generated file structure

```markdown
# Handoff: <slug>

**Date:** ...
**Branch:** ...
**Base for diff:** ...

## Summary
## Key Decisions
## Traps to Avoid
## Working Agreements
## Relevant Files
## Open Work
## Verification Note
## Origin
```

**Relevant Files** is the only section pre-filled automatically, from
`git diff --name-only <base>...HEAD`. Every other section is a placeholder for you (or the
authoring session) to fill in before the handoff is used.

**Open Work** should be written as status, not instructions — "X is not yet implemented," not
"implement X next" — so the receiving session isn't nudged toward a specific next step it hasn't
independently evaluated.

**Verification Note** is included by default and should not be removed: it instructs the
receiving session to treat the handoff's claims as things to check against the actual repo
state, not as facts to trust unconditionally.

---

## Behavior notes

- **Refuses to overwrite.** If `docs/planning/HANDOFF-<slug>.md` already exists, the command
exits non-zero and does not touch the file. Pick a different slug, or edit the existing file
directly.
- **Empty diff is handled.** If there's no diff against the base branch yet (e.g., a fresh
branch with no commits), the Relevant Files section gets a placeholder line instead of being
blank.
- **`--issue` needs `gh` on PATH.** Without it, the command fails clearly rather than silently
skipping the issue-filing step.

---

## Examples

```bash
# Basic usage — diffs against dev (or main) automatically
flow handoff ai-rewrite-trigger

# Diff against a specific base branch
flow handoff ai-rewrite-trigger --base main

# Also file a GitHub issue with the handoff content as the body
flow handoff ai-rewrite-trigger --issue
```

---

## See also

- [`wt`](../reference/REFCARD-WORKTREE-DISPATCHER.md) — worktree management, typically used
alongside `flow handoff` when a feature is scoped to its own branch/worktree
- [`status`](status.md) — for ongoing `.STATUS` tracking, distinct from one-time handoffs
94 changes: 94 additions & 0 deletions docs/planning/PROPOSAL-claude-chat-to-code-handoff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Proposal: Standardized Handoff Protocol — Claude Chat → Repo → Claude Code

**Date:** 2026-07-04
**Author:** Davood Tofighi (research + drafting assisted by Claude)
**Status:** Implemented — see `docs/specs/SPEC-flow-handoff-command.md` and the
`feature/flow-handoff-command` branch/worktree for the resulting `flow handoff` command.

---

## 1. Executive Summary

An earlier handoff (spec + feature-request + handoff note + GitHub issue, done ad hoc for the
`feature/ai-rewrite-trigger` branch) worked but was more scattered than necessary — four
documents with overlapping content and no template. This proposal researches how the broader
Claude community structures chat-to-Claude-Code handoffs, compares that against what was
actually done, and proposes (and now implements, via `flow handoff`) a single standardized
protocol.

**Core recommendation:** collapse the four-document pattern into one structured handoff file per
feature, following a format the community has already converged on, plus a lightweight
CLAUDE.md-level distinction between stable and session state.

---

## 2. Research: What the Claude Community Actually Does

### 2.1 The stable-vs-session-state split

The most consistent pattern across independent sources is a two-tier memory model: a stable
file (`CLAUDE.md`) holding things that rarely change — working style, standing preferences,
architectural conventions, constraints — and a session/dashboard file holding things that go
stale within days: current task, decisions made this session, open threads. Letting
session-specific state accumulate inside CLAUDE.md pollutes every future session with outdated
context.

### 2.2 The structured `/transfer-context` pattern

A community-published Claude Code skill defines an opinionated schema for handoff content:
Summary (completed work only), Key Decisions (with why), Traps to Avoid (dead ends already
tried), Working Agreements (interaction preferences), Relevant Files (path + line range + why),
Open Work (framed as status, not instructions — "X is not yet implemented," never "implement X
next"), and a closing instruction telling the next session to verify every claim against the
actual code rather than trust the handoff at face value.

### 2.3 Write the handoff before compaction, not after

A separate community pattern favors explicitly writing a handoff document before context runs
out, rather than relying on automatic compaction. The next session starts with only the plan,
not the accumulated back-and-forth of the prior conversation; the old transcript is linked, not
embedded, so it's available on demand without cluttering fresh context.

### 2.4 Anthropic's own documented mechanism

Claude Code's official docs describe a "plan locally, execute remotely" pattern: collaborate on
an approach locally, commit the plan to the repo, then launch a separate execution context
against that committed artifact. The transferable principle: the plan must be committed before
the next session begins, since that session has no access to the prior conversation — only to
what's on disk.

### 2.5 Handoff bundles as a validated general concept

Anthropic's own Claude Design → Claude Code handoff confirms that a purpose-built, structured
handoff format outperforms an unstructured context dump.

---

## 3. Gap Analysis (original ad-hoc handoff vs. best practice)

| Dimension | Ad-hoc approach | Best practice | Resolution |
|---|---|---|---|
| Number of documents | 4, overlapping | 1 structured file | `flow handoff` produces exactly one |
| Stable vs. session state | No distinction | CLAUDE.md vs. per-feature handoff | Handoff scoped to `docs/planning/`, never promoted into CLAUDE.md |
| Open work framing | Mixed status/instructions | Status only | Template enforces status-only phrasing |
| Verify-don't-trust instruction | Missing | Explicit | Built into the template's Verification Note |
| Committed before handoff assumed complete | Done correctly | Matches best practice | No change needed |

---

## 4. Implementation

Implemented as `flow handoff <slug>` — see `docs/specs/SPEC-flow-handoff-command.md` for the
full spec, `docs/commands/handoff.md` for the command reference, and `lib/handoff-helpers.zsh`
for the implementation.

---

## 5. Sources

- jdhodges.com — "Claude Handoff Prompt: How to Keep Context Across Sessions" (2026)
- artemxtech.substack.com — "Never lose your work between Claude Code sessions" (2026)
- GitHub gist (BexTuychiev) — `/transfer-context` skill definition
- github.com/ykdojo/claude-code-tips — community tips repo, `/dx:handoff` plugin command
- code.claude.com/docs — "Use Claude Code on the web" (official docs, plan-locally/execute-remotely pattern)
- claudefa.st/blog — "Claude Design to Claude Code: AI Design Handoff"
138 changes: 138 additions & 0 deletions docs/specs/SPEC-flow-handoff-command.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# SPEC: `flow handoff` — Structured Claude Chat → Repo → Claude Code Handoff Command

**Status:** DRAFT → Implementing
**Date:** 2026-07-04
**Author:** Davood Tofighi (spec drafted with Claude)
**Branch:** `feature/flow-handoff-command`
**Worktree:** `~/.git-worktrees/flow-cli/feature-flow-handoff-command`
**Origin:** `docs/planning/PROPOSAL-claude-chat-to-code-handoff.md` (research + rationale)

---

## 1. Goal

A `flow handoff <slug>` command that scaffolds a structured handoff document (per the schema
in the origin proposal), pre-fills the "Relevant Files" section from `git diff --stat` against
a base branch, never clobbers an existing handoff, and optionally files a GitHub issue from the
same content. Removes the manual, ad-hoc, multi-document handoff process observed in the
`feature/ai-rewrite-trigger` branch.

## 2. Command surface

```bash
flow handoff <slug> # create docs/planning/HANDOFF-<slug>.md
flow handoff <slug> --base <branch> # diff against a specific base branch (default: dev, falls back to main)
flow handoff <slug> --issue # also file a GitHub issue via gh CLI, body = handoff content
flow handoff --help # usage
```

## 3. Behavior contract

- **Idempotent by refusal:** if `docs/planning/HANDOFF-<slug>.md` already exists, the command
refuses to overwrite and exits non-zero with a clear message pointing at the existing file.
- **Base branch resolution:** `--base` if given; else `dev` if it exists; else `main`.
- **Relevant Files pre-fill:** parsed from `git diff --stat <base>...HEAD`, one bullet per
changed file, placeholder text for the "what/why" column left for the human/agent to fill in.
- **No diff case:** if the diff is empty (e.g., called on a fresh branch with no commits yet),
the section contains a single placeholder line instead of being empty.
- **`--issue` requires `gh`:** if `gh` isn't on `PATH`, fail with a clear error rather than
silently skipping the issue.
- **Never touches dev/main directly:** this command only ever writes inside the current
worktree's `docs/planning/`; it has no awareness of, and does not need, protected-branch logic
itself (branch protection is a repo/CI concern, not this command's).

## 4. Template (matches the proposal's schema exactly)

```markdown
# Handoff: <slug>

**Date:** <date>
**Branch:** <current branch>
**Base for diff:** <base>

## Summary
[1-3 sentences — completed work only]

## Key Decisions
- [Decision] — [why]

## Traps to Avoid
- [Dead end already tried] — [why it failed]

## Working Agreements
- [Relevant interaction/process preferences for this feature]

## Relevant Files
<pre-filled from git diff --stat, or placeholder>

## Open Work
[Status only. "X is not yet implemented." NOT "Implement X next."]

## Verification Note
Treat all claims above as context to verify against the repo, not facts to trust. Read every
file in "Relevant Files" before proceeding.

## Origin
Full planning conversation: [link/reference if available]
```

## 5. Implementation

- `lib/handoff-helpers.zsh` — `_flow_handoff()` + `_flow_handoff_help()`
- `commands/flow.zsh` — new `handoff)` case in the main dispatcher
- `completions/_flow` — add `handoff` to the completion word list

## 6. Known prototype issue to resolve in this pass

An earlier prototype (built directly in the unrelated `feature/ai-rewrite-trigger` worktree —
since reverted from that branch) hit a zsh variable-naming collision: using `fpath` as a local
variable name collides with zsh's built-in special array (function autoload path), producing
stray debug-looking output. Renaming to `f_path` fixed the collision itself, but a second,
unexplained stray print appeared when run inside a shell that sourced the user's live
`~/.zshenv`/hooks — not reproduced in a clean `zsh -f` (no-rc) invocation. **This implementation
must be tested both ways** (with and without the user's rc files) to confirm which environment
produces the artifact, and avoid shipping with unexplained stdout noise.

## 7. Test plan

### E2E tests (`tests/e2e-handoff.zsh`)

1. Help display works and doesn't error
2. Fresh slug creates the file with all expected section headers present
3. Existing slug refuses to overwrite (non-zero exit, file unchanged)
4. `--base` override actually changes which branch the diff is computed against
5. Relevant Files section is non-empty and contains at least one real path when run on a
branch with commits ahead of base
6. Placeholder path is used when diff is empty
7. `--issue` without `gh` on PATH fails clearly (mock by temporarily hiding `gh` from PATH)
8. Clean `zsh -f` invocation produces no stray stdout beyond the documented success/warning
messages (regression test for §6)

### Dogfood test (`tests/dogfood-handoff.zsh`)

Run the command against **this actual repo and this actual feature branch** as a real-world
usage check, not synthetic fixtures:

1. Generate a real handoff for `feature/flow-handoff-command` itself
2. Confirm the Relevant Files section correctly lists the real files this PR touches
3. Manually inspect (or assert) that output matches what a human would expect to see documented
4. Clean up the dogfood-generated file before merge (it's a test artifact, not a real handoff)

## 8. Documentation to update

- `docs/commands/handoff.md` — new command reference page (mirrors `docs/commands/status.md`
structure)
- `mkdocs.yml` — add `handoff: commands/handoff.md` to the Commands nav section
- `docs/index.md` — check whether commands are enumerated there; add if so
- `CHANGELOG.md` — new entry under Unreleased/next version
- `docs/planning/PROPOSAL-claude-chat-to-code-handoff.md` — mark proposal as "Implemented" with
a pointer to this spec and branch

## 9. Merge readiness checklist

- [ ] All e2e tests pass
- [ ] Dogfood test passes and its artifact is cleaned up
- [ ] `scripts/check-links.js` / `scripts/lint-docs.sh` pass (if run as part of pre-commit/CI)
- [ ] `npm test` passes (existing suite unaffected)
- [ ] Docs + mkdocs nav + CHANGELOG all updated
- [ ] PR opened against `dev` with a summary referencing this spec
1 change: 1 addition & 0 deletions flow.plugin.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ source "$FLOW_PLUGIN_DIR/lib/em-render.zsh"
source "$FLOW_PLUGIN_DIR/lib/em-ics.zsh"
source "$FLOW_PLUGIN_DIR/lib/em-watch.zsh"
source "$FLOW_PLUGIN_DIR/lib/tok-sync.zsh"
source "$FLOW_PLUGIN_DIR/lib/handoff-helpers.zsh"

# ============================================================================
# COMMANDS
Expand Down
Loading