CLI guide · Windows 11

hydra on the command line.

hydra opens terminals inside named environments. Each one has its own Claude Code account, GitHub login, git author and SSH key, cloud logins and secrets. A terminal stays in its environment, and none of them can quietly use another's account.

work personal client

Download the installer hydra + hydraui

Portable: hydraui.exe · hydra.exe

What hydra does

Most command-line tools read their login and settings from a folder you can move with an environment variable. Claude Code uses CLAUDE_CONFIG_DIR, the GitHub CLI uses GH_CONFIG_DIR, git uses GIT_CONFIG_GLOBAL. hydra keeps a separate set of those folders for each environment and starts your shell with them already set.

work · pwsh
[work] PS> gh api user --jq .login
work-user
[work] PS> git config user.email
work@example.com
personal · bash
[personal] $ gh api user --jq .login
my-username
  • Stop identity mix-ups. Commits and pushes always use the environment's author, SSH key and GitHub login.
  • Run Claude Code on several accounts at once. Each environment has its own Claude sign-in, usage limits and history. Your skills, plugins, settings and MCP servers stay shared.

Install and update

Download the installer hydra + hydraui

Portable: hydraui.exe · hydra.exe

The installer puts hydra.exe (and hydraui) in %LOCALAPPDATA%\Programs\hydra, adds it to your PATH and runs hydra init: open a new terminal and hydra is there. For the portable hydra-x86_64-pc-windows-msvc.exe instead (it has a .sha256 beside it in the latest release), rename it to hydra.exe, put it in a folder on your PATH, then create hydra's home folder:

PowerShell
PS> hydra init
created C:\Users\you\.hydra\config.toml

From then on, hydra update fetches the latest release and checks its SHA-256 checksum before replacing itself. hydra update --check only reports. It won't update while another hydra terminal is open.

PowerShell
PS> hydra update
hydra 0.5.0 is installed; 0.5.1 is available
updated to 0.5.1

To build from source instead, install Rust from rustup.rs, then git clone https://github.com/davojc/hydra.git and cargo build --release.

Prefer a window? hydraui, the desktop app, opens the same environments as tabs, with a file tree, git changes and account status. It reads the same ~/.hydra folder, so everything here applies to it too. See the App guide.

Walkthrough: two accounts, GitHub and Claude

This sets up a work and a personal environment, each with its own GitHub account, Claude account, git author and SSH key.

Step 1One SSH key per GitHub account

GitHub won't accept the same key on two accounts. Add each .pub file to the matching account under Settings → SSH and GPG keys.

PowerShell
ssh-keygen -t ed25519 -f $HOME\.ssh\id_ed25519_work     -C "work@example.com"
ssh-keygen -t ed25519 -f $HOME\.ssh\id_ed25519_personal -C "me@example.com"

Step 2Create the environments

Each gets its own colour. New environments start with no tools on.

PowerShell
hydra env new work
hydra env new personal

Step 3Turn on the tools each one uses

hydra add only writes configuration. It never runs a tool or signs you in.

PowerShell
hydra add claude work
hydra add git work --name "Your Name" --email work@example.com --ssh-key ~/.ssh/id_ed25519_work
hydra add github work --owner acme
hydra add git personal --name "Your Name" --email me@example.com --ssh-key ~/.ssh/id_ed25519_personal
hydra add github personal
hydra add claude personal

Step 4Sign in inside each environment

Use each tool's own sign-in command. The terminal opens even before you've signed in, and hydra lists what's missing.

Check which account the browser is signed in to. Browser sign-ins authorise whichever account the browser is currently using. Use a private window for the second account.
work · pwsh
PS> hydra shell work
hydra: claude: not signed in - run claude auth login
hydra: github: not signed in - run gh auth login
[work] PS> gh auth login
[work] PS> claude auth login
[work] PS> exit

Repeat in hydra shell personal with your personal accounts.

Step 5Check

PowerShell
PS> hydra whoami --env work
env      work · work
claude   work@example.com (Acme)                          ok
github   work-user                                        ok
git      work@example.com                                 ok

Each terminal stays in its environment until you close it, and you can have both open at once. Run claude in each: /status shows that environment's account.

How it works

