agentbundle 0.19.0__tar.gz → 0.20.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.
Files changed (161) hide show
  1. {agentbundle-0.19.0 → agentbundle-0.20.1}/PKG-INFO +3 -1
  2. {agentbundle-0.19.0 → agentbundle-0.20.1}/README.md +2 -0
  3. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/_data/pack.schema.json +24 -0
  4. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/cli.py +30 -0
  5. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/_common.py +10 -2
  6. agentbundle-0.20.1/agentbundle/commands/docs.py +117 -0
  7. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/install.py +10 -2
  8. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/source_defaults.py +11 -2
  9. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/version.py +1 -1
  10. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle.egg-info/PKG-INFO +3 -1
  11. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle.egg-info/SOURCES.txt +1 -0
  12. {agentbundle-0.19.0 → agentbundle-0.20.1}/pyproject.toml +1 -1
  13. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/__init__.py +0 -0
  14. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/__main__.py +0 -0
  15. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/_data/adapter.schema.json +0 -0
  16. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/_data/adapter.toml +0 -0
  17. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/_data/catalogue.schema.json +0 -0
  18. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/_data/install-defaults.toml +0 -0
  19. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/_data/install-marker.py +0 -0
  20. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/_data/plugin-manifest.derived.schema.json +0 -0
  21. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/_data/plugin-manifest.schema.json +0 -0
  22. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/_data/profile.schema.json +0 -0
  23. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/__init__.py +0 -0
  24. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/__main__.py +0 -0
  25. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/adapter_root_bins.py +0 -0
  26. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/adapters/__init__.py +0 -0
  27. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/adapters/claude_code.py +0 -0
  28. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/adapters/codex.py +0 -0
  29. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/adapters/copilot.py +0 -0
  30. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/adapters/cursor.py +0 -0
  31. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/adapters/gemini.py +0 -0
  32. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/adapters/kiro.py +0 -0
  33. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/adapters/kiro_cli.py +0 -0
  34. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/adapters/kiro_ide.py +0 -0
  35. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/contract.py +0 -0
  36. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/lint_packs.py +0 -0
  37. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/main.py +0 -0
  38. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/phase_order.py +0 -0
  39. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/projections/__init__.py +0 -0
  40. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/projections/codex_agent_toml.py +0 -0
  41. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/projections/copilot_agent_md.py +0 -0
  42. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/projections/copilot_hooks_json.py +0 -0
  43. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/projections/direct_directory.py +0 -0
  44. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/projections/gemini_command_toml.py +0 -0
  45. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/projections/hook_id.py +0 -0
  46. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/projections/kiro_ide_hook.py +0 -0
  47. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/projections/merge_into_agent_json.py +0 -0
  48. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/projections/merge_json.py +0 -0
  49. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/projections/user_merge_json.py +0 -0
  50. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/recipes/composite-agents-md.toml +0 -0
  51. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/recipes/composite-marketplace.toml +0 -0
  52. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/recipes/marketplace.toml +0 -0
  53. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/recipes/per-pack-apm-package.toml +0 -0
  54. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/recipes/per-pack-claude-plugin.toml +0 -0
  55. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/recipes/per-pack-overlay.toml +0 -0
  56. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/recipes/self-host.toml +0 -0
  57. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/scope_rails.py +0 -0
  58. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/self_host.py +0 -0
  59. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/shared_libs.py +0 -0
  60. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/target_resolver.py +0 -0
  61. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/__init__.py +0 -0
  62. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_adapter_claude_code.py +0 -0
  63. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_adapter_codex.py +0 -0
  64. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_adapter_copilot.py +0 -0
  65. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_adapter_cursor.py +0 -0
  66. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_adapter_gemini.py +0 -0
  67. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_adapter_kiro.py +0 -0
  68. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_adapter_kiro_alias.py +0 -0
  69. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_adapter_kiro_cli.py +0 -0
  70. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_adapter_kiro_ide.py +0 -0
  71. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_adapter_root_bins_projection.py +0 -0
  72. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_architect_design_reviewer_projection.py +0 -0
  73. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_architect_design_reviewer_rubric_parity.py +0 -0
  74. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_build_ships_seeds.py +0 -0
  75. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_contract.py +0 -0
  76. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_contract_scope.py +0 -0
  77. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_contract_v07.py +0 -0
  78. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_contract_v08.py +0 -0
  79. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_direct_directory_cleanup.py +0 -0
  80. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_end_to_end_build.py +0 -0
  81. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_lint_agents_md_diataxis_block.py +0 -0
  82. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_lint_agents_md_legacy_block.py +0 -0
  83. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_lint_agents_md_risk_block.py +0 -0
  84. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_lint_packs.py +0 -0
  85. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_load_pack_hook_wiring_safely.py +0 -0
  86. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_pack_schema.py +0 -0
  87. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_pack_schema_allowed_adapters.py +0 -0
  88. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_pack_schema_install.py +0 -0
  89. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_pipeline.py +0 -0
  90. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_plugin_manifest_schema.py +0 -0
  91. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_projectable_subset.py +0 -0
  92. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_projections_merge_json.py +0 -0
  93. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_scope_rails.py +0 -0
  94. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_security.py +0 -0
  95. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_self_host_check.py +0 -0
  96. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_self_host_fixture_guard.py +0 -0
  97. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_self_host_recipe_config.py +0 -0
  98. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_shared_libs_projection.py +0 -0
  99. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_shared_prefix_contract.py +0 -0
  100. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_shipped_packs_v07_declarations.py +0 -0
  101. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_shipped_packs_v08_declarations.py +0 -0
  102. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_user_libs_projection.py +0 -0
  103. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_validate.py +0 -0
  104. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/tests/test_writers_emit_lf.py +0 -0
  105. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/user_libs.py +0 -0
  106. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/build/validate.py +0 -0
  107. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/catalogue.py +0 -0
  108. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/catalogue_tooling/__init__.py +0 -0
  109. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/catalogue_tooling/archive.py +0 -0
  110. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/catalogue_tooling/build.py +0 -0
  111. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/catalogue_tooling/config.py +0 -0
  112. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/catalogue_tooling/defaults.py +0 -0
  113. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/catalogue_tooling/diagnostics.py +0 -0
  114. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/catalogue_tooling/lint.py +0 -0
  115. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/catalogue_tooling/package.py +0 -0
  116. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/catalogue_tooling/results.py +0 -0
  117. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/catalogue_tooling/self_host.py +0 -0
  118. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/catalogue_tooling/skill_spec_lint.py +0 -0
  119. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/catalogue_tooling/verify.py +0 -0
  120. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/categories.py +0 -0
  121. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/__init__.py +0 -0
  122. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/_drop_warning.py +0 -0
  123. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/adapt.py +0 -0
  124. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/catalogue_build.py +0 -0
  125. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/catalogue_lint.py +0 -0
  126. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/catalogue_package.py +0 -0
  127. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/catalogue_self_host.py +0 -0
  128. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/catalogue_sync_defaults.py +0 -0
  129. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/catalogue_tooling_stub.py +0 -0
  130. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/catalogue_verify.py +0 -0
  131. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/config.py +0 -0
  132. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/diff.py +0 -0
  133. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/init_state.py +0 -0
  134. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/list_installed.py +0 -0
  135. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/list_packs.py +0 -0
  136. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/list_profiles.py +0 -0
  137. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/list_targets.py +0 -0
  138. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/pack_evals.py +0 -0
  139. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/package_catalogue.py +0 -0
  140. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/profile.py +0 -0
  141. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/reconcile.py +0 -0
  142. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/render.py +0 -0
  143. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/scaffold.py +0 -0
  144. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/show.py +0 -0
  145. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/uninstall.py +0 -0
  146. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/upgrade.py +0 -0
  147. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/commands/validate.py +0 -0
  148. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/config.py +0 -0
  149. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/https_catalogue.py +0 -0
  150. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/pack_inventory.py +0 -0
  151. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/render.py +0 -0
  152. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/safety.py +0 -0
  153. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/scope.py +0 -0
  154. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/statelock.py +0 -0
  155. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle/user_config.py +0 -0
  156. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle.egg-info/dependency_links.txt +0 -0
  157. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle.egg-info/entry_points.txt +0 -0
  158. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle.egg-info/requires.txt +0 -0
  159. {agentbundle-0.19.0 → agentbundle-0.20.1}/agentbundle.egg-info/top_level.txt +0 -0
  160. {agentbundle-0.19.0 → agentbundle-0.20.1}/setup.cfg +0 -0
  161. {agentbundle-0.19.0 → agentbundle-0.20.1}/tests/test_linear_primitive.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentbundle
