gwitch 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. gwitch-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +17 -0
  2. gwitch-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +11 -0
  3. gwitch-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +8 -0
  4. gwitch-0.1.0/.github/workflows/ci.yml +34 -0
  5. gwitch-0.1.0/.github/workflows/publish.yml +40 -0
  6. gwitch-0.1.0/.gitignore +10 -0
  7. gwitch-0.1.0/CHANGELOG.md +36 -0
  8. gwitch-0.1.0/CODE_OF_CONDUCT.md +63 -0
  9. gwitch-0.1.0/CONTRIBUTING.md +45 -0
  10. gwitch-0.1.0/LICENSE +21 -0
  11. gwitch-0.1.0/PKG-INFO +143 -0
  12. gwitch-0.1.0/README.md +119 -0
  13. gwitch-0.1.0/SECURITY.md +25 -0
  14. gwitch-0.1.0/docs/specs/2026-08-29-gitsw-design.md +159 -0
  15. gwitch-0.1.0/docs/specs/2026-08-29-gw-https-support-design.md +162 -0
  16. gwitch-0.1.0/docs/specs/2026-08-29-gw-prompt-install-design.md +182 -0
  17. gwitch-0.1.0/docs/specs/2026-08-29-gw-remote-account-check-design.md +115 -0
  18. gwitch-0.1.0/pyproject.toml +42 -0
  19. gwitch-0.1.0/src/gw/__init__.py +0 -0
  20. gwitch-0.1.0/src/gw/cli.py +30 -0
  21. gwitch-0.1.0/src/gw/commands/__init__.py +0 -0
  22. gwitch-0.1.0/src/gw/commands/account.py +111 -0
  23. gwitch-0.1.0/src/gw/commands/credential_helper.py +49 -0
  24. gwitch-0.1.0/src/gw/commands/init_cmd.py +108 -0
  25. gwitch-0.1.0/src/gw/commands/status.py +55 -0
  26. gwitch-0.1.0/src/gw/commands/use.py +82 -0
  27. gwitch-0.1.0/src/gw/config.py +78 -0
  28. gwitch-0.1.0/src/gw/gh_ops.py +50 -0
  29. gwitch-0.1.0/src/gw/git_ops.py +138 -0
  30. gwitch-0.1.0/src/gw/prompt_install.py +95 -0
  31. gwitch-0.1.0/src/gw/remote_check_install.py +87 -0
  32. gwitch-0.1.0/src/gw/ssh_ops.py +38 -0
  33. gwitch-0.1.0/tests/test_account_command.py +165 -0
  34. gwitch-0.1.0/tests/test_cli_smoke.py +11 -0
  35. gwitch-0.1.0/tests/test_config.py +136 -0
  36. gwitch-0.1.0/tests/test_credential_helper_command.py +138 -0
  37. gwitch-0.1.0/tests/test_gh_ops.py +90 -0
  38. gwitch-0.1.0/tests/test_git_ops.py +261 -0
  39. gwitch-0.1.0/tests/test_init_command.py +170 -0
  40. gwitch-0.1.0/tests/test_prompt_install.py +218 -0
  41. gwitch-0.1.0/tests/test_remote_check_install.py +302 -0
  42. gwitch-0.1.0/tests/test_ssh_ops.py +65 -0
  43. gwitch-0.1.0/tests/test_status_command.py +174 -0
  44. gwitch-0.1.0/tests/test_use_command.py +291 -0
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: Bug report
3
+ about: Something isn't working as expected
4
+ labels: bug
5
+ ---
6
+
7
+ **What command did you run?**
8
+
9
+ **What did you expect to happen?**
10
+
11
+ **What actually happened?** (include the full output)
12
+
13
+ **Environment**
14
+ - `gw` version (`pipx list` or `pip show gw`):
15
+ - OS:
16
+ - Shell (zsh/bash/fish):
17
+ - `gh --version` (if relevant):
@@ -0,0 +1,11 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for gw
4
+ labels: enhancement
5
+ ---
6
+
7
+ **What problem does this solve?**
8
+
9
+ **What would you like `gw` to do instead?**
10
+
11
+ **Anything else?** (alternatives considered, related issues, etc.)
@@ -0,0 +1,8 @@
1
+ ## What does this change?
2
+
3
+ ## Why?
4
+
5
+ ## Testing
6
+
7
+ - [ ] `python -m pytest -v` passes locally
8
+ - [ ] Added/updated tests for this change
@@ -0,0 +1,34 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu-latest, macos-latest]
15
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
16
+ runs-on: ${{ matrix.os }}
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+
24
+ - name: Configure git identity for tests
25
+ run: |
26
+ git config --global user.name "CI"
27
+ git config --global user.email "ci@example.com"
28
+ git config --global init.defaultBranch main
29
+
30
+ - name: Install gw
31
+ run: pip install -e ".[dev]"
32
+
33
+ - name: Run tests
34
+ run: python -m pytest -v
@@ -0,0 +1,40 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: "3.12"
16
+
17
+ - name: Build package
18
+ run: |
19
+ pip install build
20
+ python -m build
21
+
22
+ - uses: actions/upload-artifact@v4
23
+ with:
24
+ name: dist
25
+ path: dist/
26
+
27
+ publish:
28
+ needs: build
29
+ runs-on: ubuntu-latest
30
+ environment: pypi
31
+ permissions:
32
+ id-token: write
33
+ steps:
34
+ - uses: actions/download-artifact@v4
35
+ with:
36
+ name: dist
37
+ path: dist/
38
+
39
+ - name: Publish to PyPI
40
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,10 @@
1
+ .worktrees/
2
+ .superpowers/
3
+ .venv/
4
+ __pycache__/
5
+ *.pyc
6
+ *.egg-info/
7
+ dist/
8
+ build/
9
+ .pytest_cache/
10
+ docs/plans/
@@ -0,0 +1,36 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here.
4
+ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
+
6
+ ## [Unreleased]
7
+
8
+ ### Added
9
+
10
+ - `gw init <shell> --install` — for `zsh`/`bash`, write the `gw-prompt`
11
+ script to `~/.local/bin/gw-prompt` and append an idempotent, marked block
12
+ to your shell rc file automatically, instead of pasting the snippet by hand.
13
+ - Remote-account mismatch check: `gw use <name>` now records this repo's
14
+ remote-to-account mapping in global git config, and `gw init <shell>
15
+ --install` additionally installs a `gw-check` script wired to run on every
16
+ shell `cd`, warning (to stderr, non-blocking) when the account active in
17
+ the repo you land in doesn't match the account last recorded for its
18
+ remote.
19
+
20
+ ## [0.1.0] - 2026-08-29
21
+
22
+ Initial release.
23
+
24
+ ### Added
25
+
26
+ - `gw account add/list/remove` — register, list, and remove git/GitHub
27
+ accounts, with optional SSH key generation.
28
+ - `gw use <name>` — activate an account for the current repo: local (never
29
+ global) `user.name`/`user.email`/`core.sshCommand`, plus a best-effort
30
+ `gh auth switch`. Warns when run inside a linked git worktree, since git
31
+ shares local config across worktrees by default.
32
+ - `gw status` / `gw whoami` — show the active account for the current repo,
33
+ and flag drift between it and `gh`'s currently active account.
34
+ - `gw init zsh|bash|fish` — print a pure-shell prompt snippet (no Python
35
+ spawned per render) showing the active account.
36
+ - `pipx install .` packaging with a `gw` console script.
@@ -0,0 +1,63 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in
6
+ our community a harassment-free experience for everyone, regardless of age,
7
+ body size, visible or invisible disability, ethnicity, sex characteristics,
8
+ gender identity and expression, level of experience, education,
9
+ socio-economic status, nationality, personal appearance, race, religion, or
10
+ sexual identity and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open,
13
+ welcoming, diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment:
18
+
19
+ - Demonstrating empathy and kindness toward other people
20
+ - Being respectful of differing opinions, viewpoints, and experiences
21
+ - Giving and gracefully accepting constructive feedback
22
+ - Focusing on what is best not just for us as individuals, but for the
23
+ overall community
24
+
25
+ Examples of unacceptable behavior:
26
+
27
+ - The use of sexualized language or imagery, and sexual attention or
28
+ advances of any kind
29
+ - Trolling, insulting or derogatory comments, and personal or political
30
+ attacks
31
+ - Public or private harassment
32
+ - Publishing others' private information, such as a physical or email
33
+ address, without their explicit permission
34
+ - Other conduct which could reasonably be considered inappropriate in a
35
+ professional setting
36
+
37
+ ## Enforcement Responsibilities
38
+
39
+ Project maintainers are responsible for clarifying and enforcing our
40
+ standards of acceptable behavior and will take appropriate and fair
41
+ corrective action in response to any behavior that they deem inappropriate,
42
+ threatening, offensive, or harmful.
43
+
44
+ ## Scope
45
+
46
+ This Code of Conduct applies within all community spaces (issues, pull
47
+ requests, discussions) and when an individual is officially representing
48
+ the project in public spaces.
49
+
50
+ ## Enforcement
51
+
52
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
53
+ reported to the maintainers at **askmaurya48@gmail.com**. All complaints
54
+ will be reviewed and investigated promptly and fairly.
55
+
56
+ ## Attribution
57
+
58
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
59
+ version 2.1, available at
60
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
61
+
62
+ [homepage]: https://www.contributor-covenant.org
63
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
@@ -0,0 +1,45 @@
1
+ # Contributing to gw
2
+
3
+ Thanks for considering a contribution.
4
+
5
+ ## Development setup
6
+
7
+ ```bash
8
+ git clone https://github.com/isamrish/gwitch.git
9
+ cd gwitch
10
+ python3 -m venv .venv
11
+ .venv/bin/pip install -e ".[dev]"
12
+ ```
13
+
14
+ ## Running tests
15
+
16
+ ```bash
17
+ .venv/bin/python -m pytest -v
18
+ ```
19
+
20
+ Tests exercise real `git`, `ssh-keygen`, and (mocked) `gh` subprocess calls
21
+ against temporary directories — no network access or existing GitHub
22
+ account is required to run the suite.
23
+
24
+ ## Making a change
25
+
26
+ 1. Open an issue first for anything beyond a small fix, so we can agree on
27
+ the approach before you put work into it.
28
+ 2. Follow the existing code style: qualified module imports
29
+ (`from gw import config`, not `from gw.config import x`) so tests can
30
+ monkeypatch cleanly — this convention is used throughout the codebase.
31
+ 3. Add or update tests for any behavior change. Real git/ssh-keygen calls
32
+ are preferred over mocks where practical; `gh` calls are mocked since
33
+ they need live auth.
34
+ 4. Run the full test suite before opening a pull request.
35
+
36
+ ## Pull requests
37
+
38
+ Keep PRs focused — one change per PR is easier to review than a bundle of
39
+ unrelated fixes. Describe what changed and why in the PR description.
40
+
41
+ ## Reporting bugs
42
+
43
+ Open a GitHub issue with the command you ran, what you expected, and what
44
+ happened instead. For anything involving SSH keys, GitHub tokens, or other
45
+ credentials, see [SECURITY.md](SECURITY.md) instead of a public issue.
gwitch-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amrish Kushwaha
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
gwitch-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,143 @@
1
+ Metadata-Version: 2.5
2
+ Name: gwitch
3
+ Version: 0.1.0
4
+ Summary: Switch between git/GitHub accounts per repository.
5
+ Project-URL: Homepage, https://github.com/isamrish/gwitch
6
+ Project-URL: Repository, https://github.com/isamrish/gwitch
7
+ Project-URL: Issues, https://github.com/isamrish/gwitch/issues
8
+ Author-email: Amrish Kushwaha <askmaurya48@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: MacOS
14
+ Classifier: Operating System :: POSIX :: Linux
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Software Development :: Version Control :: Git
17
+ Classifier: Topic :: Utilities
18
+ Requires-Python: >=3.9
19
+ Requires-Dist: toml>=0.10
20
+ Requires-Dist: typer>=0.9
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest>=7; extra == 'dev'
23
+ Description-Content-Type: text/markdown
24
+
25
+ # gw
26
+
27
+ [![CI](https://github.com/isamrish/gwitch/actions/workflows/ci.yml/badge.svg)](https://github.com/isamrish/gwitch/actions/workflows/ci.yml)
28
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
29
+
30
+ Switch between multiple git/GitHub accounts, per repository, and see which
31
+ account is active right in your shell prompt.
32
+
33
+ ## Install
34
+
35
+ pipx install gwitch
36
+
37
+ Published on PyPI as `gwitch`; installs the `gw` command. Or, from a
38
+ checkout of this repository:
39
+
40
+ pipx install .
41
+
42
+ ## Quick start
43
+
44
+ gw account add personal
45
+ gw account add work
46
+
47
+ cd ~/code/some-repo
48
+ gw use personal
49
+ gw status
50
+
51
+ ## Shell prompt
52
+
53
+ gw init zsh # or bash / fish
54
+
55
+ prints a small shell function, plus a one-line instruction for wiring it
56
+ into your prompt — paste both into your shell config yourself. `gw` never
57
+ edits your shell rc files automatically.
58
+
59
+ gw init zsh --install # or bash
60
+
61
+ `--install` does the wiring for you, for `zsh`/`bash` only (not `fish`
62
+ yet): it writes a `gw-prompt` script to `~/.local/bin/gw-prompt` and a
63
+ `gw-check` script to `~/.local/bin/gw-check` (the cd-triggered account-check
64
+ described below), and appends two marked blocks to your rc file — one per
65
+ script. It's idempotent — safe to re-run. Note for macOS bash users:
66
+ `~/.bashrc` isn't read by login shells (Terminal and iTerm start bash as a
67
+ login shell), so unless you've already wired `~/.bashrc` to be sourced from
68
+ `~/.bash_profile`, you'll need to add that yourself for the installed
69
+ integration to take effect.
70
+
71
+ ## What `gw use <account>` changes
72
+
73
+ - `user.name` / `user.email` — local to the current repo only (`git config --local`)
74
+ - `core.sshCommand` — forces the SSH key registered for that account
75
+ - `gw.account` — a marker read by `gw status` and the shell prompt function
76
+ - `gw-remote-map.<remote URL>.account` — records this repo's remote in **global** git config, for the cd-triggered mismatch check below
77
+
78
+ `gw use` also records this repo's remote-to-account mapping in **global**
79
+ git config (for the cd-triggered mismatch check, see below) — everything
80
+ else stays local-only. None of this touches `~/.ssh/config` or ssh-agent.
81
+
82
+ ## Remote-account mismatch check
83
+
84
+ With `gw init <shell> --install`, a `gw-check` script is wired to run every
85
+ time your shell `cd`s into a different directory. If the repo you land in
86
+ has an `origin` remote that `gw use <account>` has previously recorded, and
87
+ the account currently active in that repo doesn't match, it prints a
88
+ warning to stderr telling you which account to switch to. It never blocks
89
+ or changes anything — it's purely informational.
90
+
91
+ ## Known limitations
92
+
93
+ **`gh` (GitHub CLI) authentication is global, not per-repo.** GitHub CLI's
94
+ authenticated account is global to your machine (`gh` keeps one active user
95
+ per host), not per-repo — that's inherent to how `gh` itself works. `gw use
96
+ <account>` will call `gh auth switch` for you, which changes `gh`'s active
97
+ account machine-wide, even for other repos/terminal tabs, until you `gw use`
98
+ a different account somewhere else. Your git identity and SSH key stay
99
+ correctly isolated per-repo regardless.
100
+
101
+ `gw status` shows both this repo's git identity and gh's currently active
102
+ account as separate lines, so if they've drifted apart it's visible rather
103
+ than silent.
104
+
105
+ **Linked git worktrees share git identity.** `git config --local` in a
106
+ linked worktree (created via `git worktree add`) resolves to the *same*
107
+ shared config file as the main checkout — git only isolates local config
108
+ per-worktree if the repo opts into `extensions.worktreeConfig`, which `gw`
109
+ does not assume. That means `gw use <account>` run inside a linked worktree
110
+ changes the identity for the main checkout and every sibling worktree of
111
+ that repo too, not just the worktree you ran it in. `gw use` detects this
112
+ and prints a warning when you run it inside a linked worktree, but it does
113
+ not block the switch or set up per-worktree config automatically.
114
+
115
+ **The remote-account check is last-write-wins, URL-exact, and cd-triggered
116
+ only.** The `gw-remote-map` registry has no per-clone tracking: running `gw
117
+ use <account>` anywhere for a given remote overwrites what "the right
118
+ account" means for every other clone of that remote — this is intentional,
119
+ not a bug. It also matches on the exact remote URL string, so an SSH clone
120
+ and an HTTPS clone of the same repo are treated as two unrelated remotes.
121
+ And because the check only runs on `cd`, a shell already sitting in a
122
+ mismatched repo when it starts won't warn until you `cd` away and back.
123
+
124
+ ## Commands
125
+
126
+ - `gw account add <name>` — register an account (prompts for git name/email,
127
+ GitHub username; can generate a new SSH key for you)
128
+ - `gw account list` — list registered accounts
129
+ - `gw account remove <name>` — remove a registered account
130
+ - `gw use <name>` — activate an account for the current repo
131
+ - `gw status` / `gw whoami` — show the active account for the current repo
132
+ - `gw init <shell>` — print the shell prompt snippet for `zsh`, `bash`, or
133
+ `fish`; add `--install` (`zsh`/`bash` only) to write and wire it up automatically
134
+
135
+ ## Contributing
136
+
137
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for dev setup and how to run the
138
+ tests. Please follow the [Code of Conduct](CODE_OF_CONDUCT.md). For security
139
+ issues, see [SECURITY.md](SECURITY.md) instead of opening a public issue.
140
+
141
+ ## License
142
+
143
+ [MIT](LICENSE)
gwitch-0.1.0/README.md ADDED
@@ -0,0 +1,119 @@
1
+ # gw
2
+
3
+ [![CI](https://github.com/isamrish/gwitch/actions/workflows/ci.yml/badge.svg)](https://github.com/isamrish/gwitch/actions/workflows/ci.yml)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5
+
6
+ Switch between multiple git/GitHub accounts, per repository, and see which
7
+ account is active right in your shell prompt.
8
+
9
+ ## Install
10
+
11
+ pipx install gwitch
12
+
13
+ Published on PyPI as `gwitch`; installs the `gw` command. Or, from a
14
+ checkout of this repository:
15
+
16
+ pipx install .
17
+
18
+ ## Quick start
19
+
20
+ gw account add personal
21
+ gw account add work
22
+
23
+ cd ~/code/some-repo
24
+ gw use personal
25
+ gw status
26
+
27
+ ## Shell prompt
28
+
29
+ gw init zsh # or bash / fish
30
+
31
+ prints a small shell function, plus a one-line instruction for wiring it
32
+ into your prompt — paste both into your shell config yourself. `gw` never
33
+ edits your shell rc files automatically.
34
+
35
+ gw init zsh --install # or bash
36
+
37
+ `--install` does the wiring for you, for `zsh`/`bash` only (not `fish`
38
+ yet): it writes a `gw-prompt` script to `~/.local/bin/gw-prompt` and a
39
+ `gw-check` script to `~/.local/bin/gw-check` (the cd-triggered account-check
40
+ described below), and appends two marked blocks to your rc file — one per
41
+ script. It's idempotent — safe to re-run. Note for macOS bash users:
42
+ `~/.bashrc` isn't read by login shells (Terminal and iTerm start bash as a
43
+ login shell), so unless you've already wired `~/.bashrc` to be sourced from
44
+ `~/.bash_profile`, you'll need to add that yourself for the installed
45
+ integration to take effect.
46
+
47
+ ## What `gw use <account>` changes
48
+
49
+ - `user.name` / `user.email` — local to the current repo only (`git config --local`)
50
+ - `core.sshCommand` — forces the SSH key registered for that account
51
+ - `gw.account` — a marker read by `gw status` and the shell prompt function
52
+ - `gw-remote-map.<remote URL>.account` — records this repo's remote in **global** git config, for the cd-triggered mismatch check below
53
+
54
+ `gw use` also records this repo's remote-to-account mapping in **global**
55
+ git config (for the cd-triggered mismatch check, see below) — everything
56
+ else stays local-only. None of this touches `~/.ssh/config` or ssh-agent.
57
+
58
+ ## Remote-account mismatch check
59
+
60
+ With `gw init <shell> --install`, a `gw-check` script is wired to run every
61
+ time your shell `cd`s into a different directory. If the repo you land in
62
+ has an `origin` remote that `gw use <account>` has previously recorded, and
63
+ the account currently active in that repo doesn't match, it prints a
64
+ warning to stderr telling you which account to switch to. It never blocks
65
+ or changes anything — it's purely informational.
66
+
67
+ ## Known limitations
68
+
69
+ **`gh` (GitHub CLI) authentication is global, not per-repo.** GitHub CLI's
70
+ authenticated account is global to your machine (`gh` keeps one active user
71
+ per host), not per-repo — that's inherent to how `gh` itself works. `gw use
72
+ <account>` will call `gh auth switch` for you, which changes `gh`'s active
73
+ account machine-wide, even for other repos/terminal tabs, until you `gw use`
74
+ a different account somewhere else. Your git identity and SSH key stay
75
+ correctly isolated per-repo regardless.
76
+
77
+ `gw status` shows both this repo's git identity and gh's currently active
78
+ account as separate lines, so if they've drifted apart it's visible rather
79
+ than silent.
80
+
81
+ **Linked git worktrees share git identity.** `git config --local` in a
82
+ linked worktree (created via `git worktree add`) resolves to the *same*
83
+ shared config file as the main checkout — git only isolates local config
84
+ per-worktree if the repo opts into `extensions.worktreeConfig`, which `gw`
85
+ does not assume. That means `gw use <account>` run inside a linked worktree
86
+ changes the identity for the main checkout and every sibling worktree of
87
+ that repo too, not just the worktree you ran it in. `gw use` detects this
88
+ and prints a warning when you run it inside a linked worktree, but it does
89
+ not block the switch or set up per-worktree config automatically.
90
+
91
+ **The remote-account check is last-write-wins, URL-exact, and cd-triggered
92
+ only.** The `gw-remote-map` registry has no per-clone tracking: running `gw
93
+ use <account>` anywhere for a given remote overwrites what "the right
94
+ account" means for every other clone of that remote — this is intentional,
95
+ not a bug. It also matches on the exact remote URL string, so an SSH clone
96
+ and an HTTPS clone of the same repo are treated as two unrelated remotes.
97
+ And because the check only runs on `cd`, a shell already sitting in a
98
+ mismatched repo when it starts won't warn until you `cd` away and back.
99
+
100
+ ## Commands
101
+
102
+ - `gw account add <name>` — register an account (prompts for git name/email,
103
+ GitHub username; can generate a new SSH key for you)
104
+ - `gw account list` — list registered accounts
105
+ - `gw account remove <name>` — remove a registered account
106
+ - `gw use <name>` — activate an account for the current repo
107
+ - `gw status` / `gw whoami` — show the active account for the current repo
108
+ - `gw init <shell>` — print the shell prompt snippet for `zsh`, `bash`, or
109
+ `fish`; add `--install` (`zsh`/`bash` only) to write and wire it up automatically
110
+
111
+ ## Contributing
112
+
113
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for dev setup and how to run the
114
+ tests. Please follow the [Code of Conduct](CODE_OF_CONDUCT.md). For security
115
+ issues, see [SECURITY.md](SECURITY.md) instead of opening a public issue.
116
+
117
+ ## License
118
+
119
+ [MIT](LICENSE)
@@ -0,0 +1,25 @@
1
+ # Security Policy
2
+
3
+ `gw` manages SSH keys and delegates to GitHub CLI's stored authentication
4
+ tokens. If you find a security issue — anything that could leak, misuse, or
5
+ mismanage a credential — please report it privately rather than opening a
6
+ public issue.
7
+
8
+ ## Reporting a vulnerability
9
+
10
+ Email **askmaurya48@gmail.com** with:
11
+
12
+ - A description of the issue and its potential impact
13
+ - Steps to reproduce, if possible
14
+ - Any relevant version/environment details
15
+
16
+ Please do not open a public GitHub issue for security reports until the
17
+ issue has been addressed.
18
+
19
+ ## Scope
20
+
21
+ `gw` never stores secrets itself — SSH keys are referenced by path only,
22
+ and GitHub tokens are fetched from `gh`'s own storage on demand, never
23
+ persisted by `gw`. Reports about `gw` reading, storing, or transmitting a
24
+ credential in a way that isn't documented in the README's "Known
25
+ limitations" section are especially welcome.