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.
- gwitch-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +17 -0
- gwitch-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +11 -0
- gwitch-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +8 -0
- gwitch-0.1.0/.github/workflows/ci.yml +34 -0
- gwitch-0.1.0/.github/workflows/publish.yml +40 -0
- gwitch-0.1.0/.gitignore +10 -0
- gwitch-0.1.0/CHANGELOG.md +36 -0
- gwitch-0.1.0/CODE_OF_CONDUCT.md +63 -0
- gwitch-0.1.0/CONTRIBUTING.md +45 -0
- gwitch-0.1.0/LICENSE +21 -0
- gwitch-0.1.0/PKG-INFO +143 -0
- gwitch-0.1.0/README.md +119 -0
- gwitch-0.1.0/SECURITY.md +25 -0
- gwitch-0.1.0/docs/specs/2026-08-29-gitsw-design.md +159 -0
- gwitch-0.1.0/docs/specs/2026-08-29-gw-https-support-design.md +162 -0
- gwitch-0.1.0/docs/specs/2026-08-29-gw-prompt-install-design.md +182 -0
- gwitch-0.1.0/docs/specs/2026-08-29-gw-remote-account-check-design.md +115 -0
- gwitch-0.1.0/pyproject.toml +42 -0
- gwitch-0.1.0/src/gw/__init__.py +0 -0
- gwitch-0.1.0/src/gw/cli.py +30 -0
- gwitch-0.1.0/src/gw/commands/__init__.py +0 -0
- gwitch-0.1.0/src/gw/commands/account.py +111 -0
- gwitch-0.1.0/src/gw/commands/credential_helper.py +49 -0
- gwitch-0.1.0/src/gw/commands/init_cmd.py +108 -0
- gwitch-0.1.0/src/gw/commands/status.py +55 -0
- gwitch-0.1.0/src/gw/commands/use.py +82 -0
- gwitch-0.1.0/src/gw/config.py +78 -0
- gwitch-0.1.0/src/gw/gh_ops.py +50 -0
- gwitch-0.1.0/src/gw/git_ops.py +138 -0
- gwitch-0.1.0/src/gw/prompt_install.py +95 -0
- gwitch-0.1.0/src/gw/remote_check_install.py +87 -0
- gwitch-0.1.0/src/gw/ssh_ops.py +38 -0
- gwitch-0.1.0/tests/test_account_command.py +165 -0
- gwitch-0.1.0/tests/test_cli_smoke.py +11 -0
- gwitch-0.1.0/tests/test_config.py +136 -0
- gwitch-0.1.0/tests/test_credential_helper_command.py +138 -0
- gwitch-0.1.0/tests/test_gh_ops.py +90 -0
- gwitch-0.1.0/tests/test_git_ops.py +261 -0
- gwitch-0.1.0/tests/test_init_command.py +170 -0
- gwitch-0.1.0/tests/test_prompt_install.py +218 -0
- gwitch-0.1.0/tests/test_remote_check_install.py +302 -0
- gwitch-0.1.0/tests/test_ssh_ops.py +65 -0
- gwitch-0.1.0/tests/test_status_command.py +174 -0
- 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,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
|
gwitch-0.1.0/.gitignore
ADDED
|
@@ -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
|
+
[](https://github.com/isamrish/gwitch/actions/workflows/ci.yml)
|
|
28
|
+
[](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
|
+
[](https://github.com/isamrish/gwitch/actions/workflows/ci.yml)
|
|
4
|
+
[](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)
|
gwitch-0.1.0/SECURITY.md
ADDED
|
@@ -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.
|