agentbundle 0.9.0__tar.gz → 0.10.1__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.
- {agentbundle-0.9.0 → agentbundle-0.10.1}/PKG-INFO +9 -1
- {agentbundle-0.9.0 → agentbundle-0.10.1}/README.md +8 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/cli.py +44 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/_common.py +40 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/diff.py +4 -2
- agentbundle-0.10.1/agentbundle/commands/list_installed.py +223 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/uninstall.py +4 -1
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/upgrade.py +72 -11
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/source_defaults.py +6 -3
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/version.py +1 -1
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle.egg-info/PKG-INFO +9 -1
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle.egg-info/SOURCES.txt +1 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/pyproject.toml +1 -1
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/__init__.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/__main__.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/_data/adapter.schema.json +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/_data/adapter.toml +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/_data/install-defaults.toml +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/_data/install-marker.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/_data/pack.schema.json +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/_data/plugin-manifest.derived.schema.json +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/_data/plugin-manifest.schema.json +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/_data/profile.schema.json +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/__init__.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/__main__.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/adapter_root_bins.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/adapters/__init__.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/adapters/claude_code.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/adapters/codex.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/adapters/copilot.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/adapters/cursor.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/adapters/gemini.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/adapters/kiro.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/adapters/kiro_cli.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/adapters/kiro_ide.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/contract.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/lint_packs.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/main.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/phase_order.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/projections/__init__.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/projections/codex_agent_toml.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/projections/copilot_agent_md.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/projections/copilot_hooks_json.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/projections/direct_directory.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/projections/gemini_command_toml.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/projections/hook_id.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/projections/kiro_ide_hook.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/projections/merge_into_agent_json.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/projections/merge_json.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/projections/user_merge_json.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/scope_rails.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/self_host.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/shared_libs.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/target_resolver.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/__init__.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_adapter_claude_code.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_adapter_codex.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_adapter_copilot.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_adapter_cursor.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_adapter_gemini.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_adapter_kiro.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_adapter_kiro_alias.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_adapter_kiro_cli.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_adapter_kiro_ide.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_adapter_root_bins_projection.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_architect_design_reviewer_projection.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_architect_design_reviewer_rubric_parity.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_build_ships_seeds.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_contract.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_contract_scope.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_contract_v07.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_contract_v08.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_direct_directory_cleanup.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_end_to_end_build.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_lint_agents_md_diataxis_block.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_lint_agents_md_legacy_block.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_lint_agents_md_risk_block.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_lint_packs.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_load_pack_hook_wiring_safely.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_pack_schema.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_pack_schema_allowed_adapters.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_pack_schema_install.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_pipeline.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_plugin_manifest_schema.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_projectable_subset.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_projections_merge_json.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_scope_rails.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_security.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_self_host_check.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_self_host_fixture_guard.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_self_host_recipe_config.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_shared_libs_projection.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_shared_prefix_contract.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_shipped_packs_v07_declarations.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_shipped_packs_v08_declarations.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_user_libs_projection.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_validate.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_writers_emit_lf.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/user_libs.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/validate.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/catalogue.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/categories.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/__init__.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/_drop_warning.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/adapt.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/config.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/init_state.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/install.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/list_packs.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/list_profiles.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/list_targets.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/profile.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/reconcile.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/render.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/scaffold.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/commands/validate.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/config.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/render.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/safety.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/scope.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/statelock.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/user_config.py +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle.egg-info/dependency_links.txt +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle.egg-info/entry_points.txt +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle.egg-info/top_level.txt +0 -0
- {agentbundle-0.9.0 → agentbundle-0.10.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentbundle
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.1
|
|
4
4
|
Summary: npm for your coding agent. Install packs of skills, subagents, and hooks into any repo, for every major agent.
|
|
5
5
|
Author-email: eugenelim <eugenelim@users.noreply.github.com>
|
|
6
6
|
License: Apache-2.0 OR MIT
|
|
@@ -55,6 +55,12 @@ The install auto-detects your agent (`--adapter` overrides). Multi-IDE? Install
|
|
|
55
55
|
agentbundle list-packs
|
|
56
56
|
agentbundle list-profiles
|
|
57
57
|
|
|
58
|
+
# See what YOU have installed — pack, adapter, scope, version, and whether
|
|
59
|
+
# an upgrade is available (both scopes by default)
|
|
60
|
+
agentbundle list-installed
|
|
61
|
+
agentbundle list-installed --no-check # skip the catalogue check (offline, fast)
|
|
62
|
+
agentbundle list-installed --check-drift # also count locally edited files
|
|
63
|
+
|
|
58
64
|
# Install a whole curated profile — a single-scope set of packs — in one command
|
|
59
65
|
agentbundle install --profile inception
|
|
60
66
|
|
|
@@ -70,6 +76,8 @@ agentbundle uninstall --pack core --dry-run
|
|
|
70
76
|
agentbundle uninstall --pack core --yes
|
|
71
77
|
```
|
|
72
78
|
|
|
79
|
+
**`list-installed`** reads your state files (not the catalogue) and reports every installed `(pack, adapter)` at each scope with its version and an `up-to-date` / `upgrade-available` / `unknown` status; it degrades to `unknown` (never an error) when the catalogue can't be resolved, and `--no-check` skips the check entirely.
|
|
80
|
+
|
|
73
81
|
A **profile** is a catalogue-curated, single-scope set of packs you install in one command — it declares its own scope, so `--scope` doesn't apply. **Upgrade takes no version** — the target is whatever the catalogue you point at declares; to pin a past version, point the catalogue at that git ref. Install a pack that's **already there** and `agentbundle` offers to `upgrade` it instead (`--yes` runs it straight away).
|
|
74
82
|
|
|
75
83
|
**Mutating commands ask first.** `uninstall`, the `--force` cleanup, and the upgrade offer all preview what they'll do and confirm before touching anything; `--dry-run` previews without writing, and `--yes` skips the prompt for non-interactive / CI use (where, without it, they refuse rather than hang).
|
|
@@ -37,6 +37,12 @@ The install auto-detects your agent (`--adapter` overrides). Multi-IDE? Install
|
|
|
37
37
|
agentbundle list-packs
|
|
38
38
|
agentbundle list-profiles
|
|
39
39
|
|
|
40
|
+
# See what YOU have installed — pack, adapter, scope, version, and whether
|
|
41
|
+
# an upgrade is available (both scopes by default)
|
|
42
|
+
agentbundle list-installed
|
|
43
|
+
agentbundle list-installed --no-check # skip the catalogue check (offline, fast)
|
|
44
|
+
agentbundle list-installed --check-drift # also count locally edited files
|
|
45
|
+
|
|
40
46
|
# Install a whole curated profile — a single-scope set of packs — in one command
|
|
41
47
|
agentbundle install --profile inception
|
|
42
48
|
|
|
@@ -52,6 +58,8 @@ agentbundle uninstall --pack core --dry-run
|
|
|
52
58
|
agentbundle uninstall --pack core --yes
|
|
53
59
|
```
|
|
54
60
|
|
|
61
|
+
**`list-installed`** reads your state files (not the catalogue) and reports every installed `(pack, adapter)` at each scope with its version and an `up-to-date` / `upgrade-available` / `unknown` status; it degrades to `unknown` (never an error) when the catalogue can't be resolved, and `--no-check` skips the check entirely.
|
|
62
|
+
|
|
55
63
|
A **profile** is a catalogue-curated, single-scope set of packs you install in one command — it declares its own scope, so `--scope` doesn't apply. **Upgrade takes no version** — the target is whatever the catalogue you point at declares; to pin a past version, point the catalogue at that git ref. Install a pack that's **already there** and `agentbundle` offers to `upgrade` it instead (`--yes` runs it straight away).
|
|
56
64
|
|
|
57
65
|
**Mutating commands ask first.** `uninstall`, the `--force` cleanup, and the upgrade offer all preview what they'll do and confirm before touching anything; `--dry-run` previews without writing, and `--yes` skips the prompt for non-interactive / CI use (where, without it, they refuse rather than hang).
|
|
@@ -230,6 +230,50 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
230
230
|
)
|
|
231
231
|
sp.set_defaults(func=_lazy("list_targets"))
|
|
232
232
|
|
|
233
|
+
# --- list-installed --- (state-file reader; both scopes by default)
|
|
234
|
+
sp = subparsers.add_parser(
|
|
235
|
+
"list-installed",
|
|
236
|
+
help=(
|
|
237
|
+
"List installed packs across user and repo scope with version and "
|
|
238
|
+
"up-to-date status (vs. a catalogue). Read-only."
|
|
239
|
+
),
|
|
240
|
+
)
|
|
241
|
+
sp.add_argument(
|
|
242
|
+
"catalogue",
|
|
243
|
+
nargs="?",
|
|
244
|
+
default=None,
|
|
245
|
+
help=(
|
|
246
|
+
"Catalogue URI to compare installed versions against. Optional: when "
|
|
247
|
+
"omitted, the source is resolved from your config, an editable clone, "
|
|
248
|
+
"or the packaged default (RFC-0047). Ignored under --no-check."
|
|
249
|
+
),
|
|
250
|
+
)
|
|
251
|
+
sp.add_argument("--root", default=".")
|
|
252
|
+
sp.add_argument(
|
|
253
|
+
"--scope",
|
|
254
|
+
choices=("repo", "user"),
|
|
255
|
+
help="Limit the listing to one scope. Default: both user and repo.",
|
|
256
|
+
)
|
|
257
|
+
sp.add_argument(
|
|
258
|
+
"--no-check",
|
|
259
|
+
"--offline",
|
|
260
|
+
dest="no_check",
|
|
261
|
+
action="store_true",
|
|
262
|
+
help=(
|
|
263
|
+
"Skip the catalogue up-to-date check (no network): print only "
|
|
264
|
+
"pack/adapter/scope/installed, omitting LATEST and STATUS."
|
|
265
|
+
),
|
|
266
|
+
)
|
|
267
|
+
sp.add_argument(
|
|
268
|
+
"--check-drift",
|
|
269
|
+
action="store_true",
|
|
270
|
+
help=(
|
|
271
|
+
"Add a DRIFT column counting installed files locally edited since "
|
|
272
|
+
"install (on-disk SHA differs from the recorded SHA)."
|
|
273
|
+
),
|
|
274
|
+
)
|
|
275
|
+
sp.set_defaults(func=_lazy("list_installed"))
|
|
276
|
+
|
|
233
277
|
# --- scaffold --- (no --scope; always repo-targeted)
|
|
234
278
|
sp = subparsers.add_parser(
|
|
235
279
|
"scaffold",
|
|
@@ -16,6 +16,7 @@ from agentbundle.version import SPEC_VERSION
|
|
|
16
16
|
if TYPE_CHECKING:
|
|
17
17
|
import argparse
|
|
18
18
|
|
|
19
|
+
from agentbundle.config import PackState
|
|
19
20
|
from agentbundle.safety import Tier
|
|
20
21
|
|
|
21
22
|
|
|
@@ -199,6 +200,45 @@ def _major(version: str) -> str:
|
|
|
199
200
|
return v.split(".")[0]
|
|
200
201
|
|
|
201
202
|
|
|
203
|
+
def format_adapter_versions(rows: "dict[str, PackState]") -> str:
|
|
204
|
+
"""Render sorted ``adapter (version)`` pairs for a multi-adapter
|
|
205
|
+
disambiguator message (RFC-0052).
|
|
206
|
+
|
|
207
|
+
``rows`` is a ``{adapter: PackState}`` mapping (the shape
|
|
208
|
+
``State.rows_for_pack`` returns). Output e.g. ``claude-code (0.9.0),
|
|
209
|
+
codex (0.9.0)`` — so a "pass --adapter" refusal names not just *which*
|
|
210
|
+
adapters are installed but *at what version*, making the next command
|
|
211
|
+
actionable without a second lookup.
|
|
212
|
+
"""
|
|
213
|
+
return ", ".join(
|
|
214
|
+
f"{adapter} ({rows[adapter].installed_version})" for adapter in sorted(rows)
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def count_drifted_files(pack_state: "PackState", root: Path) -> int:
|
|
219
|
+
"""Count *pack_state*'s files whose on-disk SHA differs from the recorded SHA.
|
|
220
|
+
|
|
221
|
+
Row-scoped drift (Tier-2): compares each file against this row's own
|
|
222
|
+
recorded SHA — **not** ``safety.classify``, which resolves against the SHA
|
|
223
|
+
set across *all* rows and would undercount a co-owned path. A file absent on
|
|
224
|
+
disk is not drift (it is Tier-1, "about to (re)write"). Render-free: needs
|
|
225
|
+
only the loaded state plus on-disk bytes, so it is cheap enough to run
|
|
226
|
+
before an upgrade confirm. Shared by ``list-installed --check-drift`` and
|
|
227
|
+
the upgrade upfront drift notice.
|
|
228
|
+
"""
|
|
229
|
+
from agentbundle.safety import sha256_file
|
|
230
|
+
|
|
231
|
+
count = 0
|
|
232
|
+
for relpath in pack_state.files:
|
|
233
|
+
on_disk = root / relpath
|
|
234
|
+
if not on_disk.exists():
|
|
235
|
+
continue
|
|
236
|
+
recorded = pack_state.file_sha(relpath)
|
|
237
|
+
if recorded is not None and sha256_file(on_disk) != recorded:
|
|
238
|
+
count += 1
|
|
239
|
+
return count
|
|
240
|
+
|
|
241
|
+
|
|
202
242
|
# ---------------------------------------------------------------------------
|
|
203
243
|
# Dry-run plan formatting (shared by `install --dry-run` and `upgrade --dry-run`)
|
|
204
244
|
# ---------------------------------------------------------------------------
|
|
@@ -113,10 +113,12 @@ def run(args: argparse.Namespace) -> int:
|
|
|
113
113
|
elif len(_rows) == 1:
|
|
114
114
|
pack_state = next(iter(_rows.values()))
|
|
115
115
|
elif len(_rows) > 1:
|
|
116
|
+
from agentbundle.commands._common import format_adapter_versions
|
|
117
|
+
|
|
116
118
|
print(
|
|
117
119
|
f"diff: {pack_name} installed for multiple adapters at "
|
|
118
|
-
f"{effective_scope} scope
|
|
119
|
-
f"
|
|
120
|
+
f"{effective_scope} scope; pass --adapter to pick one: "
|
|
121
|
+
f"{format_adapter_versions(_rows)}",
|
|
120
122
|
file=sys.stderr,
|
|
121
123
|
)
|
|
122
124
|
return 1
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"""``agentbundle list-installed`` subcommand.
|
|
2
|
+
|
|
3
|
+
Lists every installed ``(pack, adapter)`` row across the user and repo scope —
|
|
4
|
+
the state-file complement to ``list-packs`` (which queries a *catalogue* of
|
|
5
|
+
what is *available*). Reads the state files **read-only**; never writes.
|
|
6
|
+
|
|
7
|
+
By default it also resolves the catalogue once and joins each row against the
|
|
8
|
+
catalogue's ``pack.toml`` version to report a status (``up-to-date`` /
|
|
9
|
+
``upgrade-available`` / ``unknown``). ``--no-check`` (alias ``--offline``) skips
|
|
10
|
+
that join and prints only the state-only columns. ``--check-drift`` adds a
|
|
11
|
+
per-row count of locally edited files (on-disk SHA ≠ the SHA recorded in state).
|
|
12
|
+
|
|
13
|
+
Exit codes:
|
|
14
|
+
0 — success (including "no packs installed" and an unresolvable catalogue).
|
|
15
|
+
1 — only on an argument/environment error the listing genuinely can't survive.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import TYPE_CHECKING
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
import argparse
|
|
25
|
+
|
|
26
|
+
from agentbundle.config import State
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def run(args: "argparse.Namespace") -> int:
|
|
30
|
+
"""Entry point for ``agentbundle list-installed``."""
|
|
31
|
+
import sys
|
|
32
|
+
|
|
33
|
+
from agentbundle import scope as scope_mod
|
|
34
|
+
from agentbundle.config import ConfigError, load_state
|
|
35
|
+
|
|
36
|
+
requested_scope = getattr(args, "scope", None)
|
|
37
|
+
scopes = [requested_scope] if requested_scope else ["user", "repo"]
|
|
38
|
+
check = not getattr(args, "no_check", False)
|
|
39
|
+
want_drift = getattr(args, "check_drift", False)
|
|
40
|
+
|
|
41
|
+
# ── Gather (scope, root, State) read-only ─────────────────────────────────
|
|
42
|
+
repo_root = Path(getattr(args, "root", ".")).resolve()
|
|
43
|
+
scope_states: list[tuple[str, Path, "State"]] = []
|
|
44
|
+
for sc in scopes:
|
|
45
|
+
if sc == "repo":
|
|
46
|
+
base, state_path = repo_root, repo_root / ".agentbundle-state.toml"
|
|
47
|
+
else: # user
|
|
48
|
+
try:
|
|
49
|
+
base = scope_mod.resolve_user_root()
|
|
50
|
+
except scope_mod.UserScopeUnresolvable:
|
|
51
|
+
# No resolvable home → no user-scope state to list. Not an error.
|
|
52
|
+
continue
|
|
53
|
+
state_path = base / ".agentbundle" / "state.toml"
|
|
54
|
+
try:
|
|
55
|
+
state = load_state(state_path)
|
|
56
|
+
except ConfigError as exc:
|
|
57
|
+
# An incompatible (e.g. legacy-schema) state file is a hard refusal
|
|
58
|
+
# on read (RFC-0052). Warn and skip that scope rather than abort —
|
|
59
|
+
# the other scope stays listable.
|
|
60
|
+
print(f"list-installed: skipping {sc} scope: {exc}", file=sys.stderr)
|
|
61
|
+
continue
|
|
62
|
+
scope_states.append((sc, base, state))
|
|
63
|
+
|
|
64
|
+
rows = _collect_rows(scope_states)
|
|
65
|
+
if not rows:
|
|
66
|
+
where = f"{requested_scope} scope" if requested_scope else "user or repo scope"
|
|
67
|
+
print(f"no packs installed at {where}.")
|
|
68
|
+
return 0
|
|
69
|
+
|
|
70
|
+
# ── Catalogue join for LATEST / STATUS (unless --no-check) ─────────────────
|
|
71
|
+
catalogue_resolved = False
|
|
72
|
+
latest_by_pack: dict[str, str | None] = {}
|
|
73
|
+
if check:
|
|
74
|
+
catalogue_resolved, latest_by_pack = _resolve_latest(args)
|
|
75
|
+
|
|
76
|
+
# ── Drift count (only when requested) ─────────────────────────────────────
|
|
77
|
+
if want_drift:
|
|
78
|
+
from agentbundle.commands._common import count_drifted_files
|
|
79
|
+
|
|
80
|
+
for row in rows:
|
|
81
|
+
row["drift"] = count_drifted_files(row["_pack_state"], row["_root"])
|
|
82
|
+
|
|
83
|
+
_print_table(rows, check=check, want_drift=want_drift,
|
|
84
|
+
catalogue_resolved=catalogue_resolved, latest_by_pack=latest_by_pack)
|
|
85
|
+
return 0
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# ---------------------------------------------------------------------------
|
|
89
|
+
# Helpers
|
|
90
|
+
# ---------------------------------------------------------------------------
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _collect_rows(
|
|
94
|
+
scope_states: list[tuple[str, Path, "State"]],
|
|
95
|
+
) -> list[dict]:
|
|
96
|
+
"""Flatten every ``(pack, adapter)`` row across scopes into sorted dicts.
|
|
97
|
+
|
|
98
|
+
Each row carries the display fields plus ``_pack_state`` / ``_root`` for a
|
|
99
|
+
later (optional) drift pass. Sorted by (pack, adapter, scope) so output is
|
|
100
|
+
deterministic.
|
|
101
|
+
"""
|
|
102
|
+
rows: list[dict] = []
|
|
103
|
+
for scope_name, root, state in scope_states:
|
|
104
|
+
for (pack, adapter), ps in state.packs.items():
|
|
105
|
+
rows.append(
|
|
106
|
+
{
|
|
107
|
+
"pack": pack,
|
|
108
|
+
"adapter": adapter,
|
|
109
|
+
"scope": scope_name,
|
|
110
|
+
"installed": ps.installed_version,
|
|
111
|
+
"_pack_state": ps,
|
|
112
|
+
"_root": root,
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
rows.sort(key=lambda r: (r["pack"], r["adapter"], r["scope"]))
|
|
116
|
+
return rows
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _resolve_latest(args: "argparse.Namespace") -> tuple[bool, dict[str, str | None]]:
|
|
120
|
+
"""Resolve the catalogue once and map each pack name to its latest version.
|
|
121
|
+
|
|
122
|
+
Returns ``(catalogue_resolved, {pack_name: version_or_None})``. On an
|
|
123
|
+
unresolvable catalogue returns ``(False, {})`` — the caller degrades every
|
|
124
|
+
row to ``unknown`` rather than failing. A pack present in the catalogue but
|
|
125
|
+
declaring an incompatible major version maps to ``None`` (also ``unknown``),
|
|
126
|
+
detected directly (``pack_spec_version`` + ``_major``) so no refusal is
|
|
127
|
+
printed — unlike ``check_spec_version_gate``, which prints and aborts.
|
|
128
|
+
"""
|
|
129
|
+
from agentbundle.catalogue import CatalogueError, resolve_catalogue
|
|
130
|
+
from agentbundle.commands._common import _major, resolve_catalogue_uri
|
|
131
|
+
from agentbundle.config import ConfigError, load_pack_toml, pack_spec_version
|
|
132
|
+
from agentbundle.version import SPEC_VERSION
|
|
133
|
+
|
|
134
|
+
try:
|
|
135
|
+
catalogue_dir = resolve_catalogue(resolve_catalogue_uri(args))
|
|
136
|
+
except CatalogueError:
|
|
137
|
+
return False, {}
|
|
138
|
+
|
|
139
|
+
# Reuse list-packs' discovery so the layouts accepted stay identical.
|
|
140
|
+
from agentbundle.commands.list_packs import _discover_pack_dirs
|
|
141
|
+
|
|
142
|
+
cli_major = _major(SPEC_VERSION)
|
|
143
|
+
latest: dict[str, str | None] = {}
|
|
144
|
+
for pack_dir in _discover_pack_dirs(catalogue_dir):
|
|
145
|
+
try:
|
|
146
|
+
toml = load_pack_toml(pack_dir / "pack.toml")
|
|
147
|
+
except ConfigError:
|
|
148
|
+
continue
|
|
149
|
+
pack = toml.get("pack", {})
|
|
150
|
+
name = pack.get("name") or pack_dir.name
|
|
151
|
+
declared = pack_spec_version(toml)
|
|
152
|
+
if declared is not None and _major(declared) != cli_major:
|
|
153
|
+
latest[name] = None # incompatible major → unknown, don't compare
|
|
154
|
+
continue
|
|
155
|
+
latest[name] = pack.get("version") or None
|
|
156
|
+
return True, latest
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _version_key(version: str) -> tuple[int, ...] | None:
|
|
160
|
+
"""Parse a dotted version into a comparable int tuple, or None if not numeric.
|
|
161
|
+
|
|
162
|
+
A non-numeric segment (a pre-release / build tag like ``1.2.0-rc1`` or
|
|
163
|
+
``1.2.post1``) intentionally yields ``None`` → the row reads ``unknown``
|
|
164
|
+
rather than risking a wrong comparison; packs ship plain numeric versions.
|
|
165
|
+
"""
|
|
166
|
+
parts = version.lstrip("v").split(".")
|
|
167
|
+
try:
|
|
168
|
+
return tuple(int(p) for p in parts)
|
|
169
|
+
except ValueError:
|
|
170
|
+
return None
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _status_for(installed: str, latest: str | None, *, catalogue_resolved: bool) -> str:
|
|
174
|
+
"""Compute a row's status from (installed, latest, resolvable?).
|
|
175
|
+
|
|
176
|
+
``up-to-date`` when installed is at or beyond latest; ``upgrade-available``
|
|
177
|
+
when latest is strictly greater; ``unknown`` when the catalogue could not be
|
|
178
|
+
resolved, the pack is absent from it, or either version isn't comparable.
|
|
179
|
+
"""
|
|
180
|
+
if not catalogue_resolved or latest is None:
|
|
181
|
+
return "unknown"
|
|
182
|
+
a, b = _version_key(installed), _version_key(latest)
|
|
183
|
+
if a is None or b is None:
|
|
184
|
+
return "unknown"
|
|
185
|
+
# Zero-pad to equal length so `0.9` vs `0.9.0` compares equal rather than
|
|
186
|
+
# `(0,9) < (0,9,0)` reading as upgrade-available.
|
|
187
|
+
width = max(len(a), len(b))
|
|
188
|
+
a += (0,) * (width - len(a))
|
|
189
|
+
b += (0,) * (width - len(b))
|
|
190
|
+
return "upgrade-available" if b > a else "up-to-date"
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _print_table(
|
|
194
|
+
rows: list[dict],
|
|
195
|
+
*,
|
|
196
|
+
check: bool,
|
|
197
|
+
want_drift: bool,
|
|
198
|
+
catalogue_resolved: bool,
|
|
199
|
+
latest_by_pack: dict[str, str | None],
|
|
200
|
+
) -> None:
|
|
201
|
+
"""Render the installed-packs table to stdout."""
|
|
202
|
+
from agentbundle.commands._common import render_table
|
|
203
|
+
|
|
204
|
+
headers = ["PACK", "ADAPTER", "SCOPE", "INSTALLED"]
|
|
205
|
+
if check:
|
|
206
|
+
headers += ["LATEST", "STATUS"]
|
|
207
|
+
if want_drift:
|
|
208
|
+
headers += ["DRIFT"]
|
|
209
|
+
|
|
210
|
+
table_rows: list[list[str]] = []
|
|
211
|
+
for r in rows:
|
|
212
|
+
cells = [r["pack"], r["adapter"], r["scope"], r["installed"]]
|
|
213
|
+
if check:
|
|
214
|
+
latest = latest_by_pack.get(r["pack"])
|
|
215
|
+
status = _status_for(
|
|
216
|
+
r["installed"], latest, catalogue_resolved=catalogue_resolved
|
|
217
|
+
)
|
|
218
|
+
cells += [latest or "—", status]
|
|
219
|
+
if want_drift:
|
|
220
|
+
cells += [str(r.get("drift", 0))]
|
|
221
|
+
table_rows.append(cells)
|
|
222
|
+
|
|
223
|
+
render_table(headers, table_rows)
|
|
@@ -141,9 +141,12 @@ def run(args: "argparse.Namespace") -> int:
|
|
|
141
141
|
elif len(rows) == 1:
|
|
142
142
|
target_adapter = next(iter(rows))
|
|
143
143
|
else:
|
|
144
|
+
from agentbundle.commands._common import format_adapter_versions
|
|
145
|
+
|
|
144
146
|
print(
|
|
145
147
|
f"uninstall: {pack_name} installed for multiple adapters at "
|
|
146
|
-
f"{effective_scope} scope
|
|
148
|
+
f"{effective_scope} scope; pass --adapter to pick one: "
|
|
149
|
+
f"{format_adapter_versions(rows)}",
|
|
147
150
|
file=sys.stderr,
|
|
148
151
|
)
|
|
149
152
|
return 1
|
|
@@ -38,7 +38,6 @@ from typing import TYPE_CHECKING
|
|
|
38
38
|
if TYPE_CHECKING:
|
|
39
39
|
import argparse
|
|
40
40
|
|
|
41
|
-
from agentbundle.config import State
|
|
42
41
|
from agentbundle.user_config import UserConfig
|
|
43
42
|
|
|
44
43
|
|
|
@@ -182,9 +181,12 @@ def run(args: "argparse.Namespace") -> int:
|
|
|
182
181
|
elif len(_rows) == 1:
|
|
183
182
|
target_adapter = next(iter(_rows))
|
|
184
183
|
elif len(_rows) > 1:
|
|
184
|
+
from agentbundle.commands._common import format_adapter_versions
|
|
185
|
+
|
|
185
186
|
print(
|
|
186
187
|
f"upgrade: {pack_name} installed for multiple adapters at "
|
|
187
|
-
f"{effective_scope} scope
|
|
188
|
+
f"{effective_scope} scope; pass --adapter to pick one: "
|
|
189
|
+
f"{format_adapter_versions(_rows)}",
|
|
188
190
|
file=sys.stderr,
|
|
189
191
|
)
|
|
190
192
|
return 1
|
|
@@ -322,6 +324,25 @@ def run(args: "argparse.Namespace") -> int:
|
|
|
322
324
|
# write happens either way) and rare; left as-is to keep the confirm above
|
|
323
325
|
# the expensive render.
|
|
324
326
|
|
|
327
|
+
# Upfront drift notice (whole-pack only): before the user confirms, tell
|
|
328
|
+
# them how many installed files have local edits that re-applying will
|
|
329
|
+
# preserve as `*.upstream` companions. Computed from on-disk-vs-state SHAs
|
|
330
|
+
# (no render needed); suppressed at zero and on a dry run (which writes
|
|
331
|
+
# nothing and already names companion actions in its plan). Gated to the
|
|
332
|
+
# whole-pack case: a per-primitive upgrade re-applies only that primitive's
|
|
333
|
+
# files, so a whole-pack count would mislead.
|
|
334
|
+
if not is_per_primitive and not getattr(args, "dry_run", False):
|
|
335
|
+
from agentbundle.commands._common import count_drifted_files
|
|
336
|
+
|
|
337
|
+
_drifted = count_drifted_files(pack_state, root)
|
|
338
|
+
if _drifted:
|
|
339
|
+
print(
|
|
340
|
+
f"upgrade: {_drifted} installed file(s) have local edits; your "
|
|
341
|
+
f"edits are preserved as .upstream companions where the file "
|
|
342
|
+
f"still ships.",
|
|
343
|
+
file=sys.stderr,
|
|
344
|
+
)
|
|
345
|
+
|
|
325
346
|
# Confirm before the first write — unless ``--yes`` or ``--dry-run`` (which
|
|
326
347
|
# writes nothing). A non-interactive stdin cannot answer the prompt, so
|
|
327
348
|
# refuse and explain rather than block on ``input()``. ``--dry-run``
|
|
@@ -330,8 +351,10 @@ def run(args: "argparse.Namespace") -> int:
|
|
|
330
351
|
if not getattr(args, "yes", False) and not getattr(args, "dry_run", False):
|
|
331
352
|
if already_current:
|
|
332
353
|
question = (
|
|
333
|
-
f"{confirm_label} is already at {to_version}
|
|
334
|
-
f"{effective_scope} scope
|
|
354
|
+
f"{confirm_label} is already at {to_version} at "
|
|
355
|
+
f"{effective_scope} scope. Re-apply to restore any missing or "
|
|
356
|
+
f"reset any unmodified bundle files? Your local edits are kept "
|
|
357
|
+
f"as .upstream companions. [y/N] "
|
|
335
358
|
)
|
|
336
359
|
else:
|
|
337
360
|
question = (
|
|
@@ -727,15 +750,19 @@ def run(args: "argparse.Namespace") -> int:
|
|
|
727
750
|
|
|
728
751
|
if is_per_primitive:
|
|
729
752
|
ptype, _src_dir = _PRIMITIVE_FLAG_MAP[prim_flag]
|
|
730
|
-
|
|
731
|
-
f"upgraded: {pack_name} {ptype}/{prim_name} @ "
|
|
732
|
-
f"{effective_scope} {from_version} -> {to_version}"
|
|
733
|
-
)
|
|
753
|
+
recap_label = f"{pack_name} {ptype}/{prim_name}"
|
|
734
754
|
else:
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
755
|
+
recap_label = pack_name
|
|
756
|
+
print(
|
|
757
|
+
_format_recap(
|
|
758
|
+
recap_label,
|
|
759
|
+
effective_scope,
|
|
760
|
+
from_version,
|
|
761
|
+
to_version,
|
|
762
|
+
already_current=already_current,
|
|
763
|
+
companion_count=len(companions),
|
|
738
764
|
)
|
|
765
|
+
)
|
|
739
766
|
return 0
|
|
740
767
|
|
|
741
768
|
|
|
@@ -744,6 +771,40 @@ def run(args: "argparse.Namespace") -> int:
|
|
|
744
771
|
# ---------------------------------------------------------------------------
|
|
745
772
|
|
|
746
773
|
|
|
774
|
+
def _format_recap(
|
|
775
|
+
label: str,
|
|
776
|
+
scope: str,
|
|
777
|
+
from_version: str,
|
|
778
|
+
to_version: str,
|
|
779
|
+
*,
|
|
780
|
+
already_current: bool,
|
|
781
|
+
companion_count: int,
|
|
782
|
+
) -> str:
|
|
783
|
+
"""Render the post-upgrade recap line, honestly distinguishing the cases.
|
|
784
|
+
|
|
785
|
+
Three verdicts, driven by the only signals available without changing what
|
|
786
|
+
the walk writes (the walk re-writes bundle-owned files unconditionally, so
|
|
787
|
+
"nothing changed on disk" is not knowable):
|
|
788
|
+
|
|
789
|
+
- version changed → ``upgraded: <label> @ <scope> <from> -> <to>``
|
|
790
|
+
- same version, no local edits preserved →
|
|
791
|
+
``re-applied: <label> @ <scope> <version> (already current)``
|
|
792
|
+
- same version, local edits preserved as companions →
|
|
793
|
+
``re-applied: <label> @ <scope> <version> — N file(s) had local edits,
|
|
794
|
+
kept as .upstream companions``
|
|
795
|
+
|
|
796
|
+
It never prints ``upgraded: … X -> X`` for a same-version re-apply.
|
|
797
|
+
"""
|
|
798
|
+
if not already_current:
|
|
799
|
+
return f"upgraded: {label} @ {scope} {from_version} -> {to_version}"
|
|
800
|
+
if companion_count:
|
|
801
|
+
return (
|
|
802
|
+
f"re-applied: {label} @ {scope} {to_version} — "
|
|
803
|
+
f"{companion_count} file(s) had local edits, kept as .upstream companions"
|
|
804
|
+
)
|
|
805
|
+
return f"re-applied: {label} @ {scope} {to_version} (already current)"
|
|
806
|
+
|
|
807
|
+
|
|
747
808
|
def _compute_new_wiring_rows(
|
|
748
809
|
pack_dir: Path,
|
|
749
810
|
pack_name: str,
|
|
@@ -38,10 +38,13 @@ _WIN_DRIVE_RE = re.compile(r"^[A-Za-z]:[\\/]")
|
|
|
38
38
|
_MARKER_DIR = "packs"
|
|
39
39
|
_MARKER_FILE = (".claude-plugin", "marketplace.json")
|
|
40
40
|
|
|
41
|
-
# The exact substring the spec pins for the all-layers-empty error.
|
|
41
|
+
# The exact substring the spec pins for the all-layers-empty error. Names the
|
|
42
|
+
# real surface: the catalogue is a trailing positional argument, not a
|
|
43
|
+
# `--catalogue` flag (no such flag exists), so the recovery text must not send
|
|
44
|
+
# the user to one.
|
|
42
45
|
_NO_SOURCE_MSG = (
|
|
43
|
-
"no catalogue source: pass
|
|
44
|
-
"source …', or pip install -e the catalogue"
|
|
46
|
+
"no catalogue source: pass a catalogue argument, run 'agentbundle config "
|
|
47
|
+
"set source …', or pip install -e the catalogue"
|
|
45
48
|
)
|
|
46
49
|
|
|
47
50
|
# Sentinel: distinguishes "caller did not pass a distribution" (load it
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentbundle
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.1
|
|
4
4
|
Summary: npm for your coding agent. Install packs of skills, subagents, and hooks into any repo, for every major agent.
|
|
5
5
|
Author-email: eugenelim <eugenelim@users.noreply.github.com>
|
|
6
6
|
License: Apache-2.0 OR MIT
|
|
@@ -55,6 +55,12 @@ The install auto-detects your agent (`--adapter` overrides). Multi-IDE? Install
|
|
|
55
55
|
agentbundle list-packs
|
|
56
56
|
agentbundle list-profiles
|
|
57
57
|
|
|
58
|
+
# See what YOU have installed — pack, adapter, scope, version, and whether
|
|
59
|
+
# an upgrade is available (both scopes by default)
|
|
60
|
+
agentbundle list-installed
|
|
61
|
+
agentbundle list-installed --no-check # skip the catalogue check (offline, fast)
|
|
62
|
+
agentbundle list-installed --check-drift # also count locally edited files
|
|
63
|
+
|
|
58
64
|
# Install a whole curated profile — a single-scope set of packs — in one command
|
|
59
65
|
agentbundle install --profile inception
|
|
60
66
|
|
|
@@ -70,6 +76,8 @@ agentbundle uninstall --pack core --dry-run
|
|
|
70
76
|
agentbundle uninstall --pack core --yes
|
|
71
77
|
```
|
|
72
78
|
|
|
79
|
+
**`list-installed`** reads your state files (not the catalogue) and reports every installed `(pack, adapter)` at each scope with its version and an `up-to-date` / `upgrade-available` / `unknown` status; it degrades to `unknown` (never an error) when the catalogue can't be resolved, and `--no-check` skips the check entirely.
|
|
80
|
+
|
|
73
81
|
A **profile** is a catalogue-curated, single-scope set of packs you install in one command — it declares its own scope, so `--scope` doesn't apply. **Upgrade takes no version** — the target is whatever the catalogue you point at declares; to pin a past version, point the catalogue at that git ref. Install a pack that's **already there** and `agentbundle` offers to `upgrade` it instead (`--yes` runs it straight away).
|
|
74
82
|
|
|
75
83
|
**Mutating commands ask first.** `uninstall`, the `--force` cleanup, and the upgrade offer all preview what they'll do and confirm before touching anything; `--dry-run` previews without writing, and `--yes` skips the prompt for non-interactive / CI use (where, without it, they refuse rather than hang).
|
|
@@ -111,6 +111,7 @@ agentbundle/commands/config.py
|
|
|
111
111
|
agentbundle/commands/diff.py
|
|
112
112
|
agentbundle/commands/init_state.py
|
|
113
113
|
agentbundle/commands/install.py
|
|
114
|
+
agentbundle/commands/list_installed.py
|
|
114
115
|
agentbundle/commands/list_packs.py
|
|
115
116
|
agentbundle/commands/list_profiles.py
|
|
116
117
|
agentbundle/commands/list_targets.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "agentbundle"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.10.1"
|
|
8
8
|
description = "npm for your coding agent. Install packs of skills, subagents, and hooks into any repo, for every major agent."
|
|
9
9
|
requires-python = ">=3.11"
|
|
10
10
|
dependencies = []
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/_data/plugin-manifest.derived.schema.json
RENAMED
|
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
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/projections/copilot_hooks_json.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/projections/gemini_command_toml.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/projections/merge_into_agent_json.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_adapter_claude_code.py
RENAMED
|
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
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_direct_directory_cleanup.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_lint_agents_md_legacy_block.py
RENAMED
|
File without changes
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_lint_agents_md_risk_block.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_pack_schema_install.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_plugin_manifest_schema.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_projections_merge_json.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_self_host_fixture_guard.py
RENAMED
|
File without changes
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_self_host_recipe_config.py
RENAMED
|
File without changes
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_shared_libs_projection.py
RENAMED
|
File without changes
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_shared_prefix_contract.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentbundle-0.9.0 → agentbundle-0.10.1}/agentbundle/build/tests/test_user_libs_projection.py
RENAMED
|
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
|