hydra starts each terminal with environment variables that point every tool at that environment's own folder under ~/.hydra/state/<env>/.

  • Nothing leaks between environments. Identity variables inherited from the terminal you started in are removed, for example GH_TOKEN, AWS_PROFILE or ANTHROPIC_API_KEY. That includes those of tools the environment doesn't use, even when one hydra terminal is started from inside another.
  • Launch fails closed. If something could make a tool fall back to another identity, hydra refuses to open the terminal and tells you how to fix it. Examples are a configured SSH key that doesn't exist, or a secret you referenced but never stored. A tool that simply isn't signed in yet doesn't block anything.
  • Secrets live in Windows Credential Manager. Config files only reference them. Values never go to disk or into hydra's output, with one exception: a gws credentials file, which is written readable by your Windows account only.

Tools

Turn a tool on with hydra add <tool> [env]. Inside a hydra terminal you can leave out the environment. hydra add with no tool lists tools and which are on; hydra remove <tool> [env] turns one off and keeps its saved logins.

ToolWhat each environment getsFlags
claudeIts own Claude Code sign-in, sharing your ~/.claude setup--mcp-exclude
github (gh)Its own gh auth login; git's HTTPS pushes to github.com use it--owner, --strict
gitAlways on, even without hydra add git: your global git config loads underneath, plus the folder guard. Adding it gives the author, email, SSH key, optional signing key and its own Git Credential Manager space for other HTTPS hosts.--name, --email, --ssh-key, --signing-key
awsAn AWS profile, optionally with private config and credentials files--profile (required), --isolate
azureIts own az login
gcloudIts own gcloud auth login and configurations
gwsIts own Google Workspace CLI login, or stored credentials--credentials-secret
kubeIts own kubeconfig--kubeconfig
codexIts own Codex CLI login
geminiGEMINI_API_KEY from a stored secret--api-key-secret (required)
jevJEV_API_KEY (TypeSafe's Jev) from a stored secret, separate from hydraui's own Jev key--api-key-secret (required)
linearLINEAR_API_KEY (a Linear personal API key) from a stored secret--api-key-secret (required)

Borrowing a login

If two environments use the same account, let one borrow the tool from the other instead of signing in twice. In envs/work/env.toml:

~/.hydra/envs/work/env.toml
[claude]
from = "personal"

[github]
from = "personal"

Or from the command line: hydra add claude work --from personal.

  • The whole tool folder is shared, not just the credential file: login, history, sessions and settings. Nothing is copied or synced, so a sign-in or refresh in personal is seen by work straight away.
  • A borrowing section holds only from. The owner's settings are used, so any other key there is an error. The owner must have the same tool turned on without from; chains aren't allowed, and an environment can't borrow from itself.
  • Except [github] owners and strict. They are guard policy, so they stay with each environment: [github] may set them next to from (hydra add github work --from personal --owner acme --strict). The borrower's own values are used, never the owner's; leaving them out means no owner list and not strict.
  • Only the folder is borrowed. A Claude login made with an API key in the owner's [env] (ANTHROPIC_API_KEY and the like) isn't borrowed; set it in the borrower's [env] too.
  • Sign in from the owner. If the borrowed tool isn't signed in, the terminal says where. hydra whoami shows the owner next to the account.
work · pwsh
PS> hydra shell work
hydra: claude: not signed in - work borrows it from personal
  -> sign in there: hydra shell personal, then claude auth login
  • git can't be borrowed. The commit author and SSH key stay per environment. Git over HTTPS signs in through gh, so borrowing github covers it.
  • Guards still compare environment names. A folder bound to personal still blocks git commit from a work terminal, even if work borrows personal's GitHub login. The guards and the SSH key read only the borrower's own env.toml.
  • Editing the owner can break borrowers. If hydra env edit personal removes a tool work borrows, work fails closed on its next launch and says why; its guard keeps working meanwhile, and hydra whoami shows the problem on that tool's line.
  • Removing and renaming are safe for owners.
    • hydra remove <tool> work on a borrower removes the section and leaves the owner's login alone.
    • hydra remove <tool> personal refuses while another environment borrows that tool from it, and names them.
    • hydra env rm personal refuses while any environment borrows from it (work borrows claude, github from personal).
    • hydra env rename personal home rewrites from = "personal" in every borrower and lists the ones it changed. It refuses while a borrower's terminal is open.

Claude Code: separate accounts, shared setup

Each environment's Claude folder (~/.hydra/state/<env>/claude) is rebuilt from your existing ~/.claude every time a terminal opens. hydra only ever reads ~/.claude and ~/.claude.json.

Linked from ~/.claude

One copy; every environment sees it.

  • skills/, commands/, agents/
  • hooks/, output-styles/
  • plugins/: install once, available everywhere

Rebuilt each launch

Shared base plus this environment's changes.

  • settings.json + envs/<env>/claude/settings.json
  • CLAUDE.md + the environment's own section
  • MCP servers from ~/.claude.json, minus --mcp-exclude

Private

Never shared between environments.

  • the Claude sign-in
  • history, projects, sessions
  • the rest of .claude.json
Changes made inside Claude don't stick. If Claude edits the rebuilt settings.json or CLAUDE.md, for example with /model, hydra saves your version as .bak on the next launch, tells you, and rebuilds the file. Put lasting changes in ~/.claude or ~/.hydra/envs/<env>/claude/.

Sign-in settings are never shared. If ~/.claude/settings.json has an apiKeyHelper or an API key under env, hydra leaves it out of every environment and warns you. Running claude outside hydra keeps using ~/.claude as before.

Each environment's settings.json also gets a PreToolUse hook that blocks git commit, git push and gh write commands in folders bound to another environment. See Folders and guards.

Folders and guards

A folder can belong to an environment. hydra then opens the right terminal there, and blocks git commit, git push and gh write commands (gh pr create, gh repo delete, gh api -X POST and the like) when they run from a terminal for a different environment. It covers commands you type and commands Claude Code runs.

Bind a folder

PowerShell
hydra bind E:\work work           # a rule in config.toml: everything under E:\work
hydra bind --file work            # or a .hydra file in the current folder
hydra bind                        # show which environment this folder resolves to
hydra bind --list                 # list the rules in config.toml
hydra unbind E:\work              # remove the rule and/or .hydra file

--file writes .hydra and adds it to the repo's .git/info/exclude, so it is never committed. You can also write rules by hand:

~/.hydra/config.toml
[bindings]
"E:/work/**" = "work"
"E:/personal/**" = "personal"

The most specific binding wins. A .hydra file beats a rule at the same or shallower depth, and among rules the longest literal prefix wins. A folder that matches nothing is unbound, and nothing is blocked there.

hydra shell with no name opens the environment bound to the current folder. hydra shell work opens in the environment's home folder (set in env.toml) when you start it from somewhere not bound to it. hydra env new work --home E:\work sets home and binds the folder in one step. hydra whoami shows a folder line.

What a block looks like

personal · pwsh
[personal] PS> git push
hydra: blocked git push - this folder belongs to work (rule E:/work/**), this terminal is personal
  -> open a work terminal here: hydra shell work
  -> or run it once anyway: hydra allow -- git push

hydra allow -- <command> runs that one command past the guard. When Claude Code is blocked, it is told to ask you to run hydra allow in your own terminal. It can't run hydra allow itself.

How it's enforced

git hooks

Each environment's gitconfig sets core.hooksPath to hydra's wrappers.

  • pre-commit and pre-push ask hydra first
  • Then the repo's own hook, or your global one, runs as usual
  • The environment's ssh_key reaches git through core.sshCommand

Claude Code hook

A PreToolUse hook on the Bash and PowerShell tools.

  • Follows cd and git -C
  • Catches --no-verify
  • Checks gh write commands too

If a binding names an environment that doesn't exist, hydra prints guard skipped and allows the command.

Git is always on. Every environment gets hydra's gitconfig, even without hydra add git. It includes your real global config (GIT_CONFIG_GLOBAL if you set it, else ~/.config/git/config and ~/.gitconfig) plus the guard. The Credential Manager namespace is written only with [git], and the gh credential helper only with [git] or [github].

Limits

The guard stops mistakes. It isn't a security boundary.

  • --no-verify skips git hooks outside Claude Code. The Claude hook catches it.
  • A repo that sets its own core.hooksPath (Husky, for example) replaces hydra's hooks, so the git guard is off there. hydra whoami says so. The Claude hook still applies.
  • In a hydra terminal, pre-commit install refuses and git lfs install complains, because core.hooksPath is set. Run them from a normal terminal.
  • git config --global inside hydra edits the generated file, which hydra rewrites on the next launch. Edit your real global file instead. The generated file's header names it.
  • The git hook looks up the binding at the repo root.
  • gh write commands you type yourself aren't guarded, even in a folder bound to another environment. gh still uses the terminal's own environment's login, so it can't act as another account.
  • Plain ssh or scp typed by hand uses ssh's normal key selection, not the environment's key.

Variables and secrets

Any other variable goes under [env] in the environment's env.toml (hydra env edit work). Values can be plain or come from a secret stored in Windows Credential Manager.

~/.hydra/envs/work/env.toml
[env]
REGION = "eu-west"
LINEAR_API_KEY = "secret:work/linear"
PowerShell
PS> hydra secret set work/linear
value: ••••••••••••••••
stored work/linear in Windows Credential Manager

For multi-line values such as JSON, pipe them in: Get-Content -Raw creds.json | hydra secret set work/gws-creds.

Commands

CommandWhat it does
hydra initCreates ~/.hydra
hydra env new|list|edit|rm|renameManages environments. env new <name> --home DIR sets where its terminals open and binds that folder. rename updates bindings, secrets, saved logins and borrowers too.
hydra add [<tool>] [<env>]Turns a tool on by writing its settings. Never signs in. --from <env> borrows the tool from another environment (see Borrowing a login).
hydra remove <tool> [<env>]Turns a tool off. Saved logins are kept.
hydra shell [<env>]Opens a terminal in an environment. With no name, the environment comes from the current folder's binding. Options: --shell pwsh|bash, --cwd DIR.
hydra run <env> -- <command>Runs one command in an environment
hydra auth <tool> <env>Runs a tool's sign-in inside an environment without opening a terminal
hydra secret set|rm <env>/<key>Stores or removes a secret
hydra bind [<path>] <env>Binds a folder to an environment. --file writes a .hydra file instead of a rule. With no arguments it shows the current folder's binding; --list lists every rule.
hydra unbind [<path>]Removes a folder's rule and/or .hydra file
hydra allow -- <command>Runs one command past the folder guard
hydra whoami [--env <env>]Shows which account each tool is actually using, and the current folder's binding
hydra update [--check]Installs the latest release from GitHub after checking its checksum

Files

~/.hydra
config.toml          global settings and [bindings]
envs/<env>/          yours: env.toml, plus optional claude/ overrides
state/<env>/         hydra's: each tool's folder, sign-ins, generated config
state/<env>/git/hooks/  hydra's git hook wrappers (the guard)
secrets.toml         names (never values) of stored secrets

HYDRA_HOME moves ~/.hydra. Deleting state/<env> resets an environment, but you'll need to sign in again.

Troubleshooting

MessageWhat to do
hydra: <tool>: not signed inSign in with that tool's own command inside the environment's terminal. If it says work borrows it from personal, sign in from the owner: hydra shell personal.
hydra: work borrows [x] from y, but y has no [x]Turn it on in the owner: hydra add x y.
hydra: work borrows [x] from y, which borrows it from zBorrowing doesn't chain. Borrow from the owner: from = "z".
secret work/x isn't sethydra secret set work/x
…id_ed25519_work not foundFix the key path: hydra add git work --ssh-key <path>
CLAUDE_CONFIG_DIR error when openingRemove CLAUDE_CONFIG_DIR from [env]; [claude] sets it. Then sign in again.
… is a real folder, not a linkMove anything you want to keep into ~/.claude, delete that folder, and reopen the terminal.
hydra: blocked git push - this folder belongs to work …The folder is bound to another environment. Open the right terminal (hydra shell work) or run it once with hydra allow -- git push. hydra bind shows which rule applies.
hydra: warning: guard skippedA binding names an environment that doesn't exist, so nothing was checked. Fix the name in config.toml or the .hydra file, or create the environment.
whoami says the repo sets its own core.hooksPathHusky or similar replaces hydra's git hooks in that repo, so the git guard is off there. The Claude hook still guards it.
A Claude setting you changed disappearedYour version is in settings.json.bak. Put lasting changes in ~/.claude/settings.json or envs/<env>/claude/settings.json.
hydra is in use - not updatingClose the listed hydra terminals, then run hydra update again.

Planned

These are designed but not built yet:

  • ssh, scp and sftp using the environment's key outside git.
  • Windows Terminal profiles. One coloured tab per environment.
  • hydra doctor and macOS / Linux support.