agentleFS
AbdurRafay2004AbdurRafay2004/handoff/CLAUDE.md

handoff

CLAUDE.md4 starsChanged 24 days agoMITView on GitHub

This file records shared contributor guidance. Claude Code reads it directly; Codex is pointed here by AGENTS.md. This repo is a Claude Code and local Codex plugin named handoff. It is not an application. It ships a hook-driven project-memory system plus an owned development workflow layer that other repos install. There is no build step and no dependency tree — the deliverable is Python hook scripts (stdlib only), a skill set, and a template tree. CI (.github/workflows/ci.yml) runs the stdlib…

  • Commits and pushes

We split this CLAUDE.md into the rules it gives an agent

8 rules. About 0 are common, 2 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Do not confuse the two layers:

    line 25
  2. Very specific:

    Stop emits decision: block plus reason, the supported continuation response for both hosts.

    line 65
  3. Very specific:

    pushed: every session; everything else (BOOT.md, MAP.md, context/*, tasks/, CHANGELOG.md, folder CONTEXT.md) is pulled on demand, zero cost …

    line 74
  4. Very specific:

    Fail-safe always: Every hook wraps main() so any exception prints nothing and exits 0.

    line 82
  5. Distinctive:

    Keep that contract; callers assume it.

    line 85
  6. Very specific:

    Run python3 tests/test_hooks.py — the same stdlib smoke suite CI runs (fixture repos piped through all three hooks, including the fail-safe …

    line 100
  7. Very specific:

    No output + exit 0 is the common (correct) result — most invocations are intentionally silent.

    line 117
  8. Very specific:

    Keep hooks stdlib-only — no third-party imports.

    line 121

≈ “Common” is an estimate: at least 1 in 5 of the 25,680 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md

CLAUDE.md

This file records shared contributor guidance. Claude Code reads it directly; Codex is pointed here by AGENTS.md.

What this repo is

This repo is a Claude Code and local Codex plugin named handoff. It is not an application. It ships a hook-driven project-memory system plus an owned development workflow layer that other repos install. There is no build step and no dependency tree — the deliverable is Python hook scripts (stdlib only), a skill set, and a template tree. CI (.github/workflows/ci.yml) runs the stdlib smoke tests in tests/test_hooks.py on every push/PR.

The skill set (v1.2.0+): setup (scaffolding), workflow (the 6-phase, risk-tiered pipeline — the constitution that owns sequencing), and thirteen technique skills (brief, plan, design, tdd, debug, architecture, delegate, verify-done, security, browser-qa, ship, learn, grill-me) forked from MIT-licensed superpowers, mattpocock-skills, gstack, and rampstack-skills with all cross-pack orchestration stripped (see ATTRIBUTION.md). When editing a technique skill, never reintroduce pack-style enforcement preambles or cross-skill process handoffs — workflow alone decides sequencing and tiering.

Do not confuse the two layers:

  • The plugin (hooks/, skills/, .claude-plugin/, .codex-plugin/) — what a developer installs into Claude Code or local Codex. Editing here changes behavior for every repo that uses it.
  • The templates/ tree — the payload the setup skill copies into a target repo as .handoff/. This is committed to the target repo so memory travels with the code. Editing here changes what newly-set-up repos get; it does not affect already-set-up repos.

Runtime model (how the pieces connect)

Everything is driven by three hooks registered in hooks/hooks.json (auto-loaded because it lives at hooks/hooks.json — the plugin manifest deliberately does not declare a hooks field; see commit 1844000). Each hook is a thin python3 entry that imports shared logic from hooks/_common.py:

  • sessionstart.py (SessionStart) — if the target repo has .handoff/, injects STATUS.md + RULES.md in full plus an on-demand pointer, captures a git baseline for the session (HEAD sha + dirty paths with status codes — so the Stop hook sees committed work too), and checks .handoff/VERSION against the plugin version (template-drift nag; missing stamp nags once per repo). If no .handoff/, emits a one-time "run setup" tip per repo (marker file in ~/.cache/handoff/) and stays silent forever after.
  • pre_edit_context.py (PreToolUse: Edit/Write/MultiEdit/NotebookEdit/apply_patch) — walks up from the file being edited to find the nearest CONTEXT.md and injects it once per session; also corrects task files about to be written to the tasks/ ROOT (they belong in inbox|now|done). Injects additionalContext only — never a permissionDecision — so it can't silently auto-approve edits. Codex supplies patch text in tool_input.command; every add/update/delete/move header is considered, with patch paths resolved against the hook's cwd.
  • stop.py (Stop) — nudges when the session made new repo changes (committed or uncommitted — session-changed = commits since baseline HEAD + dirty paths whose code changed) but didn't update durable state: STATUS.md / CHANGELOG.md / MAP.md (structural changes only) / a folder's CONTEXT.md. Also flags: task files stranded in the tasks/ root (shown once per session per stray-set), STATUS.md over 40 lines, sentinel paths (auth/migration/billing/… — configurable via .handoff/SENTINELS, forces the T3 question into the transcript), and an open .handoff/GATE (machine-readable T3 stall). The nudge instructs that state updates ride in the SAME commit as the code (amend only if unpushed AND the last commit is this session's own work). Stop emits decision: block plus reason, the supported continuation response for both hosts. Context-only hookSpecificOutput is for SessionStart/PreToolUse.

Without CLAUDE_PROJECT_DIR, root discovery uses git from the hook's cwd; without git, it looks for an ancestor .handoff/. Codex's native PLUGIN_DATA is preferred for persistent markers, with the Claude alias as fallback. Codex also sets CLAUDE_PLUGIN_ROOT, so the shared registered commands work in both.

The push/pull principle behind all of it: always-relevant state (STATUS+RULES) is pushed every session; everything else (BOOT.md, MAP.md, context/*, tasks/, CHANGELOG.md, folder CONTEXT.md) is pulled on demand, zero cost until read.

Invariants — do not break these when editing hooks

These are the load-bearing correctness properties. Most of the git history is fixing regressions against them.

  1. Fail-safe always. Every hook wraps main() so any exception prints nothing and exits 0. A hook bug must never break a user's session. New code paths must preserve this.
  2. _common.py helpers swallow errors (return None/{}/default) rather than raise. Keep that contract; callers assume it.
  3. stop.py has three independent loop-breakers — do not remove any: stop_hook_active guard, the session git baseline (only flags changes made this session, not pre-existing dirt), and the nudge-signature cooldown (never repeats the same unresolved nudge). Removing one risks an infinite Stop-continuation loop.
  4. PreToolUse injects context only, no permission decision.
  5. Path safety in pre_edit_context.py: edits outside the project root are ignored, Claude relative file paths resolve against the project root; Codex patch paths resolve against cwd. Resolve symlinks before checking the boundary, and stop the walk-up at the root. Preserve these checks (original fix: commit d6810e4).
  6. Changes under .handoff/ are excluded from the Stop hook's "new work" set, so updating state doesn't itself trigger a nudge.

Working / testing the hooks

Run python3 tests/test_hooks.py — the same stdlib smoke suite CI runs (fixture repos piped through all three hooks, including the fail-safe garbage-stdin checks). Hooks are plain python3 reading a JSON payload on stdin and emitting JSON context or a Stop continuation response on stdout. Poke one by hand by piping a payload:

# SessionStart against a target repo that has .handoff/
echo '{"cwd":"/abs/path/to/target-repo","session_id":"t1"}' | python3 hooks/sessionstart.py

# PreToolUse — nearest CONTEXT.md for a file about to be edited
echo '{"cwd":"/abs/path/to/target-repo","session_id":"t1","tool_input":{"file_path":"src/foo.ts"}}' | python3 hooks/pre_edit_context.py

# Stop — needs a baseline first (run sessionstart with the same session_id, then make
# a change); after that, a second identical run stays silent (signature cooldown).
echo '{"cwd":"/abs/path/to/target-repo","session_id":"t1","stop_hook_active":false}' | python3 hooks/stop.py

No output + exit 0 is the common (correct) result — most invocations are intentionally silent. Session state (git baseline, nudge signature, per-CONTEXT.md dedup markers) lives in <tmp>/handoff-session-<hash>/; delete that dir to reset a "session" between tests.

Keep hooks stdlib-only — no third-party imports. templates/ is markdown plus .gitkeep files only.

The setup skill

skills/setup/SKILL.md is the guided-discovery flow (set up handoff / /handoff:setup). Its contract: copy templates/ → .handoff/, read the real codebase to draft STATUS/MAP/TECH_STACK/PRODUCT, confirm with the user before saving (never invent project facts — RULES rule 5), optionally seed folder CONTEXT.md, and append a thin-fallback block to the target repo's host instruction file (CLAUDE.md for Claude, AGENTS.md for Codex). Preserve both files if present and keep their handoff blocks consistent. It must refuse to overwrite an existing .handoff/ (offer refresh instead). Codex setup must explain hook trust and cloud limitations.

Releasing

.claude-plugin/plugin.json, .codex-plugin/plugin.json, and .claude-plugin/marketplace.json carry the version — bump all three together (never hardcode the current number in docs; check the manifests). Release-bump commit subjects follow type: summary (vX.Y.Z); non-release commits omit the version suffix. The marketplace registration reads GitHub, not the local clone — a release is only live after git push.

Further reading

  • README.md — install/use, design notes, and the documented known limitations (Bash edits bypass CONTEXT injection, git status 10s timeout, /compact re-baselining, non-git repos disable the Stop nudge).
  • docs/SKILL-WORKFLOW.md — how handoff (the state/context layer) composes with other skill families rather than replacing them.
  • docs/CODEX.md — Codex installation, hook contracts, trust, and host limitations.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.