SKILL.md (6624B)
1 --- 2 name: "gh-auth-isolation" 3 description: "Safely manage multiple GitHub identities (EMU + personal) in agent workflows" 4 domain: "security, github-integration, authentication, multi-account" 5 confidence: "high" 6 source: "earned (production usage across 50+ sessions with EMU corp + personal GitHub accounts)" 7 tools: 8 - name: "gh" 9 description: "GitHub CLI for authenticated operations" 10 when: "When accessing GitHub resources requiring authentication" 11 --- 12 13 ## Context 14 15 Many developers use GitHub through an Enterprise Managed User (EMU) account at work while maintaining a personal GitHub account for open-source contributions. AI agents spawned by Squad inherit the shell's default `gh` authentication — which is usually the EMU account. This causes failures when agents try to push to personal repos, create PRs on forks, or interact with resources outside the enterprise org. 16 17 This skill teaches agents how to detect the active identity, switch contexts safely, and avoid mixing credentials across operations. 18 19 ## Patterns 20 21 ### Detect Current Identity 22 23 Before any GitHub operation, check which account is active: 24 25 ```bash 26 gh auth status 27 ``` 28 29 Look for: 30 - `Logged in to github.com as USERNAME` — the active account 31 - `Token scopes: ...` — what permissions are available 32 - Multiple accounts will show separate entries 33 34 ### Extract a Specific Account's Token 35 36 When you need to operate as a specific user (not the default): 37 38 ```bash 39 # Get the personal account token (by username) 40 gh auth token --user personaluser 41 42 # Get the EMU account token 43 gh auth token --user corpalias_enterprise 44 ``` 45 46 **Use case:** Push to a personal fork while the default `gh` auth is the EMU account. 47 48 ### Push to Personal Repos from EMU Shell 49 50 The most common scenario: your shell defaults to the EMU account, but you need to push to a personal GitHub repo. 51 52 ```bash 53 # 1. Extract the personal token 54 $token = gh auth token --user personaluser 55 56 # 2. Push using token-authenticated HTTPS 57 git push https://personaluser:$token@github.com/personaluser/repo.git branch-name 58 ``` 59 60 **Why this works:** `gh auth token --user` reads from `gh`'s credential store without switching the active account. The token is used inline for a single operation and never persisted. 61 62 ### Create PRs on Personal Forks 63 64 When the default `gh` context is EMU but you need to create a PR from a personal fork: 65 66 ```bash 67 # Option 1: Use --repo flag (works if token has access) 68 gh pr create --repo upstream/repo --head personaluser:branch --title "..." --body "..." 69 70 # Option 2: Temporarily set GH_TOKEN for one command 71 $env:GH_TOKEN = $(gh auth token --user personaluser) 72 gh pr create --repo upstream/repo --head personaluser:branch --title "..." 73 Remove-Item Env:\GH_TOKEN 74 ``` 75 76 ### Config Directory Isolation (Advanced) 77 78 For complete isolation between accounts, use separate `gh` config directories: 79 80 ```bash 81 # Personal account operations 82 $env:GH_CONFIG_DIR = "$HOME/.config/gh-public" 83 gh auth login # Login with personal account (one-time setup) 84 gh repo clone personaluser/repo 85 86 # EMU account operations (default) 87 Remove-Item Env:\GH_CONFIG_DIR 88 gh auth status # Back to EMU account 89 ``` 90 91 **Setup (one-time):** 92 ```bash 93 # Create isolated config for personal account 94 mkdir ~/.config/gh-public 95 $env:GH_CONFIG_DIR = "$HOME/.config/gh-public" 96 gh auth login --web --git-protocol https 97 ``` 98 99 ### Shell Aliases for Quick Switching 100 101 Add to your shell profile for convenience: 102 103 ```powershell 104 # PowerShell profile 105 function ghp { $env:GH_CONFIG_DIR = "$HOME/.config/gh-public"; gh @args; Remove-Item Env:\GH_CONFIG_DIR } 106 function ghe { gh @args } # Default EMU 107 108 # Usage: 109 # ghp repo clone personaluser/repo # Uses personal account 110 # ghe issue list # Uses EMU account 111 ``` 112 113 ```bash 114 # Bash/Zsh profile 115 alias ghp='GH_CONFIG_DIR=~/.config/gh-public gh' 116 alias ghe='gh' 117 118 # Usage: 119 # ghp repo clone personaluser/repo 120 # ghe issue list 121 ``` 122 123 ## Examples 124 125 ### ✓ Correct: Agent pushes blog post to personal GitHub Pages 126 127 ```powershell 128 # Agent needs to push to personaluser.github.io (personal repo) 129 # Default gh auth is corpalias_enterprise (EMU) 130 131 $token = gh auth token --user personaluser 132 git remote set-url origin https://personaluser:$token@github.com/personaluser/personaluser.github.io.git 133 git push origin main 134 135 # Clean up — don't leave token in remote URL 136 git remote set-url origin https://github.com/personaluser/personaluser.github.io.git 137 ``` 138 139 ### ✓ Correct: Agent creates a PR from personal fork to upstream 140 141 ```powershell 142 # Fork: personaluser/squad, Upstream: bradygaster/squad 143 # Agent is on branch contrib/fix-docs in the fork clone 144 145 git push origin contrib/fix-docs # Pushes to fork (may need token auth) 146 147 # Create PR targeting upstream 148 gh pr create --repo bradygaster/squad --head personaluser:contrib/fix-docs ` 149 --title "docs: fix installation guide" ` 150 --body "Fixes #123" 151 ``` 152 153 ### ✗ Incorrect: Blindly pushing with wrong account 154 155 ```bash 156 # BAD: Agent assumes default gh auth works for personal repos 157 git push origin main 158 # ERROR: Permission denied — EMU account has no access to personal repo 159 160 # BAD: Hardcoding tokens in scripts 161 git push https://personaluser:ghp_xxxxxxxxxxxx@github.com/personaluser/repo.git main 162 # SECURITY RISK: Token exposed in command history and process list 163 ``` 164 165 ### ✓ Correct: Check before you push 166 167 ```bash 168 # Always verify which account has access before operations 169 gh auth status 170 # If wrong account, use token extraction: 171 $token = gh auth token --user personaluser 172 git push https://personaluser:$token@github.com/personaluser/repo.git main 173 ``` 174 175 ## Anti-Patterns 176 177 - ❌ **Hardcoding tokens** in scripts, environment variables, or committed files. Use `gh auth token --user` to extract at runtime. 178 - ❌ **Assuming the default `gh` auth works** for all repos. EMU accounts can't access personal repos and vice versa. 179 - ❌ **Switching `gh auth login`** globally mid-session. This changes the default for ALL processes and can break parallel agents. 180 - ❌ **Storing personal tokens in `.env`** or `.squad/` files. These get committed by Scribe. Use `gh`'s credential store. 181 - ❌ **Ignoring token cleanup** after inline HTTPS pushes. Always reset the remote URL to avoid persisting tokens. 182 - ❌ **Using `gh auth switch`** in multi-agent sessions. One agent switching affects all others sharing the shell. 183 - ❌ **Mixing EMU and personal operations** in the same git clone. Use separate clones or explicit remote URLs per operation.