refactor(skills): clean up bundled skill set + add environments: relevance gate (#39028)
* refactor(skills): clean up bundled skill set + add environments: relevance gate Bundled skills cleanup pass plus a new offer-time relevance gate. Removals (redundant / dead): - spotify (covered by the spotify plugin's 7 native tools) - linear (covered by `hermes mcp install linear`) - kanban-codex-lane, debugging-hermes-tui-commands - empty category markers: diagramming, gifs, inference-sh, mlops/training, mlops/vector-databases - domain (stale orphan dup of optional/research/domain-intel) Bundled -> optional: - baoyu-article-illustrator, baoyu-comic, creative-ideation, pixel-art - dspy, subagent-driven-development - minecraft-modpack-server, pokemon-player - hermes-s6-container-supervision (-> optional/devops) Consolidation: - webhook-subscriptions + native-mcp folded into the hermes-agent skill as references/webhooks.md + references/native-mcp.md with SKILL.md pointers - writing-plans merged into plan (v2.0.0); related_skills + prose refs updated New: environments: frontmatter gate (agent/skill_utils.skill_matches_environment) - Offer-time relevance filter (kanban / docker / s6), parallel to platforms:. - Wired into the 3 OFFER surfaces only (prompt_builder skills index, skills_tool.list_skills, skill_commands slash discovery). - Explicit loads (skill_view, --skills preload) intentionally BYPASS it, so load-bearing force-loads like the kanban dispatcher's `--skills kanban-worker` always resolve. Verified via E2E. - kanban-orchestrator/kanban-worker tagged environments: [kanban]; hermes-s6-container-supervision tagged environments: [s6] + platforms: [linux]. Validation: 8/8 E2E gating assertions (incl force-load invariant); 442 targeted tests green (agent, skills_tool, skill_commands, kanban worker). * docs: regenerate skill catalogs + pages for the bundled cleanup Regenerated per-skill doc pages, catalogs, and sidebar to match the skill moves/removals in the parent commit. Moved skills' pages relocate bundled -> optional (history preserved); removed skills' pages deleted; edited skills' pages refreshed (hermes-agent now embeds the webhook + native-mcp reference pointers). zh-Hans i18n mirror: stale bundled pages and catalog rows for moved/removed skills pruned (new optional translations land via the translation pipeline). * test: drop regression test for removed kanban-codex-lane skill The kanban-codex-lane skill was removed in the bundled-skills cleanup; its dedicated regression test read the now-deleted SKILL.md and failed with FileNotFoundError on CI shard 6.
This commit is contained in:
+7
@@ -157,6 +157,10 @@ hermes mcp test NAME Test connection
|
||||
hermes mcp configure NAME Toggle tool selection
|
||||
```
|
||||
|
||||
How the built-in MCP client connects servers (stdio/HTTP), auto-discovers
|
||||
their tools, and exposes them as first-class tools, plus catalog install
|
||||
(`hermes mcp install <name>`): `skill_view(name="hermes-agent", file_path="references/native-mcp.md")`.
|
||||
|
||||
### Gateway (Messaging Platforms)
|
||||
|
||||
```
|
||||
@@ -205,6 +209,9 @@ hermes webhook remove NAME Remove a subscription
|
||||
hermes webhook test NAME Send a test POST
|
||||
```
|
||||
|
||||
Full setup, route config, payload templating, and event-driven agent-run
|
||||
patterns: `skill_view(name="hermes-agent", file_path="references/webhooks.md")`.
|
||||
|
||||
### Profiles
|
||||
|
||||
```
|
||||
|
||||
@@ -196,6 +196,30 @@ Tell them what you created in plain prose, naming the actual profiles you used:
|
||||
|
||||
**Tenant inheritance.** If `HERMES_TENANT` is set in your env, pass `tenant=os.environ.get("HERMES_TENANT")` on every `kanban_create` call so child tasks stay in the same namespace.
|
||||
|
||||
## Goal-mode cards (persistent workers)
|
||||
|
||||
By default a dispatched worker gets **one shot** at its card: it does its work, calls `kanban_complete`/`kanban_block`, and exits. For open-ended cards where one turn rarely finishes the job, pass `goal_mode=True` to wrap that worker in a Ralph-style goal loop — the same engine behind the `/goal` slash command:
|
||||
|
||||
```python
|
||||
kanban_create(
|
||||
title="Translate the full docs site to French",
|
||||
body="Acceptance: every page translated, no English left, links intact.",
|
||||
assignee="<translator-profile>",
|
||||
goal_mode=True, # judge re-checks the card after each turn
|
||||
goal_max_turns=15, # optional budget (default 20)
|
||||
)["task_id"]
|
||||
```
|
||||
|
||||
How it behaves:
|
||||
- After each worker turn, an auxiliary judge evaluates the worker's response against the card's **title + body** (treated as the acceptance criteria).
|
||||
- Not done + budget remains → the worker keeps going **in the same session** (full context retained — not a fresh respawn).
|
||||
- Worker calls `kanban_complete`/`kanban_block` itself → loop stops, normal lifecycle.
|
||||
- Budget exhausted without completion → the card is **blocked** for human review (sticky), never a silent exit.
|
||||
|
||||
When to use it: long, multi-step, or "keep going until X is true" cards. When NOT to: cheap one-shot cards (translation of a single string, a quick lookup) — the judge overhead isn't worth it, and the dispatcher's existing retry/circuit-breaker already handles transient worker failures.
|
||||
|
||||
Write the body as **explicit acceptance criteria** — the judge is only as good as the goal text. "Translate the README" is weaker than "Translate every section of the README to French; no English sentences remain."
|
||||
|
||||
## Recovering stuck workers
|
||||
|
||||
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a ⚠ badge and opens a **Recovery** section in the drawer. Three primary actions:
|
||||
|
||||
@@ -185,6 +185,7 @@ You can configure the gateway to receive cross-profile Kanban task notifications
|
||||
## Do NOT
|
||||
|
||||
- Call `delegate_task` as a substitute for `kanban_create`. `delegate_task` is for short reasoning subtasks inside YOUR run; `kanban_create` is for cross-agent handoffs that outlive one API loop.
|
||||
- Call `clarify` to ask the human a question. You are running headless — there is no live user to answer. The call will time out (default ~120s) and the task will sit silently in `running` with no signal that it needs input. Use `kanban_comment` (context) + `kanban_block(reason=...)` (decision needed) instead — the task surfaces on the board as blocked, the operator sees it, unblocks with their answer in a comment, and you respawn with the thread.
|
||||
- Modify files outside `$HERMES_KANBAN_WORKSPACE` unless the task body says to.
|
||||
- Create follow-up tasks assigned to yourself — assign to the right specialist.
|
||||
- Complete a task you didn't actually finish. Block it instead.
|
||||
|
||||
@@ -1,222 +0,0 @@
|
||||
---
|
||||
title: "Webhook Subscriptions — Webhook subscriptions: event-driven agent runs"
|
||||
sidebar_label: "Webhook Subscriptions"
|
||||
description: "Webhook subscriptions: event-driven agent runs"
|
||||
---
|
||||
|
||||
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
||||
|
||||
# Webhook Subscriptions
|
||||
|
||||
Webhook subscriptions: event-driven agent runs.
|
||||
|
||||
## Skill metadata
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/devops/webhook-subscriptions` |
|
||||
| Version | `1.1.0` |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `webhook`, `events`, `automation`, `integrations`, `notifications`, `push` |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
:::info
|
||||
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
||||
:::
|
||||
|
||||
# Webhook Subscriptions
|
||||
|
||||
Create dynamic webhook subscriptions so external services (GitHub, GitLab, Stripe, CI/CD, IoT sensors, monitoring tools) can trigger Hermes agent runs by POSTing events to a URL.
|
||||
|
||||
## Setup (Required First)
|
||||
|
||||
The webhook platform must be enabled before subscriptions can be created. Check with:
|
||||
```bash
|
||||
hermes webhook list
|
||||
```
|
||||
|
||||
If it says "Webhook platform is not enabled", set it up:
|
||||
|
||||
### Option 1: Setup wizard
|
||||
```bash
|
||||
hermes gateway setup
|
||||
```
|
||||
Follow the prompts to enable webhooks, set the port, and set a global HMAC secret.
|
||||
|
||||
### Option 2: Manual config
|
||||
Add to `~/.hermes/config.yaml`:
|
||||
```yaml
|
||||
platforms:
|
||||
webhook:
|
||||
enabled: true
|
||||
extra:
|
||||
host: "0.0.0.0"
|
||||
port: 8644
|
||||
secret: "generate-a-strong-secret-here"
|
||||
```
|
||||
|
||||
### Option 3: Environment variables
|
||||
Add to `~/.hermes/.env`:
|
||||
```bash
|
||||
WEBHOOK_ENABLED=true
|
||||
WEBHOOK_PORT=8644
|
||||
WEBHOOK_SECRET=generate-a-strong-secret-here
|
||||
```
|
||||
|
||||
After configuration, start (or restart) the gateway:
|
||||
```bash
|
||||
hermes gateway run
|
||||
# Or if using systemd:
|
||||
systemctl --user restart hermes-gateway
|
||||
```
|
||||
|
||||
Verify it's running:
|
||||
```bash
|
||||
curl http://localhost:8644/health
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
All management is via the `hermes webhook` CLI command:
|
||||
|
||||
### Create a subscription
|
||||
```bash
|
||||
hermes webhook subscribe <name> \
|
||||
--prompt "Prompt template with {payload.fields}" \
|
||||
--events "event1,event2" \
|
||||
--description "What this does" \
|
||||
--skills "skill1,skill2" \
|
||||
--deliver telegram \
|
||||
--deliver-chat-id "12345" \
|
||||
--secret "optional-custom-secret"
|
||||
```
|
||||
|
||||
Returns the webhook URL and HMAC secret. The user configures their service to POST to that URL.
|
||||
|
||||
### List subscriptions
|
||||
```bash
|
||||
hermes webhook list
|
||||
```
|
||||
|
||||
### Remove a subscription
|
||||
```bash
|
||||
hermes webhook remove <name>
|
||||
```
|
||||
|
||||
### Test a subscription
|
||||
```bash
|
||||
hermes webhook test <name>
|
||||
hermes webhook test <name> --payload '{"key": "value"}'
|
||||
```
|
||||
|
||||
## Prompt Templates
|
||||
|
||||
Prompts support `{dot.notation}` for accessing nested payload fields:
|
||||
|
||||
- `{issue.title}` — GitHub issue title
|
||||
- `{pull_request.user.login}` — PR author
|
||||
- `{data.object.amount}` — Stripe payment amount
|
||||
- `{sensor.temperature}` — IoT sensor reading
|
||||
|
||||
If no prompt is specified, the full JSON payload is dumped into the agent prompt.
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### GitHub: new issues
|
||||
```bash
|
||||
hermes webhook subscribe github-issues \
|
||||
--events "issues" \
|
||||
--prompt "New GitHub issue #{issue.number}: {issue.title}\n\nAction: {action}\nAuthor: {issue.user.login}\nBody:\n{issue.body}\n\nPlease triage this issue." \
|
||||
--deliver telegram \
|
||||
--deliver-chat-id "-100123456789"
|
||||
```
|
||||
|
||||
Then in GitHub repo Settings → Webhooks → Add webhook:
|
||||
- Payload URL: the returned webhook_url
|
||||
- Content type: application/json
|
||||
- Secret: the returned secret
|
||||
- Events: "Issues"
|
||||
|
||||
### GitHub: PR reviews
|
||||
```bash
|
||||
hermes webhook subscribe github-prs \
|
||||
--events "pull_request" \
|
||||
--prompt "PR #{pull_request.number} {action}: {pull_request.title}\nBy: {pull_request.user.login}\nBranch: {pull_request.head.ref}\n\n{pull_request.body}" \
|
||||
--skills "github-code-review" \
|
||||
--deliver github_comment
|
||||
```
|
||||
|
||||
### Stripe: payment events
|
||||
```bash
|
||||
hermes webhook subscribe stripe-payments \
|
||||
--events "payment_intent.succeeded,payment_intent.payment_failed" \
|
||||
--prompt "Payment {data.object.status}: {data.object.amount} cents from {data.object.receipt_email}" \
|
||||
--deliver telegram \
|
||||
--deliver-chat-id "-100123456789"
|
||||
```
|
||||
|
||||
### CI/CD: build notifications
|
||||
```bash
|
||||
hermes webhook subscribe ci-builds \
|
||||
--events "pipeline" \
|
||||
--prompt "Build {object_attributes.status} on {project.name} branch {object_attributes.ref}\nCommit: {commit.message}" \
|
||||
--deliver discord \
|
||||
--deliver-chat-id "1234567890"
|
||||
```
|
||||
|
||||
### Generic monitoring alert
|
||||
```bash
|
||||
hermes webhook subscribe alerts \
|
||||
--prompt "Alert: {alert.name}\nSeverity: {alert.severity}\nMessage: {alert.message}\n\nPlease investigate and suggest remediation." \
|
||||
--deliver origin
|
||||
```
|
||||
|
||||
### Direct delivery (no agent, zero LLM cost)
|
||||
|
||||
For use cases where you just want to push a notification through to a user's chat — no reasoning, no agent loop — add `--deliver-only`. The rendered `--prompt` template becomes the literal message body and is dispatched directly to the target adapter.
|
||||
|
||||
Use this for:
|
||||
- External service push notifications (Supabase/Firebase webhooks → Telegram)
|
||||
- Monitoring alerts that should forward verbatim
|
||||
- Inter-agent pings where one agent is telling another agent's user something
|
||||
- Any webhook where an LLM round trip would be wasted effort
|
||||
|
||||
```bash
|
||||
hermes webhook subscribe antenna-matches \
|
||||
--deliver telegram \
|
||||
--deliver-chat-id "123456789" \
|
||||
--deliver-only \
|
||||
--prompt "🎉 New match: {match.user_name} matched with you!" \
|
||||
--description "Antenna match notifications"
|
||||
```
|
||||
|
||||
The POST returns `200 OK` on successful delivery, `502` on target failure — so upstream services can retry intelligently. HMAC auth, rate limits, and idempotency still apply.
|
||||
|
||||
Requires `--deliver` to be a real target (telegram, discord, slack, github_comment, etc.) — `--deliver log` is rejected because log-only direct delivery is pointless.
|
||||
|
||||
## Security
|
||||
|
||||
- Each subscription gets an auto-generated HMAC-SHA256 secret (or provide your own with `--secret`)
|
||||
- The webhook adapter validates signatures on every incoming POST
|
||||
- Static routes from config.yaml cannot be overwritten by dynamic subscriptions
|
||||
- Subscriptions persist to `~/.hermes/webhook_subscriptions.json`
|
||||
|
||||
## How It Works
|
||||
|
||||
1. `hermes webhook subscribe` writes to `~/.hermes/webhook_subscriptions.json`
|
||||
2. The webhook adapter hot-reloads this file on each incoming request (mtime-gated, negligible overhead)
|
||||
3. When a POST arrives matching a route, the adapter formats the prompt and triggers an agent run
|
||||
4. The agent's response is delivered to the configured target (Telegram, Discord, GitHub comment, etc.)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If webhooks aren't working:
|
||||
|
||||
1. **Is the gateway running?** Check with `systemctl --user status hermes-gateway` or `ps aux | grep gateway`
|
||||
2. **Is the webhook server listening?** `curl http://localhost:8644/health` should return `{"status": "ok"}`
|
||||
3. **Check gateway logs:** `grep webhook ~/.hermes/logs/gateway.log | tail -20`
|
||||
4. **Signature mismatch?** Verify the secret in your service matches the one from `hermes webhook list`. GitHub sends `X-Hub-Signature-256`, GitLab sends `X-Gitlab-Token`.
|
||||
5. **Firewall/NAT?** The webhook URL must be reachable from the service. For local development, use a tunnel (ngrok, cloudflared).
|
||||
6. **Wrong event type?** Check `--events` filter matches what the service sends. Use `hermes webhook test <name>` to verify the route works.
|
||||
@@ -1,375 +0,0 @@
|
||||
---
|
||||
title: "Native Mcp — MCP client: connect servers, register tools (stdio/HTTP)"
|
||||
sidebar_label: "Native Mcp"
|
||||
description: "MCP client: connect servers, register tools (stdio/HTTP)"
|
||||
---
|
||||
|
||||
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
||||
|
||||
# Native Mcp
|
||||
|
||||
MCP client: connect servers, register tools (stdio/HTTP).
|
||||
|
||||
## Skill metadata
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/mcp/native-mcp` |
|
||||
| Version | `1.0.0` |
|
||||
| Author | Hermes Agent |
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `MCP`, `Tools`, `Integrations` |
|
||||
| Related skills | [`mcporter`](/docs/user-guide/skills/optional/mcp/mcp-mcporter) |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
:::info
|
||||
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
||||
:::
|
||||
|
||||
# Native MCP Client
|
||||
|
||||
Hermes Agent has a built-in MCP client that connects to MCP servers at startup, discovers their tools, and makes them available as first-class tools the agent can call directly. No bridge CLI needed -- tools from MCP servers appear alongside built-in tools like `terminal`, `read_file`, etc.
|
||||
|
||||
## When to Use
|
||||
|
||||
Use this whenever you want to:
|
||||
- Connect to MCP servers and use their tools from within Hermes Agent
|
||||
- Add external capabilities (filesystem access, GitHub, databases, APIs) via MCP
|
||||
- Run local stdio-based MCP servers (npx, uvx, or any command)
|
||||
- Connect to remote HTTP/StreamableHTTP MCP servers
|
||||
- Have MCP tools auto-discovered and available in every conversation
|
||||
|
||||
For ad-hoc, one-off MCP tool calls from the terminal without configuring anything, see the `mcporter` skill instead.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **mcp Python package** -- optional dependency; install with `pip install mcp`. If not installed, MCP support is silently disabled.
|
||||
- **Node.js** -- required for `npx`-based MCP servers (most community servers)
|
||||
- **uv** -- required for `uvx`-based MCP servers (Python-based servers)
|
||||
|
||||
Install the MCP SDK:
|
||||
|
||||
```bash
|
||||
pip install mcp
|
||||
# or, if using uv:
|
||||
uv pip install mcp
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
Add MCP servers to `~/.hermes/config.yaml` under the `mcp_servers` key:
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
time:
|
||||
command: "uvx"
|
||||
args: ["mcp-server-time"]
|
||||
```
|
||||
|
||||
Restart Hermes Agent. On startup it will:
|
||||
1. Connect to the server
|
||||
2. Discover available tools
|
||||
3. Register them with the prefix `mcp_time_*`
|
||||
4. Inject them into all platform toolsets
|
||||
|
||||
You can then use the tools naturally -- just ask the agent to get the current time.
|
||||
|
||||
## Configuration Reference
|
||||
|
||||
Each entry under `mcp_servers` is a server name mapped to its config. There are two transport types: **stdio** (command-based) and **HTTP** (url-based).
|
||||
|
||||
### Stdio Transport (command + args)
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
server_name:
|
||||
command: "npx" # (required) executable to run
|
||||
args: ["-y", "pkg-name"] # (optional) command arguments, default: []
|
||||
env: # (optional) environment variables for the subprocess
|
||||
SOME_API_KEY: "value"
|
||||
timeout: 120 # (optional) per-tool-call timeout in seconds, default: 120
|
||||
connect_timeout: 60 # (optional) initial connection timeout in seconds, default: 60
|
||||
```
|
||||
|
||||
### HTTP Transport (url)
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
server_name:
|
||||
url: "https://my-server.example.com/mcp" # (required) server URL
|
||||
headers: # (optional) HTTP headers
|
||||
Authorization: "Bearer sk-..."
|
||||
timeout: 180 # (optional) per-tool-call timeout in seconds, default: 120
|
||||
connect_timeout: 60 # (optional) initial connection timeout in seconds, default: 60
|
||||
```
|
||||
|
||||
### All Config Options
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|-------------------|--------|---------|---------------------------------------------------|
|
||||
| `command` | string | -- | Executable to run (stdio transport, required) |
|
||||
| `args` | list | `[]` | Arguments passed to the command |
|
||||
| `env` | dict | `{}` | Extra environment variables for the subprocess |
|
||||
| `url` | string | -- | Server URL (HTTP transport, required) |
|
||||
| `headers` | dict | `{}` | HTTP headers sent with every request |
|
||||
| `timeout` | int | `120` | Per-tool-call timeout in seconds |
|
||||
| `connect_timeout` | int | `60` | Timeout for initial connection and discovery |
|
||||
|
||||
Note: A server config must have either `command` (stdio) or `url` (HTTP), not both.
|
||||
|
||||
## How It Works
|
||||
|
||||
### Startup Discovery
|
||||
|
||||
When Hermes Agent starts, `discover_mcp_tools()` is called during tool initialization:
|
||||
|
||||
1. Reads `mcp_servers` from `~/.hermes/config.yaml`
|
||||
2. For each server, spawns a connection in a dedicated background event loop
|
||||
3. Initializes the MCP session and calls `list_tools()` to discover available tools
|
||||
4. Registers each tool in the Hermes tool registry
|
||||
|
||||
### Tool Naming Convention
|
||||
|
||||
MCP tools are registered with the naming pattern:
|
||||
|
||||
```
|
||||
mcp_{server_name}_{tool_name}
|
||||
```
|
||||
|
||||
Hyphens and dots in names are replaced with underscores for LLM API compatibility.
|
||||
|
||||
Examples:
|
||||
- Server `filesystem`, tool `read_file` → `mcp_filesystem_read_file`
|
||||
- Server `github`, tool `list-issues` → `mcp_github_list_issues`
|
||||
- Server `my-api`, tool `fetch.data` → `mcp_my_api_fetch_data`
|
||||
|
||||
### Auto-Injection
|
||||
|
||||
After discovery, MCP tools are automatically injected into all `hermes-*` platform toolsets (CLI, Discord, Telegram, etc.). This means MCP tools are available in every conversation without any additional configuration.
|
||||
|
||||
### Connection Lifecycle
|
||||
|
||||
- Each server runs as a long-lived asyncio Task in a background daemon thread
|
||||
- Connections persist for the lifetime of the agent process
|
||||
- If a connection drops, automatic reconnection with exponential backoff kicks in (up to 5 retries, max 60s backoff)
|
||||
- On agent shutdown, all connections are gracefully closed
|
||||
|
||||
### Idempotency
|
||||
|
||||
`discover_mcp_tools()` is idempotent -- calling it multiple times only connects to servers that aren't already connected. Failed servers are retried on subsequent calls.
|
||||
|
||||
## Transport Types
|
||||
|
||||
### Stdio Transport
|
||||
|
||||
The most common transport. Hermes launches the MCP server as a subprocess and communicates over stdin/stdout.
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
filesystem:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"]
|
||||
```
|
||||
|
||||
The subprocess inherits a **filtered** environment (see Security section below) plus any variables you specify in `env`.
|
||||
|
||||
### HTTP / StreamableHTTP Transport
|
||||
|
||||
For remote or shared MCP servers. Requires the `mcp` package to include HTTP client support (`mcp.client.streamable_http`).
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
remote_api:
|
||||
url: "https://mcp.example.com/mcp"
|
||||
headers:
|
||||
Authorization: "Bearer sk-..."
|
||||
```
|
||||
|
||||
If HTTP support is not available in your installed `mcp` version, the server will fail with an ImportError and other servers will continue normally.
|
||||
|
||||
## Security
|
||||
|
||||
### Environment Variable Filtering
|
||||
|
||||
For stdio servers, Hermes does NOT pass your full shell environment to MCP subprocesses. Only safe baseline variables are inherited:
|
||||
|
||||
- `PATH`, `HOME`, `USER`, `LANG`, `LC_ALL`, `TERM`, `SHELL`, `TMPDIR`
|
||||
- Any `XDG_*` variables
|
||||
|
||||
All other environment variables (API keys, tokens, secrets) are excluded unless you explicitly add them via the `env` config key. This prevents accidental credential leakage to untrusted MCP servers.
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
github:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-github"]
|
||||
env:
|
||||
# Only this token is passed to the subprocess
|
||||
GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_..."
|
||||
```
|
||||
|
||||
### Credential Stripping in Error Messages
|
||||
|
||||
If an MCP tool call fails, any credential-like patterns in the error message are automatically redacted before being shown to the LLM. This covers:
|
||||
|
||||
- GitHub PATs (`ghp_...`)
|
||||
- OpenAI-style keys (`sk-...`)
|
||||
- Bearer tokens
|
||||
- Generic `token=`, `key=`, `API_KEY=`, `password=`, `secret=` patterns
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "MCP SDK not available -- skipping MCP tool discovery"
|
||||
|
||||
The `mcp` Python package is not installed. Install it:
|
||||
|
||||
```bash
|
||||
pip install mcp
|
||||
```
|
||||
|
||||
### "No MCP servers configured"
|
||||
|
||||
No `mcp_servers` key in `~/.hermes/config.yaml`, or it's empty. Add at least one server.
|
||||
|
||||
### "Failed to connect to MCP server 'X'"
|
||||
|
||||
Common causes:
|
||||
- **Command not found**: The `command` binary isn't on PATH. Ensure `npx`, `uvx`, or the relevant command is installed.
|
||||
- **Package not found**: For npx servers, the npm package may not exist or may need `-y` in args to auto-install.
|
||||
- **Timeout**: The server took too long to start. Increase `connect_timeout`.
|
||||
- **Port conflict**: For HTTP servers, the URL may be unreachable.
|
||||
|
||||
### "MCP server 'X' requires HTTP transport but mcp.client.streamable_http is not available"
|
||||
|
||||
Your `mcp` package version doesn't include HTTP client support. Upgrade:
|
||||
|
||||
```bash
|
||||
pip install --upgrade mcp
|
||||
```
|
||||
|
||||
### Tools not appearing
|
||||
|
||||
- Check that the server is listed under `mcp_servers` (not `mcp` or `servers`)
|
||||
- Ensure the YAML indentation is correct
|
||||
- Look at Hermes Agent startup logs for connection messages
|
||||
- Tool names are prefixed with `mcp_{server}_{tool}` -- look for that pattern
|
||||
|
||||
### Connection keeps dropping
|
||||
|
||||
The client retries up to 5 times with exponential backoff (1s, 2s, 4s, 8s, 16s, capped at 60s). If the server is fundamentally unreachable, it gives up after 5 attempts. Check the server process and network connectivity.
|
||||
|
||||
## Examples
|
||||
|
||||
### Time Server (uvx)
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
time:
|
||||
command: "uvx"
|
||||
args: ["mcp-server-time"]
|
||||
```
|
||||
|
||||
Registers tools like `mcp_time_get_current_time`.
|
||||
|
||||
### Filesystem Server (npx)
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
filesystem:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/documents"]
|
||||
timeout: 30
|
||||
```
|
||||
|
||||
Registers tools like `mcp_filesystem_read_file`, `mcp_filesystem_write_file`, `mcp_filesystem_list_directory`.
|
||||
|
||||
### GitHub Server with Authentication
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
github:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-github"]
|
||||
env:
|
||||
GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_xxxxxxxxxxxxxxxxxxxx"
|
||||
timeout: 60
|
||||
```
|
||||
|
||||
Registers tools like `mcp_github_list_issues`, `mcp_github_create_pull_request`, etc.
|
||||
|
||||
### Remote HTTP Server
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
company_api:
|
||||
url: "https://mcp.mycompany.com/v1/mcp"
|
||||
headers:
|
||||
Authorization: "Bearer sk-xxxxxxxxxxxxxxxxxxxx"
|
||||
X-Team-Id: "engineering"
|
||||
timeout: 180
|
||||
connect_timeout: 30
|
||||
```
|
||||
|
||||
### Multiple Servers
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
time:
|
||||
command: "uvx"
|
||||
args: ["mcp-server-time"]
|
||||
|
||||
filesystem:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
|
||||
|
||||
github:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-github"]
|
||||
env:
|
||||
GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_xxxxxxxxxxxxxxxxxxxx"
|
||||
|
||||
company_api:
|
||||
url: "https://mcp.internal.company.com/mcp"
|
||||
headers:
|
||||
Authorization: "Bearer sk-xxxxxxxxxxxxxxxxxxxx"
|
||||
timeout: 300
|
||||
```
|
||||
|
||||
All tools from all servers are registered and available simultaneously. Each server's tools are prefixed with its name to avoid collisions.
|
||||
|
||||
## Sampling (Server-Initiated LLM Requests)
|
||||
|
||||
Hermes supports MCP's `sampling/createMessage` capability — MCP servers can request LLM completions through the agent during tool execution. This enables agent-in-the-loop workflows (data analysis, content generation, decision-making).
|
||||
|
||||
Sampling is **enabled by default**. Configure per server:
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
my_server:
|
||||
command: "npx"
|
||||
args: ["-y", "my-mcp-server"]
|
||||
sampling:
|
||||
enabled: true # default: true
|
||||
model: "gemini-3-flash" # model override (optional)
|
||||
max_tokens_cap: 4096 # max tokens per request
|
||||
timeout: 30 # LLM call timeout (seconds)
|
||||
max_rpm: 10 # max requests per minute
|
||||
allowed_models: [] # model whitelist (empty = all)
|
||||
max_tool_rounds: 5 # tool loop limit (0 = disable)
|
||||
log_level: "info" # audit verbosity
|
||||
```
|
||||
|
||||
Servers can also include `tools` in sampling requests for multi-turn tool-augmented workflows. The `max_tool_rounds` config prevents infinite tool loops. Per-server audit metrics (requests, errors, tokens, tool use count) are tracked via `get_mcp_status()`.
|
||||
|
||||
Disable sampling for untrusted servers with `sampling: { enabled: false }`.
|
||||
|
||||
## Notes
|
||||
|
||||
- MCP tools are called synchronously from the agent's perspective but run asynchronously on a dedicated background event loop
|
||||
- Tool results are returned as JSON with either `{"result": "..."}` or `{"error": "..."}`
|
||||
- The native MCP client is independent of `mcporter` -- you can use both simultaneously
|
||||
- Server connections are persistent and shared across all conversations in the same agent process
|
||||
- Adding or removing servers requires restarting the agent (no hot-reload currently)
|
||||
@@ -1,151 +0,0 @@
|
||||
---
|
||||
title: "Spotify — Spotify: play, search, queue, manage playlists and devices"
|
||||
sidebar_label: "Spotify"
|
||||
description: "Spotify: play, search, queue, manage playlists and devices"
|
||||
---
|
||||
|
||||
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
||||
|
||||
# Spotify
|
||||
|
||||
Spotify: play, search, queue, manage playlists and devices.
|
||||
|
||||
## Skill metadata
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/media/spotify` |
|
||||
| Version | `1.0.0` |
|
||||
| Author | Hermes Agent |
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `spotify`, `music`, `playback`, `playlists`, `media` |
|
||||
| Related skills | [`gif-search`](/docs/user-guide/skills/bundled/media/media-gif-search) |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
:::info
|
||||
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
||||
:::
|
||||
|
||||
# Spotify
|
||||
|
||||
Control the user's Spotify account via the Hermes Spotify toolset (7 tools). Setup guide: https://hermes-agent.nousresearch.com/docs/user-guide/features/spotify
|
||||
|
||||
## When to use this skill
|
||||
|
||||
The user says something like "play X", "pause", "skip", "queue up X", "what's playing", "search for X", "add to my X playlist", "make a playlist", "save this to my library", etc.
|
||||
|
||||
## The 7 tools
|
||||
|
||||
- `spotify_playback` — play, pause, next, previous, seek, set_repeat, set_shuffle, set_volume, get_state, get_currently_playing, recently_played
|
||||
- `spotify_devices` — list, transfer
|
||||
- `spotify_queue` — get, add
|
||||
- `spotify_search` — search the catalog
|
||||
- `spotify_playlists` — list, get, create, add_items, remove_items, update_details
|
||||
- `spotify_albums` — get, tracks
|
||||
- `spotify_library` — list/save/remove with `kind: "tracks"|"albums"`
|
||||
|
||||
Playback-mutating actions require Spotify Premium; search/library/playlist ops work on Free.
|
||||
|
||||
## Canonical patterns (minimize tool calls)
|
||||
|
||||
### "Play <artist/track/album>"
|
||||
One search, then play by URI. Do NOT loop through search results describing them unless the user asked for options.
|
||||
|
||||
```
|
||||
spotify_search({"query": "miles davis kind of blue", "types": ["album"], "limit": 1})
|
||||
→ got album URI spotify:album:1weenld61qoidwYuZ1GESA
|
||||
spotify_playback({"action": "play", "context_uri": "spotify:album:1weenld61qoidwYuZ1GESA"})
|
||||
```
|
||||
|
||||
For "play some <artist>" (no specific song), prefer `types: ["artist"]` and play the artist context URI — Spotify handles smart shuffle. If the user says "the song" or "that track", search `types: ["track"]` and pass `uris: [track_uri]` to play.
|
||||
|
||||
### "What's playing?" / "What am I listening to?"
|
||||
Single call — don't chain get_state after get_currently_playing.
|
||||
|
||||
```
|
||||
spotify_playback({"action": "get_currently_playing"})
|
||||
```
|
||||
|
||||
If it returns 204/empty (`is_playing: false`), tell the user nothing is playing. Don't retry.
|
||||
|
||||
### "Pause" / "Skip" / "Volume 50"
|
||||
Direct action, no preflight inspection needed.
|
||||
|
||||
```
|
||||
spotify_playback({"action": "pause"})
|
||||
spotify_playback({"action": "next"})
|
||||
spotify_playback({"action": "set_volume", "volume_percent": 50})
|
||||
```
|
||||
|
||||
### "Add to my <playlist name> playlist"
|
||||
1. `spotify_playlists list` to find the playlist ID by name
|
||||
2. Get the track URI (from currently playing, or search)
|
||||
3. `spotify_playlists add_items` with the playlist_id and URIs
|
||||
|
||||
```
|
||||
spotify_playlists({"action": "list"})
|
||||
→ found "Late Night Jazz" = 37i9dQZF1DX4wta20PHgwo
|
||||
spotify_playback({"action": "get_currently_playing"})
|
||||
→ current track uri = spotify:track:0DiWol3AO6WpXZgp0goxAV
|
||||
spotify_playlists({"action": "add_items",
|
||||
"playlist_id": "37i9dQZF1DX4wta20PHgwo",
|
||||
"uris": ["spotify:track:0DiWol3AO6WpXZgp0goxAV"]})
|
||||
```
|
||||
|
||||
### "Create a playlist called X and add the last 3 songs I played"
|
||||
```
|
||||
spotify_playback({"action": "recently_played", "limit": 3})
|
||||
spotify_playlists({"action": "create", "name": "Focus 2026"})
|
||||
→ got playlist_id back in response
|
||||
spotify_playlists({"action": "add_items", "playlist_id": <id>, "uris": [<3 uris>]})
|
||||
```
|
||||
|
||||
### "Save / unsave / is this saved?"
|
||||
Use `spotify_library` with the right `kind`.
|
||||
|
||||
```
|
||||
spotify_library({"kind": "tracks", "action": "save", "uris": ["spotify:track:..."]})
|
||||
spotify_library({"kind": "albums", "action": "list", "limit": 50})
|
||||
```
|
||||
|
||||
### "Transfer playback to my <device>"
|
||||
```
|
||||
spotify_devices({"action": "list"})
|
||||
→ pick the device_id by matching name/type
|
||||
spotify_devices({"action": "transfer", "device_id": "<id>", "play": true})
|
||||
```
|
||||
|
||||
## Critical failure modes
|
||||
|
||||
**`403 Forbidden — No active device found`** on any playback action means Spotify isn't running anywhere. Tell the user: "Open Spotify on your phone/desktop/web player first, start any track for a second, then retry." Don't retry the tool call blindly — it will fail the same way. You can call `spotify_devices list` to confirm; an empty list means no active device.
|
||||
|
||||
**`403 Forbidden — Premium required`** means the user is on Free and tried to mutate playback. Don't retry; tell them this action needs Premium. Reads still work (search, playlists, library, get_state).
|
||||
|
||||
**`204 No Content` on `get_currently_playing`** is NOT an error — it means nothing is playing. The tool returns `is_playing: false`. Just report that to the user.
|
||||
|
||||
**`429 Too Many Requests`** = rate limit. Wait and retry once. If it keeps happening, you're looping — stop.
|
||||
|
||||
**`401 Unauthorized` after a retry** — refresh token revoked. Tell the user to run `hermes auth spotify` again.
|
||||
|
||||
## URI and ID formats
|
||||
|
||||
Spotify uses three interchangeable ID formats. The tools accept all three and normalize:
|
||||
|
||||
- URI: `spotify:track:0DiWol3AO6WpXZgp0goxAV` (preferred)
|
||||
- URL: `https://open.spotify.com/track/0DiWol3AO6WpXZgp0goxAV`
|
||||
- Bare ID: `0DiWol3AO6WpXZgp0goxAV`
|
||||
|
||||
When in doubt, use full URIs. Search results return URIs in the `uri` field — pass those directly.
|
||||
|
||||
Entity types: `track`, `album`, `artist`, `playlist`, `show`, `episode`. Use the right type for the action — `spotify_playback.play` with a `context_uri` expects album/playlist/artist; `uris` expects an array of track URIs.
|
||||
|
||||
## What NOT to do
|
||||
|
||||
- **Don't call `get_state` before every action.** Spotify accepts play/pause/skip without preflight. Only inspect state when the user asked "what's playing" or you need to reason about device/track.
|
||||
- **Don't describe search results unless asked.** If the user said "play X", search, grab the top URI, play it. They'll hear it's wrong if it's wrong.
|
||||
- **Don't retry on `403 Premium required` or `403 No active device`.** Those are permanent until user action.
|
||||
- **Don't use `spotify_search` to find a playlist by name** — that searches the public Spotify catalog. User playlists come from `spotify_playlists list`.
|
||||
- **Don't mix `kind: "tracks"` with album URIs** in `spotify_library` (or vice versa). The tool normalizes IDs but the API endpoint differs.
|
||||
@@ -1,395 +0,0 @@
|
||||
---
|
||||
title: "Linear — Linear: manage issues, projects, teams via GraphQL + curl"
|
||||
sidebar_label: "Linear"
|
||||
description: "Linear: manage issues, projects, teams via GraphQL + curl"
|
||||
---
|
||||
|
||||
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
||||
|
||||
# Linear
|
||||
|
||||
Linear: manage issues, projects, teams via GraphQL + curl.
|
||||
|
||||
## Skill metadata
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/productivity/linear` |
|
||||
| Version | `1.0.0` |
|
||||
| Author | Hermes Agent |
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `Linear`, `Project Management`, `Issues`, `GraphQL`, `API`, `Productivity` |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
:::info
|
||||
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
||||
:::
|
||||
|
||||
# Linear — Issue & Project Management
|
||||
|
||||
Manage Linear issues, projects, and teams directly via the GraphQL API using `curl`. No MCP server, no OAuth flow, no extra dependencies.
|
||||
|
||||
## Setup
|
||||
|
||||
1. Get a personal API key from **Linear Settings > Account > Security & access > Personal API keys** (URL: https://linear.app/settings/account/security). Note: the org-level *Settings > API* page only shows OAuth apps and workspace-member keys, not personal keys.
|
||||
2. Set `LINEAR_API_KEY` in your environment (via `hermes setup` or your env config)
|
||||
|
||||
## API Basics
|
||||
|
||||
- **Endpoint:** `https://api.linear.app/graphql` (POST)
|
||||
- **Auth header:** `Authorization: $LINEAR_API_KEY` (no "Bearer" prefix for API keys)
|
||||
- **All requests are POST** with `Content-Type: application/json`
|
||||
- **Both UUIDs and short identifiers** (e.g., `ENG-123`) work for `issue(id:)`
|
||||
|
||||
Base curl pattern:
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ viewer { id name } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
## Python helper script (ergonomic alternative)
|
||||
|
||||
For faster one-liners that don't need hand-written GraphQL, this skill ships a stdlib Python CLI at `scripts/linear_api.py`. Zero dependencies. Same auth (reads `LINEAR_API_KEY`).
|
||||
|
||||
```bash
|
||||
SCRIPT=$(dirname "$(find ~/.hermes -path '*skills/productivity/linear/scripts/linear_api.py' 2>/dev/null | head -1)")/linear_api.py
|
||||
|
||||
python3 "$SCRIPT" whoami
|
||||
python3 "$SCRIPT" list-teams
|
||||
python3 "$SCRIPT" get-issue ENG-42
|
||||
python3 "$SCRIPT" get-document 38359beef67c # fetch a doc by slugId from the URL
|
||||
python3 "$SCRIPT" raw 'query { viewer { name } }'
|
||||
```
|
||||
|
||||
All subcommands: `whoami`, `list-teams`, `list-projects`, `list-states`, `list-issues`, `get-issue`, `search-issues`, `create-issue`, `update-issue`, `update-status`, `add-comment`, `list-documents`, `get-document`, `search-documents`, `raw`. Run with `--help` for flags.
|
||||
|
||||
Use the script when: you want a quick answer without crafting GraphQL. Use curl when: you need a query the script doesn't wrap, or you want to compose filters inline.
|
||||
|
||||
## Workflow States
|
||||
|
||||
Linear uses `WorkflowState` objects with a `type` field. **6 state types:**
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `triage` | Incoming issues needing review |
|
||||
| `backlog` | Acknowledged but not yet planned |
|
||||
| `unstarted` | Planned/ready but not started |
|
||||
| `started` | Actively being worked on |
|
||||
| `completed` | Done |
|
||||
| `canceled` | Won't do |
|
||||
|
||||
Each team has its own named states (e.g., "In Progress" is type `started`). To change an issue's status, you need the `stateId` (UUID) of the target state — query workflow states first.
|
||||
|
||||
**Priority values:** 0 = None, 1 = Urgent, 2 = High, 3 = Medium, 4 = Low
|
||||
|
||||
## Common Queries
|
||||
|
||||
### Get current user
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ viewer { id name email } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### List teams
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ teams { nodes { id name key } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### List workflow states for a team
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ workflowStates(filter: { team: { key: { eq: \"ENG\" } } }) { nodes { id name type } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### List issues (first 20)
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ issues(first: 20) { nodes { identifier title priority state { name type } assignee { name } team { key } url } pageInfo { hasNextPage endCursor } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### List my assigned issues
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ viewer { assignedIssues(first: 25) { nodes { identifier title state { name type } priority url } } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### Get a single issue (by identifier like ENG-123)
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ issue(id: \"ENG-123\") { id identifier title description priority state { id name type } assignee { id name } team { key } project { name } labels { nodes { name } } comments { nodes { body user { name } createdAt } } url } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### Search issues by text
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ issueSearch(query: \"bug login\", first: 10) { nodes { identifier title state { name } assignee { name } url } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### Filter issues by state type
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ issues(filter: { state: { type: { in: [\"started\"] } } }, first: 20) { nodes { identifier title state { name } assignee { name } } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### Filter by team and assignee
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ issues(filter: { team: { key: { eq: \"ENG\" } }, assignee: { email: { eq: \"user@example.com\" } } }, first: 20) { nodes { identifier title state { name } priority } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### List projects
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ projects(first: 20) { nodes { id name description progress lead { name } teams { nodes { key } } url } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### List team members
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ users { nodes { id name email active } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### List labels
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ issueLabels { nodes { id name color } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
## Common Mutations
|
||||
|
||||
### Create an issue
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"query": "mutation($input: IssueCreateInput!) { issueCreate(input: $input) { success issue { id identifier title url } } }",
|
||||
"variables": {
|
||||
"input": {
|
||||
"teamId": "TEAM_UUID",
|
||||
"title": "Fix login bug",
|
||||
"description": "Users cannot login with SSO",
|
||||
"priority": 2
|
||||
}
|
||||
}
|
||||
}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### Update issue status
|
||||
First get the target state UUID from the workflow states query above, then:
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "mutation { issueUpdate(id: \"ENG-123\", input: { stateId: \"STATE_UUID\" }) { success issue { identifier state { name type } } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### Assign an issue
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "mutation { issueUpdate(id: \"ENG-123\", input: { assigneeId: \"USER_UUID\" }) { success issue { identifier assignee { name } } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### Set priority
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "mutation { issueUpdate(id: \"ENG-123\", input: { priority: 1 }) { success issue { identifier priority } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### Add a comment
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "mutation { commentCreate(input: { issueId: \"ISSUE_UUID\", body: \"Investigated. Root cause is X.\" }) { success comment { id body } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### Set due date
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "mutation { issueUpdate(id: \"ENG-123\", input: { dueDate: \"2026-04-01\" }) { success issue { identifier dueDate } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### Add labels to an issue
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "mutation { issueUpdate(id: \"ENG-123\", input: { labelIds: [\"LABEL_UUID_1\", \"LABEL_UUID_2\"] }) { success issue { identifier labels { nodes { name } } } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### Add issue to a project
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "mutation { issueUpdate(id: \"ENG-123\", input: { projectId: \"PROJECT_UUID\" }) { success issue { identifier project { name } } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
### Create a project
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"query": "mutation($input: ProjectCreateInput!) { projectCreate(input: $input) { success project { id name url } } }",
|
||||
"variables": {
|
||||
"input": {
|
||||
"name": "Q2 Auth Overhaul",
|
||||
"description": "Replace legacy auth with OAuth2 and PKCE",
|
||||
"teamIds": ["TEAM_UUID"]
|
||||
}
|
||||
}
|
||||
}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
## Documents
|
||||
|
||||
Linear **Documents** are prose docs (RFCs, specs, notes) stored alongside issues. They have their own `documents` root query and `document(id:)` single-fetch.
|
||||
|
||||
### Document URLs and `slugId`
|
||||
|
||||
Document URLs look like:
|
||||
```
|
||||
https://linear.app/<workspace>/document/<slug>-<hexSlugId>
|
||||
```
|
||||
|
||||
The trailing hex segment is the `slugId`. Example: `https://linear.app/nousresearch/document/rfc-hermes-permission-gateway-discord-38359beef67c` → `slugId` is `38359beef67c`.
|
||||
|
||||
**Important schema detail:** the Markdown body is in the `content` field. The ProseMirror JSON is in `contentState` (not `contentData` — that field does not exist and the API returns 400).
|
||||
|
||||
### Fetch a document by slugId
|
||||
|
||||
`document(id:)` only accepts UUIDs. To fetch by the URL's hex slug, filter the collection:
|
||||
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "query($s: String!) { documents(filter: { slugId: { eq: $s } }, first: 1) { nodes { id title content contentState slugId url creator { name } project { name } updatedAt } } }", "variables": {"s": "38359beef67c"}}' \
|
||||
| python3 -m json.tool
|
||||
```
|
||||
|
||||
Or via the Python helper:
|
||||
```bash
|
||||
python3 scripts/linear_api.py get-document 38359beef67c
|
||||
```
|
||||
|
||||
### Fetch a document by UUID
|
||||
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ document(id: \"11700cff-b514-4db3-afcc-3ed1afacba1c\") { title content url } }"}' \
|
||||
| python3 -m json.tool
|
||||
```
|
||||
|
||||
### List recent documents
|
||||
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ documents(first: 25, orderBy: updatedAt) { nodes { id title slugId url updatedAt project { name } } } }"}' \
|
||||
| python3 -m json.tool
|
||||
```
|
||||
|
||||
### Search documents by title
|
||||
|
||||
Linear's schema has no `searchDocuments` root. Use a title-substring filter instead:
|
||||
|
||||
```bash
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ documents(filter: { title: { containsIgnoreCase: \"RFC\" } }, first: 25) { nodes { title slugId url } } }"}' \
|
||||
| python3 -m json.tool
|
||||
```
|
||||
|
||||
## Pagination
|
||||
|
||||
Linear uses Relay-style cursor pagination:
|
||||
|
||||
```bash
|
||||
# First page
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ issues(first: 20) { nodes { identifier title } pageInfo { hasNextPage endCursor } } }"}' | python3 -m json.tool
|
||||
|
||||
# Next page — use endCursor from previous response
|
||||
curl -s -X POST https://api.linear.app/graphql \
|
||||
-H "Authorization: $LINEAR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ issues(first: 20, after: \"CURSOR_FROM_PREVIOUS\") { nodes { identifier title } pageInfo { hasNextPage endCursor } } }"}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
Default page size: 50. Max: 250. Always use `first: N` to limit results.
|
||||
|
||||
## Filtering Reference
|
||||
|
||||
Comparators: `eq`, `neq`, `in`, `nin`, `lt`, `lte`, `gt`, `gte`, `contains`, `startsWith`, `containsIgnoreCase`
|
||||
|
||||
Combine filters with `or: [...]` for OR logic (default is AND within a filter object).
|
||||
|
||||
## Typical Workflow
|
||||
|
||||
1. **Query teams** to get team IDs and keys
|
||||
2. **Query workflow states** for target team to get state UUIDs
|
||||
3. **List or search issues** to find what needs work
|
||||
4. **Create issues** with team ID, title, description, priority
|
||||
5. **Update status** by setting `stateId` to the target workflow state
|
||||
6. **Add comments** to track progress
|
||||
7. **Mark complete** by setting `stateId` to the team's "completed" type state
|
||||
|
||||
## Rate Limits
|
||||
|
||||
- 5,000 requests/hour per API key
|
||||
- 3,000,000 complexity points/hour
|
||||
- Use `first: N` to limit results and reduce complexity cost
|
||||
- Monitor `X-RateLimit-Requests-Remaining` response header
|
||||
|
||||
## Important Notes
|
||||
|
||||
- Always use `terminal` tool with `curl` for API calls — do NOT use `web_extract` or `browser`
|
||||
- Always check the `errors` array in GraphQL responses — HTTP 200 can still contain errors
|
||||
- If `stateId` is omitted when creating issues, Linear defaults to the first backlog state
|
||||
- The `description` field supports Markdown
|
||||
- Use `python3 -m json.tool` or `jq` to format JSON responses for readability
|
||||
-172
@@ -1,172 +0,0 @@
|
||||
---
|
||||
title: "Debugging Hermes Tui Commands — Debug Hermes TUI slash commands: Python, gateway, Ink UI"
|
||||
sidebar_label: "Debugging Hermes Tui Commands"
|
||||
description: "Debug Hermes TUI slash commands: Python, gateway, Ink UI"
|
||||
---
|
||||
|
||||
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
||||
|
||||
# Debugging Hermes Tui Commands
|
||||
|
||||
Debug Hermes TUI slash commands: Python, gateway, Ink UI.
|
||||
|
||||
## Skill metadata
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/software-development/debugging-hermes-tui-commands` |
|
||||
| Version | `1.0.0` |
|
||||
| Author | Hermes Agent |
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `debugging`, `hermes-agent`, `tui`, `slash-commands`, `typescript`, `python` |
|
||||
| Related skills | [`python-debugpy`](/docs/user-guide/skills/bundled/software-development/software-development-python-debugpy), [`node-inspect-debugger`](/docs/user-guide/skills/bundled/software-development/software-development-node-inspect-debugger), [`systematic-debugging`](/docs/user-guide/skills/bundled/software-development/software-development-systematic-debugging) |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
:::info
|
||||
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
||||
:::
|
||||
|
||||
# Debugging Hermes TUI Slash Commands
|
||||
|
||||
## Overview
|
||||
|
||||
Hermes slash commands span three layers — Python command registry, tui_gateway JSON-RPC bridge, and the Ink/TypeScript frontend. When a command misbehaves (missing from autocomplete, works in CLI but not TUI, config persists but UI doesn't update), the bug is almost always one layer being out of sync with another.
|
||||
|
||||
Use this skill when you encounter issues with slash commands in the Hermes TUI, particularly when commands aren't showing in autocomplete, aren't working properly in the TUI, or need to be added/updated.
|
||||
|
||||
## When to Use
|
||||
|
||||
- A slash command exists in one part of the codebase but doesn't work fully
|
||||
- A command needs to be added to both backend and frontend
|
||||
- Command autocomplete isn't working for specific commands
|
||||
- Command behavior is inconsistent between CLI and TUI
|
||||
- A command persists config but doesn't apply live in the TUI
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
<!-- ascii-guard-ignore -->
|
||||
```
|
||||
Python backend (hermes_cli/commands.py) <- canonical COMMAND_REGISTRY
|
||||
│
|
||||
▼
|
||||
TUI gateway (tui_gateway/server.py) <- slash.exec / command.dispatch
|
||||
│
|
||||
▼
|
||||
TUI frontend (ui-tui/src/app/slash/) <- local handlers + fallthrough
|
||||
```
|
||||
<!-- ascii-guard-ignore-end -->
|
||||
|
||||
Command definitions must be registered consistently across Python and TypeScript to work properly. The Python `COMMAND_REGISTRY` is the source of truth for: CLI dispatch, gateway help, Telegram BotCommand menu, Slack subcommand map, and autocomplete data shipped to Ink.
|
||||
|
||||
## Investigation Steps
|
||||
|
||||
1. **Check if the command exists in the TUI frontend:**
|
||||
```bash
|
||||
search_files --pattern "/commandname" --file_glob "*.ts" --path ui-tui/
|
||||
search_files --pattern "/commandname" --file_glob "*.tsx" --path ui-tui/
|
||||
```
|
||||
|
||||
2. **Examine the TUI command definition:**
|
||||
```bash
|
||||
read_file ui-tui/src/app/slash/commands/core.ts
|
||||
# If not there:
|
||||
search_files --pattern "commandname" --path ui-tui/src/app/slash/commands --target files
|
||||
```
|
||||
|
||||
3. **Check if the command exists in the Python backend:**
|
||||
```bash
|
||||
search_files --pattern "CommandDef" --file_glob "*.py" --path hermes_cli/
|
||||
search_files --pattern "commandname" --path hermes_cli/commands.py --context 3
|
||||
```
|
||||
|
||||
4. **Examine the gateway implementation:**
|
||||
```bash
|
||||
search_files --pattern "complete.slash|slash.exec" --path tui_gateway/
|
||||
```
|
||||
|
||||
## Fix: Missing Command Autocomplete
|
||||
|
||||
If a command exists in the TUI but doesn't show in autocomplete:
|
||||
|
||||
1. Add a `CommandDef` entry to `COMMAND_REGISTRY` in `hermes_cli/commands.py`:
|
||||
```python
|
||||
CommandDef("commandname", "Description of the command", "Session",
|
||||
cli_only=True, aliases=("alias",),
|
||||
args_hint="[arg1|arg2|arg3]",
|
||||
subcommands=("arg1", "arg2", "arg3")),
|
||||
```
|
||||
|
||||
2. Pick `cli_only` vs gateway availability carefully:
|
||||
- `cli_only=True` — only in the interactive CLI/TUI
|
||||
- `gateway_only=True` — only in messaging platforms
|
||||
- neither — available everywhere
|
||||
- `gateway_config_gate="display.foo"` — config-gated availability in the gateway
|
||||
|
||||
3. Ensure `subcommands` matches the expected tab-completion options shown by the TUI.
|
||||
|
||||
4. If the command runs server-side, add a handler in `HermesCLI.process_command()` in `cli.py`:
|
||||
```python
|
||||
elif canonical == "commandname":
|
||||
self._handle_commandname(cmd_original)
|
||||
```
|
||||
|
||||
5. For gateway-available commands, add a handler in `gateway/run.py`:
|
||||
```python
|
||||
if canonical == "commandname":
|
||||
return await self._handle_commandname(event)
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
1. **Command shows in TUI but not in autocomplete.** The command is defined in the TUI codebase but missing from `COMMAND_REGISTRY` in `hermes_cli/commands.py`. Autocomplete data ships from Python.
|
||||
|
||||
2. **Command shows in autocomplete but doesn't work.** Check the command handler in `tui_gateway/server.py` and the frontend handler in `ui-tui/src/app/createSlashHandler.ts`. If the command is local-only in Ink, it must be handled in `app.tsx` built-in branch; otherwise it falls through to `slash.exec` and must have a Python handler.
|
||||
|
||||
3. **Command behavior differs between CLI and TUI.** The command might have different implementations. Check both `cli.py::process_command` and the TUI's local handler. Local TUI handlers take precedence over gateway dispatch.
|
||||
|
||||
4. **Command persists config but doesn't apply live.** For TUI-local commands, updating `config.set` is not enough. Also patch the relevant nanostore state immediately (usually `patchUiState(...)`) and pass any new state through rendering components. Example: `/details collapsed` must update live detail visibility, not just save `details_mode`; in-session global `/details <mode>` may need a separate command-override flag so live commands can override built-in section defaults while startup/config sync preserves default-expanded thinking/tools behavior.
|
||||
|
||||
5. **Gateway dispatch silently ignores the command.** The gateway only dispatches commands it knows about. Check `GATEWAY_KNOWN_COMMANDS` (derived from `COMMAND_REGISTRY` automatically) includes the canonical name. If the command is `cli_only` with a `gateway_config_gate`, verify the gated config value is truthy.
|
||||
|
||||
## Debugging Tactics
|
||||
|
||||
When surface-level inspection doesn't reveal the bug:
|
||||
|
||||
- **Python side hangs or misbehaves:** use the `python-debugpy` skill to break inside `_SlashWorker.exec` or the command handler. `remote-pdb` set at the handler entry is the fastest path.
|
||||
- **Ink side not reacting:** use the `node-inspect-debugger` skill to break in `app.tsx`'s slash dispatch or the local command branch. `sb('dist/app.js', <line>)` after `npm run build`.
|
||||
- **Registry mismatch / unclear which side is wrong:** compare the canonical `COMMAND_REGISTRY` entry against the TUI's local command list side-by-side.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- Don't forget to set the appropriate category for the command in `CommandDef` (e.g., "Session", "Configuration", "Tools & Skills", "Info", "Exit")
|
||||
- Make sure any aliases are properly registered in the `aliases` tuple — no other file changes are needed, everything downstream (Telegram menu, Slack mapping, autocomplete, help) derives from it
|
||||
- For commands with subcommands, ensure the `subcommands` tuple in `CommandDef` matches what's in the TUI code
|
||||
- `cli_only=True` commands won't work in gateway/messaging platforms — unless you add a `gateway_config_gate` and the gate is truthy
|
||||
- After adding live UI state, search every consumer of the old prop/helper and thread the new state through all render paths, not just the active streaming path. TUI detail rendering has at least two important paths: live `StreamingAssistant`/`ToolTrail` and transcript/pending `MessageLine` rows. A `/clean` pass should explicitly check both.
|
||||
- Rebuild the TUI (`npm --prefix ui-tui run build`) before testing — tsx watch mode may lag on first launch
|
||||
|
||||
## Verification
|
||||
|
||||
After fixing:
|
||||
|
||||
1. Rebuild the TUI:
|
||||
```bash
|
||||
cd /home/bb/hermes-agent && npm --prefix ui-tui run build
|
||||
```
|
||||
|
||||
2. Run the TUI and test the command:
|
||||
```bash
|
||||
hermes --tui
|
||||
```
|
||||
|
||||
3. Type `/` and verify the command appears in autocomplete suggestions with the expected description and args hint.
|
||||
|
||||
4. Execute the command and confirm:
|
||||
- Expected behavior fires
|
||||
- Any persisted config updates correctly (`read_file ~/.hermes/config.yaml`)
|
||||
- Live UI state reflects the change immediately (not just after restart)
|
||||
|
||||
5. If the command is also gateway-available, test it from at least one messaging platform (or run the gateway tests: `scripts/run_tests.sh tests/gateway/`).
|
||||
+1
-1
@@ -21,7 +21,7 @@ Author in-repo SKILL.md: frontmatter, validator, structure.
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `skills`, `authoring`, `hermes-agent`, `conventions`, `skill-md` |
|
||||
| Related skills | [`writing-plans`](/docs/user-guide/skills/bundled/software-development/software-development-writing-plans), [`requesting-code-review`](/docs/user-guide/skills/bundled/software-development/software-development-requesting-code-review) |
|
||||
| Related skills | [`plan`](/docs/user-guide/skills/bundled/software-development/software-development-plan), [`requesting-code-review`](/docs/user-guide/skills/bundled/software-development/software-development-requesting-code-review) |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
|
||||
+287
-7
@@ -1,14 +1,14 @@
|
||||
---
|
||||
title: "Plan — Plan mode: write markdown plan to"
|
||||
title: "Plan — Plan mode: write an actionable markdown plan to"
|
||||
sidebar_label: "Plan"
|
||||
description: "Plan mode: write markdown plan to"
|
||||
description: "Plan mode: write an actionable markdown plan to"
|
||||
---
|
||||
|
||||
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
||||
|
||||
# Plan
|
||||
|
||||
Plan mode: write markdown plan to .hermes/plans/, no exec.
|
||||
Plan mode: write an actionable markdown plan to .hermes/plans/, no execution. Bite-sized tasks, exact paths, complete code.
|
||||
|
||||
## Skill metadata
|
||||
|
||||
@@ -16,12 +16,12 @@ Plan mode: write markdown plan to .hermes/plans/, no exec.
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/software-development/plan` |
|
||||
| Version | `1.0.0` |
|
||||
| Author | Hermes Agent |
|
||||
| Version | `2.0.0` |
|
||||
| Author | Hermes Agent (writing-craft adapted from obra/superpowers) |
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `planning`, `plan-mode`, `implementation`, `workflow` |
|
||||
| Related skills | [`writing-plans`](/docs/user-guide/skills/bundled/software-development/software-development-writing-plans), [`subagent-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-subagent-driven-development) |
|
||||
| Tags | `planning`, `plan-mode`, `implementation`, `workflow`, `design`, `documentation` |
|
||||
| Related skills | [`subagent-driven-development`](/docs/user-guide/skills/optional/software-development/software-development-subagent-driven-development), [`test-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-test-driven-development), [`requesting-code-review`](/docs/user-guide/skills/bundled/software-development/software-development-requesting-code-review) |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
@@ -74,3 +74,283 @@ If not, create a sensible timestamped filename yourself under `.hermes/plans/`.
|
||||
- If no explicit instruction accompanies `/plan`, infer the task from the current conversation context.
|
||||
- If it is genuinely underspecified, ask a brief clarifying question instead of guessing.
|
||||
- After saving the plan, reply briefly with what you planned and the saved path.
|
||||
|
||||
---
|
||||
|
||||
# Writing the Plan Well
|
||||
|
||||
The rest of this skill is the craft of authoring a *good* implementation plan — the content that goes inside the markdown file above.
|
||||
|
||||
## Overview
|
||||
|
||||
Write comprehensive implementation plans assuming the implementer has zero context for the codebase and questionable taste. Document everything they need: which files to touch, complete code, testing commands, docs to check, how to verify. Give them bite-sized tasks. DRY. YAGNI. TDD. Frequent commits.
|
||||
|
||||
Assume the implementer is a skilled developer but knows almost nothing about the toolset or problem domain. Assume they don't know good test design very well.
|
||||
|
||||
**Core principle:** A good plan makes implementation obvious. If someone has to guess, the plan is incomplete.
|
||||
|
||||
## When a Full Implementation Plan Helps
|
||||
|
||||
**Always use before:**
|
||||
- Implementing multi-step features
|
||||
- Breaking down complex requirements
|
||||
- Delegating to subagents via subagent-driven-development
|
||||
|
||||
**Don't skip when:**
|
||||
- Feature seems simple (assumptions cause bugs)
|
||||
- You plan to implement it yourself (future you needs guidance)
|
||||
- Working alone (documentation matters)
|
||||
|
||||
## Bite-Sized Task Granularity
|
||||
|
||||
**Each task = 2-5 minutes of focused work.**
|
||||
|
||||
Every step is one action:
|
||||
- "Write the failing test" — step
|
||||
- "Run it to make sure it fails" — step
|
||||
- "Implement the minimal code to make the test pass" — step
|
||||
- "Run the tests and make sure they pass" — step
|
||||
- "Commit" — step
|
||||
|
||||
**Too big:**
|
||||
```markdown
|
||||
### Task 1: Build authentication system
|
||||
[50 lines of code across 5 files]
|
||||
```
|
||||
|
||||
**Right size:**
|
||||
```markdown
|
||||
### Task 1: Create User model with email field
|
||||
[10 lines, 1 file]
|
||||
|
||||
### Task 2: Add password hash field to User
|
||||
[8 lines, 1 file]
|
||||
|
||||
### Task 3: Create password hashing utility
|
||||
[15 lines, 1 file]
|
||||
```
|
||||
|
||||
## Plan Document Structure
|
||||
|
||||
### Header (Required)
|
||||
|
||||
Every plan MUST start with:
|
||||
|
||||
```markdown
|
||||
# [Feature Name] Implementation Plan
|
||||
|
||||
> **For Hermes:** Use subagent-driven-development skill to implement this plan task-by-task.
|
||||
|
||||
**Goal:** [One sentence describing what this builds]
|
||||
|
||||
**Architecture:** [2-3 sentences about approach]
|
||||
|
||||
**Tech Stack:** [Key technologies/libraries]
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
### Task Structure
|
||||
|
||||
Each task follows this format:
|
||||
|
||||
````markdown
|
||||
### Task N: [Descriptive Name]
|
||||
|
||||
**Objective:** What this task accomplishes (one sentence)
|
||||
|
||||
**Files:**
|
||||
- Create: `exact/path/to/new_file.py`
|
||||
- Modify: `exact/path/to/existing.py:45-67` (line numbers if known)
|
||||
- Test: `tests/path/to/test_file.py`
|
||||
|
||||
**Step 1: Write failing test**
|
||||
|
||||
```python
|
||||
def test_specific_behavior():
|
||||
result = function(input)
|
||||
assert result == expected
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify failure**
|
||||
|
||||
Run: `pytest tests/path/test.py::test_specific_behavior -v`
|
||||
Expected: FAIL — "function not defined"
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
```python
|
||||
def function(input):
|
||||
return expected
|
||||
```
|
||||
|
||||
**Step 4: Run test to verify pass**
|
||||
|
||||
Run: `pytest tests/path/test.py::test_specific_behavior -v`
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add tests/path/test.py src/path/file.py
|
||||
git commit -m "feat: add specific feature"
|
||||
```
|
||||
````
|
||||
|
||||
## Writing Process
|
||||
|
||||
### Step 1: Understand Requirements
|
||||
|
||||
Read and understand:
|
||||
- Feature requirements
|
||||
- Design documents or user description
|
||||
- Acceptance criteria
|
||||
- Constraints
|
||||
|
||||
### Step 2: Explore the Codebase
|
||||
|
||||
Use Hermes tools to understand the project:
|
||||
|
||||
```python
|
||||
# Understand project structure
|
||||
search_files("*.py", target="files", path="src/")
|
||||
|
||||
# Look at similar features
|
||||
search_files("similar_pattern", path="src/", file_glob="*.py")
|
||||
|
||||
# Check existing tests
|
||||
search_files("*.py", target="files", path="tests/")
|
||||
|
||||
# Read key files
|
||||
read_file("src/app.py")
|
||||
```
|
||||
|
||||
### Step 3: Design Approach
|
||||
|
||||
Decide:
|
||||
- Architecture pattern
|
||||
- File organization
|
||||
- Dependencies needed
|
||||
- Testing strategy
|
||||
|
||||
### Step 4: Write Tasks
|
||||
|
||||
Create tasks in order:
|
||||
1. Setup/infrastructure
|
||||
2. Core functionality (TDD for each)
|
||||
3. Edge cases
|
||||
4. Integration
|
||||
5. Cleanup/documentation
|
||||
|
||||
### Step 5: Add Complete Details
|
||||
|
||||
For each task, include:
|
||||
- **Exact file paths** (not "the config file" but `src/config/settings.py`)
|
||||
- **Complete code examples** (not "add validation" but the actual code)
|
||||
- **Exact commands** with expected output
|
||||
- **Verification steps** that prove the task works
|
||||
|
||||
### Step 6: Review the Plan
|
||||
|
||||
Check:
|
||||
- [ ] Tasks are sequential and logical
|
||||
- [ ] Each task is bite-sized (2-5 min)
|
||||
- [ ] File paths are exact
|
||||
- [ ] Code examples are complete (copy-pasteable)
|
||||
- [ ] Commands are exact with expected output
|
||||
- [ ] No missing context
|
||||
- [ ] DRY, YAGNI, TDD principles applied
|
||||
|
||||
## Principles
|
||||
|
||||
### DRY (Don't Repeat Yourself)
|
||||
|
||||
**Bad:** Copy-paste validation in 3 places
|
||||
**Good:** Extract validation function, use everywhere
|
||||
|
||||
### YAGNI (You Aren't Gonna Need It)
|
||||
|
||||
**Bad:** Add "flexibility" for future requirements
|
||||
**Good:** Implement only what's needed now
|
||||
|
||||
```python
|
||||
# Bad — YAGNI violation
|
||||
class User:
|
||||
def __init__(self, name, email):
|
||||
self.name = name
|
||||
self.email = email
|
||||
self.preferences = {} # Not needed yet!
|
||||
self.metadata = {} # Not needed yet!
|
||||
|
||||
# Good — YAGNI
|
||||
class User:
|
||||
def __init__(self, name, email):
|
||||
self.name = name
|
||||
self.email = email
|
||||
```
|
||||
|
||||
### TDD (Test-Driven Development)
|
||||
|
||||
Every task that produces code should include the full TDD cycle:
|
||||
1. Write failing test
|
||||
2. Run to verify failure
|
||||
3. Write minimal code
|
||||
4. Run to verify pass
|
||||
|
||||
See `test-driven-development` skill for details.
|
||||
|
||||
### Frequent Commits
|
||||
|
||||
Commit after every task:
|
||||
```bash
|
||||
git add [files]
|
||||
git commit -m "type: description"
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
### Vague Tasks
|
||||
|
||||
**Bad:** "Add authentication"
|
||||
**Good:** "Create User model with email and password_hash fields"
|
||||
|
||||
### Incomplete Code
|
||||
|
||||
**Bad:** "Step 1: Add validation function"
|
||||
**Good:** "Step 1: Add validation function" followed by the complete function code
|
||||
|
||||
### Missing Verification
|
||||
|
||||
**Bad:** "Step 3: Test it works"
|
||||
**Good:** "Step 3: Run `pytest tests/test_auth.py -v`, expected: 3 passed"
|
||||
|
||||
### Missing File Paths
|
||||
|
||||
**Bad:** "Create the model file"
|
||||
**Good:** "Create: `src/models/user.py`"
|
||||
|
||||
## Execution Handoff
|
||||
|
||||
After saving the plan, offer the execution approach:
|
||||
|
||||
**"Plan complete and saved. Ready to execute using subagent-driven-development — I'll dispatch a fresh subagent per task with two-stage review (spec compliance then code quality). Shall I proceed?"**
|
||||
|
||||
When executing, use the `subagent-driven-development` skill:
|
||||
- Fresh `delegate_task` per task with full context
|
||||
- Spec compliance review after each task
|
||||
- Code quality review after spec passes
|
||||
- Proceed only when both reviews approve
|
||||
|
||||
## Remember
|
||||
|
||||
```
|
||||
Bite-sized tasks (2-5 min each)
|
||||
Exact file paths
|
||||
Complete code (copy-pasteable)
|
||||
Exact commands with expected output
|
||||
Verification steps
|
||||
DRY, YAGNI, TDD
|
||||
Frequent commits
|
||||
```
|
||||
|
||||
**A good plan makes implementation obvious.**
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ Pre-commit review: security scan, quality gates, auto-fix.
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `code-review`, `security`, `verification`, `quality`, `pre-commit`, `auto-fix` |
|
||||
| Related skills | [`subagent-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-subagent-driven-development), [`writing-plans`](/docs/user-guide/skills/bundled/software-development/software-development-writing-plans), [`test-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-test-driven-development), [`github-code-review`](/docs/user-guide/skills/bundled/github/github-github-code-review) |
|
||||
| Related skills | [`subagent-driven-development`](/docs/user-guide/skills/optional/software-development/software-development-subagent-driven-development), [`plan`](/docs/user-guide/skills/bundled/software-development/software-development-plan), [`test-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-test-driven-development), [`github-code-review`](/docs/user-guide/skills/bundled/github/github-github-code-review) |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
@@ -284,7 +284,7 @@ The two-stage review (spec compliance + code quality) uses this pipeline.
|
||||
**test-driven-development:** This pipeline verifies TDD discipline was followed —
|
||||
tests exist, tests pass, no regressions.
|
||||
|
||||
**writing-plans:** Validates implementation matches the plan requirements.
|
||||
**plan:** Validates implementation matches the plan requirements.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ Throwaway experiments to validate an idea before build.
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `spike`, `prototype`, `experiment`, `feasibility`, `throwaway`, `exploration`, `research`, `planning`, `mvp`, `proof-of-concept` |
|
||||
| Related skills | [`sketch`](/docs/user-guide/skills/bundled/creative/creative-sketch), [`writing-plans`](/docs/user-guide/skills/bundled/software-development/software-development-writing-plans), [`subagent-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-subagent-driven-development), [`plan`](/docs/user-guide/skills/bundled/software-development/software-development-plan) |
|
||||
| Related skills | [`sketch`](/docs/user-guide/skills/bundled/creative/creative-sketch), [`subagent-driven-development`](/docs/user-guide/skills/optional/software-development/software-development-subagent-driven-development), [`plan`](/docs/user-guide/skills/bundled/software-development/software-development-plan) |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
@@ -38,7 +38,7 @@ Load this when the user says things like "let me try this", "I want to see if X
|
||||
## When NOT to use this
|
||||
|
||||
- The answer is knowable from docs or reading code — just do research, don't build
|
||||
- The work is production path — use `writing-plans` / `plan` instead
|
||||
- The work is production path — use the `plan` skill instead
|
||||
- The idea is already validated — jump straight to implementation
|
||||
|
||||
## If the user has the full GSD system installed
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ description: "4-phase root cause debugging: understand bugs before fixing"
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `debugging`, `troubleshooting`, `problem-solving`, `root-cause`, `investigation` |
|
||||
| Related skills | [`test-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-test-driven-development), [`writing-plans`](/docs/user-guide/skills/bundled/software-development/software-development-writing-plans), [`subagent-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-subagent-driven-development) |
|
||||
| Related skills | [`test-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-test-driven-development), [`plan`](/docs/user-guide/skills/bundled/software-development/software-development-plan), [`subagent-driven-development`](/docs/user-guide/skills/optional/software-development/software-development-subagent-driven-development) |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ TDD: enforce RED-GREEN-REFACTOR, tests before code.
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `testing`, `tdd`, `development`, `quality`, `red-green-refactor` |
|
||||
| Related skills | [`systematic-debugging`](/docs/user-guide/skills/bundled/software-development/software-development-systematic-debugging), [`writing-plans`](/docs/user-guide/skills/bundled/software-development/software-development-writing-plans), [`subagent-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-subagent-driven-development) |
|
||||
| Related skills | [`systematic-debugging`](/docs/user-guide/skills/bundled/software-development/software-development-systematic-debugging), [`plan`](/docs/user-guide/skills/bundled/software-development/software-development-plan), [`subagent-driven-development`](/docs/user-guide/skills/optional/software-development/software-development-subagent-driven-development) |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
|
||||
-315
@@ -1,315 +0,0 @@
|
||||
---
|
||||
title: "Writing Plans — Write implementation plans: bite-sized tasks, paths, code"
|
||||
sidebar_label: "Writing Plans"
|
||||
description: "Write implementation plans: bite-sized tasks, paths, code"
|
||||
---
|
||||
|
||||
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
||||
|
||||
# Writing Plans
|
||||
|
||||
Write implementation plans: bite-sized tasks, paths, code.
|
||||
|
||||
## Skill metadata
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/software-development/writing-plans` |
|
||||
| Version | `1.1.0` |
|
||||
| Author | Hermes Agent (adapted from obra/superpowers) |
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `planning`, `design`, `implementation`, `workflow`, `documentation` |
|
||||
| Related skills | [`subagent-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-subagent-driven-development), [`test-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-test-driven-development), [`requesting-code-review`](/docs/user-guide/skills/bundled/software-development/software-development-requesting-code-review) |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
:::info
|
||||
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
||||
:::
|
||||
|
||||
# Writing Implementation Plans
|
||||
|
||||
## Overview
|
||||
|
||||
Write comprehensive implementation plans assuming the implementer has zero context for the codebase and questionable taste. Document everything they need: which files to touch, complete code, testing commands, docs to check, how to verify. Give them bite-sized tasks. DRY. YAGNI. TDD. Frequent commits.
|
||||
|
||||
Assume the implementer is a skilled developer but knows almost nothing about the toolset or problem domain. Assume they don't know good test design very well.
|
||||
|
||||
**Core principle:** A good plan makes implementation obvious. If someone has to guess, the plan is incomplete.
|
||||
|
||||
## When to Use
|
||||
|
||||
**Always use before:**
|
||||
- Implementing multi-step features
|
||||
- Breaking down complex requirements
|
||||
- Delegating to subagents via subagent-driven-development
|
||||
|
||||
**Don't skip when:**
|
||||
- Feature seems simple (assumptions cause bugs)
|
||||
- You plan to implement it yourself (future you needs guidance)
|
||||
- Working alone (documentation matters)
|
||||
|
||||
## Bite-Sized Task Granularity
|
||||
|
||||
**Each task = 2-5 minutes of focused work.**
|
||||
|
||||
Every step is one action:
|
||||
- "Write the failing test" — step
|
||||
- "Run it to make sure it fails" — step
|
||||
- "Implement the minimal code to make the test pass" — step
|
||||
- "Run the tests and make sure they pass" — step
|
||||
- "Commit" — step
|
||||
|
||||
**Too big:**
|
||||
```markdown
|
||||
### Task 1: Build authentication system
|
||||
[50 lines of code across 5 files]
|
||||
```
|
||||
|
||||
**Right size:**
|
||||
```markdown
|
||||
### Task 1: Create User model with email field
|
||||
[10 lines, 1 file]
|
||||
|
||||
### Task 2: Add password hash field to User
|
||||
[8 lines, 1 file]
|
||||
|
||||
### Task 3: Create password hashing utility
|
||||
[15 lines, 1 file]
|
||||
```
|
||||
|
||||
## Plan Document Structure
|
||||
|
||||
### Header (Required)
|
||||
|
||||
Every plan MUST start with:
|
||||
|
||||
```markdown
|
||||
# [Feature Name] Implementation Plan
|
||||
|
||||
> **For Hermes:** Use subagent-driven-development skill to implement this plan task-by-task.
|
||||
|
||||
**Goal:** [One sentence describing what this builds]
|
||||
|
||||
**Architecture:** [2-3 sentences about approach]
|
||||
|
||||
**Tech Stack:** [Key technologies/libraries]
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
### Task Structure
|
||||
|
||||
Each task follows this format:
|
||||
|
||||
````markdown
|
||||
### Task N: [Descriptive Name]
|
||||
|
||||
**Objective:** What this task accomplishes (one sentence)
|
||||
|
||||
**Files:**
|
||||
- Create: `exact/path/to/new_file.py`
|
||||
- Modify: `exact/path/to/existing.py:45-67` (line numbers if known)
|
||||
- Test: `tests/path/to/test_file.py`
|
||||
|
||||
**Step 1: Write failing test**
|
||||
|
||||
```python
|
||||
def test_specific_behavior():
|
||||
result = function(input)
|
||||
assert result == expected
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify failure**
|
||||
|
||||
Run: `pytest tests/path/test.py::test_specific_behavior -v`
|
||||
Expected: FAIL — "function not defined"
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
```python
|
||||
def function(input):
|
||||
return expected
|
||||
```
|
||||
|
||||
**Step 4: Run test to verify pass**
|
||||
|
||||
Run: `pytest tests/path/test.py::test_specific_behavior -v`
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add tests/path/test.py src/path/file.py
|
||||
git commit -m "feat: add specific feature"
|
||||
```
|
||||
````
|
||||
|
||||
## Writing Process
|
||||
|
||||
### Step 1: Understand Requirements
|
||||
|
||||
Read and understand:
|
||||
- Feature requirements
|
||||
- Design documents or user description
|
||||
- Acceptance criteria
|
||||
- Constraints
|
||||
|
||||
### Step 2: Explore the Codebase
|
||||
|
||||
Use Hermes tools to understand the project:
|
||||
|
||||
```python
|
||||
# Understand project structure
|
||||
search_files("*.py", target="files", path="src/")
|
||||
|
||||
# Look at similar features
|
||||
search_files("similar_pattern", path="src/", file_glob="*.py")
|
||||
|
||||
# Check existing tests
|
||||
search_files("*.py", target="files", path="tests/")
|
||||
|
||||
# Read key files
|
||||
read_file("src/app.py")
|
||||
```
|
||||
|
||||
### Step 3: Design Approach
|
||||
|
||||
Decide:
|
||||
- Architecture pattern
|
||||
- File organization
|
||||
- Dependencies needed
|
||||
- Testing strategy
|
||||
|
||||
### Step 4: Write Tasks
|
||||
|
||||
Create tasks in order:
|
||||
1. Setup/infrastructure
|
||||
2. Core functionality (TDD for each)
|
||||
3. Edge cases
|
||||
4. Integration
|
||||
5. Cleanup/documentation
|
||||
|
||||
### Step 5: Add Complete Details
|
||||
|
||||
For each task, include:
|
||||
- **Exact file paths** (not "the config file" but `src/config/settings.py`)
|
||||
- **Complete code examples** (not "add validation" but the actual code)
|
||||
- **Exact commands** with expected output
|
||||
- **Verification steps** that prove the task works
|
||||
|
||||
### Step 6: Review the Plan
|
||||
|
||||
Check:
|
||||
- [ ] Tasks are sequential and logical
|
||||
- [ ] Each task is bite-sized (2-5 min)
|
||||
- [ ] File paths are exact
|
||||
- [ ] Code examples are complete (copy-pasteable)
|
||||
- [ ] Commands are exact with expected output
|
||||
- [ ] No missing context
|
||||
- [ ] DRY, YAGNI, TDD principles applied
|
||||
|
||||
### Step 7: Save the Plan
|
||||
|
||||
```bash
|
||||
mkdir -p docs/plans
|
||||
# Save plan to docs/plans/YYYY-MM-DD-feature-name.md
|
||||
git add docs/plans/
|
||||
git commit -m "docs: add implementation plan for [feature]"
|
||||
```
|
||||
|
||||
## Principles
|
||||
|
||||
### DRY (Don't Repeat Yourself)
|
||||
|
||||
**Bad:** Copy-paste validation in 3 places
|
||||
**Good:** Extract validation function, use everywhere
|
||||
|
||||
### YAGNI (You Aren't Gonna Need It)
|
||||
|
||||
**Bad:** Add "flexibility" for future requirements
|
||||
**Good:** Implement only what's needed now
|
||||
|
||||
```python
|
||||
# Bad — YAGNI violation
|
||||
class User:
|
||||
def __init__(self, name, email):
|
||||
self.name = name
|
||||
self.email = email
|
||||
self.preferences = {} # Not needed yet!
|
||||
self.metadata = {} # Not needed yet!
|
||||
|
||||
# Good — YAGNI
|
||||
class User:
|
||||
def __init__(self, name, email):
|
||||
self.name = name
|
||||
self.email = email
|
||||
```
|
||||
|
||||
### TDD (Test-Driven Development)
|
||||
|
||||
Every task that produces code should include the full TDD cycle:
|
||||
1. Write failing test
|
||||
2. Run to verify failure
|
||||
3. Write minimal code
|
||||
4. Run to verify pass
|
||||
|
||||
See `test-driven-development` skill for details.
|
||||
|
||||
### Frequent Commits
|
||||
|
||||
Commit after every task:
|
||||
```bash
|
||||
git add [files]
|
||||
git commit -m "type: description"
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
### Vague Tasks
|
||||
|
||||
**Bad:** "Add authentication"
|
||||
**Good:** "Create User model with email and password_hash fields"
|
||||
|
||||
### Incomplete Code
|
||||
|
||||
**Bad:** "Step 1: Add validation function"
|
||||
**Good:** "Step 1: Add validation function" followed by the complete function code
|
||||
|
||||
### Missing Verification
|
||||
|
||||
**Bad:** "Step 3: Test it works"
|
||||
**Good:** "Step 3: Run `pytest tests/test_auth.py -v`, expected: 3 passed"
|
||||
|
||||
### Missing File Paths
|
||||
|
||||
**Bad:** "Create the model file"
|
||||
**Good:** "Create: `src/models/user.py`"
|
||||
|
||||
## Execution Handoff
|
||||
|
||||
After saving the plan, offer the execution approach:
|
||||
|
||||
**"Plan complete and saved. Ready to execute using subagent-driven-development — I'll dispatch a fresh subagent per task with two-stage review (spec compliance then code quality). Shall I proceed?"**
|
||||
|
||||
When executing, use the `subagent-driven-development` skill:
|
||||
- Fresh `delegate_task` per task with full context
|
||||
- Spec compliance review after each task
|
||||
- Code quality review after spec passes
|
||||
- Proceed only when both reviews approve
|
||||
|
||||
## Remember
|
||||
|
||||
```
|
||||
Bite-sized tasks (2-5 min each)
|
||||
Exact file paths
|
||||
Complete code (copy-pasteable)
|
||||
Exact commands with expected output
|
||||
Verification steps
|
||||
DRY, YAGNI, TDD
|
||||
Frequent commits
|
||||
```
|
||||
|
||||
**A good plan makes implementation obvious.**
|
||||
+15
-15
@@ -14,8 +14,8 @@ Article illustrations: type × style × palette consistency.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/creative/baoyu-article-illustrator` |
|
||||
| Source | Optional — install with `hermes skills install official/creative/baoyu-article-illustrator` |
|
||||
| Path | `optional-skills/creative/baoyu-article-illustrator` |
|
||||
| Version | `1.57.0` |
|
||||
| Author | 宝玉 (JimLiu) |
|
||||
| License | MIT |
|
||||
@@ -48,7 +48,7 @@ Trigger this skill when the user asks to illustrate an article, add images to an
|
||||
|
||||
Combine freely: `type=infographic, style=vector-illustration, palette=macaron`.
|
||||
|
||||
Or use presets: `edu-visual` → type + style + palette in one shot. See [style-presets.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-article-illustrator/references/style-presets.md).
|
||||
Or use presets: `edu-visual` → type + style + palette in one shot. See [style-presets.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-article-illustrator/references/style-presets.md).
|
||||
|
||||
## Types
|
||||
|
||||
@@ -63,7 +63,7 @@ Or use presets: `edu-visual` → type + style + palette in one shot. See [style-
|
||||
|
||||
## Styles
|
||||
|
||||
See [references/styles.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-article-illustrator/references/styles.md) for Core Styles, the full gallery, and Type × Style compatibility.
|
||||
See [references/styles.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-article-illustrator/references/styles.md) for Core Styles, the full gallery, and Type × Style compatibility.
|
||||
|
||||
## Output Structure
|
||||
|
||||
@@ -116,7 +116,7 @@ If the user supplies reference images (paths pasted inline, attachments, or a UR
|
||||
2. **Do not** try to copy the binary via `write_file` / `read_file` — those are text-only. If you want a local copy for the record, use `terminal` (`cp "$src" "{output-dir}/references/NN-ref-{slug}.{ext}"`). The skill itself never needs to read the binary; it works off the vision description.
|
||||
3. Since `image_generate` doesn't take image inputs, the vision description is what gets embedded in prompts during Step 5.
|
||||
|
||||
Full procedures: [references/workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-article-illustrator/references/workflow.md#step-1-detect-reference-images).
|
||||
Full procedures: [references/workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-article-illustrator/references/workflow.md#step-1-detect-reference-images).
|
||||
|
||||
### Step 2: Analyze
|
||||
|
||||
@@ -129,7 +129,7 @@ Full procedures: [references/workflow.md](https://github.com/NousResearch/hermes
|
||||
|
||||
Read source (file path → `read_file`, or pasted text) and write the analysis to `{output-dir}/analysis.md` using `write_file`.
|
||||
|
||||
Full procedures: [references/workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-article-illustrator/references/workflow.md#step-2-analyze).
|
||||
Full procedures: [references/workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-article-illustrator/references/workflow.md#step-2-analyze).
|
||||
|
||||
### Step 3: Confirm Settings
|
||||
|
||||
@@ -145,7 +145,7 @@ Use the `clarify` tool. Since `clarify` handles one question at a time, ask the
|
||||
|
||||
Don't ask more than 2-3 `clarify` questions in a row. If the user already specified these in their request, skip entirely.
|
||||
|
||||
Full procedures: [references/workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-article-illustrator/references/workflow.md#step-3-confirm-settings).
|
||||
Full procedures: [references/workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-article-illustrator/references/workflow.md#step-3-confirm-settings).
|
||||
|
||||
### Step 4: Generate Outline → `outline.md`
|
||||
|
||||
@@ -159,7 +159,7 @@ Save `{output-dir}/outline.md` using `write_file` with frontmatter (type, densit
|
||||
**Filename**: 01-infographic-concept-name.png
|
||||
```
|
||||
|
||||
Full template: [references/workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-article-illustrator/references/workflow.md#step-4-generate-outline).
|
||||
Full template: [references/workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-article-illustrator/references/workflow.md#step-4-generate-outline).
|
||||
|
||||
### Step 5: Generate Prompts
|
||||
|
||||
@@ -167,7 +167,7 @@ Full template: [references/workflow.md](https://github.com/NousResearch/hermes-a
|
||||
|
||||
For each illustration:
|
||||
|
||||
1. Create a prompt file per [references/prompt-construction.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-article-illustrator/references/prompt-construction.md).
|
||||
1. Create a prompt file per [references/prompt-construction.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-article-illustrator/references/prompt-construction.md).
|
||||
2. Save to `{output-dir}/prompts/NN-{type}-{slug}.md` using `write_file` with YAML frontmatter.
|
||||
3. Prompts MUST use type-specific templates with structured sections (ZONES / LABELS / COLORS / STYLE / ASPECT).
|
||||
4. LABELS MUST include article-specific data: actual numbers, terms, metrics, quotes.
|
||||
@@ -186,7 +186,7 @@ Note: the underlying image-generation backend is user-configured (default: FAL F
|
||||
|
||||
### Step 7: Finalize
|
||||
|
||||
Insert `` after the corresponding paragraph. Alt text: concise description in the article's language.
|
||||
Insert `` after the corresponding paragraph. Alt text: concise description in the article's language.
|
||||
|
||||
Report:
|
||||
|
||||
@@ -208,11 +208,11 @@ Images: X/N generated
|
||||
|
||||
| File | Content |
|
||||
|------|---------|
|
||||
| [references/workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-article-illustrator/references/workflow.md) | Detailed procedures |
|
||||
| [references/usage.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-article-illustrator/references/usage.md) | Invocation examples |
|
||||
| [references/styles.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-article-illustrator/references/styles.md) | Style gallery + Palette gallery |
|
||||
| [references/style-presets.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-article-illustrator/references/style-presets.md) | Preset shortcuts (type + style + palette) |
|
||||
| [references/prompt-construction.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-article-illustrator/references/prompt-construction.md) | Prompt templates |
|
||||
| [references/workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-article-illustrator/references/workflow.md) | Detailed procedures |
|
||||
| [references/usage.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-article-illustrator/references/usage.md) | Invocation examples |
|
||||
| [references/styles.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-article-illustrator/references/styles.md) | Style gallery + Palette gallery |
|
||||
| [references/style-presets.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-article-illustrator/references/style-presets.md) | Preset shortcuts (type + style + palette) |
|
||||
| [references/prompt-construction.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-article-illustrator/references/prompt-construction.md) | Prompt templates |
|
||||
|
||||
## Pitfalls
|
||||
|
||||
+13
-13
@@ -14,8 +14,8 @@ Knowledge comics (知识漫画): educational, biography, tutorial.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/creative/baoyu-comic` |
|
||||
| Source | Optional — install with `hermes skills install official/creative/baoyu-comic` |
|
||||
| Path | `optional-skills/creative/baoyu-comic` |
|
||||
| Version | `1.56.1` |
|
||||
| Author | 宝玉 (JimLiu) |
|
||||
| License | MIT |
|
||||
@@ -89,7 +89,7 @@ Character consistency is driven by **text descriptions** in `characters/characte
|
||||
| Images only | Generate images from existing prompts directory |
|
||||
| Regenerate N | Regenerate specific page(s) only (e.g., `3` or `2,5,8`) |
|
||||
|
||||
Details: [references/partial-workflows.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-comic/references/partial-workflows.md)
|
||||
Details: [references/partial-workflows.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-comic/references/partial-workflows.md)
|
||||
|
||||
### Art, Tone & Preset Catalogue
|
||||
|
||||
@@ -107,7 +107,7 @@ Details: [references/partial-workflows.md](https://github.com/NousResearch/herme
|
||||
|
||||
Full rules at `references/presets/<preset>.md` — load the file when a preset is picked.
|
||||
|
||||
- **Compatibility matrix** and **content-signal → preset** table live in [references/auto-selection.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-comic/references/auto-selection.md). Read it before recommending combinations in Step 2.
|
||||
- **Compatibility matrix** and **content-signal → preset** table live in [references/auto-selection.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-comic/references/auto-selection.md). Read it before recommending combinations in Step 2.
|
||||
|
||||
## File Structure
|
||||
|
||||
@@ -185,7 +185,7 @@ Input → Analyze → [Check Existing?] → [Confirm: Style + Reviews] → Story
|
||||
|
||||
### User Questions
|
||||
|
||||
Use the `clarify` tool to confirm options. Since `clarify` handles one question at a time, ask the most important question first and proceed sequentially. See [references/workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-comic/references/workflow.md) for the full Step 2 question set.
|
||||
Use the `clarify` tool to confirm options. Since `clarify` handles one question at a time, ask the most important question first and proceed sequentially. See [references/workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-comic/references/workflow.md) for the full Step 2 question set.
|
||||
|
||||
**Timeout handling (CRITICAL)**: `clarify` can return `"The user did not provide a response within the time limit. Use your best judgement to make the choice and proceed."` — this is NOT user consent to default everything.
|
||||
|
||||
@@ -221,15 +221,15 @@ Use Hermes' built-in `image_generate` tool for all image rendering. Its schema a
|
||||
|
||||
**Backup rule**: existing `prompts/…md` and `…png` files → rename with `-backup-YYYYMMDD-HHMMSS` suffix before regenerating.
|
||||
|
||||
Full step-by-step workflow (analysis, storyboard, review gates, regeneration variants): [references/workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-comic/references/workflow.md).
|
||||
Full step-by-step workflow (analysis, storyboard, review gates, regeneration variants): [references/workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-comic/references/workflow.md).
|
||||
|
||||
## References
|
||||
|
||||
**Core Templates**:
|
||||
- [analysis-framework.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-comic/references/analysis-framework.md) - Deep content analysis
|
||||
- [character-template.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-comic/references/character-template.md) - Character definition format
|
||||
- [storyboard-template.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-comic/references/storyboard-template.md) - Storyboard structure
|
||||
- [ohmsha-guide.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-comic/references/ohmsha-guide.md) - Ohmsha manga specifics
|
||||
- [analysis-framework.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-comic/references/analysis-framework.md) - Deep content analysis
|
||||
- [character-template.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-comic/references/character-template.md) - Character definition format
|
||||
- [storyboard-template.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-comic/references/storyboard-template.md) - Storyboard structure
|
||||
- [ohmsha-guide.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-comic/references/ohmsha-guide.md) - Ohmsha manga specifics
|
||||
|
||||
**Style Definitions**:
|
||||
- `references/art-styles/` - Art styles (ligne-claire, manga, realistic, ink-brush, chalk, minimalist)
|
||||
@@ -238,9 +238,9 @@ Full step-by-step workflow (analysis, storyboard, review gates, regeneration var
|
||||
- `references/layouts/` - Layouts (standard, cinematic, dense, splash, mixed, webtoon, four-panel)
|
||||
|
||||
**Workflow**:
|
||||
- [workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-comic/references/workflow.md) - Full workflow details
|
||||
- [auto-selection.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-comic/references/auto-selection.md) - Content signal analysis
|
||||
- [partial-workflows.md](https://github.com/NousResearch/hermes-agent/blob/main/skills/creative/baoyu-comic/references/partial-workflows.md) - Partial workflow options
|
||||
- [workflow.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-comic/references/workflow.md) - Full workflow details
|
||||
- [auto-selection.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-comic/references/auto-selection.md) - Content signal analysis
|
||||
- [partial-workflows.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/creative/baoyu-comic/references/partial-workflows.md) - Partial workflow options
|
||||
|
||||
## Page Modification
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@ Generate project ideas via creative constraints.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/creative/creative-ideation` |
|
||||
| Source | Optional — install with `hermes skills install official/creative/creative-ideation` |
|
||||
| Path | `optional-skills/creative/creative-ideation` |
|
||||
| Version | `1.0.0` |
|
||||
| Author | SHL0MS |
|
||||
| License | MIT |
|
||||
+2
-2
@@ -14,8 +14,8 @@ Pixel art w/ era palettes (NES, Game Boy, PICO-8).
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/creative/pixel-art` |
|
||||
| Source | Optional — install with `hermes skills install official/creative/pixel-art` |
|
||||
| Path | `optional-skills/creative/pixel-art` |
|
||||
| Version | `2.0.0` |
|
||||
| Author | dodo-reach |
|
||||
| License | MIT |
|
||||
+3
-2
@@ -14,11 +14,12 @@ Modify, debug, or extend the s6-overlay supervision tree inside the Hermes Agent
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/software-development/hermes-s6-container-supervision` |
|
||||
| Source | Optional — install with `hermes skills install official/devops/hermes-s6-container-supervision` |
|
||||
| Path | `optional-skills/devops/hermes-s6-container-supervision` |
|
||||
| Version | `1.0.0` |
|
||||
| Author | Hermes Agent |
|
||||
| License | MIT |
|
||||
| Platforms | linux |
|
||||
| Tags | `docker`, `s6`, `supervision`, `gateway`, `profiles` |
|
||||
| Related skills | [`hermes-agent`](/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent), `hermes-agent-dev` |
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@ Host modded Minecraft servers (CurseForge, Modrinth).
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/gaming/minecraft-modpack-server` |
|
||||
| Source | Optional — install with `hermes skills install official/gaming/minecraft-modpack-server` |
|
||||
| Path | `optional-skills/gaming/minecraft-modpack-server` |
|
||||
| Platforms | linux, macos |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
+2
-2
@@ -14,8 +14,8 @@ Play Pokemon via headless emulator + RAM reads.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/gaming/pokemon-player` |
|
||||
| Source | Optional — install with `hermes skills install official/gaming/pokemon-player` |
|
||||
| Path | `optional-skills/gaming/pokemon-player` |
|
||||
| Platforms | linux, macos, windows |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
+2
-2
@@ -14,8 +14,8 @@ DSPy: declarative LM programs, auto-optimize prompts, RAG.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/mlops/research/dspy` |
|
||||
| Source | Optional — install with `hermes skills install official/mlops/dspy` |
|
||||
| Path | `optional-skills/mlops/research/dspy` |
|
||||
| Version | `1.0.0` |
|
||||
| Author | Orchestra Research |
|
||||
| License | MIT |
|
||||
+7
-7
@@ -14,14 +14,14 @@ Execute plans via delegate_task subagents (2-stage review).
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Bundled (installed by default) |
|
||||
| Path | `skills/software-development/subagent-driven-development` |
|
||||
| Source | Optional — install with `hermes skills install official/software-development/subagent-driven-development` |
|
||||
| Path | `optional-skills/software-development/subagent-driven-development` |
|
||||
| Version | `1.1.0` |
|
||||
| Author | Hermes Agent (adapted from obra/superpowers) |
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `delegation`, `subagent`, `implementation`, `workflow`, `parallel` |
|
||||
| Related skills | [`writing-plans`](/docs/user-guide/skills/bundled/software-development/software-development-writing-plans), [`requesting-code-review`](/docs/user-guide/skills/bundled/software-development/software-development-requesting-code-review), [`test-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-test-driven-development) |
|
||||
| Related skills | [`plan`](/docs/user-guide/skills/bundled/software-development/software-development-plan), [`requesting-code-review`](/docs/user-guide/skills/bundled/software-development/software-development-requesting-code-review), [`test-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-test-driven-development) |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
@@ -40,7 +40,7 @@ Execute implementation plans by dispatching fresh subagents per task with system
|
||||
## When to Use
|
||||
|
||||
Use this skill when:
|
||||
- You have an implementation plan (from writing-plans skill or user requirements)
|
||||
- You have an implementation plan (from the `plan` skill or user requirements)
|
||||
- Tasks are mostly independent
|
||||
- Quality and spec compliance are important
|
||||
- You want automated review between tasks
|
||||
@@ -272,10 +272,10 @@ git add -A && git commit -m "feat: complete [feature name] implementation"
|
||||
|
||||
## Integration with Other Skills
|
||||
|
||||
### With writing-plans
|
||||
### With plan
|
||||
|
||||
This skill EXECUTES plans created by the writing-plans skill:
|
||||
1. User requirements → writing-plans → implementation plan
|
||||
This skill EXECUTES plans created by the `plan` skill:
|
||||
1. User requirements → plan → implementation plan
|
||||
2. Implementation plan → subagent-driven-development → working code
|
||||
|
||||
### With test-driven-development
|
||||
Reference in New Issue
Block a user