acd watches a Git worktree and turns file edits into local commits while you
keep working. It is built for AI coding tools such as Claude Code, Codex,
Cursor, OpenCode, and Pi, but the daemon itself is just a static Go binary.
The flow is: your AI tool tells acd that work happened, the daemon records a
durable capture, then replay turns that capture into a normal Git commit.
flowchart TB
Hook["AI tool hook<br/>Claude Code, Codex, Cursor, OpenCode, Pi"]
subgraph Capture["1. Notice and capture edits"]
CLI["acd start / wake / flush<br/>refreshes the repo session"]
Daemon["acd daemon<br/>watches files and records events"]
end
subgraph State["2. Keep the work durable"]
DB[("state.db<br/>event ledger")]
Blobs[("git blobs<br/>captured file content")]
end
subgraph Replay["3. Publish a safe commit"]
Scratch["scratch index replay<br/>rebuilds the intended tree"]
Commit["git commit + update-ref<br/>moves the branch only after checks pass"]
end
Hook --> CLI --> Daemon --> DB
Daemon --> Blobs
DB --> Scratch
Blobs --> Scratch
Scratch --> Commit
classDef external fill:#233142,stroke:#7aa2f7,color:#e6edf3
classDef capture fill:#203a31,stroke:#9ece6a,color:#eaffdf
classDef durable fill:#3d2f1f,stroke:#f6c177,color:#fff4d6
classDef publish fill:#332b46,stroke:#bb9af7,color:#f4edff
class Hook external
class CLI,Daemon capture
class DB,Blobs durable
class Scratch,Commit publish
Building from source or using go install requires Go 1.26.5 or newer.
brew install KristjanPikhof/tap/acdOther options:
curl -fsSL https://raw.githubusercontent.com/KristjanPikhof/Auto-Commit-Daemon/main/scripts/install.sh | sh
go install github.com/KristjanPikhof/Auto-Commit-Daemon/cmd/acd@latestRun the setup command for the tool you use, then paste the printed snippet into
the target config file. Do not redirect with > when you already have custom
hooks, because that replaces the whole file.
acd setup claude-code
acd setup codex
acd setup cursor
acd setup opencode
acd setup pi
acd setup shell| Tool | Config file | Notes |
|---|---|---|
| Claude Code | ~/.claude/settings.json |
Native hook support. |
| Codex | ~/.codex/hooks.json |
Run /hooks after changing the file so Codex re-approves it. |
| Cursor | ~/.cursor/hooks.json |
User-global hooks only. Approve in Settings -> Hooks. |
| OpenCode | ~/.config/opencode/hook/hooks.yaml |
Uses the OpenCode-Hooks adapter. |
| Pi | ~/.pi/agent/hook/hooks.yaml |
Uses the Pi-YAML-Hooks adapter. |
| Shell | .envrc or shell rc |
Fallback when no native harness exists. |
Fresh Cursor install with no existing hooks:
mkdir -p ~/.cursor
acd setup cursor --raw > ~/.cursor/hooks.jsonIf ~/.codex/config.toml pins feature flags, keep hooks enabled:
[features]
hooks = trueAfter setup:
acd doctordoctor checks that the installed snippet still matches the current template.
| Strategy | What happens | Best for |
|---|---|---|
event |
One captured edit becomes one commit. This is the default. | Offline use, CI, shared branches, strict traceability. |
intent |
An AI planner groups related captures before replay writes a commit. | Local work where reviewable commits matter more than one-edit history. |
Offline default:
export ACD_AI_PROVIDER=deterministic
export ACD_COMMIT_STRATEGY=eventAI grouping:
export ACD_AI_PROVIDER=openai-compat
export ACD_AI_API_KEY=$YOUR_API_KEY
export ACD_AI_BASE_URL=https://your-endpoint/v1
export ACD_AI_MODEL=gpt-5.4-mini
export ACD_AI_DIFF_EGRESS=1
export ACD_COMMIT_STRATEGY=intent
export ACD_INTENT_WINDOW=10
export ACD_INTENT_MIN_PENDING=4
export ACD_INTENT_SETTLE_WINDOW=10s
export ACD_INTENT_MAX_PENDING_AGE=5m
export ACD_INTENT_DEFER_LIMIT=1ACD_AI_DIFF_EGRESS=1 lets the planner see redacted captured diffs. Leave it
unset when the endpoint should receive metadata only.
Intent mode waits briefly after the pending-count gate before planning. This
settle window lets a burst of related edits reach one planner-visible window,
while acd flush --logical still drains the current visible batch from an
active harness session.
If the configured planner times out or returns unsafe output, ACD commits with
the deterministic planner instead of stalling the queue. A persisted circuit
breaker pauses repeated provider calls for 30 seconds, then 2 minutes, then 10
minutes. One probe is allowed after each cooldown, and a successful validated
plan closes the circuit. Bare acd reports degraded fallback health;
acd status and acd diagnose show the circuit state, failure count, bypass
count, and next probe time.
When one visible window contains separate intents, the planner prompt asks for
ordered commit_groups so replay can publish atomic commits instead of forcing
the whole window into one commit.
Message format:
| Format | Example subject | Notes |
|---|---|---|
imperative |
Add commit format selection |
Default. Subjects start with an imperative verb. |
conventional |
feat: add commit format selection |
Optional scope-less Conventional Commit style. |
export ACD_COMMIT_FORMAT=conventionalConventional mode accepts only feat, fix, docs, refactor, test,
build, ci, chore, perf, style, and revert. Scopes and breaking
markers are not supported. Body bullets keep the same - prefix and wrapping
rules as the default format.
After setup, leave ACD running in the background. Use the three short commands below for normal health and lifecycle control; the hook protocol stays automatic.
| Need | Command |
|---|---|
| Check this repo and get one recommended next action | acd |
| Enable ACD and ensure the daemon is running | acd on |
| Disable ACD and stop the daemon without deleting state | acd off |
| Watch enabled repos | acd list |
| Show this repo state | acd status |
| Follow capture, group, publish, and block decisions | acd events --watch |
| Ask why a path behaved a certain way | acd explain --path FILE |
| Ask what ACD did for a commit | acd explain --commit HEAD |
| Tail the daemon log | acd logs --follow |
| Create a support bundle | acd doctor --bundle |
Bare acd is read-only. acd on and acd off are idempotent, work from a
subdirectory, and preserve .git/acd/state.db. Harness integrations continue
to use the lower-level start, wake, touch, flush, and stop commands.
See the command reference for every public command and its
read or write behavior.
ACD first tries to heal the queue itself. It reconciles the complete unpublished chain for one branch generation, never an isolated blocker:
- If stable
HEADalready has the chain's exact final touched-path state, ACD marks the chain published and keeps a hidden proof ref. - Otherwise ACD writes the reconstructed tree to a hidden recovery ref, marks
the chain recovered, reseeds from
HEAD, and captures the still-dirty worktree again. - If objects are missing, the branch changes during proof, or a recovery ref
collides, ACD leaves the queue, live
HEAD, index, and worktree unchanged. A hidden evidence ref may remain so a safe retry can reuse the same tree.
Start with the short read-only path:
acd
acd diagnose
acd events --watchUse fix when you want to preview or run the same recovery manually. Preview
first, turn ACD off so hooks cannot restart the daemon during repair, then turn
it on again:
acd fix --dry-run
acd off
acd fix --yes
acd on
acd--force means archive-only recovery. It does not purge, retarget, or discard
captured events:
acd fix --force --dry-run
acd off
acd fix --force --yes
acd onacd fix creates a SQLite-consistent backup before it mutates state and refuses
to run while a live daemon owns the database. If the problem is only a manual
pause marker, run:
acd resume --yesTo inspect or restore an archived chain, use the /archive ref printed by
acd events; see Inspect or restore archived work.
If acd diagnose --json reports generated pending deletes under a tracked
cache directory such as .derivedData-provider-core, acd fix --yes cleans
only ACD's queue. Record the Git cleanup separately after review:
git status -- .derivedData-provider-core
git add -u -- .derivedData-provider-core
git commit -m "Remove tracked generated cache files"Use commit-all when files changed while no daemon was running:
acd commit-all --dry-run
acd commit-all --yes
acd commit-all --yes --jsonDetached HEAD, in-progress Git operations, and manual pause markers are refused
for previews and apply. If an authorized run reaches its mutation phase, it
also refuses while the per-repo daemon is alive. Dry-run, a declined
confirmation, and a clean no-op do not acquire daemon.lock; the first two are
read-only and do not capture files, start the AI provider, create recovery refs,
or write ACD state. An incomplete drain exits non-zero and leaves the captured
queue protected for diagnosis.
Most repos need no manual setup. Harness hooks call acd start, which creates
<gitDir>/acd/state.db and registers the repo.
For normal use, prefer acd on and acd off. Use the explicit lifecycle
commands below for bulk administration, registry cleanup, or when global
autodiscovery is disabled:
acd repo init
acd repo disable --repo /path/to/repo
acd repo enable --repo /path/to/repo
acd repo manage
acd list --interactive
acd repo list
acd repo remove --dry-run
acd repo remove --yes
acd repo remove --yes --purge-stateacd repo disable stops a live repo daemon, clears start caches, preserves
.git/acd/state.db, and records disabled lifecycle state in the central
registry. Hook-driven start, wake, touch, and flush calls then skip
cleanly with repo_disabled; manual acd start tells you to run
acd repo enable --repo <path>. Normal acd list snapshots hide disabled
repos; use acd repo list, acd repo manage, or acd list --interactive to
inspect and re-enable them. acd repo enable only clears that disabled state;
it does not start the daemon. Use repo remove when you want to unregister a
row instead of temporarily disabling it.
acd repo manage and acd list --interactive open the same line-oriented
manager. Compact mode is the default; --verbose starts with state DB, last
seen, harness, and status details. Inside the manager: t N toggles a repo,
e N enables, d N disables, r refreshes, v switches compact/verbose,
and q exits.
Disable autodiscovery in ~/.config/acd/config.json:
{
"repo_lifecycle": {
"autodiscovery": false
}
}Override it for one process:
ACD_REPO_AUTODISCOVERY=disabled acd start
ACD_REPO_AUTODISCOVERY=enabled acd startThe daemon never rewrites history on its own. Use rewrite-commits only for an
explicit local cleanup before sharing a branch:
acd rewrite-commits --from-nr 5 --plan-out rewrite.json --plan-only
acd rewrite-commits --show-plan rewrite.json
acd off
acd rewrite-commits --apply-plan rewrite.json --dry-run
acd rewrite-commits --apply-plan rewrite.json --yes
acd onUse --from-sha <sha> when you want a commit-ish selector, --range-nr 5-12
for positions, or --range-sha base..head for a simple git range. Progress goes
to stderr; stdout remains safe for command output and --json. Use
--progress json for JSONL progress events or --progress off to disable them.
If apply prints a backup ref or SHA and review fails:
git reset --hard <backup-ref-or-sha>| Variable | Default | Use |
|---|---|---|
ACD_COMMIT_STRATEGY |
event |
event for one capture per commit, intent for AI grouping. |
ACD_COMMIT_FORMAT |
imperative |
imperative keeps the current subject rules; conventional opts into scope-less Conventional Commit subjects. |
ACD_AI_PROVIDER |
deterministic |
deterministic, openai-compat, or subprocess:<name>. |
ACD_AI_API_KEY |
unset | Required by openai-compat. |
ACD_AI_BASE_URL |
https://api.openai.com/v1 |
OpenAI-compatible endpoint. |
ACD_AI_MODEL |
gpt-5.4-mini |
Model passed to the provider. |
ACD_AI_DIFF_EGRESS |
off | Truthy sends redacted captured diffs to providers that ask for diffs. |
ACD_INTENT_WINDOW |
10 |
Max captures offered to one planner pass. |
ACD_INTENT_MIN_PENDING |
10 |
Preferred count before planning. Lower it for sparse repos. |
ACD_INTENT_SETTLE_WINDOW |
10s |
Burst settle delay after the count gate. 0 disables it. |
ACD_INTENT_MAX_PENDING_AGE |
5m |
Age escape hatch for sparse queues. |
ACD_INTENT_DEFER_LIMIT |
1 |
Deferrals before ACD forces a one-capture window. |
ACD_INTENT_RETRY_ON_INVALID |
2 |
Max correction retries after invalid planner output. |
ACD_SAFE_IGNORE |
enabled | Set false-like value to stop pruning generated trees. |
ACD_SAFE_IGNORE_EXTRA |
unset | Extra generated trees, such as dist/,build/. |
ACD_SENSITIVE_GLOBS |
built in | Non-empty values replace the protected path globs. Unset or empty uses the defaults. |
ACD_TRACE |
off | Writes daemon decision summaries under <gitDir>/acd/trace/. |
ACD_AI_PROMPT_TRACE |
off | Writes local AI request diagnostics. Treat as sensitive. |
Restart a running daemon after changing daemon runtime environment.
| Doc | Use it for |
|---|---|
| docs/overview.md | A short system map. |
| docs/commands.md | Every public command, its side effects, and safe examples. |
| docs/user-workflows.md | Daily status, recovery, support bundles, and commit-all. |
| docs/capture-replay.md | Storage, replay, branch safety, blockers, and trace classes. |
| docs/intent-commit-flow.md | Intent grouping behavior and planner observability. |
| docs/intent-commit-rewrite-flow.md | Safe history rewrite workflow. |
| docs/rewrite-commits.md | rewrite-commits command grammar. |
| docs/ai-providers.md | Provider setup, diff privacy, prompt tracing, and plugin protocol. |
| docs/multi-tool.md | Running ACD next to another auto-committer. |
MIT. See LICENSE.