agent-history-hygiene
agent-history-hygiene
Keep agent chat transcripts and plan files committed together with the
code they produced, without leaking secrets. Pairs with the
redact-agent-secrets + gitleaks pre-commit hooks the skill installs.
Three surfaces, separated by purpose:
| Surface | Question it answers |
|---|---|
find-session.sh |
"Which transcript / plan file is my current session?" |
stage-agent-artifacts.sh |
"Which agent files belong in the next commit?" |
bootstrap-project.sh |
"How do I get pre-commit + gitleaks + redactor into a repo?" |
scan-staged.sh |
"Is there a leaked secret in what I'm about to commit?" |
references/remediation.md |
"I already pushed a secret — now what?" |
Core invariants
- Agent transcripts and plan files are committed alongside the diff
that produced them. Never add them to
.gitignore. An agent that drops these from a commit has broken the user's review trail. - Rotate at the provider before any git rewrite. The only act that revokes a leaked credential is rotation. History rewriting scrubs bytes on one clone and leaves them on every other.
git push --forceagainst a shared branch is never the fix for a leak. At best it's useless; at worst it destroys teammate work and silently re-introduces the secret when someone merges their old history back.
When to use this skill
Use it when the user (or you) surface any of:
- "Commit my chat" / "save the specstory session" / "include the plan file in this commit" / "把 plan 跟 specstory 一起 commit 進去".
- You see dirty
.specstory/history/*.md,.claude/plans/*.md,.cursor/plans/*.md, or any other configured agent artifact duringgit statusand you're about to commit a feature. - "Scrub this transcript" / "redact my key" / "gitleaks flagged my chat history".
- "Set up pre-commit for this repo" / "I'm starting a new project — how do I get the hook stack?" / "bootstrap secret scanning here".
- "I pushed a
.env" / "a secret went to main" / "do I need to force push?" — the agent must steer toreferences/remediation.mdand stop the user from force-pushing reflexively.
When NOT to use
- The user explicitly wants agent transcripts excluded from the
repo. Respect that; suggest a one-liner
.gitignoreaddition and skip this skill entirely. - The leak is already on a shared
main/release branch. Do not offer to rewrite history — jump toreferences/remediation.md§5. - The project genuinely has no agent session (no
.specstory/, no.claude/plans/, etc.). Nothing to stage. - Single-file, single-commit hygiene that the agent handles without any script (e.g., adding a missing trailing newline).
Integration with existing infrastructure
This skill sits on top of any chezmoi-managed stack the user already has. It does not duplicate:
- chezmoi's global
core.hooksPath(~/.config/git/hooks/pre-commit) — that wrapper runs the repo's.pre-commit-config.yamland then optionallygitleaks git --staged. The skill bootstraps the repo-level config the wrapper expects to find. - chezmoi's
.gitleaks.toml— the user's config already carries curated rules for common API keys (OpenAI, Anthropic, Supabase, Linear, WakaTime, Cursor, HuggingFace, Notion, Tailscale, Clash / V2Ray tokens). The skill'sassets/gitleaks.toml.templateships the same rule IDs so.gitleaksignore/ allowlist tweaks stay portable. - chezmoi's
scripts/redact_secrets.py— remains the upstream source of truth. The skill bundles a copy so non-chezmoi users get protection; sync procedure inreferences/pre-commit-redaction-stack.md.
What this skill adds:
- Agent-facing discipline (this
SKILL.md+references/remediation.md). - A single-command project bootstrap (
bootstrap-project.sh) for repos without chezmoi or where the user wants the stack in one go. - Session-discovery heuristics (
find-session.sh) for the "find my current transcript among many" problem. - An exit-code wrapper (
scan-staged.sh) agents can branch on before committing.
Workflow A: commit-time hygiene
Default flow when the agent is about to commit feature changes plus chat/plan artifacts.
# 1. Make sure the agent knows which session is "ours" — mostly
# relevant when multiple Claude/SpecStory sessions run in the repo.
bash skills/local/agent-history-hygiene/scripts/find-session.sh
# 2. Stage code the usual way, then auto-add agent artifacts.
git add path/to/feature/file.ts
bash skills/local/agent-history-hygiene/scripts/stage-agent-artifacts.sh
# Use --session-only if you want ONLY the current SpecStory + newest plan;
# default stages every dirty *.md in every configured agent dir.
# 3. Belt-and-suspenders secret scan before commit. Exit 0 = clean.
bash skills/local/agent-history-hygiene/scripts/scan-staged.sh || {
# Exit 10/20: leaks found. Jump to references/remediation.md.
echo "Leaks detected — see references/remediation.md before committing." >&2
exit 1
}
# 4. Commit. pre-commit (installed by bootstrap) runs redact-agent-secrets
# then gitleaks again as a catch-all.
git commit -m "feat: ..."
Workflow B: bootstrap a new project
For repos that don't yet have .pre-commit-config.yaml / .gitleaks.toml
installed. Runs once per repo.
cd /path/to/new/project
bash skills/local/agent-history-hygiene/scripts/bootstrap-project.sh \
--install-hook # optional: auto-stage on every commit
# Verify: shake out any existing issues in the working tree.
pre-commit run --all-files
What bootstrap-project.sh does:
- Drops
.pre-commit-config.yaml+.gitleaks.tomlinto the repo (skips if already present unless--force). - Writes
scripts/redact_secrets.py(bundled copy; use--from-chezmoito symlink the chezmoi source so fixes propagate). - Runs
pre-commit install(oruvx pre-commit@4 installif pre-commit isn't onPATH). - Audits
.gitignore/.git/info/excludefor patterns that would silently hide an agent artifact dir — warns without editing. - Checks
~/.claude/settings.jsonforplansDirectory; prints the one-line patch if missing. - With
--install-hook: writes aprepare-commit-msghook that callsstage-agent-artifacts.sh --session-only --allow-emptyso everygit commitauto-attaches the current session file.
Workflow C: post-leak remediation
When scan-staged.sh reports exit 10/20, or the user says "I
committed / pushed a secret":
- STOP the user from running
git push --forcereflexively. - Read
references/remediation.mdend-to-end. - Walk the user through step 1 (rotate) regardless of blast radius. Only after rotation does the question of scrubbing history become worth discussing.
- Use the decision tree in the runbook to pick the right git action.
Gotchas
plansDirectoryproject-level sometimes ignored. Claude Code issue #19537 reports project-levelplansDirectorybeing ignored in some versions. After running a/plan, verify the file actually landed where you expected before relying onstage-agent-artifacts.shpicking it up. User-level config (~/.claude/settings.jsonwith"plansDirectory": "./.claude/plans") is the recommended default.gitleaks protectis deprecated. Since v8.19.0 usegitleaks git --staged --redact(pre-commit) andgitleaks dir <path>(working directory). The older commands still work but emit a deprecation notice. This skill uses the modern syntax everywhere.pre-commit installis per-clone. Each teammate must runpre-commit installin their own clone for hooks to fire. CI cannot be trusted as the single gate — it's second-chance, not last-chance.- Transcript files can be huge. A long SpecStory session can exceed
2 MB. The template bumps
check-added-large-filesto--maxkb=2048to avoid false positives, but a very long session can still overflow. If you hit the limit, rotate sessions (specstory run claudecreates a fresh file) instead of raising the cap further. - Session-UUID divergence between SpecStory CLI and VS Code
extension. The extension autosaves into
.specstory/history/continuously; the CLI (specstory run claude) creates one file per invocation. If both are active you can end up with two transcripts for what feels like "one session" — mtime-newest wins infind-session.sh. - Global
core.hooksPathmeans bare repos aren't protected. The chezmoi setup's global hook runs.pre-commit-config.yamlIF it exists — so a repo without.pre-commit-config.yamlhas no protection. Runbootstrap-project.shbefore the first commit with agent artifacts, not after. - Active SpecStory writer can defeat the redact loop. The standard
git add → git commit → pre-commit auto-fixes → re-stage → re-commitflow assumes the file is quiescent during the commit. SpecStory'sspecstory_*_watchdaemon tails the agent transcript continuously, so if the chat capturedps -axo args-style output that contained an unrelated daemon's secret in argv (e.g. SpecStory's own--cloud-token …flag), every diagnostic command (grep,sed -n '<line>p',cat | head | tail) prints the secret again, SpecStory appends it to the transcript, and the redact-then-restage cycle never converges. Symptom: pre-commit says "Successfully redacted N file(s)" butgitleaks-systemimmediately fails on the same line, re-runninggit add && git commitdoesn't help, andgrep -c '<secret-prefix>' fileshows the count increasing over commit attempts. Workaround: a single atomicpython3 -c "<in-place re.sub>" && git add <file> && git commit -m "..."pipeline so the index is frozen before any new specstory write lands. Don't print, grep, or diff the secret line during the recovery — every print echoes back into the transcript. Diagnose withlsof <file>(looking forspecstory_*writers) instead. Seepitfalls/redact-secrets-loop-with-active-specstory-writer.mdin upstream chezmoi for the full debugging trail.
Available scripts
-
scripts/find-session.sh [--format=specstory|claude|both] [--json]Discover the current agent session files for$PWD. TSV default,--jsonfor structured callers. Never exits non-zero (always 0, empty fields signal absence). -
scripts/stage-agent-artifacts.sh [--session-only] [--include-all-plans] [--dry-run] [--allow-empty]git addthe right agent artifacts before the next commit.--session-onlystages only the current SpecStory + newest plan; default stages every dirty*.mdin every configured artifact dir. Refuses to run if there are no code changes (prevents "commit just transcript"); override with--allow-empty. -
scripts/scan-staged.sh [--redact] [--verbose]Rungitleaks git --stagedwith agent-friendly exit codes (0 clean / 10 redacted / 20 leaks / 30 gitleaks missing). JSON lines on stdout, prose diagnostics on stderr. -
scripts/bootstrap-project.sh [--from-chezmoi] [--install-hook] [--force] [--dry-run]Install.pre-commit-config.yaml+.gitleaks.toml+ the redactor into the current repo, then runpre-commit install. Audits.gitignoreand~/.claude/settings.jsonfor misconfigurations (warns, never silently edits).
Bundled assets
assets/artifact-dirs.txt— the canonical list of agent artifact directories (SpecStory, Claude plans, Cursor plans + rules, OpenCode plans, Spec-kit, Codex). Consumed bystage-agent-artifacts.shand bybootstrap-project.shwhen rendering the pre-commitfiles:regex.assets/pre-commit-config.yaml.template— minimal.pre-commit-config.yamlwithredact-agent-secrets+ gitleaks + standard hygiene hooks.assets/gitleaks.toml.template— portable subset of the chezmoi.gitleaks.tomlwith custom rule IDs + a path-scoped allowlist for agent artifact dirs.assets/redact_secrets.py— bundled copy of chezmoi'sscripts/redact_secrets.py. Chezmoi version is upstream; sync doc inreferences/pre-commit-redaction-stack.md.
Reference files
references/transcript-session-discovery.md— SpecStory / Claude session layouts and the$PWD → slugalgorithm. Read whenfind-session.shreturns empty or ambiguous results.references/pre-commit-redaction-stack.md— three-layer defense (redact → gitleaks →scan-staged.sh), allowlist design, sync procedure for the bundled redactor. Read when tuning rules or debugging unexpected pre-commit failures.references/remediation.md— rotate-first runbook for "I committed / pushed a secret". Read before anygit filter-repo/git push --forceaction.
Tests
The skill ships with a three-level test suite under
tests/. Run from repo root:
make test-skill
test_redact_secrets.py— pytest for pure redactor functions.test_gitleaks_corpus.py— golden-corpus fixtures staged in tmp git repos, asserting real-key shapes fire and example shapes are allowlisted only inside configured artifact dirs.test_scan_staged.sh— exit-code contract forscripts/scan-staged.sh(0 / 20 / 30 / 2).
The corpus + shell tests skip gracefully when gitleaks isn't on
PATH. See tests/README.md for what each
regression the suite locks in.
Related skills
project-knowledge-harness— complementary memory harness (TODO.md + backlog/ + pitfalls/) that references.claude/plans/as "ephemeral agent scratchpads". This skill fills the gap: those scratchpads belong in git, not ignored.
More from daviddwlee84/agent-skills
project-knowledge-harness
Set up a structured project memory for any software project — TODO.md as priority/effort-tagged index of future work, backlog/ for resume-friendly research/design notes on P? items, and pitfalls/ as a symptom-grep-able knowledge base of past traps. Use when a user wants somewhere to record "maybe later" ideas, freeze troubleshooting state, capture trade-off analysis, or stop re-debugging the same problem.
15mkdocs-site-bootstrap
Bootstrap MkDocs Material docs sites with optional GitHub Pages deploy, uv-pinned tooling, llms.txt/copy-to-LLM support, page/nav helpers, and mkdocs-static-i18n languages such as zh-TW. Use when the user asks to set up docs, publish docs to GitHub Pages, create an MkDocs site, turn README or markdown notes into a site, add bilingual/multilingual docs, add zh-TW/Traditional Chinese, i18n, or translate docs. Consent-gated; records repo preferences and never auto-migrates existing docs.
11pueue-job-queue
Drive Nukesor/pueue (https://github.com/Nukesor/pueue) for queued, parallel, scheduled, and lightly-DAG'd shell jobs — wraps `pueue add --after`, `pueue status --json`, `pueue log --json`, group-level parallelism, and `pueued` daemon health. Use when the user wants to background long-running shell commands across reboots, queue dozens of jobs with capped parallelism, run a fan-out / fan-in pipeline of shell steps, says "pueue", "pueued", "pueue add", "pueue queue", "pueue group", "task queue for shell", "background this job", or asks how to schedule/parallelize CLI work without a real orchestrator (Airflow/Prefect/Dagster). Good fit for ML sweeps, long-running data pipelines, batched evaluations, scheduled `--delay` jobs, "wait for X then run Y" sequences.
4marimo-notebook
Write a marimo notebook in a Python file in the right format.
3skill-author
Author a new agent skill or refactor an existing one to follow agentskills.io best practices — gotchas sections, output templates, validation loops, calibrated specificity (fragility-based), and agentic script design (--help, --dry-run, structured stdout, stderr diagnostics, PEP 723 inline deps, pinned uvx/npx versions). Use whenever the user wants to create a new skill from scratch, scaffold a SKILL.md, write a reference file, design a script meant to be invoked by an agent, lint a draft skill for quality, or convert an ad-hoc workflow into a reusable skill. For evaluating skill output quality with test cases, benchmarking, or optimizing the description trigger rate, defer to the `skill-creator` skill instead — this skill focuses on authoring, not evaluation.
2dvc-ml-workflow
Set up and operate a DVC (Data Version Control) workflow for ML projects — `dvc init`, `dvc.yaml` pipelines, `params.yaml`, `dvc exp run --queue` for parallel sweeps with metrics auto-bound to ephemeral git commits, and remote storage (S3/SSH/GDrive). Use whenever the user wants reproducible ML pipelines, data/model versioning that lives alongside git, parameter sweeps without standing up a tracking server, queued/parallel experiment execution, or asks about `dvc.yaml` / `dvc exp run` / `dvc queue` / `params.yaml` / `dvc add` / `dvc push` / `.dvc/cache`. Always references the official docs at https://dvc.org/doc and the upstream repo https://github.com/treeverse/dvc (Iterative was acquired by Treeverse in 2024 — `pip install dvc` resolves to this repo).
2