3
- Version: 0.19.0
3
+ Version: 0.20.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
@@ -34,6 +34,8 @@ Requires-Dist: pyyaml>=6.0; extra == "lint"
34
34
  pip install agentbundle
35
35
  ```
36
36
 
37
+ Requires Python 3.11+. Runs on macOS, Linux, and Windows.
38
+
37
39
  **Install into a repo** — so everyone who clones it gets the pack. `core` is the flagship pack, the loop itself:
38
40
 
39
41
  ```bash
@@ -12,6 +12,8 @@
12
12
  pip install agentbundle
13
13
  ```
14
14
 
15
+ Requires Python 3.11+. Runs on macOS, Linux, and Windows.
16
+
15
17
  **Install into a repo** — so everyone who clones it gets the pack. `core` is the flagship pack, the loop itself:
16
18
 
17
19
  ```bash
@@ -199,6 +199,30 @@
199
199
  "pattern": "^[^/].*"
200
200
  }
201
201
  },
202
+ "runtime-dependencies": {
203
+ "type": "array",
204
+ "description": "External runtime dependencies required by this pack's skills.",
205
+ "items": {
206
+ "type": "object",
207
+ "additionalProperties": false,
208
+ "required": ["ecosystem", "package"],
209
+ "properties": {
210
+ "ecosystem": {
211
+ "type": "string",
212
+ "enum": ["pypi", "npm", "cargo", "go", "homebrew", "apt", "system"]
213
+ },
214
+ "package": {"type": "string"},
215
+ "version": {"type": "string"},
216
+ "optional": {"type": "boolean", "default": false},
217
+ "skills": {
218
+ "type": "array",
219
+ "items": {"type": "string"}
220
+ },
221
+ "install": {"type": "string"},
222
+ "note": {"type": "string"}
223
+ }
224
+ }
225
+ },
202
226
  "layout": {
203
227
  "type": "object",
204
228
  "additionalProperties": false,
@@ -328,6 +328,29 @@ def _build_parser() -> argparse.ArgumentParser:
328
328
  )
