cookbook: add copilot-session-resume recipe - #469
Conversation
Add a cookbook recipe wrapping the copilot command so each agterm tab reopens its own Copilot CLI session after a restart. Copilot's --session-id flag both creates and resumes a session under a given id, so the function needs no mapping file or existence check: it always pins the tab's AGTERM_SESSION_ID as the session id unless the invocation should pass through untouched (subcommand, explicit --resume/--session-id/--continue, headless -p, etc). The script is strict POSIX sh, verified with sh -n/bash -n/zsh -n/ dash -n, and functionally tested with a stub copilot binary across sh, bash, dash and zsh for passthrough, injection, and restore-replay cases, with no variable leakage into the sourcing shell. Co-authored-by: Copilot
umputun
left a comment
There was a problem hiding this comment.
one blocker, three smaller fixes, one note.
the function always returns 0. every path in copilot() runs unset after command copilot, and POSIX return with no argument yields the status of the last command, which is that unset. So the wrapper reports success whatever copilot did: copilot -p "..." && git commit commits after a failed prompt, a || fallback never fires, and an exit-status prompt segment stays green after a crash. With copilot not installed the shell prints command not found and the function still returns 0.
the three sibling recipes keep the status, but they use local, which you deliberately avoid to stay POSIX so the file works in bash. rc=$?; return $rc does not work here either, since the helper has to be unset and the unset is what destroys the status. What keeps your POSIX property is making command copilot "$@" the last statement on every path, with each unset moved in front of its invocation and the pinned argv built first:
set -- --session-id "$_copilot_resume_sid" "$@"
unset _copilot_resume_sid
command copilot "$@"a function's positional parameters are restored on return, so set -- inside copilot() leaves the caller's alone.
the passthrough list misses the documented long form of --prompt. it carries --session-id=*, --resume=* and --connect=*, but only the bare --prompt. GitHub's current command reference spells that option -p PROMPT, --prompt=PROMPT, and documents no space form for the long flag, so the list covers a spelling the docs do not have and misses the one they do. copilot --prompt="..." runs as copilot --session-id <tab-id> --prompt=..., writing a scripted one-shot into that tab's pinned interactive conversation, which Limits says cannot happen. Adding --prompt=* to the case covers it.
setup points bash users at the wrong file. line 23 says the function has to go in ~/.zshrc or ~/.bashrc and calls .bash_profile too early. agterm's panes run a login shell, and a login bash reads ~/.bash_profile, ~/.bash_login or ~/.profile, not ~/.bashrc. The /etc/profile to /etc/bashrc chain on macOS does not bridge that. So the documented install does nothing in bash, which is the shell this recipe adds over the three zsh-only ones. Point bash users at ~/.bash_profile, or at the usual stanza that sources ~/.bashrc from it.
the check on line 50 cannot pass. it says to run copilot, say a few words, quit it, then restart the terminal. Quitting copilot first is what breaks it: agterm captures the pane's foreground command at quit, and a pane sitting at its shell prompt captures nothing, so the tab comes back as a plain shell and a correct install reads as broken. Line 60 already describes it correctly. Drop the quit step, and quit agterm while copilot is still the pane's foreground job.
minor, non-blocking: subcommand names are matched in every argument position, so copilot -C help treats the directory value as the help subcommand and skips pinning. Not worth a full argument parser, just noting it.
everything else checks out: the subcommand set matches the reference exactly, and --session-id's documented conflicts (--resume, --continue, --connect) all already pass through, so the pinning never competes with another session selector.
Add a cookbook recipe wrapping the copilot command so each agterm tab reopens its own Copilot CLI session after a restart. Copilot's --session-id flag both creates and resumes a session under a given id, so the function needs no mapping file or existence check: it always pins the tab's AGTERM_SESSION_ID as the session id unless the invocation should pass through untouched (subcommand, explicit --resume/--session-id/--continue, headless -p, etc).
The script is strict POSIX sh, verified with sh -n/bash -n/zsh -n/ dash -n, and functionally tested with a stub copilot binary across sh, bash, dash and zsh for passthrough, injection, and restore-replay cases, with no variable leakage into the sourcing shell.
Co-authored-by: Copilot