Per-workspace identity for Claude Code: scope MCP servers, GitHub auth, and git commit identity to the directory you are in.
π The why behind the design: Race-Free Identity in Claude Code, aka multiple gh, linear, notion, slack and other accounts.
You describe each workspace once; inscope owns the moving parts and keeps them in sync from a single source of truth:
- a
.mcp.jsonat each workspace root, with uniquely named servers - one zsh
chpwdhook that resolves the right tokens from$PWD - git
includeIfrules so commits land with the right author email per path
Nothing sensitive is written to disk: GitHub tokens come from the gh keyring and Slack tokens from the macOS Keychain, resolved live by the hook. It is race-free across concurrent shells and Claude Code sessions, with no global toggles, and idempotent: only the blocks it owns inside .zshrc, .gitconfig, and .mcp.json are ever touched.
Install globally (the CLI manages your shell hook, so a global install is expected):
npm i -g inscopeScoping GitHub accounts? Sign each one into gh once with gh auth login (that is gh's own command, not inscope); inscope reads tokens from the accounts you have signed in. Then:
# set up the config + hook, and source it from ~/.zshrc
inscope init
# map a workspace - inscope walks you through gh account, git identity, and servers
inscope add ~/acme
inscope add ~/personal
# reload your shell, then verify
source ~/.zshrc
inscope doctorcd ~/acme/api and you are the work account, with work MCP servers and your work commit email. cd ~/personal/blog and you are you. Launch claude from inside a mapped directory (or relaunch) to pick up the identity.
Prefer flags or CI? Every prompt has a flag, and -y takes the defaults non-interactively:
inscope add ~/acme --gh <account> --email you@work.com --servers github,linear -ymacOS, zsh, and Claude Code.
gh is needed only for workspaces that scope a GitHub account.
inscope init Create the config, generate the hook, source it from ~/.zshrc
inscope add [path] Map a directory to a GitHub account, git email, and MCP servers
inscope edit [path] Edit a workspace interactively, then re-apply
inscope rm [path] Remove a workspace mapping (alias: remove)
inscope list List configured workspaces (alias: ls)
inscope diff Preview what apply would change; --adopt pulls on-disk extras back
inscope apply Regenerate the hook, git includes, and .mcp.json (alias: sync)
inscope doctor Verify tokens, identities, and the hook resolve correctly
-v, --version Display version
-h, --help Display help
Run any command with -h for its full options.
Create the config, generate the chpwd hook, and add a source line to ~/.zshrc. Safe to run again; it never overwrites your config.
Map a directory. Run it bare and it walks you through everything: pick the GitHub account from your signed-in gh accounts, accept your global git identity or set a per-workspace one, and toggle which MCP servers to enable. Enabling Slack adds a keychain prompt and a Yes/No for posting messages. Pass any flag to skip its prompt, or -y to take the defaults non-interactively (for scripts and CI).
--gh <account> gh account whose token this workspace uses
--email <email> git commit email (omit to inherit your global identity)
--git-name <name> git commit author name (omit to inherit global)
--label <name> workspace name; defaults to the directory basename
--servers <list> comma-separated, any of: github, atlassian, canva,
clickup, hubspot, intercom, linear, monday, notion,
plane, sentry, slack, stripe, vercel, webflow
(default: github)
--slack-keychain <s> keychain service for the Slack token
(default: SLACK_MCP_XOXP_TOKEN_<LABEL> when slack is on)
--slack-message allow the Slack MCP server to post messages
--seed-slack prompt for the Slack token and store it in the keychain
-y, --yes accept defaults, skip all prompts (non-interactive)
Step through a workspace's prompts pre-filled with its current values (pick it, or pass its path/label), then inscope re-applies on save.
Remove a workspace mapping (alias remove). Drops its git include and the MCP servers inscope manages; your keychain entries and gh accounts are left untouched. Asks you to type the label to confirm, or pass -y to skip the prompt.
List the configured workspaces with their path, gh account, git email, and enabled servers (alias ls). Run inscope doctor to verify they actually resolve.
Preview exactly what apply would write: a colored diff of the hook, git includes, and each .mcp.json against your config. --adopt pulls config-expressible on-disk settings (a Slack add-message tool, a custom server URL) back into the config, so the next apply keeps them instead of dropping them. --exit-code exits non-zero when anything is out of sync, so it works as a CI or pre-commit gate.
Regenerate the hook, git includes, and every .mcp.json from the config (alias sync). Idempotent and surgical: only the managed blocks are touched, and writes are atomic. Run it any time you edit inscope.json by hand.
Verify that tokens, identities, the hook, and each .mcp.json resolve correctly. Exits non-zero if anything fails, so it doubles as a health gate.
| Surface | Location |
|---|---|
| Config | ~/.config/inscope/inscope.json |
| chpwd hook | ~/.config/inscope/inscope.zsh |
| MCP servers | <workspace>/.mcp.json |
| Git identity | ~/.gitconfig includeIf + ~/.config/inscope/git/<name>.gitconfig |
inscope only touches the blocks it owns; your other .zshrc, .gitconfig, and .mcp.json content is left alone. Edit inscope.json by hand if you like, then run inscope apply.
Each enabled server is written into the workspace .mcp.json with a name suffixed by the workspace label (for example github-acme), so servers from different workspaces never collide.
| Server | Transport | Auth |
|---|---|---|
github |
http | GITHUB_TOKEN from the active gh account |
atlassian |
http | OAuth (Jira / Confluence) |
canva |
http | OAuth |
clickup |
http | OAuth |
hubspot |
http | OAuth |
intercom |
http | OAuth |
linear |
http | OAuth |
monday |
http | OAuth |
notion |
http | OAuth |
plane |
http | OAuth |
sentry |
http | OAuth |
slack |
stdio | SLACK_MCP_XOXP_TOKEN from the macOS Keychain |
stripe |
http | OAuth |
vercel |
http | OAuth |
webflow |
http | OAuth |
Slack is opt-in. Enable it during add (shown above), or with flags, then store the token once:
inscope add ~/acme --gh neeraj-acme-org --servers github,slack --seed-slack--seed-slack prompts for the xoxp token and writes it to the Keychain. Pass --slack-message to allow the Slack MCP server to post messages.
You need a Slack app with a user OAuth (xoxp) token first. If you don't have one, follow the slack-mcp-server authentication guide. inscope points you there during add when Slack is enabled.
The source of truth is ~/.config/inscope/inscope.json:
Edit it directly, then run inscope apply to regenerate the hook, git includes, and every .mcp.json. inscope doctor will tell you if anything no longer resolves.
Issues and pull requests are welcome. Run the tests with bun test and the type checks with bun run typecheck before opening a PR. See CONTRIBUTING.md for the toolchain and architecture.
MIT Β© Neeraj Dalal
{ "version": 1, "workspaces": [ { "name": "acme", "path": "~/acme", "gh": "neeraj-acme-org", "git": { "email": "neeraj@acme.org" }, "servers": { "github": true, "linear": true, "slack": { "keychain": "SLACK_MCP_XOXP_TOKEN_ACME", "addMessageTool": false, }, // every other server (atlassian, canva, β¦ webflow) defaults to false }, }, ], }