agentnet-cli 0.3.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/CHANGELOG.md +8 -0
- agentnet_cli-0.4.0/CLAUDE.md +80 -0
- agentnet_cli-0.4.0/GLOSSARY.md +598 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/PKG-INFO +2 -2
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/README.md +1 -1
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/pyproject.toml +1 -1
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/cli/main.py +78 -11
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/cursor.py +9 -0
- agentnet_cli-0.4.0/src/agentnet_cli/connectors/cursor_hook.py +108 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/hermes.py +9 -0
- agentnet_cli-0.4.0/src/agentnet_cli/connectors/hermes_hook.py +188 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/templates/SKILL.hosted.md +1 -1
- agentnet_cli-0.4.0/src/agentnet_cli/connectors/templates/cursor/agent.md +22 -0
- agentnet_cli-0.4.0/src/agentnet_cli/connectors/templates/cursor/agentnet.mdc +32 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/integrations/openclaw/openclaw.plugin.json +1 -1
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/integrations/openclaw/package.json +1 -1
- agentnet_cli-0.4.0/src/agentnet_cli/tools/claude_hook.py +93 -0
- agentnet_cli-0.4.0/src/agentnet_cli/tools/cursor_hook.py +100 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/tools/hermes/plugin.yaml +1 -1
- agentnet_cli-0.4.0/src/agentnet_cli/tools/hermes_hook.py +111 -0
- agentnet_cli-0.4.0/src/agentnet_cli/tools/skillfire/__init__.py +38 -0
- agentnet_cli-0.4.0/src/agentnet_cli/tools/skillfire/broker.py +82 -0
- agentnet_cli-0.4.0/src/agentnet_cli/tools/skillfire/candidates.py +59 -0
- agentnet_cli-0.4.0/src/agentnet_cli/tools/skillfire/classifier.py +174 -0
- agentnet_cli-0.4.0/src/agentnet_cli/tools/skillfire/config.py +73 -0
- agentnet_cli-0.4.0/src/agentnet_cli/tools/skillfire/content.py +152 -0
- agentnet_cli-0.4.0/src/agentnet_cli/tools/skillfire/render.py +59 -0
- agentnet_cli-0.4.0/src/agentnet_cli/tools/skillfire/session.py +111 -0
- agentnet_cli-0.4.0/src/agentnet_cli/tools/skillfire/steer.py +99 -0
- agentnet_cli-0.4.0/src/agentnet_cli/tools/skillfire/worker.py +116 -0
- agentnet_cli-0.4.0/tests/skillfire/__init__.py +0 -0
- agentnet_cli-0.4.0/tests/skillfire/test_broker.py +58 -0
- agentnet_cli-0.4.0/tests/skillfire/test_candidates.py +32 -0
- agentnet_cli-0.4.0/tests/skillfire/test_classifier.py +120 -0
- agentnet_cli-0.4.0/tests/skillfire/test_config.py +15 -0
- agentnet_cli-0.4.0/tests/skillfire/test_content.py +139 -0
- agentnet_cli-0.4.0/tests/skillfire/test_init.py +117 -0
- agentnet_cli-0.4.0/tests/skillfire/test_render.py +35 -0
- agentnet_cli-0.4.0/tests/skillfire/test_steer.py +19 -0
- agentnet_cli-0.4.0/tests/skillfire/test_worker.py +239 -0
- agentnet_cli-0.4.0/tests/test_claude_hook.py +250 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_cli.py +22 -0
- agentnet_cli-0.4.0/tests/test_cursor_hook.py +226 -0
- agentnet_cli-0.4.0/tests/test_discovery_skill.py +110 -0
- agentnet_cli-0.4.0/tests/test_hermes_hook.py +268 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_updater.py +46 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/uv.lock +1 -1
- agentnet_cli-0.3.0/CLAUDE.md +0 -74
- agentnet_cli-0.3.0/src/agentnet_cli/connectors/templates/cursor/agent.md +0 -9
- agentnet_cli-0.3.0/src/agentnet_cli/connectors/templates/cursor/agentnet.mdc +0 -6
- agentnet_cli-0.3.0/src/agentnet_cli/tools/hook.py +0 -674
- agentnet_cli-0.3.0/tests/test_discovery_skill.py +0 -55
- agentnet_cli-0.3.0/tests/test_skill_hook.py +0 -583
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/.github/workflows/ci.yml +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/.github/workflows/publish.yml +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/.gitignore +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/ARCHITECTURE.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/docs/archive/superpowers/plans/2026-05-09-hermes-native-plugin.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/docs/archive/superpowers/plans/2026-05-09-marketplace-cli-and-skill.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/docs/archive/superpowers/plans/2026-05-10-claude-native-plugin.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/docs/archive/superpowers/plans/2026-05-10-openclaw-native-plugin.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/docs/archive/superpowers/specs/2026-05-09-hermes-native-plugin-design.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/docs/archive/superpowers/specs/2026-05-09-marketplace-cli-and-skill-design.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/docs/archive/superpowers/specs/2026-05-10-claude-native-plugin-design.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/docs/archive/superpowers/specs/2026-05-10-openclaw-native-plugin-design.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/__init__.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/cli/__init__.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/cli/core/__init__.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/cli/core/connect.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/cli/core/detect.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/cli/core/disconnect.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/cli/core/register.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/cli/core/setup_wizard.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/cli/core/status.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/cli/core/updater.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/cli/marketplace/__init__.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/cli/marketplace/agent.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/cli/marketplace/discover.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/README.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/__init__.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/base.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/claude.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/claude_search_hook.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/codex.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/copilot.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/openclaw.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/registry.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/shims.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/templates/README.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/templates/codex/skill.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/templates/copilot/agentnet.agent.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/templates/shared/context.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/templates/shared/default-chat.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/templates/vscode/instructions.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/connectors/vscode.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/infra/__init__.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/infra/config.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/infra/manifest.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/infra/package_paths.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/infra/paths.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/infra/platform.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/integrations/claude/.claude-plugin/marketplace.json +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/integrations/claude/plugin/.claude-plugin/plugin.json +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/integrations/claude/plugin/.mcp.json +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/integrations/claude/plugin/agents/marketplace.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/integrations/claude/plugin/hooks/hooks.json +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/integrations/claude/plugin/skills/agentnet/SKILL.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/integrations/openclaw/.mcp.json +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/integrations/openclaw/index.js +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/integrations/openclaw/skills/agentnet/SKILL.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/integrations/shared/discovery-skill.base.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/marketplace/__init__.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/marketplace/auth.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/marketplace/catalogs/__init__.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/marketplace/catalogs/claude_marketplace.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/marketplace/catalogs/clawhub.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/marketplace/client.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/marketplace/skills/__init__.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/marketplace/skills/client.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/marketplace/skills/discovery.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/marketplace/skills/skillsmp.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/tools/__init__.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/tools/handlers.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/tools/hermes/__init__.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/tools/hermes/handlers.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/tools/hermes/schemas.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/tools/hermes/skills/agentnet/SKILL.md +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/src/agentnet_cli/tools/mcp_server.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/__init__.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/conftest.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_agent_cmd.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_claude.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_claude_marketplace.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_claude_search_hook.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_clawhub_client.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_codex.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_config.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_copilot.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_cursor.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_detect.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_discover_cmd.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_discovery.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_e2e.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_hermes.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_hermes_plugin.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_manifest.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_marketplace.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_mcp_tools.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_openclaw.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_paths.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_platform_client.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_platform_config.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_register.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_server.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_skills_client.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_skillsmp_client.py +0 -0
- {agentnet_cli-0.3.0 → agentnet_cli-0.4.0}/tests/test_vscode.py +0 -0
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0 - 2026-07-23
|
|
4
|
+
|
|
5
|
+
- Add every-prompt skill-fire support for Cursor and Hermes.
|
|
6
|
+
- Split skill-fire hook logic into a ports-and-adapters package for cleaner connector-specific integrations.
|
|
7
|
+
- Share Hermes user memory with the skill-fire relevance gate.
|
|
8
|
+
- Add Cursor and Hermes hook test coverage for the new hard-nudge flow.
|
|
9
|
+
- Bump bundled Hermes, hosted skill, and OpenClaw integration metadata to match the CLI release.
|
|
10
|
+
|
|
3
11
|
## 0.3.0 - 2026-07-18
|
|
4
12
|
|
|
5
13
|
- Add Claude Code search-fire hook support so AgentNet can surface relevant marketplace skills during search workflows.
|
|
@@ -0,0 +1,80 @@
|
|
|
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 (475 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)` (mid-run hard-nudge text or `None`), `check_fallback(session, *, timeout)` (turn-end fallback text or `None`), `run_fetch` (the CLI-invoked worker entrypoint), plus the `SUBAGENT_ENV`/`AGENTNET_SENTINEL` constants. 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` to force-steer the agent **mid-flight** once the outcome is ready (`{"decision":"block","reason":…}`); `Stop` → `agentnet skill-hook --post` calls `skillfire.check_fallback`, the guaranteed fallback (`{"decision":"block", …additionalContext}`) for no-tool answers. 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
|
+
## Testing Patterns
|
|
56
|
+
|
|
57
|
+
- **CLI tests:** `typer.testing.CliRunner` + `fake_home` fixture (temp dir with patched `Path.home()`)
|
|
58
|
+
- **HTTP tests:** `httpx.MockTransport` for platform API mocking
|
|
59
|
+
- **MCP tests:** Mock stdin/stdout with `io.StringIO`, mock `ToolHandlers`
|
|
60
|
+
- **Agent tests:** Create fake config dirs in `fake_home` to simulate installed agents
|
|
61
|
+
|
|
62
|
+
## CI/CD
|
|
63
|
+
|
|
64
|
+
- **CI (`ci.yml`):** Lint (ruff) + tests across Python 3.11/3.12/3.13 on PRs and pushes to main
|
|
65
|
+
- **Publish (`publish.yml`):** Tags matching `v*` trigger PyPI publish via trusted publisher (OIDC)
|
|
66
|
+
|
|
67
|
+
## Documentation Requirements
|
|
68
|
+
|
|
69
|
+
After any change that affects the project's public interface, structure, or developer workflow, update the relevant docs before committing:
|
|
70
|
+
|
|
71
|
+
- **README.md** — Update if commands, flags, supported agents, install steps, or architecture change
|
|
72
|
+
- **CLAUDE.md** — Update if repo structure, key patterns, test counts, or commands change
|
|
73
|
+
- **Inline docstrings** — Update if a function's contract (params, return, side effects) changes
|
|
74
|
+
|
|
75
|
+
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.
|
|
76
|
+
|
|
77
|
+
## Related Repos
|
|
78
|
+
|
|
79
|
+
- [agentnet-platform](https://github.com/TheAgent-net/agentnet-platform) — FastAPI backend
|
|
80
|
+
- [agentnet-frontend](https://github.com/TheAgent-net/agentnet-frontend) — Admin dashboard, user dashboard, marketplace SPAs
|