agentnet-cli 0.3.0__tar.gz → 0.4.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. agentnet_cli-0.4.1/CHANGELOG.md +24 -0
  2. agentnet_cli-0.4.1/CLAUDE.md +82 -0
  3. agentnet_cli-0.4.1/GLOSSARY.md +598 -0
  4. agentnet_cli-0.4.1/LICENSE +21 -0
  5. agentnet_cli-0.4.1/PKG-INFO +409 -0
  6. agentnet_cli-0.4.1/README.md +381 -0
  7. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/pyproject.toml +1 -1
  8. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/cli/main.py +78 -11
  9. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/cursor.py +9 -0
  10. agentnet_cli-0.4.1/src/agentnet_cli/connectors/cursor_hook.py +108 -0
  11. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/hermes.py +9 -0
  12. agentnet_cli-0.4.1/src/agentnet_cli/connectors/hermes_hook.py +188 -0
  13. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/templates/SKILL.hosted.md +1 -1
  14. agentnet_cli-0.4.1/src/agentnet_cli/connectors/templates/cursor/agent.md +22 -0
  15. agentnet_cli-0.4.1/src/agentnet_cli/connectors/templates/cursor/agentnet.mdc +32 -0
  16. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/integrations/openclaw/openclaw.plugin.json +1 -1
  17. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/integrations/openclaw/package.json +1 -1
  18. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/marketplace/client.py +50 -1
  19. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/marketplace/skills/discovery.py +39 -4
  20. agentnet_cli-0.4.1/src/agentnet_cli/tools/claude_hook.py +206 -0
  21. agentnet_cli-0.4.1/src/agentnet_cli/tools/cursor_hook.py +100 -0
  22. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/tools/hermes/plugin.yaml +1 -1
  23. agentnet_cli-0.4.1/src/agentnet_cli/tools/hermes_hook.py +111 -0
  24. agentnet_cli-0.4.1/src/agentnet_cli/tools/skillfire/__init__.py +44 -0
  25. agentnet_cli-0.4.1/src/agentnet_cli/tools/skillfire/broker.py +205 -0
  26. agentnet_cli-0.4.1/src/agentnet_cli/tools/skillfire/candidates.py +75 -0
  27. agentnet_cli-0.4.1/src/agentnet_cli/tools/skillfire/classifier.py +203 -0
  28. agentnet_cli-0.4.1/src/agentnet_cli/tools/skillfire/config.py +79 -0
  29. agentnet_cli-0.4.1/src/agentnet_cli/tools/skillfire/content.py +152 -0
  30. agentnet_cli-0.4.1/src/agentnet_cli/tools/skillfire/render.py +59 -0
  31. agentnet_cli-0.4.1/src/agentnet_cli/tools/skillfire/session.py +111 -0
  32. agentnet_cli-0.4.1/src/agentnet_cli/tools/skillfire/steer.py +137 -0
  33. agentnet_cli-0.4.1/src/agentnet_cli/tools/skillfire/worker.py +188 -0
  34. agentnet_cli-0.4.1/tests/skillfire/__init__.py +0 -0
  35. agentnet_cli-0.4.1/tests/skillfire/test_broker.py +146 -0
  36. agentnet_cli-0.4.1/tests/skillfire/test_candidates.py +64 -0
  37. agentnet_cli-0.4.1/tests/skillfire/test_classifier.py +161 -0
  38. agentnet_cli-0.4.1/tests/skillfire/test_config.py +15 -0
  39. agentnet_cli-0.4.1/tests/skillfire/test_content.py +139 -0
  40. agentnet_cli-0.4.1/tests/skillfire/test_init.py +117 -0
  41. agentnet_cli-0.4.1/tests/skillfire/test_render.py +35 -0
  42. agentnet_cli-0.4.1/tests/skillfire/test_steer.py +88 -0
  43. agentnet_cli-0.4.1/tests/skillfire/test_worker.py +453 -0
  44. agentnet_cli-0.4.1/tests/test_claude_hook.py +379 -0
  45. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_cli.py +22 -0
  46. agentnet_cli-0.4.1/tests/test_cursor_hook.py +226 -0
  47. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_discovery.py +52 -0
  48. agentnet_cli-0.4.1/tests/test_discovery_skill.py +110 -0
  49. agentnet_cli-0.4.1/tests/test_hermes_hook.py +268 -0
  50. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_platform_client.py +57 -0
  51. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_updater.py +46 -0
  52. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/uv.lock +1 -1
  53. agentnet_cli-0.3.0/CHANGELOG.md +0 -9
  54. agentnet_cli-0.3.0/CLAUDE.md +0 -74
  55. agentnet_cli-0.3.0/PKG-INFO +0 -264
  56. agentnet_cli-0.3.0/README.md +0 -237
  57. agentnet_cli-0.3.0/src/agentnet_cli/connectors/templates/cursor/agent.md +0 -9
  58. agentnet_cli-0.3.0/src/agentnet_cli/connectors/templates/cursor/agentnet.mdc +0 -6
  59. agentnet_cli-0.3.0/src/agentnet_cli/tools/hook.py +0 -674
  60. agentnet_cli-0.3.0/tests/test_discovery_skill.py +0 -55
  61. agentnet_cli-0.3.0/tests/test_skill_hook.py +0 -583
  62. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/.github/workflows/ci.yml +0 -0
  63. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/.github/workflows/publish.yml +0 -0
  64. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/.gitignore +0 -0
  65. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/ARCHITECTURE.md +0 -0
  66. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/docs/archive/superpowers/plans/2026-05-09-hermes-native-plugin.md +0 -0
  67. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/docs/archive/superpowers/plans/2026-05-09-marketplace-cli-and-skill.md +0 -0
  68. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/docs/archive/superpowers/plans/2026-05-10-claude-native-plugin.md +0 -0
  69. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/docs/archive/superpowers/plans/2026-05-10-openclaw-native-plugin.md +0 -0
  70. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/docs/archive/superpowers/specs/2026-05-09-hermes-native-plugin-design.md +0 -0
  71. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/docs/archive/superpowers/specs/2026-05-09-marketplace-cli-and-skill-design.md +0 -0
  72. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/docs/archive/superpowers/specs/2026-05-10-claude-native-plugin-design.md +0 -0
  73. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/docs/archive/superpowers/specs/2026-05-10-openclaw-native-plugin-design.md +0 -0
  74. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/__init__.py +0 -0
  75. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/cli/__init__.py +0 -0
  76. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/cli/core/__init__.py +0 -0
  77. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/cli/core/connect.py +0 -0
  78. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/cli/core/detect.py +0 -0
  79. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/cli/core/disconnect.py +0 -0
  80. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/cli/core/register.py +0 -0
  81. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/cli/core/setup_wizard.py +0 -0
  82. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/cli/core/status.py +0 -0
  83. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/cli/core/updater.py +0 -0
  84. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/cli/marketplace/__init__.py +0 -0
  85. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/cli/marketplace/agent.py +0 -0
  86. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/cli/marketplace/discover.py +0 -0
  87. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/README.md +0 -0
  88. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/__init__.py +0 -0
  89. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/base.py +0 -0
  90. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/claude.py +0 -0
  91. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/claude_search_hook.py +0 -0
  92. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/codex.py +0 -0
  93. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/copilot.py +0 -0
  94. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/openclaw.py +0 -0
  95. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/registry.py +0 -0
  96. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/shims.py +0 -0
  97. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/templates/README.md +0 -0
  98. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/templates/codex/skill.md +0 -0
  99. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/templates/copilot/agentnet.agent.md +0 -0
  100. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/templates/shared/context.md +0 -0
  101. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/templates/shared/default-chat.md +0 -0
  102. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/templates/vscode/instructions.md +0 -0
  103. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/connectors/vscode.py +0 -0
  104. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/infra/__init__.py +0 -0
  105. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/infra/config.py +0 -0
  106. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/infra/manifest.py +0 -0
  107. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/infra/package_paths.py +0 -0
  108. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/infra/paths.py +0 -0
  109. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/infra/platform.py +0 -0
  110. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/integrations/claude/.claude-plugin/marketplace.json +0 -0
  111. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/integrations/claude/plugin/.claude-plugin/plugin.json +0 -0
  112. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/integrations/claude/plugin/.mcp.json +0 -0
  113. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/integrations/claude/plugin/agents/marketplace.md +0 -0
  114. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/integrations/claude/plugin/hooks/hooks.json +0 -0
  115. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/integrations/claude/plugin/skills/agentnet/SKILL.md +0 -0
  116. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/integrations/openclaw/.mcp.json +0 -0
  117. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/integrations/openclaw/index.js +0 -0
  118. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/integrations/openclaw/skills/agentnet/SKILL.md +0 -0
  119. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/integrations/shared/discovery-skill.base.md +0 -0
  120. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/marketplace/__init__.py +0 -0
  121. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/marketplace/auth.py +0 -0
  122. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/marketplace/catalogs/__init__.py +0 -0
  123. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/marketplace/catalogs/claude_marketplace.py +0 -0
  124. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/marketplace/catalogs/clawhub.py +0 -0
  125. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/marketplace/skills/__init__.py +0 -0
  126. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/marketplace/skills/client.py +0 -0
  127. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/marketplace/skills/skillsmp.py +0 -0
  128. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/tools/__init__.py +0 -0
  129. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/tools/handlers.py +0 -0
  130. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/tools/hermes/__init__.py +0 -0
  131. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/tools/hermes/handlers.py +0 -0
  132. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/tools/hermes/schemas.py +0 -0
  133. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/tools/hermes/skills/agentnet/SKILL.md +0 -0
  134. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/src/agentnet_cli/tools/mcp_server.py +0 -0
  135. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/__init__.py +0 -0
  136. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/conftest.py +0 -0
  137. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_agent_cmd.py +0 -0
  138. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_claude.py +0 -0
  139. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_claude_marketplace.py +0 -0
  140. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_claude_search_hook.py +0 -0
  141. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_clawhub_client.py +0 -0
  142. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_codex.py +0 -0
  143. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_config.py +0 -0
  144. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_copilot.py +0 -0
  145. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_cursor.py +0 -0
  146. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_detect.py +0 -0
  147. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_discover_cmd.py +0 -0
  148. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_e2e.py +0 -0
  149. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_hermes.py +0 -0
  150. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_hermes_plugin.py +0 -0
  151. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_manifest.py +0 -0
  152. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_marketplace.py +0 -0
  153. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_mcp_tools.py +0 -0
  154. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_openclaw.py +0 -0
  155. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_paths.py +0 -0
  156. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_platform_config.py +0 -0
  157. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_register.py +0 -0
  158. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_server.py +0 -0
  159. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_skills_client.py +0 -0
  160. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_skillsmp_client.py +0 -0
  161. {agentnet_cli-0.3.0 → agentnet_cli-0.4.1}/tests/test_vscode.py +0 -0
