agyswap-cli 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.
@@ -0,0 +1,12 @@
1
+ __pycache__/
2
+ *.py[oc]
3
+ build/
4
+ dist/
5
+ *.egg-info
6
+ .venv
7
+ .claude
8
+ .agents
9
+ graphify-out/*
10
+ !graphify-out/GRAPH_REPORT.md
11
+ !graphify-out/graph.html
12
+ !graphify-out/graph.json
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 rasvanjaya21
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.
@@ -0,0 +1,175 @@
1
+ Metadata-Version: 2.5
2
+ Name: agyswap-cli
3
+ Version: 0.1.0
4
+ Summary: Switch between multiple Antigravity CLI accounts, with a quota dashboard for every account
5
+ Project-URL: Homepage, https://github.com/rasvanjaya21/agyswap
6
+ Project-URL: Repository, https://github.com/rasvanjaya21/agyswap
7
+ Project-URL: Issues, https://github.com/rasvanjaya21/agyswap/issues
8
+ Author-email: rasvanjaya21 <rasvanjaya21@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: account-switcher,agy,antigravity,cli,gemini
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Utilities
22
+ Requires-Python: >=3.12
23
+ Requires-Dist: rich>=15
24
+ Requires-Dist: textual<9,>=8.2.8
25
+ Description-Content-Type: text/markdown
26
+
27
+ <p align="center">
28
+ <a href="#"><img src=".github/assets/banner.webp" width="250"></a>
29
+ </p>
30
+
31
+ <p align="center">
32
+ <strong>Switch between multiple Antigravity CLI accounts, with a quota dashboard for every account.</strong>
33
+ </p>
34
+
35
+ <p align="center">
36
+ <a href="#"><img src="https://img.shields.io/badge/author-rasvanjaya21-white" alt="author-name"></a>
37
+ <a href="#"><img src="https://img.shields.io/badge/version-0.1.0-blue" alt="project-version"></a>
38
+ <a href="https://pypi.org/project/agyswap-cli/"><img src="https://img.shields.io/pypi/v/agyswap-cli?label=pip" alt="pypi-version"></a>
39
+ <a href="https://github.com/rasvanjaya21/agyswap/actions/workflows/ci.yml"><img src="https://github.com/rasvanjaya21/agyswap/actions/workflows/ci.yml/badge.svg" alt="build-status"></a>
40
+ </p>
41
+
42
+ ## Description
43
+
44
+ agyswap switches the Google account used by the Antigravity CLI (`agy`) without signing in again, and shows the quota left on every account. It does not work with the Antigravity IDE, Gemini CLI, or other Google AI products.
45
+
46
+ agy keeps its login in the OS keyring as a single OAuth token. agyswap stores a copy of each account's token, and switching writes another account's copy back to the keyring. The next `agy` you start runs as that account.
47
+
48
+ Inspired by [claude-swap](https://github.com/realiti4/claude-swap).
49
+
50
+ ## Status
51
+
52
+ **Usable on Linux.** Adding accounts, switching between them, the quota list, and the interactive dashboard all work, and switching between two real accounts without signing in again has been verified.
53
+
54
+ Not built yet: automatic switching when an account runs low, parallel sessions with different accounts, aliases, enable/disable, export/import, and macOS/Windows keyrings. `TODO.md` lists every open item.
55
+
56
+ ## Techstacks
57
+
58
+ Python 3.12+ managed with uv. The dashboard uses Textual and Rich; everything else is the standard library, plus `secret-tool` (libsecret) for the keyring.
59
+
60
+ ## Installation
61
+
62
+ ```bash
63
+ $ uv tool install agyswap-cli # or: pipx install agyswap-cli / pip install agyswap-cli
64
+ $ agyswap --help # the command is still agyswap
65
+ ```
66
+
67
+ Until the first release is on PyPI, install from GitHub instead:
68
+
69
+ ```bash
70
+ $ uv tool install git+https://github.com/rasvanjaya21/agyswap
71
+ ```
72
+
73
+ agyswap needs Linux with a Secret Service keyring (GNOME Keyring or KWallet) and `secret-tool` (`dnf install libsecret` or `apt install libsecret-tools`).
74
+
75
+ ## Configuration
76
+
77
+ | Variable | What it does |
78
+ | --- | --- |
79
+ | `AGYSWAP_HOME` | Where agyswap keeps its account store. Defaults to `~/.agyswap`. The store, `accounts.json`, holds refresh tokens and is written with mode `0600`. |
80
+
81
+ ## Usage
82
+
83
+ Unlike Claude Code, agy has no account picker. To add an account, sign out of agy, sign in with that account, then store it:
84
+
85
+ ```bash
86
+ $ agy # /logout, then sign in with account A, then exit
87
+ $ agyswap add
88
+ $ agy # /logout, then sign in with account B, then exit
89
+ $ agyswap add
90
+ ```
91
+
92
+ Signing out of agy does not revoke the token agyswap already stored.
93
+
94
+ Run `agyswap` on its own (or `agyswap tui`) for the dashboard. It shows every account's quota for both model groups (Gemini, and Claude/GPT), each with its 5-hour and weekly window and reset times, and marks the active account. Usage refreshes every 2 minutes.
95
+
96
+ | Key | Action |
97
+ | --- | --- |
98
+ | `enter` / `s` | Switch to the highlighted account |
99
+ | `a` | Add the account agy is signed in with |
100
+ | `d` | Remove the highlighted account |
101
+ | `r` | Refresh usage |
102
+ | `j` / `k` | Move |
103
+ | `q` | Quit |
104
+
105
+ The same actions are available as commands:
106
+
107
+ ```bash
108
+ $ agyswap switch # rotate to the next account
109
+ $ agyswap switch 2 # by slot
110
+ $ agyswap switch user@gmail.com # by email
111
+ $ agyswap list # quota of every account
112
+ $ agyswap status
113
+ $ agyswap remove 2 # asks first; add --yes (-y) in scripts
114
+ ```
115
+
116
+ Exit agy before you switch. A running agy reads the keyring only when it starts and saves its own token back every hour, which would undo the switch. `agyswap switch` refuses while agy is running; `--ignore-running` overrides that. `--force` switches without first copying the live login's token back into its slot.
117
+
118
+ ## Development
119
+
120
+ ```bash
121
+ $ git clone https://github.com/rasvanjaya21/agyswap && cd agyswap
122
+ $ uv sync # creates .venv with agyswap installed in editable mode
123
+ $ uv run agyswap
124
+ ```
125
+
126
+ For a manual run against your real agy login, use a throwaway store and shred it afterwards:
127
+
128
+ ```bash
129
+ $ export AGYSWAP_HOME=$(mktemp -d)
130
+ $ uv run agyswap add && uv run agyswap list
131
+ $ shred -u "$AGYSWAP_HOME/accounts.json"
132
+ ```
133
+
134
+ ## Testing
135
+
136
+ ```bash
137
+ $ uv run ruff format . # formatter
138
+ $ uv run ruff check . # linter
139
+ $ uv run pytest -q # tests
140
+ $ uv build # wheel and sdist into dist/
141
+ ```
142
+
143
+ Tests never touch the real keyring, the network, or `~/.agyswap/`. The keyring, the store, and every Google request are faked.
144
+
145
+ ## Deployment
146
+
147
+ Releases are published to PyPI by `.github/workflows/publish.yml` when a `v*` tag is pushed. The version lives only in `pyproject.toml`.
148
+
149
+ ```bash
150
+ $ uv version --bump patch
151
+ $ uv lock
152
+ $ git commit -am "chore: release v$(uv version --short)"
153
+ $ git push # wait for CI to pass
154
+ $ git tag "v$(uv version --short)" && git push origin "v$(uv version --short)"
155
+ ```
156
+
157
+ A published version cannot be replaced. To roll back, yank it on PyPI and release a patch. The one-time PyPI and GitHub setup is in `CONTRIBUTING.md`.
158
+
159
+ ## Architecture
160
+
161
+ Design decisions and the reasoning behind them live in `architecture/`, one file per workflow that produced it. `OBSERVE.md` maps how agy stores its login and reports quota, with the evidence for each fact; `SPEC.md` specifies the current version; `PLAN.md` lays out the next tasks; `REVIEW.md` holds the latest code review.
162
+
163
+ `AGENTS.md` holds the conventions and the development cycle, and is the single channel shared by every agent working here. `TODO.md` holds open findings and is deleted entry by entry as they are resolved.
164
+
165
+ ## Credit
166
+
167
+ - id: agyswap
168
+ - displayName: agyswap - Antigravity CLI Accounts Swap
169
+ - authorName: rasvanjaya21
170
+ - authorEmail: rasvanjaya21@gmail.com
171
+ - authorURL: https://github.com/rasvanjaya21
172
+
173
+ ## Member
174
+
175
+ - @rasvanjaya21 [assigned]
@@ -0,0 +1,149 @@
1
+ <p align="center">
2
+ <a href="#"><img src=".github/assets/banner.webp" width="250"></a>
3
+ </p>
4
+
5
+ <p align="center">
6
+ <strong>Switch between multiple Antigravity CLI accounts, with a quota dashboard for every account.</strong>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <a href="#"><img src="https://img.shields.io/badge/author-rasvanjaya21-white" alt="author-name"></a>
11
+ <a href="#"><img src="https://img.shields.io/badge/version-0.1.0-blue" alt="project-version"></a>
12
+ <a href="https://pypi.org/project/agyswap-cli/"><img src="https://img.shields.io/pypi/v/agyswap-cli?label=pip" alt="pypi-version"></a>
13
+ <a href="https://github.com/rasvanjaya21/agyswap/actions/workflows/ci.yml"><img src="https://github.com/rasvanjaya21/agyswap/actions/workflows/ci.yml/badge.svg" alt="build-status"></a>
14
+ </p>
15
+
16
+ ## Description
17
+
18
+ agyswap switches the Google account used by the Antigravity CLI (`agy`) without signing in again, and shows the quota left on every account. It does not work with the Antigravity IDE, Gemini CLI, or other Google AI products.
19
+
20
+ agy keeps its login in the OS keyring as a single OAuth token. agyswap stores a copy of each account's token, and switching writes another account's copy back to the keyring. The next `agy` you start runs as that account.
21
+
22
+ Inspired by [claude-swap](https://github.com/realiti4/claude-swap).
23
+
24
+ ## Status
25
+
26
+ **Usable on Linux.** Adding accounts, switching between them, the quota list, and the interactive dashboard all work, and switching between two real accounts without signing in again has been verified.
27
+
28
+ Not built yet: automatic switching when an account runs low, parallel sessions with different accounts, aliases, enable/disable, export/import, and macOS/Windows keyrings. `TODO.md` lists every open item.
29
+
30
+ ## Techstacks
31
+
32
+ Python 3.12+ managed with uv. The dashboard uses Textual and Rich; everything else is the standard library, plus `secret-tool` (libsecret) for the keyring.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ $ uv tool install agyswap-cli # or: pipx install agyswap-cli / pip install agyswap-cli
38
+ $ agyswap --help # the command is still agyswap
39
+ ```
40
+
41
+ Until the first release is on PyPI, install from GitHub instead:
42
+
43
+ ```bash
44
+ $ uv tool install git+https://github.com/rasvanjaya21/agyswap
45
+ ```
46
+
47
+ agyswap needs Linux with a Secret Service keyring (GNOME Keyring or KWallet) and `secret-tool` (`dnf install libsecret` or `apt install libsecret-tools`).
48
+
49
+ ## Configuration
50
+
51
+ | Variable | What it does |
52
+ | --- | --- |
53
+ | `AGYSWAP_HOME` | Where agyswap keeps its account store. Defaults to `~/.agyswap`. The store, `accounts.json`, holds refresh tokens and is written with mode `0600`. |
54
+
55
+ ## Usage
56
+
57
+ Unlike Claude Code, agy has no account picker. To add an account, sign out of agy, sign in with that account, then store it:
58
+
59
+ ```bash
60
+ $ agy # /logout, then sign in with account A, then exit
61
+ $ agyswap add
62
+ $ agy # /logout, then sign in with account B, then exit
63
+ $ agyswap add
64
+ ```
65
+
66
+ Signing out of agy does not revoke the token agyswap already stored.
67
+
68
+ Run `agyswap` on its own (or `agyswap tui`) for the dashboard. It shows every account's quota for both model groups (Gemini, and Claude/GPT), each with its 5-hour and weekly window and reset times, and marks the active account. Usage refreshes every 2 minutes.
69
+
70
+ | Key | Action |
71
+ | --- | --- |
72
+ | `enter` / `s` | Switch to the highlighted account |
73
+ | `a` | Add the account agy is signed in with |
74
+ | `d` | Remove the highlighted account |
75
+ | `r` | Refresh usage |
76
+ | `j` / `k` | Move |
77
+ | `q` | Quit |
78
+
79
+ The same actions are available as commands:
80
+
81
+ ```bash
82
+ $ agyswap switch # rotate to the next account
83
+ $ agyswap switch 2 # by slot
84
+ $ agyswap switch user@gmail.com # by email
85
+ $ agyswap list # quota of every account
86
+ $ agyswap status
87
+ $ agyswap remove 2 # asks first; add --yes (-y) in scripts
88
+ ```
89
+
90
+ Exit agy before you switch. A running agy reads the keyring only when it starts and saves its own token back every hour, which would undo the switch. `agyswap switch` refuses while agy is running; `--ignore-running` overrides that. `--force` switches without first copying the live login's token back into its slot.
91
+
92
+ ## Development
93
+
94
+ ```bash
95
+ $ git clone https://github.com/rasvanjaya21/agyswap && cd agyswap
96
+ $ uv sync # creates .venv with agyswap installed in editable mode
97
+ $ uv run agyswap
98
+ ```
99
+
100
+ For a manual run against your real agy login, use a throwaway store and shred it afterwards:
101
+
102
+ ```bash
103
+ $ export AGYSWAP_HOME=$(mktemp -d)
104
+ $ uv run agyswap add && uv run agyswap list
105
+ $ shred -u "$AGYSWAP_HOME/accounts.json"
106
+ ```
107
+
108
+ ## Testing
109
+
110
+ ```bash
111
+ $ uv run ruff format . # formatter
112
+ $ uv run ruff check . # linter
113
+ $ uv run pytest -q # tests
114
+ $ uv build # wheel and sdist into dist/
115
+ ```
116
+
117
+ Tests never touch the real keyring, the network, or `~/.agyswap/`. The keyring, the store, and every Google request are faked.
118
+
119
+ ## Deployment
120
+
121
+ Releases are published to PyPI by `.github/workflows/publish.yml` when a `v*` tag is pushed. The version lives only in `pyproject.toml`.
122
+
123
+ ```bash
124
+ $ uv version --bump patch
125
+ $ uv lock
126
+ $ git commit -am "chore: release v$(uv version --short)"
127
+ $ git push # wait for CI to pass
128
+ $ git tag "v$(uv version --short)" && git push origin "v$(uv version --short)"
129
+ ```
130
+
131
+ A published version cannot be replaced. To roll back, yank it on PyPI and release a patch. The one-time PyPI and GitHub setup is in `CONTRIBUTING.md`.
132
+
133
+ ## Architecture
134
+
135
+ Design decisions and the reasoning behind them live in `architecture/`, one file per workflow that produced it. `OBSERVE.md` maps how agy stores its login and reports quota, with the evidence for each fact; `SPEC.md` specifies the current version; `PLAN.md` lays out the next tasks; `REVIEW.md` holds the latest code review.
136
+
137
+ `AGENTS.md` holds the conventions and the development cycle, and is the single channel shared by every agent working here. `TODO.md` holds open findings and is deleted entry by entry as they are resolved.
138
+
139
+ ## Credit
140
+
141
+ - id: agyswap
142
+ - displayName: agyswap - Antigravity CLI Accounts Swap
143
+ - authorName: rasvanjaya21
144
+ - authorEmail: rasvanjaya21@gmail.com
145
+ - authorURL: https://github.com/rasvanjaya21
146
+
147
+ ## Member
148
+
149
+ - @rasvanjaya21 [assigned]
@@ -0,0 +1,62 @@
1
+ [project]
2
+ name = "agyswap-cli"
3
+ version = "0.1.0"
4
+ description = "Switch between multiple Antigravity CLI accounts, with a quota dashboard for every account"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = [
8
+ "rich>=15",
9
+ "textual>=8.2.8,<9",
10
+ ]
11
+ authors = [{name = "rasvanjaya21", email = "rasvanjaya21@gmail.com"}]
12
+ license = {text = "MIT"}
13
+ keywords = ["antigravity", "agy", "gemini", "account-switcher", "cli"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Environment :: Console",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Operating System :: POSIX :: Linux",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ "Programming Language :: Python :: 3.14",
24
+ "Topic :: Utilities",
25
+ ]
26
+
27
+ [project.urls]
28
+ Homepage = "https://github.com/rasvanjaya21/agyswap"
29
+ Repository = "https://github.com/rasvanjaya21/agyswap"
30
+ Issues = "https://github.com/rasvanjaya21/agyswap/issues"
31
+
32
+ [project.scripts]
33
+ agyswap = "agyswap.cli:main"
34
+
35
+ [build-system]
36
+ requires = ["hatchling"]
37
+ build-backend = "hatchling.build"
38
+
39
+ [tool.hatch.build.targets.wheel]
40
+ packages = ["src/agyswap"]
41
+
42
+ [tool.hatch.build.targets.sdist]
43
+ include = ["src/agyswap", "tests", "README.md", "LICENSE", "pyproject.toml", "uv.lock"]
44
+
45
+ [dependency-groups]
46
+ dev = [
47
+ "pytest>=9.1.1",
48
+ "ruff>=0.16.10",
49
+ ]
50
+
51
+ [tool.pytest.ini_options]
52
+ testpaths = ["tests"]
53
+ pythonpath = ["src"]
54
+
55
+ [tool.ruff]
56
+ line-length = 120
57
+ target-version = "py312"
58
+ # Generated or vendored: docs/ (scripts/docs.py), skills/ (scripts/skills.py), graphify-out/.
59
+ extend-exclude = ["docs", "skills", "graphify-out"]
60
+
61
+ [tool.ruff.lint]
62
+ select = ["E", "F", "W", "I", "UP", "B"]
@@ -0,0 +1,6 @@
1
+ from importlib.metadata import PackageNotFoundError, version
2
+
3
+ try:
4
+ __version__ = version("agyswap-cli")
5
+ except PackageNotFoundError:
6
+ __version__ = "0.0.0"
@@ -0,0 +1,5 @@
1
+ import sys
2
+
3
+ from agyswap.cli import main
4
+
5
+ sys.exit(main())