-
Notifications
You must be signed in to change notification settings - Fork 144
feat(claude-code): add transcript_retention_days and Stop-hook idle sentinel #866
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,7 +13,7 @@ Install and configure the [Claude Code](https://docs.anthropic.com/en/docs/agent | |
| ```tf | ||
| module "claude-code" { | ||
| source = "registry.coder.com/coder/claude-code/coder" | ||
| version = "5.0.0" | ||
| version = "5.1.0" | ||
| agent_id = coder_agent.main.id | ||
| anthropic_api_key = "xxxx-xxxxx-xxxx" | ||
| } | ||
|
|
@@ -47,7 +47,7 @@ locals { | |
|
|
||
| module "claude-code" { | ||
| source = "registry.coder.com/coder/claude-code/coder" | ||
| version = "5.0.0" | ||
| version = "5.1.0" | ||
| agent_id = coder_agent.main.id | ||
| workdir = local.claude_workdir | ||
| anthropic_api_key = "xxxx-xxxxx-xxxx" | ||
|
|
@@ -78,7 +78,7 @@ resource "coder_app" "claude" { | |
| ```tf | ||
| module "claude-code" { | ||
| source = "registry.coder.com/coder/claude-code/coder" | ||
| version = "5.0.0" | ||
| version = "5.1.0" | ||
| agent_id = coder_agent.main.id | ||
| workdir = "/home/coder/project" | ||
| enable_ai_gateway = true | ||
|
|
@@ -102,7 +102,7 @@ This example shows version pinning, a pre-installed binary path, a custom model, | |
| ```tf | ||
| module "claude-code" { | ||
| source = "registry.coder.com/coder/claude-code/coder" | ||
| version = "5.0.0" | ||
| version = "5.1.0" | ||
| agent_id = coder_agent.main.id | ||
| workdir = "/home/coder/project" | ||
|
|
||
|
|
@@ -166,7 +166,7 @@ Downstream `coder_script` resources can wait for this module's install pipeline | |
| ```tf | ||
| module "claude-code" { | ||
| source = "registry.coder.com/coder/claude-code/coder" | ||
| version = "5.0.0" | ||
| version = "5.1.0" | ||
| agent_id = coder_agent.main.id | ||
| workdir = "/home/coder/project" | ||
| anthropic_api_key = "xxxx-xxxxx-xxxx" | ||
|
|
@@ -189,6 +189,26 @@ resource "coder_script" "post_claude" { | |
| } | ||
| ``` | ||
|
|
||
| ### Session lifecycle | ||
|
|
||
| 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. | ||
| - sets `cleanupPeriodDays` when `transcript_retention_days` is provided, so Claude Code prunes session JSONL transcripts under `~/.claude/projects/` automatically. When unset, Claude Code's default retention (30 days) applies. | ||
|
|
||
| ```tf | ||
| module "claude-code" { | ||
| source = "registry.coder.com/coder/claude-code/coder" | ||
| version = "5.1.0" | ||
| agent_id = coder_agent.main.id | ||
| workdir = "/home/coder/project" | ||
| anthropic_api_key = "xxxx-xxxxx-xxxx" | ||
| transcript_retention_days = 7 | ||
| } | ||
| ``` | ||
|
|
||
| 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. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we, in this case, write to the user's |
||
|
|
||
| ### Usage with AWS Bedrock | ||
|
|
||
| #### Prerequisites | ||
|
|
@@ -252,7 +272,7 @@ resource "coder_env" "bedrock_api_key" { | |
|
|
||
| module "claude-code" { | ||
| source = "registry.coder.com/coder/claude-code/coder" | ||
| version = "5.0.0" | ||
| version = "5.1.0" | ||
| agent_id = coder_agent.main.id | ||
| workdir = "/home/coder/project" | ||
| model = "global.anthropic.claude-sonnet-4-5-20250929-v1:0" | ||
|
|
@@ -309,7 +329,7 @@ resource "coder_env" "google_application_credentials" { | |
|
|
||
| module "claude-code" { | ||
| source = "registry.coder.com/coder/claude-code/coder" | ||
| version = "5.0.0" | ||
| version = "5.1.0" | ||
| agent_id = coder_agent.main.id | ||
| workdir = "/home/coder/project" | ||
| model = "claude-sonnet-4@20250514" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,7 @@ ARG_CLAUDE_BINARY_PATH="$${ARG_CLAUDE_BINARY_PATH//\$HOME/$HOME}" | |
| ARG_MCP=$(echo -n '${ARG_MCP}' | base64 -d) | ||
| ARG_MCP_CONFIG_REMOTE_PATH=$(echo -n '${ARG_MCP_CONFIG_REMOTE_PATH}' | base64 -d) | ||
| ARG_ENABLE_AI_GATEWAY='${ARG_ENABLE_AI_GATEWAY}' | ||
| ARG_TRANSCRIPT_RETENTION_DAYS='${ARG_TRANSCRIPT_RETENTION_DAYS}' | ||
|
|
||
| export PATH="$${ARG_CLAUDE_BINARY_PATH}:$PATH" | ||
|
|
||
|
|
@@ -29,6 +30,7 @@ printf "ARG_CLAUDE_BINARY_PATH: %s\n" "$${ARG_CLAUDE_BINARY_PATH}" | |
| printf "ARG_MCP: %s\n" "$${ARG_MCP}" | ||
| printf "ARG_MCP_CONFIG_REMOTE_PATH: %s\n" "$${ARG_MCP_CONFIG_REMOTE_PATH}" | ||
| printf "ARG_ENABLE_AI_GATEWAY: %s\n" "$${ARG_ENABLE_AI_GATEWAY}" | ||
| printf "ARG_TRANSCRIPT_RETENTION_DAYS: %s\n" "$${ARG_TRANSCRIPT_RETENTION_DAYS}" | ||
|
|
||
| echo "--------------------------------" | ||
|
|
||
|
|
@@ -144,6 +146,36 @@ function setup_claude_configurations() { | |
|
|
||
| } | ||
|
|
||
| function configure_lifecycle_settings() { | ||
| local dropin_dir="/etc/claude-code/managed-settings.d" | ||
| 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" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should depend on |
||
|
|
||
| local payload | ||
| payload=$(jq -n \ | ||
| --arg cmd "touch $${sentinel}" \ | ||
| --arg retention "$${ARG_TRANSCRIPT_RETENTION_DAYS}" \ | ||
| '{ | ||
| hooks: { Stop: [{ hooks: [{ type: "command", command: $cmd }] }] } | ||
| } + (if $retention != "" then { cleanupPeriodDays: ($retention | tonumber) } else {} end)') | ||
|
|
||
| if command_exists sudo && sudo -n true 2> /dev/null; then | ||
| sudo mkdir -p "$${dropin_dir}" | ||
| echo "$${payload}" | sudo tee "$${target}" > /dev/null | ||
| sudo chmod 0644 "$${target}" | ||
| elif mkdir -p "$${dropin_dir}" 2> /dev/null; then | ||
| echo "$${payload}" > "$${target}" | ||
| chmod 0644 "$${target}" | ||
| else | ||
| echo "Warning: cannot write to $${dropin_dir} (no sudo and directory not writable); skipping lifecycle settings" | ||
| return | ||
| fi | ||
|
|
||
| echo "Wrote Claude Code lifecycle settings to $${target}" | ||
| } | ||
|
|
||
| function configure_standalone_mode() { | ||
| echo "Configuring Claude Code for standalone mode..." | ||
|
|
||
|
|
@@ -189,4 +221,5 @@ EOF | |
|
|
||
| install_claude_code_cli | ||
| setup_claude_configurations | ||
| configure_lifecycle_settings | ||
| configure_standalone_mode | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we elaborate a bit more on how templates can use this for activity tracking?