feat(claude-code): add transcript_retention_days and Stop-hook idle sentinel#866
feat(claude-code): add transcript_retention_days and Stop-hook idle sentinel#866morganl-ant wants to merge 1 commit intocoder:mainfrom
Conversation
matifali
left a comment
There was a problem hiding this comment.
@morganl-ant thanks for your contribution. I think we can merge this to main and release a new patch version to unblock your users. Bit for other PRs, let's rebase them once #861 (likely today) lands.
|
Also, you would need to bump the patch version in README.md examples and fix the failing tests. |
|
Thanks, both addressed in 11925ea:
Full suite is 23/23 locally now. |
…entinel Re-authored on top of coder#861. The original PR also fixed the hardcoded TASK_SESSION_ID in start.sh (coder#726); coder#861 removed start.sh entirely so that fix is no longer needed and coder#726 is resolved by coder#861 itself. What remains is install-time: - transcript_retention_days input maps to Claude Code's cleanupPeriodDays setting via a managed-settings.d drop-in so long-lived workspaces do not accumulate unbounded session JSONL. - A Stop hook touches ~/.coder-modules/coder/claude-code/last-stop on every turn end so templates can drive workspace autostop or activity tracking off that file's mtime. Both are written to /etc/claude-code/managed-settings.d/30-coder-lifecycle.json, which the Claude CLI reads regardless of inference backend.
11925ea to
108d41f
Compare
|
Rebased onto post-#861 main. The session-ID derivation half of the original PR fell away with #861's removal of |
matifali
left a comment
There was a problem hiding this comment.
Claude Code is very fast-paced. And we see new features and settings being added every other week. Do you think we should have a more flexible generic way to configure it than adding new named module inputs for each new feature?
For example, https://code.claude.com/docs/en/settings shows many options that can be useful for Enterprises, but adding all of them as named modules does not seem scalable and maintainable to me.
Curious about what you think about this?
Otherwise, I am happy to accept this. One reason for the larger refactor we did in v5.0.0 was to increase the flexibility of configuration so we do not limit users on how they want to use Claude code in a coder workspace.
Thanks
| local target="$${dropin_dir}/30-coder-lifecycle.json" | ||
| # Bake the absolute path at install time so the hook does not depend on | ||
| # $HOME being set identically when Claude Code executes it. | ||
| local sentinel="$HOME/.coder-modules/coder/claude-code/last-stop" |
There was a problem hiding this comment.
This should depend on module_dir_name input. Although we have a very strict regex there, but hardcoding this would be less flexible for any future changes.
|
|
||
| The module writes a small managed-settings drop-in to `/etc/claude-code/managed-settings.d/30-coder-lifecycle.json` that: | ||
|
|
||
| - registers a `Stop` hook which touches `~/.coder-modules/coder/claude-code/last-stop` whenever Claude finishes a turn. Templates can read that file's modification time to drive workspace autostop or activity tracking. |
There was a problem hiding this comment.
Can we elaborate a bit more on how templates can use this for activity tracking?
| } | ||
| ``` | ||
|
|
||
| The drop-in is a local file read by the Claude CLI at startup; it works with any inference backend (Anthropic API, Bedrock, Vertex, AI Gateway). If `/etc/claude-code` is not writable in the workspace image and `sudo` is unavailable, the install script logs a warning and skips the write. |
There was a problem hiding this comment.
Should we, in this case, write to the user's $HOME, e.g., $HOME/.claude/settings.json?
|
@DevelopmentCats I would wait for what @morganl-ant thinks. So maybe keep it open for now. |
Problem
Two install-time lifecycle gaps in the v5 module:
~/.claude/projects/are never pruned by the module, so long-lived workspaces accumulate unbounded transcript files unless the user knows to setcleanupPeriodDaysthemselves.Changes
transcript_retention_daysinput (number, default null, validated >= 1). When set, the module writescleanupPeriodDaysto a managed-settings drop-in so Claude Code prunes old transcripts automatically. When unset, Claude Code's built-in 30-day default applies.Stophook that touches~/.coder-modules/coder/claude-code/last-stopwhenever Claude finishes a turn. Templates can read that file's mtime to drive autostop or activity bumping./etc/claude-code/managed-settings.d/30-coder-lifecycle.json. This is the local managed-settings file mechanism, read by the Claude CLI regardless of inference backend (Anthropic API, Bedrock, Vertex, AI Gateway). If/etc/claude-codeis not writable andsudois unavailable, install logs a warning and continues.lifecycle-settings-written(retention set) andlifecycle-settings-default-retention(Stop hook present, nocleanupPeriodDays).Relationship to #861
The original revision of this PR also replaced the hardcoded
TASK_SESSION_IDinstart.shwith a workspace-derived UUIDv5 (#726). #861 removedstart.shand module-managed sessions entirely, which resolves #726 directly: there is no longer a hardcoded session ID because the module no longer starts Claude. This PR is now reduced to the install-time pieces above.Validation
terraform fmtcleanterraform validatecleanterraform test14/14 passbun test14/14 pass locally (one pre-existing docker-cleanup race inclaude-mcp-configis flaky in full-suite runs but passes in isolation; unrelated to this change)Disclosure: I work on Claude Code at Anthropic. This is one of a small set of contributions we are proposing to the
claude-codemodule; happy to discuss the overall direction in whichever venue the maintainers prefer.