<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rulesets/.claude/settings.json, branch main</title>
<subtitle>Claude Code skills, rules, and language bundles
</subtitle>
<id>https://git.cjennings.net/rulesets/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/rulesets/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/'/>
<updated>2026-06-12T07:33:46+00:00</updated>
<entry>
<title>chore: set opus as the machine-default model</title>
<updated>2026-06-12T07:33:46+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-12T07:33:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=5feaa94b3ba6c1ce52742a771d37e3186eb81230'/>
<id>urn:sha1:5feaa94b3ba6c1ce52742a771d37e3186eb81230</id>
<content type='text'>
</content>
</entry>
<entry>
<title>feat(hooks): title sessions "host project" for the remote session list</title>
<updated>2026-06-11T18:23:13+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-11T18:23:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=bdc9a5d6e1320032770f54c747c210e4f465c399'/>
<id>urn:sha1:bdc9a5d6e1320032770f54c747c210e4f465c399</id>
<content type='text'>
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 "&lt;uname -n&gt; &lt;project&gt;" (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.
</content>
</entry>
<entry>
<title>feat(install): adopt the statusline script into the managed set</title>
<updated>2026-06-11T16:35:45+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-11T16:35:45+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=3df14fc985ddad041c290c732b5b5b8eae41f68e'/>
<id>urn:sha1:3df14fc985ddad041c290c732b5b5b8eae41f68e</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>chore(ai): archive session record</title>
<updated>2026-06-11T06:37:55+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-11T06:37:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=cf957630668be9b8a51fba5a42aea5829ff4bcc4'/>
<id>urn:sha1:cf957630668be9b8a51fba5a42aea5829ff4bcc4</id>
<content type='text'>
</content>
</entry>
<entry>
<title>chore(claude): pin model to fable in settings</title>
<updated>2026-06-10T19:05:11+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-10T19:05:11+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=c6bd31f1650330d911de35e120f707eae8ca2baa'/>
<id>urn:sha1:c6bd31f1650330d911de35e120f707eae8ca2baa</id>
<content type='text'>
</content>
</entry>
<entry>
<title>feat(flush): add /flush skill and SessionStart(clear) resume hook</title>
<updated>2026-06-03T01:36:18+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-03T01:36:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=526df6dd7872890e525b9af33917169cfdf705d8'/>
<id>urn:sha1:526df6dd7872890e525b9af33917169cfdf705d8</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>feat(hooks): hard-deny the AskUserQuestion popup machine-wide</title>
<updated>2026-05-26T17:58:14+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-26T17:58:14+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=9bfb13aced68e9e0778f9d46b0eeb939cef05a30'/>
<id>urn:sha1:9bfb13aced68e9e0778f9d46b0eeb939cef05a30</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>chore(settings): enable remoteControlAtStartup</title>
<updated>2026-05-13T20:09:46+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-13T20:09:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=159d55a33476df828a49c705940855c4ec38e8ba'/>
<id>urn:sha1:159d55a33476df828a49c705940855c4ec38e8ba</id>
<content type='text'>
</content>
</entry>
<entry>
<title>chore: Claude Code settings — keep bypassPermissions default; notification/UI toggles</title>
<updated>2026-05-12T22:59:10+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-12T22:59:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=b77a18d08a5c82415668ca30a77677a533d67298'/>
<id>urn:sha1:b77a18d08a5c82415668ca30a77677a533d67298</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>chore(claude): bump skillListingBudgetFraction to 5%</title>
<updated>2026-05-07T02:59:52+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-07T02:59:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=201377f57430ef28d02e703a2191434bbee55c75'/>
<id>urn:sha1:201377f57430ef28d02e703a2191434bbee55c75</id>
<content type='text'>
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 &lt;=1000 chars each.
</content>
</entry>
</feed>