329
329
  sp.set_defaults(func=_lazy("show"))
330
330
 
331
+ # --- docs --- (catalogue query; reads packs/<pack>/docs/)
332
+ sp = subparsers.add_parser(
333
+ "docs",
334
+ help=(
335
+ "Read pack documentation from the catalogue source. "
336
+ "Displays index.md by default; use --list to enumerate files."
337
+ ),
338
+ )
339
+ sp.add_argument("pack", help="Pack name to read docs for (e.g. core).")
340
+ sp.add_argument(
341
+ "file",
342
+ nargs="?",
343
+ default=None,
344
+ help="Documentation file stem to display (e.g. 'concept'). Default: index.",
345
+ )
346
+ sp.add_argument(
347
+ "--list",
348
+ action="store_true",
349
+ dest="list_docs",
350
+ help="List available documentation files for the pack.",
351
+ )
352
+ sp.set_defaults(func=_lazy("docs"))
353
+
331
354
  # --- scaffold --- (no --scope; always repo-targeted)
332
355
  sp = subparsers.add_parser(
333
356
  "scaffold",
@@ -913,6 +936,13 @@ def _normalise_path_separators(args: argparse.Namespace) -> None:
913
936
 
914
937
 
915
938
  def main(argv: Sequence[str] | None = None) -> int:
939
+ # Windows cp1252 consoles can't represent non-ASCII chars (⚠, →, etc.).
940
+ # Reconfigure to UTF-8 with backslash-escape fallback so the process
941
+ # never crashes on non-ASCII output regardless of console code page.
942
+ if hasattr(sys.stdout, "reconfigure"):
943
+ sys.stdout.reconfigure(encoding="utf-8", errors="backslashreplace")
944
+ if hasattr(sys.stderr, "reconfigure"):
945
+ sys.stderr.reconfigure(encoding="utf-8", errors="backslashreplace")
916
946
  parser = _build_parser()
917
947
  args = parser.parse_args(argv)
918
948
  if not getattr(args, "func", None):
@@ -100,13 +100,21 @@ def _classify_seeds(seeds_dir: Path, root: Path) -> list[SeedDelivery]:
100
100
  from agentbundle import safety
101
101
 
102
102
  footer_path = seeds_dir / "_agents-footer.md"
103
- footer_ok = footer_path.is_file() and not footer_path.is_symlink()
103
+ try:
104
+ footer_is_symlink = footer_path.is_symlink()
105
+ except OSError:
106
+ footer_is_symlink = True # can't determine; skip conservatively
107
+ footer_ok = footer_path.is_file() and not footer_is_symlink
104
108
 
105
109
  seed_files: list[Path] = []
106
110
  for dirpath, _dirnames, filenames in os.walk(seeds_dir, followlinks=False):
107
111
  for fname in filenames:
108
112
  fpath = Path(dirpath) / fname
109
- if fpath.is_symlink():
113
+ try:
114
+ fpath_is_symlink = fpath.is_symlink()
115
+ except OSError:
116
+ fpath_is_symlink = True # can't determine; skip conservatively
117
+ if fpath_is_symlink:
110
118
  continue
111
119
  seed_files.append(fpath)
112
120
 
@@ -0,0 +1,117 @@
1
+ """``agentbundle docs <pack>`` subcommand.
2
+
3
+ Display pack documentation from the pack's docs/ directory.
4
+
5
+ agentbundle docs <pack> — display index.md
6
+ agentbundle docs <pack> --list — list available .md files by stem
7
+ agentbundle docs <pack> <file> — display a specific file by stem
8
+
9
+ Resolution uses the same four-layer source chain as install. The docs/
10
+ directory travels inside Artifactory archives, so this verb works across
11
+ all four source types (local path, editable install, git+https, archive).
12
+
13
+ Exit codes:
14
+ 0 — success
15
+ 1 — catalogue unavailable, pack not found, no docs/ directory, or file
16
+ not found
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import sys
22
+ from pathlib import Path
23
+ from typing import TYPE_CHECKING
24
+
25
+ if TYPE_CHECKING:
26
+ import argparse
27
+
28
+ _BOLD_ON = "\x1b[1m"
29
+ _BOLD_OFF = "\x1b[0m"
30
+
31
+
32
+ def run(args: "argparse.Namespace") -> int:
33
+ from agentbundle.catalogue import CatalogueError, resolve_catalogue
34
+ from agentbundle.commands._common import resolve_catalogue_uri
35
+ from agentbundle.commands.show import _find_pack_dir
36
+
37
+ pack_name: str = args.pack
38
+ file_stem: str | None = getattr(args, "file", None)
39
+ list_mode: bool = getattr(args, "list_docs", False)
40
+
41
+ try:
42
+ catalogue_dir = resolve_catalogue(resolve_catalogue_uri(args))
43
+ except CatalogueError as exc:
44
+ print(f"docs: {exc}", file=sys.stderr)
45
+ return 1
46
+
47
+ match = _find_pack_dir(catalogue_dir, pack_name)
48
+ if match is None:
49
+ print(f"docs: pack {pack_name!r} not found in catalogue", file=sys.stderr)
50
+ return 1
51
+
52
+ pack_dir, _ = match
53
+ docs_dir = pack_dir / "docs"
54
+ if not docs_dir.is_dir():
55
+ print(f"docs: {pack_name}: no docs directory in pack source", file=sys.stderr)
56
+ return 1
57
+
58
+ md_files = sorted(
59
+ p for p in docs_dir.iterdir()
60
+ if p.suffix == ".md" and not p.name.startswith("_")
61
+ )
62
+
63
+ if list_mode:
64
+ for f in md_files:
65
+ print(f.stem)
66
+ return 0
67
+
68
+ stem = file_stem or "index"
69
+ target: Path | None = None
70
+ for f in md_files:
71
+ if f.stem == stem:
72
+ target = f
73
+ break
74
+
75
+ if target is None:
76
+ available = ", ".join(f.stem for f in md_files) or "none"
77
+ print(
78
+ f"docs: {pack_name}: file {stem!r} not found. Available: {available}",
79
+ file=sys.stderr,
80
+ )
81
+ return 1
82
+
83
+ text = target.read_text(encoding="utf-8")
84
+ tty = sys.stdout.isatty()
85
+ print(_render_md(text, tty=tty), end="")
86
+ return 0
87
+
88
+
89
+ def _render_md(text: str, *, tty: bool) -> str:
90
+ """Render Markdown as plain text, optionally with ANSI bold headings.
91
+
92
+ Preserves code blocks verbatim. Strips heading # markers (bold on tty,
93
+ plain text otherwise). Strips link syntax [text](url) to bare text.
94
+ """
95
+ import re
96
+
97
+ lines = text.splitlines(keepends=False)
98
+ out: list[str] = []
99
+ in_code = False
100
+
101
+ for line in lines:
102
+ if line.startswith("```"):
103
+ in_code = not in_code
104
+ out.append(line)
105
+ continue
106
+ if in_code:
107
+ out.append(line)
108
+ continue
109
+ m = re.match(r"^(#{1,6})\s+(.*)", line)
110
+ if m:
111
+ content = m.group(2)
112
+ out.append(f"{_BOLD_ON}{content}{_BOLD_OFF}" if tty else content)
113
+ continue
114
+ processed = re.sub(r"\[([^\]]+)\]\([^)]*\)", r"\1", line)
115
+ out.append(processed)
116
+
117
+ return "\n".join(out) + ("\n" if out else "")
@@ -1648,7 +1648,11 @@ def _deliver_user_scope_floor(
1648
1648
  # Reject a symlinked primitive dir itself (os.walk(top=symlink) enumerates
1649
1649
  # the link target's real files, which the per-entry is_symlink() skip below
1650
1650
  # would not catch) — see collect_pack_root_bins for the bin/ twin.
1651
- has_lib = lib_src_root.is_dir() and not lib_src_root.is_symlink()
1651
+ try:
1652
+ lib_src_is_symlink = lib_src_root.is_symlink()
1653
+ except OSError:
1654
+ lib_src_is_symlink = True # can't determine; skip conservatively
1655
+ has_lib = lib_src_root.is_dir() and not lib_src_is_symlink
1652
1656
  if not bin_sources and not has_lib:
1653
1657
  # No floor content in this pack — nothing to deliver, and no reason to
1654
1658
  # gate the install on the floor dirs' modes.
@@ -1686,7 +1690,11 @@ def _deliver_user_scope_floor(
1686
1690
  )
1687
1691
  for fname in sorted(filenames):
1688
1692
  src = Path(dirpath) / fname
1689
- if src.is_symlink():
1693
+ try:
1694
+ src_is_symlink = src.is_symlink()
1695
+ except OSError:
1696
+ src_is_symlink = True # can't determine; skip conservatively
1697
+ if src_is_symlink:
1690
1698
  continue
1691
1699
  rel = src.relative_to(lib_src_root)
1692
1700
  relpath = (Path(".agentbundle") / "lib" / rel).as_posix()
@@ -294,7 +294,11 @@ def _enclosing_git_root(start: Path) -> Path | None:
294
294
  """
