Skip to content

Commit ba93c55

Browse files
Merge branch 'main' into cat/local-windows-rdp
2 parents 4f3e960 + e5ccf74 commit ba93c55

File tree

4 files changed

+170
-28
lines changed

4 files changed

+170
-28
lines changed

.github/scripts/version-bump.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,15 @@ main() {
190190

191191
done <<< "$modules"
192192

193+
# Always run formatter to ensure consistent formatting
194+
echo "🔧 Running formatter to ensure consistent formatting..."
195+
if command -v bun >/dev/null 2>&1; then
196+
bun fmt >/dev/null 2>&1 || echo "⚠️ Warning: bun fmt failed, but continuing..."
197+
else
198+
echo "⚠️ Warning: bun not found, skipping formatting"
199+
fi
200+
echo ""
201+
193202
echo "📋 Summary:"
194203
echo "Bump Type: $bump_type"
195204
echo ""

.github/workflows/version-bump.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ jobs:
2525
fetch-depth: 0
2626
token: ${{ secrets.GITHUB_TOKEN }}
2727

28+
- name: Set up Bun
29+
uses: oven-sh/setup-bun@v2
30+
with:
31+
bun-version: latest
32+
33+
- name: Set up Terraform
34+
uses: coder/coder/.github/actions/setup-tf@main
35+
36+
- name: Install dependencies
37+
run: bun install
38+
2839
- name: Extract bump type from label
2940
id: bump-type
3041
run: |

registry/coder/modules/claude-code/README.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Run the [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude
1414
```tf
1515
module "claude-code" {
1616
source = "registry.coder.com/coder/claude-code/coder"
17-
version = "1.3.1"
17+
version = "1.4.0"
1818
agent_id = coder_agent.example.id
1919
folder = "/home/coder"
2020
install_claude_code = true
@@ -88,7 +88,7 @@ resource "coder_agent" "main" {
8888
module "claude-code" {
8989
count = data.coder_workspace.me.start_count
9090
source = "registry.coder.com/coder/claude-code/coder"
91-
version = "1.3.1"
91+
version = "1.4.0"
9292
agent_id = coder_agent.example.id
9393
folder = "/home/coder"
9494
install_claude_code = true
@@ -100,14 +100,37 @@ module "claude-code" {
100100
}
101101
```
102102

103+
## Session Persistence (Experimental)
104+
105+
Enable automatic session persistence to maintain Claude Code sessions across workspace restarts:
106+
107+
```tf
108+
module "claude-code" {
109+
count = data.coder_workspace.me.start_count
110+
source = "registry.coder.com/coder/claude-code/coder"
111+
version = "1.4.0"
112+
agent_id = coder_agent.example.id
113+
folder = "/home/coder"
114+
install_claude_code = true
115+
116+
# Enable tmux with session persistence
117+
experiment_use_tmux = true
118+
experiment_tmux_session_persistence = true
119+
experiment_tmux_session_save_interval = "10" # Save every 10 minutes
120+
experiment_report_tasks = true
121+
}
122+
```
123+
124+
Session persistence automatically saves and restores your Claude Code environment, including working directory and command history.
125+
103126
## Run standalone
104127

105128
Run Claude Code as a standalone app in your workspace. This will install Claude Code and run it directly without using screen or any task reporting to the Coder UI.
106129

107130
```tf
108131
module "claude-code" {
109132
source = "registry.coder.com/coder/claude-code/coder"
110-
version = "1.3.1"
133+
version = "1.4.0"
111134
agent_id = coder_agent.example.id
112135
folder = "/home/coder"
113136
install_claude_code = true

registry/coder/modules/claude-code/main.tf

Lines changed: 124 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,18 @@ variable "experiment_post_install_script" {
8484
default = null
8585
}
8686

87+
variable "experiment_tmux_session_persistence" {
88+
type = bool
89+
description = "Whether to enable tmux session persistence across workspace restarts."
90+
default = false
91+
}
92+
93+
variable "experiment_tmux_session_save_interval" {
94+
type = string
95+
description = "How often to save tmux sessions in minutes."
96+
default = "15"
97+
}
98+
8799
locals {
88100
encoded_pre_install_script = var.experiment_pre_install_script != null ? base64encode(var.experiment_pre_install_script) : ""
89101
encoded_post_install_script = var.experiment_post_install_script != null ? base64encode(var.experiment_post_install_script) : ""
@@ -98,12 +110,28 @@ resource "coder_script" "claude_code" {
98110
#!/bin/bash
99111
set -e
100112
101-
# Function to check if a command exists
102113
command_exists() {
103114
command -v "$1" >/dev/null 2>&1
104115
}
105116
106-
# Check if the specified folder exists
117+
install_tmux() {
118+
echo "Installing tmux..."
119+
if command_exists apt-get; then
120+
sudo apt-get update && sudo apt-get install -y tmux
121+
elif command_exists yum; then
122+
sudo yum install -y tmux
123+
elif command_exists dnf; then
124+
sudo dnf install -y tmux
125+
elif command_exists pacman; then
126+
sudo pacman -S --noconfirm tmux
127+
elif command_exists apk; then
128+
sudo apk add tmux
129+
else
130+
echo "Error: Unable to install tmux automatically. Package manager not recognized."
131+
exit 1
132+
fi
133+
}
134+
107135
if [ ! -d "${var.folder}" ]; then
108136
echo "Warning: The specified folder '${var.folder}' does not exist."
109137
echo "Creating the folder..."
@@ -112,20 +140,37 @@ resource "coder_script" "claude_code" {
112140
mkdir -p "${var.folder}"
113141
echo "Folder created successfully."
114142
fi
115-
116-
# Run pre-install script if provided
117143
if [ -n "${local.encoded_pre_install_script}" ]; then
118144
echo "Running pre-install script..."
119145
echo "${local.encoded_pre_install_script}" | base64 -d > /tmp/pre_install.sh
120146
chmod +x /tmp/pre_install.sh
121147
/tmp/pre_install.sh
122148
fi
123149
124-
# Install Claude Code if enabled
125150
if [ "${var.install_claude_code}" = "true" ]; then
126151
if ! command_exists npm; then
127-
echo "Error: npm is not installed. Please install Node.js and npm first."
128-
exit 1
152+
echo "npm not found, checking for Node.js installation..."
153+
if ! command_exists node; then
154+
echo "Node.js not found, installing Node.js via NVM..."
155+
export NVM_DIR="$HOME/.nvm"
156+
if [ ! -d "$NVM_DIR" ]; then
157+
mkdir -p "$NVM_DIR"
158+
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
159+
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
160+
else
161+
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
162+
fi
163+
164+
nvm install --lts
165+
nvm use --lts
166+
nvm alias default node
167+
168+
echo "Node.js installed: $(node --version)"
169+
echo "npm installed: $(npm --version)"
170+
else
171+
echo "Node.js is installed but npm is not available. Please install npm manually."
172+
exit 1
173+
fi
129174
fi
130175
echo "Installing Claude Code..."
131176
npm install -g @anthropic-ai/claude-code@${var.claude_code_version}
@@ -136,54 +181,104 @@ resource "coder_script" "claude_code" {
136181
coder exp mcp configure claude-code ${var.folder}
137182
fi
138183
139-
# Run post-install script if provided
140184
if [ -n "${local.encoded_post_install_script}" ]; then
141185
echo "Running post-install script..."
142186
echo "${local.encoded_post_install_script}" | base64 -d > /tmp/post_install.sh
143187
chmod +x /tmp/post_install.sh
144188
/tmp/post_install.sh
145189
fi
146190
147-
# Handle terminal multiplexer selection (tmux or screen)
148191
if [ "${var.experiment_use_tmux}" = "true" ] && [ "${var.experiment_use_screen}" = "true" ]; then
149192
echo "Error: Both experiment_use_tmux and experiment_use_screen cannot be true simultaneously."
150193
echo "Please set only one of them to true."
151194
exit 1
152195
fi
153196
154-
# Run with tmux if enabled
155-
if [ "${var.experiment_use_tmux}" = "true" ]; then
156-
echo "Running Claude Code in the background with tmux..."
197+
if [ "${var.experiment_tmux_session_persistence}" = "true" ] && [ "${var.experiment_use_tmux}" != "true" ]; then
198+
echo "Error: Session persistence requires tmux to be enabled."
199+
echo "Please set experiment_use_tmux = true when using session persistence."
200+
exit 1
201+
fi
157202
158-
# Check if tmux is installed
203+
if [ "${var.experiment_use_tmux}" = "true" ]; then
159204
if ! command_exists tmux; then
160-
echo "Error: tmux is not installed. Please install tmux manually."
161-
exit 1
205+
install_tmux
162206
fi
163207
164-
touch "$HOME/.claude-code.log"
208+
if [ "${var.experiment_tmux_session_persistence}" = "true" ]; then
209+
echo "Setting up tmux session persistence..."
210+
if ! command_exists git; then
211+
echo "Git not found, installing git..."
212+
if command_exists apt-get; then
213+
sudo apt-get update && sudo apt-get install -y git
214+
elif command_exists yum; then
215+
sudo yum install -y git
216+
elif command_exists dnf; then
217+
sudo dnf install -y git
218+
elif command_exists pacman; then
219+
sudo pacman -S --noconfirm git
220+
elif command_exists apk; then
221+
sudo apk add git
222+
else
223+
echo "Error: Unable to install git automatically. Package manager not recognized."
224+
echo "Please install git manually to enable session persistence."
225+
exit 1
226+
fi
227+
fi
228+
229+
mkdir -p ~/.tmux/plugins
230+
if [ ! -d ~/.tmux/plugins/tpm ]; then
231+
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
232+
fi
233+
234+
cat > ~/.tmux.conf << EOF
235+
# Claude Code tmux persistence configuration
236+
set -g @plugin 'tmux-plugins/tmux-resurrect'
237+
set -g @plugin 'tmux-plugins/tmux-continuum'
238+
239+
# Configure session persistence
240+
set -g @resurrect-processes ':all:'
241+
set -g @resurrect-capture-pane-contents 'on'
242+
set -g @resurrect-save-bash-history 'on'
243+
set -g @continuum-restore 'on'
244+
set -g @continuum-save-interval '${var.experiment_tmux_session_save_interval}'
245+
set -g @continuum-boot 'on'
246+
set -g @continuum-save-on 'on'
247+
248+
# Initialize plugin manager
249+
run '~/.tmux/plugins/tpm/tpm'
250+
EOF
251+
252+
~/.tmux/plugins/tpm/scripts/install_plugins.sh
253+
fi
165254
255+
echo "Running Claude Code in the background with tmux..."
256+
touch "$HOME/.claude-code.log"
166257
export LANG=en_US.UTF-8
167258
export LC_ALL=en_US.UTF-8
168259
169-
# Create a new tmux session in detached mode
170-
tmux new-session -d -s claude-code -c ${var.folder} "claude --dangerously-skip-permissions \"$CODER_MCP_CLAUDE_TASK_PROMPT\""
171-
260+
if [ "${var.experiment_tmux_session_persistence}" = "true" ]; then
261+
sleep 3
262+
263+
if ! tmux has-session -t claude-code 2>/dev/null; then
264+
# Only create a new session if one doesn't exist
265+
tmux new-session -d -s claude-code -c ${var.folder} "claude --dangerously-skip-permissions \"$CODER_MCP_CLAUDE_TASK_PROMPT\""
266+
fi
267+
else
268+
if ! tmux has-session -t claude-code 2>/dev/null; then
269+
tmux new-session -d -s claude-code -c ${var.folder} "claude --dangerously-skip-permissions \"$CODER_MCP_CLAUDE_TASK_PROMPT\""
270+
fi
271+
fi
172272
fi
173273
174-
# Run with screen if enabled
175274
if [ "${var.experiment_use_screen}" = "true" ]; then
176275
echo "Running Claude Code in the background..."
177-
178-
# Check if screen is installed
179276
if ! command_exists screen; then
180277
echo "Error: screen is not installed. Please install screen manually."
181278
exit 1
182279
fi
183280
184281
touch "$HOME/.claude-code.log"
185-
186-
# Ensure the screenrc exists
187282
if [ ! -f "$HOME/.screenrc" ]; then
188283
echo "Creating ~/.screenrc and adding multiuser settings..." | tee -a "$HOME/.claude-code.log"
189284
echo -e "multiuser on\nacladd $(whoami)" > "$HOME/.screenrc"
@@ -198,6 +293,7 @@ resource "coder_script" "claude_code" {
198293
echo "Adding 'acladd $(whoami)' to ~/.screenrc..." | tee -a "$HOME/.claude-code.log"
199294
echo "acladd $(whoami)" >> "$HOME/.screenrc"
200295
fi
296+
201297
export LANG=en_US.UTF-8
202298
export LC_ALL=en_US.UTF-8
203299
@@ -207,7 +303,6 @@ resource "coder_script" "claude_code" {
207303
exec bash
208304
'
209305
else
210-
# Check if claude is installed before running
211306
if ! command_exists claude; then
212307
echo "Error: Claude Code is not installed. Please enable install_claude_code or install it manually."
213308
exit 1
@@ -231,6 +326,10 @@ resource "coder_app" "claude_code" {
231326
if [ "${var.experiment_use_tmux}" = "true" ]; then
232327
if tmux has-session -t claude-code 2>/dev/null; then
233328
echo "Attaching to existing Claude Code tmux session." | tee -a "$HOME/.claude-code.log"
329+
# If Claude isn't running in the session, start it without the prompt
330+
if ! tmux list-panes -t claude-code -F '#{pane_current_command}' | grep -q "claude"; then
331+
tmux send-keys -t claude-code "cd ${var.folder} && claude -c --dangerously-skip-permissions" C-m
332+
fi
234333
tmux attach-session -t claude-code
235334
else
236335
echo "Starting a new Claude Code tmux session." | tee -a "$HOME/.claude-code.log"

0 commit comments

Comments
 (0)