@@ -0,0 +1,24 @@
1
+ # Changelog
2
+
3
+ ## 0.4.1 - 2026-07-23
4
+
5
+ - Add Claude-safe skill-fire steer wording and system-message support.
6
+ - Include platform usage context in skill-fire discovery flows.
7
+ - Refresh README placement for the agent bootstrap command.
8
+ - Bump bundled Hermes, hosted skill, and OpenClaw integration metadata to match the CLI release.
9
+
10
+ ## 0.4.0 - 2026-07-23
11
+
12
+ - Add every-prompt skill-fire support for Cursor and Hermes.
13
+ - Split skill-fire hook logic into a ports-and-adapters package for cleaner connector-specific integrations.
14
+ - Share Hermes user memory with the skill-fire relevance gate.
15
+ - Add Cursor and Hermes hook test coverage for the new hard-nudge flow.
16
+ - Bump bundled Hermes, hosted skill, and OpenClaw integration metadata to match the CLI release.
17
+
18
+ ## 0.3.0 - 2026-07-18
19
+
20
+ - Add Claude Code search-fire hook support so AgentNet can surface relevant marketplace skills during search workflows.
21
+ - Add `agentnet enable-search-fire` for one-command Claude hook installation.
22
+ - Preserve malformed Claude settings files instead of overwriting them during connector setup.
23
+ - Add setup telemetry hooks and a platform client telemetry helper.
24
+ - Bump bundled Hermes, hosted skill, and OpenClaw integration metadata to match the CLI release.
@@ -0,0 +1,82 @@
1
+ # agentnet-cli
2
+
3
+ CLI tool that detects AI coding agents on your system and connects them to the [Agent-net](https://agentnet.market) marketplace via MCP.
4
+
5
+ ## Tech Stack
6
+
7
+ - **Language:** Python 3.11+ (ruff linting, 100-char line length)
8
+ - **Package manager:** uv
9
+ - **CLI framework:** Typer + Rich
10
+ - **HTTP client:** httpx
11
+ - **Testing:** pytest (511 tests), pytest-cov
12
+ - **CI:** GitHub Actions (lint + test matrix on 3.11/3.12/3.13)
13
+ - **Publish:** PyPI via trusted publisher (tag `v*`)
14
+
15
+ ## Repository Structure
16
+
17
+ See [ARCHITECTURE.md](ARCHITECTURE.md). Layers:
18
+
19
+ - `cli/` — Typer entry (`cli/main.py`), core commands, marketplace JSON commands
20
+ - `connectors/` — per-agent wiring + `templates/` for file injection
21
+ - `marketplace/` — platform client, external catalogs, skill discovery
22
+ - `tools/` — MCP stdio server, Hermes plugin, and `skillfire/` (the every-prompt skill-fire pipeline)
23
+ - `infra/` — config, paths, manifest
24
+ - `src/agentnet_cli/integrations/` — Claude and OpenClaw native plugin trees (bundled in wheel)
25
+
26
+ ## Key Commands
27
+
28
+ ```bash
29
+ uv sync --group dev # Install deps
30
+ uv run pytest -v # Run tests
31
+ uv run pytest --cov -q # With coverage
32
+ uv run ruff check . # Lint
33
+ uv run agentnet --help # Run locally
34
+ ```
35
+
36
+ ## Key Patterns
37
+
38
+ - **Agent Connector:** Abstract `AgentConnector` base with `detect()`, `connect()`, `disconnect()`. Add new agents by subclassing and registering in `registry.py`.
39
+ - **Manifest rollback:** `manifest.py` tracks every file injected during `connect` so `disconnect` can cleanly remove them.
40
+ - **Config persistence:** `~/.agentnet/config.json` stores platform credentials (0600 permissions). Agent custom paths stored separately.
41
+ - **MCP server:** `agentnet mcp-serve` (hidden command) starts stdio JSON-RPC server. Agents launch this as a subprocess.
42
+ - **Marketplace commands:** All output JSON to stdout. Errors output `{"error": "..."}` with exit code 1.
43
+ - **Claude Code Plugin:** `agentnet connect claude` delegates to `claude plugin marketplace add` + `claude plugin install` instead of writing files directly. The plugin at `claude-plugin/` is installed via Claude Code's native marketplace system.
44
+ - **Hermes Plugin:** `agentnet connect hermes` copies the plugin to `~/.hermes/plugins/agentnet/` and skills to `~/.hermes/skills/agentnet/`, using Hermes's native plugin system.
45
+ - **OpenClaw Plugin:** `agentnet connect openclaw` delegates to `openclaw plugins install` + `openclaw plugins uninstall` instead of writing files directly. The plugin at `openclaw-plugin/` is a native OpenClaw plugin with `openclaw.plugin.json` manifest, publishable to ClawHub.
46
+ - **Plugin hint:** The CLI emits a `<claude-code-hint>` tag on stderr when `CLAUDECODE=1` is set, prompting Claude Code users to install the plugin.
47
+ - **Auto-update on the hook flow:** `maybe_auto_update()` (rate-limited 24h via manifest `last_update_check_at`, gated by `AGENTNET_AUTO_UPDATE`, PyPI version check, background installer upgrade + stale-integration refresh) runs on every non-hook `agentnet` command via the Typer `@app.callback()`. The **hook** commands (`{skill,cursor,hermes}-hook`) are excluded there (`_HOOK_COMMANDS`) so `--pre`/`--peek`/`--post` never block a tool call; the update runs **once per turn from the detached `--fetch` worker** (`skillfire.run_fetch`), off the agent's critical path.
48
+ - **Skill-fire architecture — `tools/skillfire/` (ports & adapters):** the every-prompt skill-fire pipeline shared by all three harnesses lives in `tools/skillfire/`, split by responsibility — `config.py` (constants/credentials), `session.py` (event/cache/atomic-claim primitives), `candidates.py` (skills.sh discovery), `classifier.py` (the three backend gate runners), `render.py` (**pure**, zero I/O — the fenced user-facing list), `content.py` (`npx skills use` fetch, owns that `subprocess` call site so a test patching it can't affect the classifier's or candidate-discovery's), `broker.py` (brokered-A2A fallback), `worker.py` (orchestrates discovery → classify → render → content/broker → cache, plus `spawn_worker`), `steer.py` (steer-text + the `check_steer`/`check_fallback` decisions). `tools/skillfire/__init__.py` is **the port** — the only surface the three adapters (`tools/claude_hook.py`, `tools/cursor_hook.py`, `tools/hermes_hook.py`) may import: `spawn_worker(session, prompt, *, limit, timeout, classifier)` (launch the detached worker, spawn-claim + stale-cleanup + `Popen` in one call), `check_steer(session)`/`check_fallback(session, *, timeout)` (the shared, wrapped decision — mid-run/fallback text or `None` — used by Cursor/Hermes), `check_steer_raw`/`check_fallback_raw` (same decision, bare outcome with no wrapper text, so a harness can build its own presentation — used by Claude, see below), `run_fetch` (the CLI-invoked worker entrypoint), plus the `SUBAGENT_ENV`/`AGENTNET_SENTINEL` constants. The `_raw` variants are purely additive — appended to `steer.py`, never touching `check_steer`/`check_fallback`'s own bodies — so Cursor/Hermes are byte-for-byte unaffected by anything Claude-specific. Internals are free to reshuffle without touching an adapter or `main.py`, since none of them reach past the port. Tests mirror the module split 1:1 under `tests/skillfire/`.
49
+ - **Every-prompt skill hook (Claude Code):** `agentnet enable-skill-fire` (and `connect claude`) install three hooks in `~/.claude/settings.json` (also bundled in the plugin's `hooks/hooks.json`), dispatched to `tools/claude_hook.py`. `UserPromptSubmit` → `agentnet skill-hook --pre` calls `skillfire.spawn_worker(..., classifier="claude")` and returns immediately (0 latency). The worker discovers **installable skill candidates** (`discover_skills` → skills.sh, each carrying a `<repo>@<slug>`) + runs a cheap no-tool `claude -p` **classifier** (Haiku) as the reliable relevance **gate** (a bare yes/no gate isn't — the model just answers). Two-phase so the outcome reaches the hooks fast: **Phase 1** caches the **recommendation list** (relevant skills by name + why + skills.sh link) the moment the gate opens (~12s); **Phase 2** *appends* the top match fetched via `npx skills use <repo>@<slug>` (which downloads the skill — SKILL.md + references — to a temp dir; single-file skills are materialized to a temp `SKILL.md`) as a **concise header (name + description) + the on-disk path**, not a full SKILL.md dump. The injected outcome is thus the list *then* "Reading the top match and applying it." + that block — the agent surfaces the list and reads/applies the methodology from disk, which is what makes it *act* on the skill rather than just mention it. No files are written to the repo. If content is unavailable (no `npx`/all fetches miss), Phase 2 falls back — behind the same open gate — to the live **Skills Agent** over **brokered A2A**: `PlatformClient.use_agent(agent_id="agentnet-skills-agent", task=…)` with the user's `setup` identity; the platform relays A2A and returns `{status:"settled", agent_response}` in one call. **No skills-agent token is ever held client-side.** Only a `settled` response is used. Injection is layered: `PostToolUse` → `agentnet skill-hook --peek` calls `skillfire.check_steer_raw` (the bare outcome, no wrapper) to force-steer the agent **mid-flight** once the outcome is ready (`{"decision":"block","reason":…, "systemMessage":…}`); `Stop` → `agentnet skill-hook --post` calls `skillfire.check_fallback_raw`, the guaranteed fallback (`{"decision":"block", "systemMessage":…, …additionalContext}`) for no-tool answers. Claude builds its **own** plain-language wording in `claude_hook.py` rather than the shared `steer_reason`/`fold_context` Cursor/Hermes use (see below) — no STEP-numbered "reproduce this verbatim" scaffolding, and no claim that any section is hidden from the user. Reason: Claude Code prints the entire `reason`/`additionalContext` payload to the user's terminal (native CLI behavior), so the shared wording's `AGENT_ONLY` label ("do not show the user") is an observable lie there — live testing showed a session flag it as a probable prompt injection and refuse to comply. `systemMessage` (set on both events) is a separate, platform-guaranteed display channel — never passed to the model, shown to the user regardless of what the model does next — so the skill list's visibility no longer depends on model compliance the way `reason`/`additionalContext` do. Because the hooks are registered in **both** `settings.json` (via `connect`/`enable-skill-fire`) and the plugin's `hooks.json`, Claude Code may run each twice in parallel — so idempotence is enforced with **atomic `O_EXCL` once-claims** inside `session.py`: a per-`(session,prompt)` **spawn marker** so duplicate `--pre` hooks spawn exactly one worker (not 2× classifier cost), and a per-prompt **emit marker** shared by peek + post so exactly one steer fires (and a re-fired `Stop` no-ops). The cache carries a **`final`** flag: Phase 1 writes `final:false` (the list names skills but has no methodology), Phase 2 writes `final:true` once content is attached — or promotes the list to `final` when no content is reachable. **A mid-run steer only fires on a `final` outcome**, so it can't burn its one shot on a list the agent has nothing to apply from; the `Stop`/fallback surface takes a non-final list as a last resort. Session-keyed JSON cache `$TMPDIR/agentnet-skill/<session>.json` (`{outcome, final}`) + sibling `.emitted`/`.<hash>.spawn` markers; `AGENTNET_SKILL_SUBAGENT=1` guards recursion. All best-effort — no token/binary/candidates/unreachable-platform/timeout injects nothing. `agent_id` overridable via `AGENTNET_SKILLS_AGENT_ID`/config. Implemented in `tools/skillfire/` + `tools/claude_hook.py` + `connectors/claude_search_hook.py`.
50
+
51
+ - **Every-prompt skill hook (Cursor):** `agentnet connect cursor` also installs three hooks in `~/.cursor/hooks.json` (`connectors/cursor_hook.py`) that call the *same* `skillfire` port as Claude — only the thin I/O adapter differs (`tools/cursor_hook.py`, command `agentnet cursor-hook --pre/--peek/--post`; session key is Cursor's `conversation_id`). `beforeSubmitPrompt` → `--pre` calls `spawn_worker(..., classifier="cursor")` and allows the prompt (`{"continue":true}` — this event can't inject). `preToolUse` → `--peek` is the **hard nudge**: Cursor's only forceful steer is a denied action, so `check_steer` denies the first tool call **once** (`{"permission":"deny","agent_message":…}`) once the outcome is ready, and the agent must read+apply the skill then retry; every later call is allowed. `stop` → `--post` calls `check_fallback`, the fallback for no-tool answers via `followup_message` (auto-submitted next turn); it's `[AgentNet]`-tagged so the re-fired `--pre` recognizes its own injection and won't loop. The relevance **gate runs on the user's own Cursor model** via `cursor-agent -p --mode ask --output-format text --trust` (`classify(backend="cursor")` in `tools/skillfire/classifier.py`). The backend-aware classifier tries the requested CLI first and falls back to the other (`claude -p` ↔ `cursor-agent -p`) so a machine with only one still gates; Cursor needs `cursor-agent login` (auth), and `AGENTNET_CURSOR_CLASSIFIER_MODEL` pins a cheaper/faster gate model than the default.
52
+
53
+ - **Every-prompt skill hook (Hermes):** `agentnet connect hermes` also installs three **shell hooks** in `~/.hermes/config.yaml` (`connectors/hermes_hook.py`), calling the *same* `skillfire` port; only the I/O adapter differs (`tools/hermes_hook.py`, `agentnet hermes-hook --pre/--peek/--post`; session key is `session_id`, the prompt is `extra.user_message`). `pre_llm_call` → `--pre` calls `spawn_worker(..., classifier="hermes")` (Hermes' documented `UserPromptSubmit` equivalent; it *can* inject `{"context":…}` but the worker needs ~20s, so the steer lands later). `pre_tool_call` → `--peek` is the hard nudge: Hermes **natively accepts the Claude-Code `{"decision":"block","reason":…}` shape** (it normalizes to `{"action":"block","message":…}`) and returns the reason to the model as the tool's error, so it re-plans inline. `pre_verify` → `--post` fires when the agent edited code and is about to finish; `{"action":"continue","message":…}` appends a synthetic user turn (gated on `extra.attempt` since it re-fires per nudge, bounded by `agent.max_verify_nudges`). Gate backend `hermes` runs an **in-process `AIAgent`** on the user's own model via `gateway.run._resolve_gateway_model` + `_resolve_runtime_agent_kwargs` (no subprocess, no separate auth; `skip_memory=False` shares the user's memory/profile so the gate ranks per-user, while `disabled_toolsets` (incl. `memory`) + `max_iterations=1` keep it a one-shot classify), falling back to the CLI backends when not importable. Shell hooks need **consent** — install writes scoped entries to `~/.hermes/shell-hooks-allowlist.json` for our three commands only (narrower than global `hooks_auto_accept`), and registers the **absolute** binary path since `hermes hooks doctor` stats the command's first token. Verify headlessly with `hermes hooks list` / `doctor` / `test <event> --payload-file`.
54
+
55
+ - **Platform call context & usage analytics:** the skill-fire pipeline attaches optional call context to its platform calls, but **the gate model rides only on post-classification records, never on the retrieval call.** `GET /skills/discover` (`marketplace/skills/discovery.py`) is candidate *retrieval* — it fires **before** the classifier runs, so which model/backend will gate is unknown there (and the backend can fall back), so it carries **only** `harness` (`claude`/`cursor`/`hermes`, the requested backend — still which IDE the user is in, unaffected by fallback) and `session_id`. The **post-gate** records — the brokered `POST /agents/{id}/use` (`marketplace/client.py::use_agent`, via `broker.negotiate_via_platform`) and the usage-telemetry `POST /skills/discover/feedback` (`broker.report_recommendation`) — additionally carry `classifier_model` and `model`, resolved for the **backend that *actually* ran** (`classify()` returns `(relevant, actual_backend)`; `worker.py` resolves the model from `actual_backend`, not the requested one). `classifier_model` comes from `classifier.resolve_classifier_model()`, a pure per-backend lookup done *without* invoking the classifier: the fixed `SUBAGENT_MODEL` constant for Claude, the `AGENTNET_CURSOR_CLASSIFIER_MODEL` env value for Cursor if pinned, `_resolve_gateway_model()` for Hermes. `model` is Hermes-only — identical to `classifier_model`, since Hermes classifies on the user's own model in-process; confirmed unobtainable for Claude/Cursor (no hooked event payload exposes the driving model, per Claude Code's own hook docs). Because discovery makes **no** model claim, its record can never *conflict* with the authoritative model on the feedback/broker record for the same recommendation. Every field is added only when resolvable — omitted, never sent as `null` or guessed — and the platform's routes ignore unrecognized query params/JSON keys by default, so this ships independently of the platform's own timeline. `broker.report_recommendation()` fires the feedback `POST` the moment the classifier gate opens (non-empty relevant list) — usage telemetry for "which skills get recommended," dispatched to a **daemon thread** so it never delays the phase-1 cache write, and **`.join()`-ed (bounded by `config.REPORT_JOIN_TIMEOUT`) right before the worker returns** so a fast-exiting process doesn't kill the thread before its HTTP call lands. Wrapped in the same try/except-everywhere pattern as every other platform call here, so a `404` (route not yet live) is silently absorbed exactly like a network failure would be. The feedback payload matches the platform's `SkillFeedbackRequest` exactly (`use_case`, `recommended:[{name,why,score}]` with `score` always a `str|None`, `harness`, `session_id`, `classifier_model`, `model`). Verified end-to-end (not just unit-tested) against a real local platform build: a genuine `uvicorn` server, real FastAPI/Pydantic validation, unmodified CLI code, only the DB session/auth resolution mocked.
56
+
57
+ ## Testing Patterns
58
+
59
+ - **CLI tests:** `typer.testing.CliRunner` + `fake_home` fixture (temp dir with patched `Path.home()`)
60
+ - **HTTP tests:** `httpx.MockTransport` for platform API mocking
61
+ - **MCP tests:** Mock stdin/stdout with `io.StringIO`, mock `ToolHandlers`
62
+ - **Agent tests:** Create fake config dirs in `fake_home` to simulate installed agents
63
+
64
+ ## CI/CD
65
+
66
+ - **CI (`ci.yml`):** Lint (ruff) + tests across Python 3.11/3.12/3.13 on PRs and pushes to main
67
+ - **Publish (`publish.yml`):** Tags matching `v*` trigger PyPI publish via trusted publisher (OIDC)
68
+
69
+ ## Documentation Requirements
70
+
71
+ After any change that affects the project's public interface, structure, or developer workflow, update the relevant docs before committing:
72
+
73
+ - **README.md** — Update if commands, flags, supported agents, install steps, or architecture change
74
+ - **CLAUDE.md** — Update if repo structure, key patterns, test counts, or commands change
75
+ - **Inline docstrings** — Update if a function's contract (params, return, side effects) changes
76
+
77
+ Do not leave docs describing old behavior. If you add a command, it goes in the README. If you add a test file, update the test count here. If you change a pattern, update the Key Patterns section.
78
+
79
+ ## Related Repos
80
+
81
+ - [agentnet-platform](https://github.com/TheAgent-net/agentnet-platform) — FastAPI backend
82
+ - [agentnet-frontend](https://github.com/TheAgent-net/agentnet-frontend) — Admin dashboard, user dashboard, marketplace SPAs