| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
| |
wrap-it-up drops /tmp/ai-wrap-teardown-<project> to ask the Stop hook to kill the tmux session once the wrap certifies clean. When certification fails the Stop hook blocks and leaves the sentinel armed, which I did on purpose so a wrap blocked by a dirty tree can retry on a later stop without re-running the workflow.
I never bounded that retry to the session. An uncertified sentinel sat armed indefinitely and fired in whatever session next reached a clean tree. work's 11:37 wrap today left one armed. The 13:20 session ran startup, committed the task filing and the template sync, went clean, and the next stop consumed the two-hour-old sentinel and killed the terminal mid-work. Every stop before those commits had been blocked by the same sentinel failing certification, so the session spent its whole life either blocked or dead. archsetup's had been armed since Saturday on a live attached terminal, and home's was armed and waiting.
session-start-disarm.sh clears the project's sentinels at SessionStart. A new session means the wrap that armed one is gone, so its pending teardown is meaningless. Within-session retry is untouched, since the hook only runs at session start, and a test pins that. If teardown is still wanted, wrap-it-up re-arms it.
I disarmed the three live ones by hand before writing this, backed up under /tmp/disarmed-sentinels.
Four tests cover the disarm, one pins the retry behavior I did not want to lose. The scoping test matters most: a concurrent session in another project keeps its own sentinel.
|
| |
|
|
| |
Centralize repository-state checks, bind teardown to a certified clean HEAD, and allow inbox-only refreshes. Guard installed symlinks from cross-project writes and add regression coverage.
|
| |
|
|
|
|
|
|
| |
The "check inbox/ at every task boundary" rule was prose-only in protocols.org, so it held only as well as the agent remembered it and a handoff could pass a turn unseen. inbox-boundary-check.sh is a Stop hook that backs the rule: when inbox-status -q reports pending items it blocks the yield once and injects the count, so the agent processes them before returning.
It soft-nudges rather than hard-blocks. On the harness re-entry (stop_hook_active: true) the hook steps aside and lets the turn end, so a mid-task pause to ask a question, or an item the agent genuinely can't process, never wedges the session. A hard block would instead push inbox processing ahead of that clarifying question.
The hook self-skips where it doesn't apply: no inbox/ dir, no inbox-status, or a clean inbox each exit 0 silently, so one global hook covers every project with no config. It prefers the project-local .ai/scripts/inbox-status and falls back to one on PATH. It's wired into the Stop array ahead of ai-wrap-teardown in both the tracked settings.json (which the live ~/.claude/settings.json symlinks to) and the documented snippet. bats covers pending, clean, the re-entry step-aside, no-inbox, and the absent-status degrade.
|
| |
|
|
|
|
| |
Craig's call, 2026-07-16. This reverses the fable pin from e91073d rather than
drifting into it — the field has flip-flopped four times now, so noting that
this one was chosen.
|
| |
|
|
| |
d5bc9b3 was meant to keep the opus-to-fable flip but recorded only a case change (opus to Opus) — the harness had rewritten the file before staging. This lands the value Craig actually chose.
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
| |
The hooks/settings-snippet.json doc carried the Stop block, but the live tracked .claude/settings.json (symlinked to ~/.claude/settings.json) needed it too for the teardown to actually fire. Activates next session, when the harness reads hooks.
Claude-Session: https://claude.ai/code/session_017PtX1nt1rtYVATuzmzBS4f
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
| |
Remote sessions showed up on claude.ai/code and mobile under auto-generated names, so picking the right one meant guessing. Claude Code 2.1.152+ lets a SessionStart hook set the title via hookSpecificOutput.sessionTitle.
hooks/session-title.sh emits "<uname -n> <project>" (ratio rulesets, velox work) on startup and resume. Project is the git-toplevel basename so a session started in a subdirectory still names the project, with the cwd basename as fallback. The hook stays silent when a title already exists, so a /rename or an earlier run isn't clobbered on resume. The harness ignores titles on clear and compact, so the settings matcher restricts to startup|resume.
Wired in settings.json and the install-hooks snippet. As a default hook it reaches every machine through make install on the next session start.
|
| |
|
|
|
|
| |
An archsetup session added a statusLine entry to the tracked settings.json on 2026-06-11 (Craig's request), pointing at ~/.claude/statusline-command.sh, but the script itself lived outside the repo on one machine. This commits the settings entry and brings the script into .claude/, linked by make install like the rest of the config, so it reaches every machine on the next session.
Two fixes over the original: uname -n instead of hostname (Arch doesn't ship hostname by default, so the host rendered empty with stderr noise), and the tilde replacement is escaped (unquoted, bash expands the replacement ~ straight back to $HOME, which defeated the abbreviation). scripts/tests/statusline-command.bats covers the format, branch handling, and the no-stderr contract.
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
| |
Flush is the checkpoint half of the wrap/restart rhythm. It refreshes the session-context anchor in place, the user runs /clear, and the session resumes from the anchor instead of starting cold. One logical session stays alive across a /clear boundary without the archive-and-commit of wrap-it-up or the full cold boot of startup, which buys cheaper tokens and a sharper context window.
The mechanism splits into two halves around /clear, which wipes the conversation so nothing runs straight through it. The /flush skill is the pre-clear half: dump live state, refresh the anchor's Summary, append a dated flush marker, verify the write landed, then prompt the user to /clear. The agent can initiate at a clean task boundary on its own judgment, but /clear is user-only, so the agent does the work and the user supplies the single keystroke. The session-clear-resume.sh hook is the post-clear half, a SessionStart matcher=clear hook that points the fresh session at the anchor to resume, or at startup when no anchor exists.
I packaged the pre-clear half as a skill rather than a project-workflow doc so both halves are global. The hook was already global, so /flush is now callable by name from any project with no per-project sync.
The hook is canonicalized under hooks/ and symlinked into ~/.claude/hooks/, matching precompact-priorities.sh. settings.json wires the SessionStart entry, and settings-snippet.json carries it so a fresh machine wires the hook on make install-hooks.
|
| |
|
|
|
|
| |
The no-popup-menus rule in interaction.md was too easy to forget, so the popup kept slipping back into choice prompts. I added a PreToolUse hook on AskUserQuestion that denies the call outright and returns the rule as the reason, which routes choices back to inline numbered lists. Since ~/.claude/settings.json symlinks to this repo's .claude/settings.json, the hook is machine-wide and version-controlled across machines.
I documented it under the rule in interaction.md, including the consequence: the deny is unconditional, so the old "use the popup for this one" exception now needs the hook disabled via /hooks first.
|
| | |
|
| |
|
|
|
|
| |
notification/UI toggles
Working copy had drifted permissions.defaultMode to "auto"; reset to "bypassPermissions" to match HEAD. Other tweaks: awaySummaryEnabled false, terminalProgressBarEnabled false, inputNeededNotifEnabled true, skipAutoPermissionPrompt true, skillListingBudgetFraction moved to top.
|
| |
|
|
| |
Default 1% of context maps to ~8K chars (the floor). The current skill listing totals ~10K chars and overflows on small-context models, triggering the truncation warning. Bumping to 5% leaves headroom even with the model-invocable skills' full descriptions present, and the file-based skill descriptions are now <=1000 chars each.
|
| |
|
|
|
|
|
| |
Removed the PreToolUse → Bash hook entry from settings.json. The hook
script stays in hooks/ for other machines that may want it. The local
~/.claude/hooks/destructive-bash-confirm.py symlink was also removed
on this machine.
|
|
|
I moved Claude Code's user-level config into this repo so it travels with rulesets across machines instead of being machine-specific. The three pieces are settings.json, .mcp.json, and commands/refactor.md.
I extended make install, uninstall, and list to handle the new .claude/ directory. The wildcard for CLAUDE_CONFIG matches both `*.json` and `.*.json` because make's glob skips dotfiles by default. Without the dot variant, .mcp.json wouldn't get picked up.
I also added settings.local.json to .gitignore. That file is per-machine by convention and shouldn't ever land in the shared repo.
|