agent-toggle 0.16.2__tar.gz → 0.17.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.
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/PKG-INFO +15 -9
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/README.md +14 -8
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/__init__.py +1 -1
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/backends/flag_json.py +1 -1
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/backends/plugin_cli.py +1 -1
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/cli.py +1 -1
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/cost.py +1 -1
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/doctor.py +2 -1
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/harnesses.py +1 -1
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/ui/config_menu.py +1 -1
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/ui/picker.py +1 -1
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/update_prompt.py +7 -4
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle.egg-info/PKG-INFO +15 -9
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle.egg-info/SOURCES.txt +1 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/pyproject.toml +5 -1
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_backends.py +1 -1
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_cli.py +1 -1
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_cost.py +2 -1
- agent_toggle-0.17.0/tests/test_mod_version.py +20 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_picker.py +2 -2
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_update_prompt.py +12 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/LICENSE +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/__main__.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/backends/__init__.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/backends/mcp_json.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/backends/mcp_toml.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/companions.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/completions.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/config.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/fs.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/help.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/i18n.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/locales/__init__.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/locales/zh_tw_cli.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/locales/zh_tw_common.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/locales/zh_tw_config.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/locales/zh_tw_picker.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/mechanisms.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/ops.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/output.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/profiles.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/settings.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/shims/claude.md.tmpl +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/shims/generic.md.tmpl +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/spinner.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/store.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/toml_check.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/ui/__init__.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/ui/logo.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/ui/menu.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/ui/model.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/ui/theme.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/undo.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle/update_check.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle.egg-info/dependency_links.txt +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle.egg-info/entry_points.txt +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle.egg-info/requires.txt +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/agent_toggle.egg-info/top_level.txt +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/setup.cfg +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_alias.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_all_type.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_cli_surface.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_color.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_companions.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_completions.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_config.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_config_menu.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_conformance.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_containment.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_crash.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_doctor.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_encoding.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_fs.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_harnesses.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_help.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_i18n.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_install.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_logo.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_mechanisms.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_menu.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_mods.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_platform.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_profiles.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_project.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_safety.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_same_name.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_secret_audit.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_settings.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_store.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_theme.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_undo.py +0 -0
- {agent_toggle-0.16.2 → agent_toggle-0.17.0}/tests/test_update_check.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-toggle
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.0
|
|
4
4
|
Summary: Temporarily disable / re-enable AI-agent skills, agents, commands, rules, plugins and MCP servers across harnesses (Claude Code, Codex, Grok, OpenCode, OpenClaw, Copilot, Vibe, Devin, Antigravity)
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/weskao/agent-toggle
|
|
@@ -168,6 +168,9 @@ installs above, type this at the prompt of a Claude Code terminal session (2.1.2
|
|
|
168
168
|
```
|
|
169
169
|
|
|
170
170
|
Answer `y` to add the marketplace, pick a scope (user is the default), then run `/agent-toggle`.
|
|
171
|
+
The same mod is also listed in the `weskao-agent-plugins` marketplace
|
|
172
|
+
(`claude plugin marketplace add weskao/weskao-agent-plugins`, then
|
|
173
|
+
`claude plugin install agent-toggle@weskao-agent-plugins`); install it from one of the two, not both.
|
|
171
174
|
|
|
172
175
|
See [Claude Code pane mod](#claude-code-pane-mod).
|
|
173
176
|
|
|
@@ -260,7 +263,7 @@ Flags accepted by every command, before or after the subcommand:
|
|
|
260
263
|
|
|
261
264
|
Extra row fields: `list` rows carry `at`, `mechanism`, `companions`; `cost` rows
|
|
262
265
|
carry `enabled`, `tokens`, `would_save`, `chars`, and the final `total` row
|
|
263
|
-
carries `total_tokens`, `saved_tokens`, `formula`. Rows for a
|
|
266
|
+
carries `total_tokens`, `saved_tokens`, `formula`, `version`. Rows for a
|
|
264
267
|
directory shared with another harness (see below) carry `shared_with`, the other
|
|
265
268
|
harnesses that read it: `disable` / `enable` rows relative to the harness you
|
|
266
269
|
asked, plus `owner`, the harness whose park dir and state entry hold the item;
|
|
@@ -527,9 +530,9 @@ tag (`git ls-remote --tags`) and always installs that tag with
|
|
|
527
530
|
`uv tool install --force --no-sources git+<repo>@<tag>` (`pipx install --force` for a pipx install).
|
|
528
531
|
A dev checkout, a branch or commit install, or an unmanaged install is replaced by the tag too
|
|
529
532
|
(with uv, else pipx); only an install made from exactly that tag is already up to date.
|
|
530
|
-
It then runs, with the new binary and in order: when the Claude Code plugin is installed
|
|
531
|
-
`claude plugin marketplace update
|
|
532
|
-
then `agent-toggle install-shims`. A failing step prints a warning and makes the exit code `1`.
|
|
533
|
+
It then runs, with the new binary and in order: when the Claude Code plugin is installed (from any
|
|
534
|
+
marketplace), `claude plugin marketplace update <marketplace>` and
|
|
535
|
+
`claude plugin update agent-toggle@<marketplace>`, then `agent-toggle install-shims`. A failing step prints a warning and makes the exit code `1`.
|
|
533
536
|
It never prompts and writes to stderr only.
|
|
534
537
|
|
|
535
538
|
| Exit | Meaning |
|
|
@@ -1011,8 +1014,9 @@ CLI (`cost --json`, `disable|enable --json`) and works for the claude harness on
|
|
|
1011
1014
|
`agent-toggle ui` stays the cross-harness UI.
|
|
1012
1015
|
|
|
1013
1016
|
Install it with `/plugin install agent-toggle --marketplace weskao/agent-toggle` (see
|
|
1014
|
-
[Install](#install));
|
|
1015
|
-
|
|
1017
|
+
[Install](#install)); `/agent-toggle update` picks up a new release: it runs `agent-toggle update`,
|
|
1018
|
+
which updates the CLI, this mod and the shims together (restart Claude Code to load the new mod).
|
|
1019
|
+
The mod and the CLI share one version. To run your own checkout instead (edits reload as you save):
|
|
1016
1020
|
|
|
1017
1021
|
```sh
|
|
1018
1022
|
claude --plugin-dir ./mod # then run /agent-toggle inside Claude
|
|
@@ -1144,8 +1148,10 @@ prints a `::notice::` and exits 0, so it never adds a second red X.
|
|
|
1144
1148
|
## Releasing
|
|
1145
1149
|
|
|
1146
1150
|
A release is a git tag `vX.Y.Z` (where `X.Y.Z` must match `agent_toggle.__version__`).
|
|
1147
|
-
|
|
1148
|
-
|
|
1151
|
+
`version` in `mod/.claude-plugin/plugin.json` must be the same value (the mod ships in lockstep;
|
|
1152
|
+
without the bump `claude plugin update` does not hand marketplace installs the new mod).
|
|
1153
|
+
`tests/test_mod_version.py` and the release workflow both fail on a mismatch.
|
|
1154
|
+
The `weskao-agent-plugins` marketplace lists the mod without a version, so it needs no bump there.
|
|
1149
1155
|
Pushing the tag triggers `.github/workflows/release.yml`:
|
|
1150
1156
|
|
|
1151
1157
|
1. **Build** job checks that the tag matches `__version__`, builds a wheel and
|
|
@@ -134,6 +134,9 @@ installs above, type this at the prompt of a Claude Code terminal session (2.1.2
|
|
|
134
134
|
```
|
|
135
135
|
|
|
136
136
|
Answer `y` to add the marketplace, pick a scope (user is the default), then run `/agent-toggle`.
|
|
137
|
+
The same mod is also listed in the `weskao-agent-plugins` marketplace
|
|
138
|
+
(`claude plugin marketplace add weskao/weskao-agent-plugins`, then
|
|
139
|
+
`claude plugin install agent-toggle@weskao-agent-plugins`); install it from one of the two, not both.
|
|
137
140
|
|
|
138
141
|
See [Claude Code pane mod](#claude-code-pane-mod).
|
|
139
142
|
|
|
@@ -226,7 +229,7 @@ Flags accepted by every command, before or after the subcommand:
|
|
|
226
229
|
|
|
227
230
|
Extra row fields: `list` rows carry `at`, `mechanism`, `companions`; `cost` rows
|
|
228
231
|
carry `enabled`, `tokens`, `would_save`, `chars`, and the final `total` row
|
|
229
|
-
carries `total_tokens`, `saved_tokens`, `formula`. Rows for a
|
|
232
|
+
carries `total_tokens`, `saved_tokens`, `formula`, `version`. Rows for a
|
|
230
233
|
directory shared with another harness (see below) carry `shared_with`, the other
|
|
231
234
|
harnesses that read it: `disable` / `enable` rows relative to the harness you
|
|
232
235
|
asked, plus `owner`, the harness whose park dir and state entry hold the item;
|
|
@@ -493,9 +496,9 @@ tag (`git ls-remote --tags`) and always installs that tag with
|
|
|
493
496
|
`uv tool install --force --no-sources git+<repo>@<tag>` (`pipx install --force` for a pipx install).
|
|
494
497
|
A dev checkout, a branch or commit install, or an unmanaged install is replaced by the tag too
|
|
495
498
|
(with uv, else pipx); only an install made from exactly that tag is already up to date.
|
|
496
|
-
It then runs, with the new binary and in order: when the Claude Code plugin is installed
|
|
497
|
-
`claude plugin marketplace update
|
|
498
|
-
then `agent-toggle install-shims`. A failing step prints a warning and makes the exit code `1`.
|
|
499
|
+
It then runs, with the new binary and in order: when the Claude Code plugin is installed (from any
|
|
500
|
+
marketplace), `claude plugin marketplace update <marketplace>` and
|
|
501
|
+
`claude plugin update agent-toggle@<marketplace>`, then `agent-toggle install-shims`. A failing step prints a warning and makes the exit code `1`.
|
|
499
502
|
It never prompts and writes to stderr only.
|
|
500
503
|
|
|
501
504
|
| Exit | Meaning |
|
|
@@ -977,8 +980,9 @@ CLI (`cost --json`, `disable|enable --json`) and works for the claude harness on
|
|
|
977
980
|
`agent-toggle ui` stays the cross-harness UI.
|
|
978
981
|
|
|
979
982
|
Install it with `/plugin install agent-toggle --marketplace weskao/agent-toggle` (see
|
|
980
|
-
[Install](#install));
|
|
981
|
-
|
|
983
|
+
[Install](#install)); `/agent-toggle update` picks up a new release: it runs `agent-toggle update`,
|
|
984
|
+
which updates the CLI, this mod and the shims together (restart Claude Code to load the new mod).
|
|
985
|
+
The mod and the CLI share one version. To run your own checkout instead (edits reload as you save):
|
|
982
986
|
|
|
983
987
|
```sh
|
|
984
988
|
claude --plugin-dir ./mod # then run /agent-toggle inside Claude
|
|
@@ -1110,8 +1114,10 @@ prints a `::notice::` and exits 0, so it never adds a second red X.
|
|
|
1110
1114
|
## Releasing
|
|
1111
1115
|
|
|
1112
1116
|
A release is a git tag `vX.Y.Z` (where `X.Y.Z` must match `agent_toggle.__version__`).
|
|
1113
|
-
|
|
1114
|
-
|
|
1117
|
+
`version` in `mod/.claude-plugin/plugin.json` must be the same value (the mod ships in lockstep;
|
|
1118
|
+
without the bump `claude plugin update` does not hand marketplace installs the new mod).
|
|
1119
|
+
`tests/test_mod_version.py` and the release workflow both fail on a mismatch.
|
|
1120
|
+
The `weskao-agent-plugins` marketplace lists the mod without a version, so it needs no bump there.
|
|
1115
1121
|
Pushing the tag triggers `.github/workflows/release.yml`:
|
|
1116
1122
|
|
|
1117
1123
|
1. **Build** job checks that the tag matches `__version__`, builds a wheel and
|
|
@@ -298,7 +298,7 @@ def cmd_cost(state: dict, out: Result, harness: str | None = None,
|
|
|
298
298
|
if len(shown) > len(items):
|
|
299
299
|
_say_hidden(out, f"{len(shown) - len(items)} hidden by settings (agent-toggle config)")
|
|
300
300
|
out.row(harness, type_, None, "cost", "ok", "total", show=False, items=len(items),
|
|
301
|
-
total_tokens=live, saved_tokens=saved, formula=cost.FORMULA,
|
|
301
|
+
total_tokens=live, saved_tokens=saved, formula=cost.FORMULA, version=__version__,
|
|
302
302
|
**({"project": str(proj)} if proj else {}))
|
|
303
303
|
|
|
304
304
|
|
|
@@ -26,10 +26,10 @@ from __future__ import annotations
|
|
|
26
26
|
import json
|
|
27
27
|
import re
|
|
28
28
|
from collections import Counter
|
|
29
|
+
from collections.abc import Callable
|
|
29
30
|
from concurrent.futures import ThreadPoolExecutor
|
|
30
31
|
from dataclasses import dataclass
|
|
31
32
|
from pathlib import Path
|
|
32
|
-
from typing import Callable
|
|
33
33
|
|
|
34
34
|
from . import fs
|
|
35
35
|
from .backends.flag_json import jsonc_loads
|
|
@@ -15,8 +15,9 @@ import filecmp
|
|
|
15
15
|
import json
|
|
16
16
|
import os
|
|
17
17
|
import shutil
|
|
18
|
+
from collections.abc import Callable
|
|
18
19
|
from pathlib import Path
|
|
19
|
-
from typing import
|
|
20
|
+
from typing import NamedTuple
|
|
20
21
|
|
|
21
22
|
from . import fs, ops, store
|
|
22
23
|
from .backends.flag_json import jsonc_loads
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
4
|
import os
|
|
5
|
+
from collections.abc import Mapping
|
|
5
6
|
from dataclasses import dataclass, field
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
from types import MappingProxyType
|
|
8
|
-
from typing import Mapping
|
|
9
9
|
|
|
10
10
|
from . import fs
|
|
11
11
|
from .backends import flag_json
|
|
@@ -17,8 +17,8 @@ import contextlib
|
|
|
17
17
|
import io
|
|
18
18
|
import sys
|
|
19
19
|
import time
|
|
20
|
+
from collections.abc import Callable
|
|
20
21
|
from dataclasses import dataclass
|
|
21
|
-
from typing import Callable
|
|
22
22
|
|
|
23
23
|
from .. import __version__, config, doctor, fs, harnesses, i18n, settings, undo
|
|
24
24
|
from ..i18n import t
|
|
@@ -498,7 +498,7 @@ def ask_save(win, v: View, pal: theme.Palette, g: theme.Glyphs,
|
|
|
498
498
|
top = min(top, max(0, len(changed) - max(1, page)))
|
|
499
499
|
row_y = y0 + (2 if bh >= 7 else 1)
|
|
500
500
|
|
|
501
|
-
def put(y, segments):
|
|
501
|
+
def put(y, segments, x0=x0, inner=inner):
|
|
502
502
|
theme.draw_segments(win, y, x0, [(g.v, "accent"),
|
|
503
503
|
*clip(segments, inner, g.ellipsis), (g.v, "accent")], pal)
|
|
504
504
|
|
|
@@ -29,7 +29,6 @@ from .ui import theme
|
|
|
29
29
|
|
|
30
30
|
DIST = "agent-toggle"
|
|
31
31
|
REPO = update_check.REPO
|
|
32
|
-
PLUGIN = "agent-toggle@agent-toggle"
|
|
33
32
|
UPDATE = [DIST, "update"]
|
|
34
33
|
RELEASE_NOTES = "https://github.com/weskao/agent-toggle/releases/tag/v%s"
|
|
35
34
|
ANSWERS = (update_check.UPDATE_NOW, update_check.SKIP, update_check.SKIP_VERSION)
|
|
@@ -48,9 +47,13 @@ def after_steps() -> list[list[str]]:
|
|
|
48
47
|
installed, then the shims."""
|
|
49
48
|
steps: list[list[str]] = []
|
|
50
49
|
# bare "claude": what a person pastes; _run() resolves it, as claude is often off PATH
|
|
51
|
-
if plugin_cli.claude_bin()
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
if plugin_cli.claude_bin():
|
|
51
|
+
# any marketplace the mod came from; one id lists once per scope
|
|
52
|
+
installed = sorted({p["id"] for p in plugin_cli.list_plugins(lambda _msg: None)
|
|
53
|
+
if p["id"].partition("@")[0] == DIST})
|
|
54
|
+
for pid in installed:
|
|
55
|
+
steps += [["claude", "plugin", "marketplace", "update", pid.partition("@")[2]],
|
|
56
|
+
["claude", "plugin", "update", pid]]
|
|
54
57
|
return [*steps, [DIST, "install-shims"]]
|
|
55
58
|
|
|
56
59
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-toggle
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.0
|
|
4
4
|
Summary: Temporarily disable / re-enable AI-agent skills, agents, commands, rules, plugins and MCP servers across harnesses (Claude Code, Codex, Grok, OpenCode, OpenClaw, Copilot, Vibe, Devin, Antigravity)
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/weskao/agent-toggle
|
|
@@ -168,6 +168,9 @@ installs above, type this at the prompt of a Claude Code terminal session (2.1.2
|
|
|
168
168
|
```
|
|
169
169
|
|
|
170
170
|
Answer `y` to add the marketplace, pick a scope (user is the default), then run `/agent-toggle`.
|
|
171
|
+
The same mod is also listed in the `weskao-agent-plugins` marketplace
|
|
172
|
+
(`claude plugin marketplace add weskao/weskao-agent-plugins`, then
|
|
173
|
+
`claude plugin install agent-toggle@weskao-agent-plugins`); install it from one of the two, not both.
|
|
171
174
|
|
|
172
175
|
See [Claude Code pane mod](#claude-code-pane-mod).
|
|
173
176
|
|
|
@@ -260,7 +263,7 @@ Flags accepted by every command, before or after the subcommand:
|
|
|
260
263
|
|
|
261
264
|
Extra row fields: `list` rows carry `at`, `mechanism`, `companions`; `cost` rows
|
|
262
265
|
carry `enabled`, `tokens`, `would_save`, `chars`, and the final `total` row
|
|
263
|
-
carries `total_tokens`, `saved_tokens`, `formula`. Rows for a
|
|
266
|
+
carries `total_tokens`, `saved_tokens`, `formula`, `version`. Rows for a
|
|
264
267
|
directory shared with another harness (see below) carry `shared_with`, the other
|
|
265
268
|
harnesses that read it: `disable` / `enable` rows relative to the harness you
|
|
266
269
|
asked, plus `owner`, the harness whose park dir and state entry hold the item;
|
|
@@ -527,9 +530,9 @@ tag (`git ls-remote --tags`) and always installs that tag with
|
|
|
527
530
|
`uv tool install --force --no-sources git+<repo>@<tag>` (`pipx install --force` for a pipx install).
|
|
528
531
|
A dev checkout, a branch or commit install, or an unmanaged install is replaced by the tag too
|
|
529
532
|
(with uv, else pipx); only an install made from exactly that tag is already up to date.
|
|
530
|
-
It then runs, with the new binary and in order: when the Claude Code plugin is installed
|
|
531
|
-
`claude plugin marketplace update
|
|
532
|
-
then `agent-toggle install-shims`. A failing step prints a warning and makes the exit code `1`.
|
|
533
|
+
It then runs, with the new binary and in order: when the Claude Code plugin is installed (from any
|
|
534
|
+
marketplace), `claude plugin marketplace update <marketplace>` and
|
|
535
|
+
`claude plugin update agent-toggle@<marketplace>`, then `agent-toggle install-shims`. A failing step prints a warning and makes the exit code `1`.
|
|
533
536
|
It never prompts and writes to stderr only.
|
|
534
537
|
|
|
535
538
|
| Exit | Meaning |
|
|
@@ -1011,8 +1014,9 @@ CLI (`cost --json`, `disable|enable --json`) and works for the claude harness on
|
|
|
1011
1014
|
`agent-toggle ui` stays the cross-harness UI.
|
|
1012
1015
|
|
|
1013
1016
|
Install it with `/plugin install agent-toggle --marketplace weskao/agent-toggle` (see
|
|
1014
|
-
[Install](#install));
|
|
1015
|
-
|
|
1017
|
+
[Install](#install)); `/agent-toggle update` picks up a new release: it runs `agent-toggle update`,
|
|
1018
|
+
which updates the CLI, this mod and the shims together (restart Claude Code to load the new mod).
|
|
1019
|
+
The mod and the CLI share one version. To run your own checkout instead (edits reload as you save):
|
|
1016
1020
|
|
|
1017
1021
|
```sh
|
|
1018
1022
|
claude --plugin-dir ./mod # then run /agent-toggle inside Claude
|
|
@@ -1144,8 +1148,10 @@ prints a `::notice::` and exits 0, so it never adds a second red X.
|
|
|
1144
1148
|
## Releasing
|
|
1145
1149
|
|
|
1146
1150
|
A release is a git tag `vX.Y.Z` (where `X.Y.Z` must match `agent_toggle.__version__`).
|
|
1147
|
-
|
|
1148
|
-
|
|
1151
|
+
`version` in `mod/.claude-plugin/plugin.json` must be the same value (the mod ships in lockstep;
|
|
1152
|
+
without the bump `claude plugin update` does not hand marketplace installs the new mod).
|
|
1153
|
+
`tests/test_mod_version.py` and the release workflow both fail on a mismatch.
|
|
1154
|
+
The `weskao-agent-plugins` marketplace lists the mod without a version, so it needs no bump there.
|
|
1149
1155
|
Pushing the tag triggers `.github/workflows/release.yml`:
|
|
1150
1156
|
|
|
1151
1157
|
1. **Build** job checks that the tag matches `__version__`, builds a wheel and
|
|
@@ -61,4 +61,8 @@ line-length = 100
|
|
|
61
61
|
[tool.ruff.lint]
|
|
62
62
|
# Pinned instead of ruff's moving default set, so a ruff upgrade cannot turn
|
|
63
63
|
# CI red on unchanged code.
|
|
64
|
-
select = ["E4", "E7", "E9", "F", "I", "W"]
|
|
64
|
+
select = ["E4", "E7", "E9", "F", "I", "W", "UP", "B023", "B904"]
|
|
65
|
+
|
|
66
|
+
[tool.ruff.lint.per-file-ignores]
|
|
67
|
+
# %-format fills JSON fixtures full of braces; f-strings would double every one.
|
|
68
|
+
"tests/*" = ["UP031"]
|
|
@@ -345,7 +345,7 @@ class CopilotMcpTest(CliCase):
|
|
|
345
345
|
|
|
346
346
|
def test_enable_says_to_restore_a_vanished_key_or_file_first(self) -> None:
|
|
347
347
|
self.disable()
|
|
348
|
-
self.cfg.write_bytes('{"other": 1}\n'
|
|
348
|
+
self.cfg.write_bytes(b'{"other": 1}\n')
|
|
349
349
|
self.assert_refused(self.enable(), "restore mcp-config.json", b'{"other": 1}\n')
|
|
350
350
|
self.assertIn("mcpServers", self.enable()[1]["results"][0]["detail"])
|
|
351
351
|
self.cfg.unlink()
|
|
@@ -298,7 +298,7 @@ class UpdateCheckTest(CliCase):
|
|
|
298
298
|
for code in (0, 1, 2):
|
|
299
299
|
seen = {}
|
|
300
300
|
|
|
301
|
-
def fake(**kw):
|
|
301
|
+
def fake(seen=seen, code=code, **kw):
|
|
302
302
|
seen.update(kw, after=list(kw["after"]), # lazy: read while after_steps is mocked
|
|
303
303
|
to_stderr=kw["out"] is sys.stderr) # run_cli swaps stderr
|
|
304
304
|
kw["out"].write("kit says hi\n")
|
|
@@ -13,7 +13,7 @@ from test_cli_surface import CliCase, snapshot
|
|
|
13
13
|
from test_conformance import FIXTURES
|
|
14
14
|
from test_project import ProjectCase
|
|
15
15
|
|
|
16
|
-
from agent_toggle import cost, fs
|
|
16
|
+
from agent_toggle import __version__, cost, fs
|
|
17
17
|
from agent_toggle.backends import plugin_cli
|
|
18
18
|
from agent_toggle.harnesses import build
|
|
19
19
|
|
|
@@ -119,6 +119,7 @@ class CostCommandTest(CliCase):
|
|
|
119
119
|
total = self.results("cost")[-1]
|
|
120
120
|
self.assertEqual(total["total_tokens"], sum(tokens))
|
|
121
121
|
self.assertEqual(total["formula"]["chars_per_token"], 4)
|
|
122
|
+
self.assertEqual(total["version"], __version__)
|
|
122
123
|
|
|
123
124
|
def test_parked_costs_zero_and_reports_would_save(self) -> None:
|
|
124
125
|
self.assertEqual(self.run_cli("disable", "skill", "big")[0], 0)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""The pane mod ships with the CLI: one version, so `claude plugin update` fetches the mod on every release."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
import unittest
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from agent_toggle import __version__
|
|
9
|
+
|
|
10
|
+
PLUGIN_JSON = Path(__file__).resolve().parent.parent / "mod" / ".claude-plugin" / "plugin.json"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ModVersionTest(unittest.TestCase):
|
|
14
|
+
def test_the_mod_version_is_the_cli_version(self) -> None:
|
|
15
|
+
mod = json.loads(PLUGIN_JSON.read_text(encoding="utf-8"))["version"]
|
|
16
|
+
self.assertEqual(mod, __version__, "bump mod/.claude-plugin/plugin.json with agent_toggle/__init__.py")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
if __name__ == "__main__":
|
|
20
|
+
unittest.main()
|
|
@@ -414,10 +414,10 @@ class KeysTest(ScreenCase):
|
|
|
414
414
|
for label, expected in (("Yes", [("alpha", False)]), ("No", None)):
|
|
415
415
|
self.rows = demo_rows()
|
|
416
416
|
win = FakeWin(["\t", "\x1b", picker.curses.KEY_MOUSE, picker.curses.KEY_MOUSE])
|
|
417
|
-
def click():
|
|
417
|
+
def click(win=win, label=label):
|
|
418
418
|
line = next(y for y, text in enumerate(win.screen) if "[Y] Yes" in text)
|
|
419
419
|
return (0, win.screen[line].index(label), line, 0, picker.curses.BUTTON1_CLICKED)
|
|
420
|
-
with mock.patch.object(picker.curses, "getmouse", side_effect=lambda:
|
|
420
|
+
with mock.patch.object(picker.curses, "getmouse", side_effect=lambda win=win:
|
|
421
421
|
click() if len(win.keys) == 0 else (0, 0, 0, 0, picker.curses.BUTTON1_CLICKED)):
|
|
422
422
|
out = picker.loop(win, self.rows, glyphs=theme.UNICODE)
|
|
423
423
|
self.assertEqual(None if out is None else self.names(out), expected)
|
|
@@ -37,6 +37,18 @@ class AfterStepsTest(unittest.TestCase):
|
|
|
37
37
|
self.assertEqual(self.steps("claude", ["other@x"]), [shims])
|
|
38
38
|
self.assertEqual(self.steps(None, []), [shims])
|
|
39
39
|
|
|
40
|
+
def test_the_mod_is_updated_from_whichever_marketplace_it_was_installed_from(self) -> None:
|
|
41
|
+
shims = ["agent-toggle", "install-shims"]
|
|
42
|
+
self.assertEqual(self.steps("claude", ["agent-toggle@weskao-agent-plugins"]), [
|
|
43
|
+
["claude", "plugin", "marketplace", "update", "weskao-agent-plugins"],
|
|
44
|
+
["claude", "plugin", "update", "agent-toggle@weskao-agent-plugins"], shims])
|
|
45
|
+
|
|
46
|
+
def test_one_install_per_scope_is_updated_once_and_other_plugins_are_left_alone(self) -> None:
|
|
47
|
+
ids = ["agent-toggle@agent-toggle", "agent-toggle@agent-toggle", "agent-toggle-x@agent-toggle"]
|
|
48
|
+
self.assertEqual(self.steps("claude", ids), [
|
|
49
|
+
["claude", "plugin", "marketplace", "update", "agent-toggle"],
|
|
50
|
+
["claude", "plugin", "update", "agent-toggle@agent-toggle"], ["agent-toggle", "install-shims"]])
|
|
51
|
+
|
|
40
52
|
|
|
41
53
|
class OfferTest(unittest.TestCase):
|
|
42
54
|
"""What the panel's answer does: Update now is `update` (update_kit, newest tag)."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|