Metadata-Version: 2.5
Name: gwitch
Version: 0.1.0
Summary: Switch between git/GitHub accounts per repository.
Project-URL: Homepage, https://github.com/isamrish/gwitch
Project-URL: Repository, https://github.com/isamrish/gwitch
Project-URL: Issues, https://github.com/isamrish/gwitch/issues
Author-email: Amrish Kushwaha <askmaurya48@gmail.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Version Control :: Git
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Requires-Dist: toml>=0.10
Requires-Dist: typer>=0.9
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == 'dev'
Description-Content-Type: text/markdown

# gw

[![CI](https://github.com/isamrish/gwitch/actions/workflows/ci.yml/badge.svg)](https://github.com/isamrish/gwitch/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

Switch between multiple git/GitHub accounts, per repository, and see which
account is active right in your shell prompt.

## Install

    pipx install gwitch

Published on PyPI as `gwitch`; installs the `gw` command. Or, from a
checkout of this repository:

    pipx install .

## Quick start

    gw account add personal
    gw account add work

    cd ~/code/some-repo
    gw use personal
    gw status

## Shell prompt

    gw init zsh    # or bash / fish

prints a small shell function, plus a one-line instruction for wiring it
into your prompt — paste both into your shell config yourself. `gw` never
edits your shell rc files automatically.

    gw init zsh --install    # or bash

`--install` does the wiring for you, for `zsh`/`bash` only (not `fish`
yet): it writes a `gw-prompt` script to `~/.local/bin/gw-prompt` and a
`gw-check` script to `~/.local/bin/gw-check` (the cd-triggered account-check
described below), and appends two marked blocks to your rc file — one per
script. It's idempotent — safe to re-run. Note for macOS bash users:
`~/.bashrc` isn't read by login shells (Terminal and iTerm start bash as a
login shell), so unless you've already wired `~/.bashrc` to be sourced from
`~/.bash_profile`, you'll need to add that yourself for the installed
integration to take effect.

## What `gw use <account>` changes

- `user.name` / `user.email` — local to the current repo only (`git config --local`)
- `core.sshCommand` — forces the SSH key registered for that account
- `gw.account` — a marker read by `gw status` and the shell prompt function
- `gw-remote-map.<remote URL>.account` — records this repo's remote in **global** git config, for the cd-triggered mismatch check below

`gw use` also records this repo's remote-to-account mapping in **global**
git config (for the cd-triggered mismatch check, see below) — everything
else stays local-only. None of this touches `~/.ssh/config` or ssh-agent.

## Remote-account mismatch check

With `gw init <shell> --install`, a `gw-check` script is wired to run every
time your shell `cd`s into a different directory. If the repo you land in
has an `origin` remote that `gw use <account>` has previously recorded, and
the account currently active in that repo doesn't match, it prints a
warning to stderr telling you which account to switch to. It never blocks
or changes anything — it's purely informational.

## Known limitations

**`gh` (GitHub CLI) authentication is global, not per-repo.** GitHub CLI's
authenticated account is global to your machine (`gh` keeps one active user
per host), not per-repo — that's inherent to how `gh` itself works. `gw use
<account>` will call `gh auth switch` for you, which changes `gh`'s active
account machine-wide, even for other repos/terminal tabs, until you `gw use`
a different account somewhere else. Your git identity and SSH key stay
correctly isolated per-repo regardless.

`gw status` shows both this repo's git identity and gh's currently active
account as separate lines, so if they've drifted apart it's visible rather
than silent.

**Linked git worktrees share git identity.** `git config --local` in a
linked worktree (created via `git worktree add`) resolves to the *same*
shared config file as the main checkout — git only isolates local config
per-worktree if the repo opts into `extensions.worktreeConfig`, which `gw`
does not assume. That means `gw use <account>` run inside a linked worktree
changes the identity for the main checkout and every sibling worktree of
that repo too, not just the worktree you ran it in. `gw use` detects this
and prints a warning when you run it inside a linked worktree, but it does
not block the switch or set up per-worktree config automatically.

**The remote-account check is last-write-wins, URL-exact, and cd-triggered
only.** The `gw-remote-map` registry has no per-clone tracking: running `gw
use <account>` anywhere for a given remote overwrites what "the right
account" means for every other clone of that remote — this is intentional,
not a bug. It also matches on the exact remote URL string, so an SSH clone
and an HTTPS clone of the same repo are treated as two unrelated remotes.
And because the check only runs on `cd`, a shell already sitting in a
mismatched repo when it starts won't warn until you `cd` away and back.

## Commands

- `gw account add <name>` — register an account (prompts for git name/email,
  GitHub username; can generate a new SSH key for you)
- `gw account list` — list registered accounts
- `gw account remove <name>` — remove a registered account
- `gw use <name>` — activate an account for the current repo
- `gw status` / `gw whoami` — show the active account for the current repo
- `gw init <shell>` — print the shell prompt snippet for `zsh`, `bash`, or
  `fish`; add `--install` (`zsh`/`bash` only) to write and wire it up automatically

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for dev setup and how to run the
tests. Please follow the [Code of Conduct](CODE_OF_CONDUCT.md). For security
issues, see [SECURITY.md](SECURITY.md) instead of opening a public issue.

## License

[MIT](LICENSE)