295
295
  cur = start
296
296
  while True:
297
- if (cur / ".git").exists():
297
+ try:
298
+ exists = (cur / ".git").exists()
299
+ except OSError:
300
+ exists = False
301
+ if exists:
298
302
  return cur
299
303
  if cur.parent == cur:
300
304
  return None
@@ -354,7 +358,12 @@ def _detect_editable_source(dist: object, *, stream: TextIO | None = None) -> st
354
358
  return None
355
359
  if parts.netloc not in ("", "localhost"):
356
360
  return None
357
- pkg_path = Path(url2pathname(unquote(parts.path)))
361
+ raw = url2pathname(unquote(parts.path))
362
+ # url2pathname on some Windows Python builds returns "/C:\path" with a
363
+ # spurious leading slash before the drive letter; strip it.
364
+ if sys.platform == "win32" and len(raw) >= 3 and raw[0] == "/" and raw[2] == ":":
365
+ raw = raw[1:]
366
+ pkg_path = Path(raw)
358
367
  try:
359
368
  pkg_root = pkg_path.resolve(strict=True)
360
369
  except OSError:
@@ -14,7 +14,7 @@ import tomllib
14
14
  from importlib.resources import files
15
15
  from pathlib import Path
16
16
 
17
- CLI_VERSION = "0.19.0"
17
+ CLI_VERSION = "0.20.1"
18
18
 
19
19
  _HERE = Path(__file__).resolve().parent
20
20
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentbundle
3
- Version: 0.19.0
3
+ Version: 0.20.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
@@ -34,6 +34,8 @@ Requires-Dist: pyyaml>=6.0; extra == "lint"
34
34
  pip install agentbundle
35
35
  ```
36
36
 
37
+ Requires Python 3.11+. Runs on macOS, Linux, and Windows.
38
+
37
39
  **Install into a repo** — so everyone who clones it gets the pack. `core` is the flagship pack, the loop itself:
38
40
 
39
41
  ```bash
@@ -139,6 +139,7 @@ agentbundle/commands/catalogue_tooling_stub.py
139
139
  agentbundle/commands/catalogue_verify.py
140
140
  agentbundle/commands/config.py
141
141
  agentbundle/commands/diff.py
142
+ agentbundle/commands/docs.py
142
143
  agentbundle/commands/init_state.py
143
144
  agentbundle/commands/install.py
144
145
  agentbundle/commands/list_installed.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "agentbundle"
7
- version = "0.19.0"
7
+ version = "0.20.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