Repository navigation
fix(hooks): keep the ponytail level per Claude Code session - #1366
Open
buildwithme wants to merge 1 commit into
Open
buildwithme wants to merge 1 commit into
buildwithme wants to merge 1 commit into
Conversation
The live level was kept per project plus one shared flag. A new session that starts at an "off" default deleted both, so a session that was still on lost its level: the band showed off, compaction re-activated as off, and subagents got no rules. Resume also reset the level to the default. Claude Code passes CLAUDE_CODE_SESSION_ID to every hook, so the hooks now also write ponytail-modes/session-<id>, and readMode reads it first. Off is recorded as "off" instead of deleting the file, so a session never falls back to a flag another session wrote. Resume keeps the session's own level; a session with no record yet starts at the default. The band reads the session file first and the shared flag as a fallback. Session files untouched for 30 days are pruned at a fresh start. Hosts without the env var keep the per-project and shared flags as before. The statusline still reads the shared flag. Refs DietrichGebert#1162, DietrichGebert#1318
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
With the default level
off, every new Claude Code session deletes the per-project flag and the shared.ponytail-activeflag (clearMode()fromponytail-activate.js). A session that is still on then readsoff:off, because it reads only the shared flag,off(readMode() || 'off'), so the ruleset is gone for the rest of the session,Resume also resets the level to the default (#1318). In the Claude Code desktop app this happens all the time: every new session in any repo, and every app restart that resumes a session.
Change
Claude Code passes
CLAUDE_CODE_SESSION_IDto every hook, likeCLAUDE_PROJECT_DIR. When it is set:setModealso writesponytail-modes/session-<id>, andreadModereads that file first.clearModerecordsoffin the session file instead of deleting it, so a session never falls back to a flag another session wrote.Hosts without that env var (Codex, Copilot, Qoder, Cursor and the rest) take the same path as today. The per-project and shared flags are still written, so the statusline works as before.
About #992
#992 was closed because keying by session "would touch every hook on every host". This change touches one runtime file, the SessionStart hook and the band, and only on Claude Code. The band is what makes the bug visible now: it shows one level per session, and it flips to
offwhenever another session starts.Not in this PR
session_id, so it can read the session file in a follow-up.Tests
npm test: 173 of 174 pass. The one failure iscsv: correct pandas one-liner passes; pandas is not installed on this machine.claude plugin test .: 33 of 33 band tests pass, with one new case: the band shows its own session level, not the flag another session left behind.node scripts/check-rule-copies.jsandnode scripts/check-versions.jspass.off. Session A switches tofull. Session B starts, switches and stops. A staysfullthrough compact, resume and subagent start; B staysoffon resume./compact. The level stayedfull.Refs #1162 (band and compaction part; the statusline part stays), #1318 (level part).
Related: #1175, #1321, #1174.