GoogleCloudPlatform / GoogleCloudPlatform/scion

feat: support tmux -f ~/.tmux.conf when launching agent sessions

Open
#294 0 comments 0 reactions 0 assignees View on GitHub
area:harness type:feature
Dominant language
Go
Stars
1.7k
Forks
263
Avg merge
7h 6m
Merged PRs (30d)
447

Description

# Support tmux configuration files in agent containers

## Description

### Problem

User tmux configurations (prefix key, mode-keys, custom bindings) are ignored when Scion launches agent containers, even when the config file exists at `~/.tmux.conf` inside the container. This affects user experience when interacting with agents via `scion attach`.

### Current Behavior

Scion hardcodes the tmux invocation in `pkg/runtime/common.go:413-415`:

```go
tmuxCmd := fmt.Sprintf(
"tmux new-session -d -s scion -n agent %s \\; set-option -g window-size latest \\; new-window -t scion -n shell \\; select-window -t scion:agent \\; attach-session -t scion",
cmdLine,
)
```

This starts tmux **without the `-f` flag**, so tmux uses its built-in defaults:
- `prefix C-b` (not user's preferred `C-a`)
- `mode-keys emacs` (not user's preferred `vi`)
- No custom keybindings or settings

### Expected Behavior

When a user has a tmux config file at `~/.tmux.conf` (either baked into their custom image or synced via harness configs), tmux should load and use it.

### Reproduction Steps

1. **Create custom Dockerfile** with user's tmux config:
```dockerfile
FROM _________2187.dkr.ecr.us-east-1.amazonaws.com/scion/scion-base:latest
# ... existing scion-pi setup ...

USER scion
COPY --chown=scion:scion tmux.conf /home/scion/.tmux.conf
USER root
```

2. **Build and push image** to ECR

3. **Start agent** using custom image:
```bash
scion start test-agent "Simple task"
```

4. **Attach to agent**:
```bash
scion attach test-agent
```

5. **Check tmux settings**:
```bash
tmux show-options -g prefix # Shows "C-b" (default)
tmux show-options -g mode-keys # Shows "emacs" (default)
```

6. **Verify config exists**:
```bash
cat ~/.tmux.conf | grep "prefix C-a" # Config is present
```

**Result**: Config file exists but is not loaded by tmux.

---

## Investigation & Root Cause

### 1. Primary Issue: Missing `-f` Flag

The tmux command in `pkg/runtime/common.go` and `pkg/runtime/k8s_runtime.go` does not include `-f ~/.tmux.conf`:

**Current**:
```bash
tmux new-session -d -s scion -n agent ...
```

**Should be**:
```bash
tmux -f ~/.tmux.conf new-session -d -s scion -n agent ...
```

### 2. Attempted Workarounds

#### Workaround A: Manual Reload (Doesn't Persist)
```bash
tmux source-file ~/.tmux.conf
```
- ✅ Works temporarily
- ❌ Must be run manually after attaching
- ❌ Doesn't apply to new windows/panes created before reload

#### Workaround B: Post-Start Hook (Timing Issues)
Added hook at `/etc/scion/hooks/post-start.d/10-reload-tmux-config`:
```bash
#!/bin/bash
if command -v tmux >/dev/null 2>&1 && [ -f "$HOME/.tmux.conf" ]; then
tmux source-file "$HOME/.tmux.conf" 2>/dev/null || true
fi
```

**Result**:
- ✅ Hook executes (confirmed in logs: `Running post-start hooks...`)
- ❌ Config not successfully reloaded
- **Root cause**: Hook runs too early (before tmux fully initializes) or in wrong environment (can't access tmux socket)

#### Workaround C: Harness Config Home Files (Doesn't Work in Hub Mode)
Placing config in `~/.scion/harness-configs/pi-sonnet/home/.tmux.conf`:
- ✅ Works in `--no-hub` local mode
- ❌ **Not synced in Hub mode** (related to issue #101)

### 3. Related Issues

This issue is related to:
- **#101** [CLOSED] "Hub-dispatched agents do not apply harness config or template volumes" - harness home files aren't synced in Hub mode
- **#257** [CLOSED] "sciontool's chownRecursive aborts on read-only bind mounts" - permission issues with home directory files
- **#87** [OPEN] "Harness home directories should exist before sync into non-root homes" - precondition for home file sync
- **#212** [OPEN] "default_harness_config is not respected after grove is init" - broader harness config issues

---

## Proposed Solutions

### Solution 1: Add `-f ~/.tmux.conf` Flag (Preferred)

**Modify** `pkg/runtime/common.go` line 413:

```diff
tmuxCmd := fmt.Sprintf(
- "tmux new-session -d -s scion -n agent %s \\; ...",
+ "tmux -f ~/.tmux.conf new-session -d -s scion -n agent %s \\; ...",
cmdLine,
)
```

**Also update** `pkg/runtime/k8s_runtime.go` with same change.

**Benefits**:
- ✅ Simple one-line change
- ✅ Respects user preferences
- ✅ Standard tmux behavior
- ✅ No breaking changes (if file missing, tmux falls back to defaults)

**Fallback safety**: If `~/.tmux.conf` doesn't exist, tmux silently uses defaults.

### Solution 2: Make Hook Timing Reliable (Alternative)

Document how to make post-start hooks work reliably with tmux:
- Add `$HOME` environment to hook execution
- Ensure hook runs after tmux socket is available
- Add retry logic in hook system

**Benefits**:
- ✅ More flexible (works for other config files)
- ❌ More complex
- ❌ Timing still tricky

### Solution 3: Configuration Option (Most Flexible)

Add harness config option:

```yaml
# ~/.scion/harness-configs/pi-sonnet/config.yaml
tmux:
config_file: ~/.tmux.conf # or null to use defaults
options:
- "set-option -g prefix C-a"
- "setw -g mode-keys vi"
```

**Benefits**:
- ✅ Most flexible
- ✅ Doesn't require baking config into image
- ❌ Most complex to implement
- ❌ Yet another config layer

---

## Impact & Use Cases

### Who This Affects

**Current workaround** for affected users: Use `--no-hub` mode, which loses Hub features (secrets management, web UI, broker coordination).

**Affected users**:
1. **Power users** with muscle memory for custom tmux keybindings
2. **Teams** standardizing on specific tmux configs across agents
3. **Users with accessibility needs** requiring specific keybindings
4. **Vim users** who expect vi-mode in copy/paste operations

### Real-World Scenario

User has Ctrl-a prefix and vi-mode in their local tmux. When they `scion attach` to debug an agent, they:
- Press `Ctrl-a d` to detach → nothing happens (prefix is still Ctrl-b)
- Enter copy mode → emacs keys, not vi keys
- Repeatedly hit wrong keybindings, slowing down debugging

---

## Testing

### Test Case 1: Config File Present
```bash
# In Dockerfile
COPY tmux.conf /home/scion/.tmux.conf

# After agent starts
$ tmux show-options -g prefix
prefix C-a # ✅ Should show user's custom prefix

$ tmux show-options -g mode-keys
mode-keys vi # ✅ Should show user's custom mode
```

### Test Case 2: No Config File
```bash
# Don't add tmux.conf to image

# After agent starts
$ tmux show-options -g prefix
prefix C-b # ✅ Should fall back to defaults

$ tmux show-options -g mode-keys
mode-keys emacs # ✅ Should fall back to defaults
```

### Test Case 3: Invalid Config
```bash
# Add broken tmux.conf
COPY broken-tmux.conf /home/scion/.tmux.conf

# tmux should fail gracefully with error message
# Container should still start (don't fail hard on bad config)
```

---

## Implementation Notes

### Files to Modify

1. **`pkg/runtime/common.go`** (line ~413):
```go
tmuxCmd := fmt.Sprintf(
"tmux -f ~/.tmux.conf new-session -d -s scion -n agent %s \\; ...",
cmdLine,
)
```

2. **`pkg/runtime/k8s_runtime.go`** (similar location):
Same change for Kubernetes runtime

3. **Tests to update**:
- `pkg/runtime/common_test.go` - update expected tmux commands
- `pkg/runtime/k8s_runtime_tmux_test.go` - same

### Backward Compatibility

✅ **No breaking changes**: If `~/.tmux.conf` doesn't exist, tmux silently uses built-in defaults (standard tmux behavior).

### Documentation to Update

- Harness configuration docs: mention users can bake tmux.conf into images
- Container build docs: example of adding custom tmux config
- Troubleshooting: note about `-f` flag for debugging tmux issues

---

## Environment

- **Scion version**: `main` branch (commit d20a238+)
- **Runtime**: Apple container CLI
- **Harness**: pi
- **OS**: macOS (Apple container)
- **Image**: Custom `scion-pi:latest` with tmux.conf baked in

---

## Additional Context

### Example Custom Config

User's `~/.tmux.conf` that should be loaded:
```bash
# Prefix
unbind C-b
set -g prefix C-a
bind C-a send-prefix

# Vi mode
setw -g mode-keys vi
bind -T copy-mode-vi v send-keys -X begin-selection
bind -T copy-mode-vi y send-keys -X copy-selection

# Splits
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
```

### Logs Showing Hook Execution

From `scion logs test-agent`:
```
2026-06-01 18:43:37 [sciontool] [INFO] Running post-start hooks...
```

Hook was called but config not loaded (timing/environment issue).

---

## Questions for Maintainers

1. **Is Solution 1** (adding `-f ~/.tmux.conf`) acceptable? Any concerns about the change?

2. **Should we also** support a `TMUX_CONF` env var override?
```bash
TMUX_CONF=/custom/path/tmux.conf scion start ...
```

3. **Post-start hooks**: What's the intended use case? Our hook executes but can't reliably interact with tmux. Is this expected?

4. **Hub mode vs local mode**: Related to #101 - is there a roadmap for making harness home files work in Hub mode, or should users bake configs into images?

---

## Workaround (Until Fixed)

For users who need custom tmux configs NOW:

### Option A: Use --no-hub Mode
```bash
scion start --no-hub agent-name "task"
```
- ✅ Harness configs work
- ❌ Lose Hub features (secrets, web UI, coordination)

### Option B: Manually Reload After Attach
```bash
scion attach agent-name
# Then inside container:
tmux source-file ~/.tmux.conf
```
- ✅ Works immediately
- ❌ Must do every time
- ❌ Doesn't affect windows created before reload

### Option C: Alias in Shell RC
Add to image's `~/.zshrc` or `~/.bashrc`:
```bash
alias ta='tmux source-file ~/.tmux.conf && echo "Tmux config reloaded"'
```
Then run `ta` after attaching.

---

## References

- tmux documentation: `man tmux`, specifically `-f file` flag
- Scion hook system: `pkg/sciontool/hooks/lifecycle.go`
- Tmux invocation: `pkg/runtime/common.go:413-415`
- Related PR #76 (mentioned in #87): Precreate harness home directories

---

**Would appreciate any guidance on the preferred solution!** Happy to submit a PR for Solution 1 if that direction makes sense.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.