fix: Make Codespaces secrets reach non-login shells and improve agent sessions (no-changelog) (#36042)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Declan Carroll 2026-08-11 12:49:44 +01:00 committed by GitHub
parent 99d19cafec
commit 4f91ee02f5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 35 additions and 4 deletions

View File

@ -24,6 +24,11 @@ COPY gitcredential-refresh.sh /usr/local/bin/gitcredential-refresh.sh
COPY gh-shim.sh /usr/local/bin/gh
RUN chmod +x /usr/local/bin/gitcredential-refresh.sh /usr/local/bin/gh
# VS Code terminals are non-login shells: they read bashrc, not profile.d
RUN echo '. /usr/local/lib/codespaces-env.sh' >> /etc/bash.bashrc
COPY tmux.conf /etc/tmux.conf
RUN echo node ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/node && chmod 0440 /etc/sudoers.d/node
RUN mkdir -p /workspaces && chown node:node /workspaces
RUN corepack enable

View File

@ -32,6 +32,8 @@ pnpm session rm # delete the codespace
```
- **Detach** with `Ctrl-b d` — the agent keeps working without you.
- **Scroll** with the mouse wheel (tmux mouse mode is on). To use the
terminal's own text selection, hold **Shift** and drag.
- **Reattach** by running the same `pnpm session <name>` from any machine.
- Each named session gets its own worktree (`/workspaces/wt-<name>`, branch
`session/<name>`), so parallel agents never touch each other's tree. Builds
@ -92,8 +94,17 @@ After a stop, `pnpm session <name>` restarts the codespace (~30–60 s); run
`sshd` devcontainer feature, don't remove it.
- **User secrets aren't visible in ssh shells by default**: the codespace
agent injects them into VS Code sessions only; they're delivered
base64-encoded to `/workspaces/.codespaces/shared/.env-secrets`. The image's
profile shim exports them for ssh/tmux sessions.
base64-encoded to `/workspaces/.codespaces/shared/.env-secrets`. The image
sources `/usr/local/lib/codespaces-env.sh` in login shells (profile.d), in
interactive shells (bashrc), and in the `pnpm session` prelude. If Claude
Code shows `Missing environment variables: FLAKY_MCP_TOKEN`, the shell that
started Claude did not source the file. Run
`. /usr/local/lib/codespaces-env.sh` and start Claude again.
- **You cannot paste images into a remote Claude session.** Image paste reads
the clipboard of the machine where `claude` runs — the codespace, not your
laptop. Drag the file into the VS Code explorer (or
`gh codespace cp shot.png remote:/workspaces/n8n/`) and give Claude the
path. The file stays on disk and survives detach and `--resume`.
- **`git push` / `gh` return 401 in tmux and long sessions** — same root
cause as the secrets gotcha, plus rotation: Codespaces refreshes the
on-disk `GITHUB_TOKEN` every few minutes, so a login-time snapshot goes

View File

@ -2,6 +2,13 @@
# one-time registrations.
. /usr/local/lib/codespaces-env.sh
# Claude Code keeps its first-run state in ~/.claude.json. Write the defaults
# so a new codespace does not show the theme and trust prompts. The env
# secrets supply the login.
[ -f "$HOME/.claude.json" ] || printf '%s\n' \
'{"hasCompletedOnboarding":true,"theme":"dark","projects":{"/workspaces/n8n":{"hasTrustDialogAccepted":true}}}' \
>"$HOME/.claude.json"
# Register the Flaky MCP server for Claude Code. The config keeps a literal
# ${FLAKY_MCP_TOKEN}; Claude Code expands it at connect time, so the token is
# not written to disk. Forks have no repo secrets and skip this.

View File

@ -0,0 +1,4 @@
# Mouse scroll, a deep scrollback, and correct colors for agent sessions.
set -g mouse on
set -g history-limit 50000
set -g default-terminal "tmux-256color"

View File

@ -56,17 +56,21 @@ function ensureCodespace() {
return cs.name;
}
// The preludes go inside tmux's '…' argument: do not use single quotes in them.
// tmux commands are not login shells. Source the shared secrets so Claude Code
// finds ${FLAKY_MCP_TOKEN} in its process env.
const SECRETS = '. /usr/local/lib/codespaces-env.sh 2>/dev/null || true';
// Worktrees share the pnpm store but not the turbo cache; a shared TURBO_CACHE_DIR
// (seeded from the main checkout) keeps new-worktree builds at cache-hit speed.
// No single quotes allowed here: the whole prelude rides inside tmux's '…' arg.
const CACHE = 'export TURBO_CACHE_DIR=/workspaces/.turbo-cache; [ -d "$TURBO_CACHE_DIR" ] || cp -r /workspaces/n8n/.turbo/cache "$TURBO_CACHE_DIR" 2>/dev/null || mkdir -p "$TURBO_CACHE_DIR"';
function remoteCommand(session, extraArgs) {
const claude = `claude ${extraArgs}`.trim();
if (session === 'agent') return `${CACHE}; cd /workspaces/n8n && ${claude}`;
if (session === 'agent') return `${SECRETS}; ${CACHE}; cd /workspaces/n8n && ${claude}`;
const wt = `/workspaces/wt-${session}`;
const branch = `session/${session}`;
return [
SECRETS,
CACHE,
`if [ ! -d "${wt}" ]; then echo "Setting up worktree ${wt}…"`,
`git -C /workspaces/n8n worktree add "${wt}" -b "${branch}" 2>/dev/null || git -C /workspaces/n8n worktree add "${wt}" "${branch}"`,