Skip to content

Commit 74ccf85

Browse files
authored
Merge pull request #17 from MrVampy/fix/save-hook-path-augment
fix: augment hook PATH so python3 is reachable from restricted tmux servers
2 parents ca7cfd1 + 980cb5a commit 74ccf85

3 files changed

Lines changed: 90 additions & 0 deletions

File tree

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ cat ~/.tmux/resurrect/assistant-save.log
318318
| Save finds 0 sessions | Run `ps -eo pid=,ppid=,args= \| grep -E 'claude\|opencode\|codex'` to verify assistants are running |
319319
| Session ID missing for Claude | Verify the hook is installed: `jq '.hooks.SessionStart' ~/.claude/settings.json` |
320320
| Session ID missing for OpenCode | Launch with `-s <id>`, or verify the plugin: `ls ~/.config/opencode/plugins/session-tracker.js` |
321+
| Codex/OpenCode session ID missing (python3 methods) | The save hook auto-detects `python3` in common locations. If your setup uses a non-standard path, set it in tmux: `set-environment -g PATH "/your/python3/dir:$PATH"` |
321322
| Restore launches but assistant says "session not found" | The session ID may have expired. This is normal — start a fresh session and the next save will pick up the new ID |
322323
| Assistants launch twice after restore | Make sure assistants are **not** listed in `@resurrect-processes` — the plugin handles all resuming via the post-restore hook |
323324
| `just test` fails with Docker errors | Ensure Docker is running and you have network access (the image pulls npm packages) |
@@ -371,6 +372,30 @@ State files live in a user-only directory (mode 0700).
371372
> sidecar JSON persist to disk and may outlive the process they were captured
372373
> from.
373374
375+
### PATH in restricted environments (NixOS, systemd services)
376+
377+
When tmux runs as a systemd user service, the server inherits a stripped-down
378+
`PATH` that may not include `python3`. The save hook automatically checks common
379+
system locations (`/run/current-system/sw/bin`, `/opt/homebrew/bin`,
380+
`/usr/local/bin`, `/usr/bin`) and augments `PATH` if needed. This is a no-op
381+
when `python3` is already on `PATH`.
382+
383+
If your `python3` is in a non-standard location, the recommended fix is at the
384+
tmux level:
385+
386+
```bash
387+
# In tmux.conf — ensures all hooks and plugins see the right PATH:
388+
set-environment -g PATH "/your/custom/bin:/usr/local/bin:/usr/bin:/bin"
389+
```
390+
391+
Or fix it in the systemd unit:
392+
393+
```ini
394+
# ~/.config/systemd/user/tmux.service.d/override.conf
395+
[Service]
396+
Environment=PATH=/run/current-system/sw/bin:/usr/local/bin:/usr/bin:/bin
397+
```
398+
374399
### Continuum save interval
375400

376401
Edit `config/resurrect-assistants.conf`:

scripts/save-assistant-sessions.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,21 @@
11
#!/usr/bin/env bash
2+
# The tmux server may have been started with a limited PATH (e.g. via a
3+
# systemd user service with a whitelisted runtime environment). That PATH
4+
# is inherited by every hook this script runs in, so utilities like
5+
# python3 — needed by Methods 3 and 4 of get_codex_session — can be
6+
# missing even though they are installed and work fine from an
7+
# interactive shell. Augment PATH with common system locations so the
8+
# hook context sees what the rest of the system sees.
9+
if ! command -v python3 >/dev/null 2>&1; then
10+
for _dir in /run/current-system/sw/bin /opt/homebrew/bin /usr/local/bin /usr/bin; do
11+
if [ -x "$_dir/python3" ]; then
12+
PATH="$_dir:$PATH"
13+
break
14+
fi
15+
done
16+
unset _dir
17+
fi
18+
219
# tmux-resurrect save hook — collects assistant session IDs from all tmux panes.
320
# Writes a sidecar JSON file alongside resurrect's save files.
421
#

test/run-tests.sh

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,54 @@ fi
10561056
HOME="$ORIG_HOME"
10571057
rm -rf "$ROLLOUT_TEST_DIR"
10581058
1059+
# --- Codex rollout: restricted PATH (regression for PATH augmentation) ---
1060+
# When the tmux server inherits a stripped PATH (e.g. systemd user service),
1061+
# python3 may not be found. The save script augments PATH at startup so that
1062+
# python3-based methods (Codex rollout, OpenCode DB) still work.
1063+
1064+
echo ""
1065+
echo "=== PATH augmentation: Codex rollout works under restricted PATH ==="
1066+
echo ""
1067+
1068+
PATH_TEST_DIR=$(mktemp -d)
1069+
mkdir -p "$PATH_TEST_DIR/.codex/sessions/2026/04/23"
1070+
cat >"$PATH_TEST_DIR/.codex/sessions/2026/04/23/rollout-path-test.jsonl" <<'PATHROLLOUT'
1071+
{"timestamp":"2026-04-23T10:00:00.000Z","type":"session_meta","payload":{"id":"ses_path_repro","timestamp":"2026-04-23T10:00:00.000Z","cwd":"/tmp/path-repro","originator":"codex_cli_rs","cli_version":"0.116.0"}}
1072+
PATHROLLOUT
1073+
1074+
# Build a minimal PATH that has the coreutils the script needs but NOT python3
1075+
rbin=$(mktemp -d)
1076+
for _c in dirname mkdir sed ps tr tail mv cat date jq awk gzip tar md5sum; do
1077+
_p=$(command -v "$_c" 2>/dev/null || true)
1078+
[ -n "$_p" ] && ln -sf "$_p" "$rbin/$_c"
1079+
done
1080+
# Also need bash itself for the subshell
1081+
ln -sf "$(command -v bash)" "$rbin/bash"
1082+
1083+
# Run the save script's preamble + get_codex_session under the restricted PATH.
1084+
# The PATH augmentation block should find python3 and make Method 3 work.
1085+
ORIG_HOME_PATH="$HOME"
1086+
HOME="$PATH_TEST_DIR"
1087+
path_aug_sid=$(PATH="$rbin" ${TEST_BASH:-bash} -c '
1088+
source "'"$REPO_DIR"'/scripts/save-assistant-sessions.sh"
1089+
get_codex_session $$ "codex" "/tmp/path-repro"
1090+
')
1091+
HOME="$ORIG_HOME_PATH"
1092+
1093+
assert_eq "Codex rollout lookup works with restricted hook PATH" "ses_path_repro" "$path_aug_sid"
1094+
1095+
# Verify that when python3 IS already on PATH, the augmentation is a no-op
1096+
path_before="$PATH"
1097+
# Re-source the script (it guards with command -v python3)
1098+
source "$REPO_DIR/scripts/save-assistant-sessions.sh"
1099+
if [ "$PATH" = "$path_before" ]; then
1100+
pass "PATH unchanged when python3 already available"
1101+
else
1102+
fail "PATH was modified even though python3 was already on PATH"
1103+
fi
1104+
1105+
rm -rf "$PATH_TEST_DIR" "$rbin"
1106+
10591107
# --- OpenCode: -s and --session arg extraction ---
10601108
assert_eq "OpenCode -s extraction" "ses_oc_456" "$(get_opencode_session 99999 "opencode -s ses_oc_456" "/tmp")"
10611109
assert_eq "OpenCode --session extraction" "ses_oc_789" "$(get_opencode_session 99999 "opencode --session ses_oc_789" "/tmp")"

0 commit comments

Comments
 (0)