Skip to main content
Agents never use the owner’s GitHub login (owner decision 2026-10-20, STA-208, ADR 0230 rule 5). Every agent call to GitHub goes through a bot wrapper that mints a GitHub App installation token from Infisical /agents and passes it only to its own gh or git child. A wrapper whose token cannot be minted exits 1 before running anything, so it never falls back to another login.

Who acts as whom

Coordinator commands

In a pipe or $(...), pass --silent: without it pnpm prints a $ infisical run ... line to stdout. There is no GH_TOKEN=... gh form: an empty GH_TOKEN (a failed mint) makes gh fall back to the owner’s stored login.

The private Figentra OS repo

figentra/os is in both apps’ installations. Each app has one installation for the figentra organization, so the installation ids already in Infisical cover it:
  • pnpm bot:gh -- pr list -R figentra/os
  • pnpm pr:merge -R figentra/os 3
  • pnpm bot:git -- -C ~/Projects/figentra-os push origin HEAD. pnpm runs scripts from the stackra root, so name the directory with -C.
  • pnpm bot:review -- pr diff 3 -R figentra/os

What the guards deny

.agents/hooks/guard-bash.mjs (Claude Code) checks the command, every $(...) and backtick body (inside double quotes too), and every sh -c or eval string. It denies:
  • gh at command position, also behind sudo, env, xargs, VAR= assignments or a full path, whatever GH_TOKEN is set to;
  • network git at command position: push, fetch, pull, clone, ls-remote, submodule, subtree, remote update|show|prune and archive --remote, for every repository, public or private. Each goes through pnpm bot:git --. A bot push to main is denied too, with the branch read in the checkout the push runs in (after a cd, -C <dir>, --git-dir or --work-tree; an unknown $VAR target counts as main);
  • pack plumbing, bare or through pnpm bot:git: send-pack, receive-pack, fetch-pack and upload-pack;
  • a merge outside pnpm pr:merge: pnpm bot:gh -- pr merge ..., pnpm bot:gh -- api .../pulls/<n>/merge with any method, and the mergePullRequest / enablePullRequestAutoMerge GraphQL mutations. bot-gh.mjs refuses them itself as well;
  • anything that could print or store a token: pnpm bot:token, a $GH_TOKEN or $GITHUB_TOKEN reference, pnpm bot:gh -- auth ..., pnpm bot:review -- auth ..., and git credential fill|approve|reject or a git credential-<helper> (credential-osxkeychain get included), bare or through pnpm bot:git; they answer with the owner’s token. bot-gh.mjs refuses gh auth, git credential and git credential-* itself as well.
Local git (status, log, diff, add, commit, switch, rebase, worktree, remote -v) needs no login and stays allowed. A plain git commit carries the developer’s git name, so builders commit with pnpm bot:git -- commit. The OpenCode guard (.opencode/plugins/guard/decide.ts) is stricter. Executors run no gh, and no git push, fetch, pull, clone, ls-remote, submodule, subtree, remote update, remote show, remote prune, archive with --remote, pack plumbing, credential or credential-<helper>. They also run no pnpm bot:* and no pnpm pr:merge, and the same substitution bodies are checked.

Honest limit

The guards are an accident guard, not isolation. They do not follow aliases, shell functions, variables used as a command name, npx or pnpm dlx. Agents run as the owner’s macOS user, so the keychain and ~/.config/gh are readable by any process an agent starts. The structural fix is owner steps 5 and 6 below: after them, an agent’s plain gh or git finds no owner credential to fall back to. Full isolation needs agents to run as a separate OS user, or on the EC2 agent host, where the owner’s login does not exist.

What the owner does

  1. figentra/stackra branch protection (checked 2026-10-21, nothing to change). main is protected and requires the Quality Gate check for non-admins, and there are no rulesets. The bot merges through that protection: it is not an admin, so the gate must be green, and pnpm pr:merge never passes --admin. If “Restrict who can push to matching branches” is ever turned on, add the stackra-bot app to the allowed list, or every merge fails.
  2. figentra/os has no branch protection. It is private on the free plan, and GitHub answers “Upgrade to GitHub Pro or make this repository public” for its rules. Nothing on GitHub stops a direct push to its main; only the guards and pnpm pr:merge do. To protect it, move the organization to GitHub Team, then require Quality Gate on main as on stackra.
  3. App permissions are enough, nothing to change. stackra-bot holds contents, pull requests, issues, actions and workflows: write, and checks and statuses: read. That covers push, PR, squash merge and branch delete. stackra-reviewer holds pull requests: write and contents: read. The bot cannot read classic branch protection (administration: read is not granted), and does not need to.
  4. Private notes repo. figentra/stackra-notes is in neither installation, so an agent cannot fetch or push it. Add it to the stackra-bot installation (organization Settings, GitHub Apps, stackra-bot, Repository access), and agents push with pnpm bot:git -- -C ~/Projects/stackra-notes push.
  5. Move the owner’s gh login out of the default config (structural fix). In the owner’s own terminal: GH_CONFIG_DIR=~/.config/gh-owner gh auth login, then gh auth logout for the default config. Then add alias gh='GH_CONFIG_DIR=~/.config/gh-owner gh' to the owner’s own shell profile. Agent shells do not load that alias, so their plain gh finds no login.
  6. Remove gh auth git-credential from the global git config agents see (structural fix). Run git config --global --unset-all credential.https://github.com.helper and the same for credential.https://gist.github.com.helper. Then erase any GitHub entry the macOS keychain helper stored: printf 'protocol=https\nhost=github.com\n\n' | git credential-osxkeychain erase. For the owner’s own pushes, add to the shell profile: alias ogit='git -c credential.helper= -c "credential.helper=!GH_CONFIG_DIR=$HOME/.config/gh-owner gh auth git-credential"'. pnpm bot:git sets its own helper and keeps working.
  7. Approve only in the GitHub UI. An owner approval is an APPROVED pull request review on the head commit whose body ends with owner-approval, submitted from the web or mobile app with 2FA. A counted reviewer AI-REVIEW: FAIL on the same commit still blocks the merge.