* docs: adding cli doc

* docs: adding generated script and content and github workflow

* chore: removing workflow

* fix: (docs) re-format and add details to cli-reference docs

---------

Co-authored-by: Vineeth Voruganti <13438633+VVoruganti@users.noreply.github.com>
This commit is contained in:
ajspig 2026-04-20 23:25:12 -04:00 committed by GitHub
parent 7fae16b351
commit ca1dc858ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 1030 additions and 1 deletions

View File

@ -84,7 +84,8 @@
"group": "Reference",
"pages": [
"v3/documentation/reference/platform",
"v3/documentation/reference/sdk"
"v3/documentation/reference/sdk",
"v3/documentation/reference/cli"
]
}
]

View File

@ -0,0 +1,547 @@
{/*
GENERATED by honcho-cli/scripts/generate_cli_docs.py — do not edit.
Re-generate with: uv run --package honcho-cli python honcho-cli/scripts/generate_cli_docs.py
Source of truth: honcho-cli/src/honcho_cli/commands/
*/}
## honcho conclusion
List, search, create, and delete peer conclusions (Honcho's memory atoms).
<AccordionGroup>
<Accordion title="create">
Create a conclusion.
```bash
honcho conclusion create <content>
```
<ParamField path="content" type="string" required />
<ParamField path="--observer" type="string">
Observer peer ID.
</ParamField>
<ParamField path="--observed" type="string">
Observed peer ID.
</ParamField>
<ParamField path="--session" type="string">
Session context. Short alias: `-s`.
</ParamField>
</Accordion>
<Accordion title="delete">
Delete a conclusion.
```bash
honcho conclusion delete <conclusion_id>
```
<ParamField path="conclusion_id" type="string" required />
<ParamField path="--observer" type="string">
Observer peer ID.
</ParamField>
<ParamField path="--observed" type="string">
Observed peer ID.
</ParamField>
<ParamField path="--yes" type="boolean">
Skip confirmation. Short alias: `-y`.
</ParamField>
</Accordion>
<Accordion title="list">
List conclusions.
```bash
honcho conclusion list
```
<ParamField path="--observer" type="string">
Observer peer ID.
</ParamField>
<ParamField path="--observed" type="string">
Observed peer ID.
</ParamField>
<ParamField path="--limit" type="number" default="10">
Max results.
</ParamField>
</Accordion>
<Accordion title="search">
Semantic search over conclusions.
```bash
honcho conclusion search <query>
```
<ParamField path="query" type="string" required />
<ParamField path="--observer" type="string">
Observer peer ID.
</ParamField>
<ParamField path="--observed" type="string">
Observed peer ID.
</ParamField>
<ParamField path="--top-k" type="number" default="10">
Max results.
</ParamField>
</Accordion>
</AccordionGroup>
## honcho config
Inspect CLI configuration.
```bash
honcho config
```
## honcho doctor
Verify config and connectivity. Scope with -w / -p to check workspace, peer, and queue health.
```bash
honcho doctor
```
## honcho help
Show help message.
```bash
honcho help
```
## honcho init
Set API key and server URL in ~/.honcho/config.json.
Press Enter to keep the current value or type a replacement.
Workspace / peer / session scoping is per-command via -w / -p / -s
or HONCHO_* env vars — never persisted.
```bash
honcho init
```
<ParamField path="--api-key" type="string">
API key (admin JWT).
</ParamField>
<ParamField path="--base-url" type="string">
Honcho API URL (e.g. https://api.honcho.dev, http://localhost:8000).
</ParamField>
## honcho message
List, create, and get messages within a session.
<AccordionGroup>
<Accordion title="create">
Create a message in a session.
```bash
honcho message create <content>
```
<ParamField path="content" type="string" required />
<ParamField path="--peer" type="string" required>
Peer ID of the message sender. Short alias: `-p`.
</ParamField>
<ParamField path="--metadata" type="string">
JSON metadata to associate with the message.
</ParamField>
<ParamField path="--session" type="string">
Session ID. Short alias: `-s`.
</ParamField>
</Accordion>
<Accordion title="get">
Get a single message by ID.
```bash
honcho message get <message_id>
```
<ParamField path="message_id" type="string" required />
<ParamField path="--session" type="string">
Session ID. Short alias: `-s`.
</ParamField>
</Accordion>
<Accordion title="list">
List messages in a session. Scoped to a peer with -p.
```bash
honcho message list [<session_id>]
```
<ParamField path="session_id" type="string" />
<ParamField path="--last" type="number" default="20">
Number of recent messages.
</ParamField>
<ParamField path="--reverse" type="boolean">
Show oldest first (default is newest first).
</ParamField>
<ParamField path="--brief" type="boolean">
Show only IDs, peer, token count, and created_at (no content).
</ParamField>
<ParamField path="--peer" type="string">
Filter by peer ID. Short alias: `-p`.
</ParamField>
</Accordion>
</AccordionGroup>
## honcho peer
List, create, chat with, search, and manage peers and their representations.
<AccordionGroup>
<Accordion title="card">
Get raw peer card content.
```bash
honcho peer card [<peer_id>]
```
<ParamField path="peer_id" type="string" />
<ParamField path="--target" type="string">
Target peer for relationship card.
</ParamField>
</Accordion>
<Accordion title="chat">
Query the dialectic about a peer.
```bash
honcho peer chat <query>
```
<ParamField path="query" type="string" required />
<ParamField path="--target" type="string">
Target peer for perspective.
</ParamField>
<ParamField path="--reasoning" type="string">
Reasoning level: minimal, low, medium, high, max. Short alias: `-r`.
</ParamField>
</Accordion>
<Accordion title="create">
Create or get a peer.
```bash
honcho peer create <peer_id>
```
<ParamField path="peer_id" type="string" required />
<ParamField path="--observe-me" type="boolean">
Whether Honcho will form a representation of this peer. Negate with `--no-observe-me`.
</ParamField>
<ParamField path="--metadata" type="string">
JSON metadata to associate with the peer.
</ParamField>
</Accordion>
<Accordion title="get-metadata">
Get metadata for a peer.
```bash
honcho peer get-metadata [<peer_id>]
```
<ParamField path="peer_id" type="string" />
</Accordion>
<Accordion title="inspect">
Inspect a peer: card, session count, recent conclusions.
```bash
honcho peer inspect [<peer_id>]
```
<ParamField path="peer_id" type="string" />
</Accordion>
<Accordion title="list">
List all peers in the workspace.
```bash
honcho peer list
```
</Accordion>
<Accordion title="representation">
Get the formatted representation for a peer.
```bash
honcho peer representation [<peer_id>]
```
<ParamField path="peer_id" type="string" />
<ParamField path="--target" type="string">
Target peer to get representation about.
</ParamField>
<ParamField path="--search-query" type="string">
Semantic search query to filter conclusions.
</ParamField>
<ParamField path="--max-conclusions" type="number">
Maximum number of conclusions to include.
</ParamField>
</Accordion>
<Accordion title="search">
Search a peer's messages.
```bash
honcho peer search <query>
```
<ParamField path="query" type="string" required />
<ParamField path="--limit" type="number" default="10">
Max results.
</ParamField>
</Accordion>
<Accordion title="set-metadata">
Set metadata for a peer.
```bash
honcho peer set-metadata <metadata>
```
<ParamField path="metadata" type="string" required />
<ParamField path="--peer" type="string">
Peer ID (uses default if omitted). Short alias: `-p`.
</ParamField>
</Accordion>
</AccordionGroup>
## honcho session
List, inspect, create, delete, and manage conversation sessions and their peers.
<AccordionGroup>
<Accordion title="add-peers">
Add peers to a session.
```bash
honcho session add-peers <session_id> <peer_ids>
```
<ParamField path="session_id" type="string" required />
<ParamField path="peer_ids" type="string" required />
</Accordion>
<Accordion title="context">
Get session context (what an agent would see).
```bash
honcho session context [<session_id>]
```
<ParamField path="session_id" type="string" />
<ParamField path="--tokens" type="number">
Token budget.
</ParamField>
<ParamField path="--summary" type="boolean" default="true">
Include summary. Negate with `--no-summary`.
</ParamField>
</Accordion>
<Accordion title="create">
Create or get a session.
```bash
honcho session create <session_id>
```
<ParamField path="session_id" type="string" required />
<ParamField path="--peers" type="string">
Comma-separated peer IDs to add to the session.
</ParamField>
<ParamField path="--metadata" type="string">
JSON metadata to associate with the session.
</ParamField>
</Accordion>
<Accordion title="delete">
Delete a session and all its data. Destructive — requires --yes or interactive confirm.
```bash
honcho session delete [<session_id>]
```
<ParamField path="session_id" type="string" />
<ParamField path="--yes" type="boolean">
Skip confirmation. Short alias: `-y`.
</ParamField>
</Accordion>
<Accordion title="get-metadata">
Get metadata for a session.
```bash
honcho session get-metadata [<session_id>]
```
<ParamField path="session_id" type="string" />
</Accordion>
<Accordion title="inspect">
Inspect a session: peers, message count, summaries, config.
```bash
honcho session inspect [<session_id>]
```
<ParamField path="session_id" type="string" />
</Accordion>
<Accordion title="list">
List sessions in the workspace.
```bash
honcho session list
```
<ParamField path="--peer" type="string">
Filter by peer. Short alias: `-p`.
</ParamField>
</Accordion>
<Accordion title="peers">
List peers in a session.
```bash
honcho session peers [<session_id>]
```
<ParamField path="session_id" type="string" />
</Accordion>
<Accordion title="remove-peers">
Remove peers from a session.
```bash
honcho session remove-peers <session_id> <peer_ids>
```
<ParamField path="session_id" type="string" required />
<ParamField path="peer_ids" type="string" required />
</Accordion>
<Accordion title="representation">
Get the representation of a peer within a session.
```bash
honcho session representation <peer_id> [<session_id>]
```
<ParamField path="peer_id" type="string" required />
<ParamField path="session_id" type="string" />
<ParamField path="--target" type="string">
Target peer (what peer_id knows about target).
</ParamField>
<ParamField path="--search-query" type="string">
Semantic search query to filter conclusions.
</ParamField>
<ParamField path="--max-conclusions" type="number">
Maximum number of conclusions to include.
</ParamField>
</Accordion>
<Accordion title="search">
Search messages in a session.
```bash
honcho session search <query> [<session_id>]
```
<ParamField path="query" type="string" required />
<ParamField path="session_id" type="string" />
<ParamField path="--limit" type="number" default="10">
Max results.
</ParamField>
</Accordion>
<Accordion title="set-metadata">
Set metadata for a session.
```bash
honcho session set-metadata [<session_id>]
```
<ParamField path="session_id" type="string" />
<ParamField path="--data" type="string" required>
JSON metadata to set (e.g. '\{"key": "value"\}'). Short alias: `-d`.
</ParamField>
</Accordion>
<Accordion title="summaries">
Get session summaries (short + long).
```bash
honcho session summaries [<session_id>]
```
<ParamField path="session_id" type="string" />
</Accordion>
</AccordionGroup>
## honcho workspace
List, create, inspect, delete, and search workspaces.
<AccordionGroup>
<Accordion title="create">
Create or get a workspace.
```bash
honcho workspace create <workspace_id>
```
<ParamField path="workspace_id" type="string" required />
<ParamField path="--metadata" type="string">
JSON metadata to associate with the workspace.
</ParamField>
</Accordion>
<Accordion title="delete">
Delete a workspace. Use --dry-run first to see what will be deleted.
Requires --yes to skip confirmation, or will prompt interactively.
If sessions exist, requires --cascade to delete them first.
```bash
honcho workspace delete <workspace_id>
```
<ParamField path="workspace_id" type="string" required />
<ParamField path="--yes" type="boolean">
Skip confirmation prompt (for scripted/agent use). Short alias: `-y`.
</ParamField>
<ParamField path="--cascade" type="boolean">
Delete all sessions before deleting the workspace.
</ParamField>
<ParamField path="--dry-run" type="boolean">
Show what would be deleted without deleting.
</ParamField>
</Accordion>
<Accordion title="inspect">
Inspect a workspace: peers, sessions, config.
```bash
honcho workspace inspect [<workspace_id>]
```
<ParamField path="workspace_id" type="string" />
</Accordion>
<Accordion title="list">
List all accessible workspaces.
```bash
honcho workspace list
```
</Accordion>
<Accordion title="queue-status">
Get queue processing status.
```bash
honcho workspace queue-status
```
<ParamField path="--observer" type="string">
Filter by observer peer.
</ParamField>
<ParamField path="--sender" type="string">
Filter by sender peer.
</ParamField>
</Accordion>
<Accordion title="search">
Search messages across workspace.
```bash
honcho workspace search <query>
```
<ParamField path="query" type="string" required />
<ParamField path="--limit" type="number" default="10">
Max results.
</ParamField>
</Accordion>
</AccordionGroup>

View File

@ -0,0 +1,220 @@
---
title: 'CLI Reference'
description: 'Command-line interface for Honcho — inspect workspaces, peers, sessions, and memory from your terminal'
icon: 'terminal'
---
import CliCommands from "/snippets/cli-commands.mdx";
## Install
<CodeGroup>
```bash uv (recommended)
uv tool install honcho-cli
```
```bash uvx (ephemeral)
uvx honcho-cli
```
</CodeGroup>
## Quick Start
```bash
honcho init # confirm/set apiKey + Honcho URL in ~/.honcho/config.json
honcho doctor # verify your config + connectivity
honcho # show banner + command list
```
## Configuration
The CLI resolves config in this order: **flag → env var → config file → default**.
| Value | File key | Env var | Flag | Persisted? |
|-------------|-------------------|------------------------|------------------------|------------|
| API key | `apiKey` | `HONCHO_API_KEY` | — | Yes |
| API URL | `environmentUrl` | `HONCHO_BASE_URL` | — | Yes |
| Workspace | — | `HONCHO_WORKSPACE_ID` | `-w` / `--workspace` | No |
| Peer | — | `HONCHO_PEER_ID` | `-p` / `--peer` | No |
| Session | — | `HONCHO_SESSION_ID` | `-s` / `--session` | No |
| JSON output | — | `HONCHO_JSON` | `--json` | No |
### Persisted config
The CLI shares `~/.honcho/config.json` with sibling Honcho tools. It owns only
`apiKey` and `environmentUrl` at the top level — everything else (`hosts`,
`sessions`, etc.) is written by other tools and left untouched on save.
```json
{
"apiKey": "hch-v3-...",
"environmentUrl": "https://api.honcho.dev",
"hosts": { "claude_code": { "...": "..." } }
}
```
<Info>
Per-command scoping (workspace / peer / session) is handled via `-w` / `-p` / `-s`
flags or `HONCHO_*` env vars. **Not** persisted as CLI defaults. This is
deliberate: every invocation is explicit about what it operates on.
</Info>
### Runtime overrides
Workspace, peer, and session scoping are **per-command only** — pass flags or
`HONCHO_*` env vars on every invocation.
```bash
# Per-command flags
honcho peer card -w prod -p user
# Or export once per shell
export HONCHO_WORKSPACE_ID=prod
export HONCHO_PEER_ID=user
honcho peer card
# One-off against a different server
HONCHO_BASE_URL=http://localhost:8000 honcho workspace list
# CI/CD — env vars only, no config file needed
export HONCHO_API_KEY=hch-v3-xxx
export HONCHO_BASE_URL=https://api.honcho.dev
honcho workspace list
```
## Output & exit codes
Every command adapts its output to the context:
- **TTY** — human-readable tables via Rich.
- **Piped or redirected** — JSON automatically (detected via `isatty`).
- **`--json` flag / `HONCHO_JSON=1`** — force JSON regardless of terminal.
Collection commands emit JSON arrays; single-resource commands emit JSON objects. Errors are always structured:
```json
{
"error": {
"code": "PEER_NOT_FOUND",
"message": "Peer 'abc' not found in workspace 'my-ws'",
"details": {"workspace_id": "my-ws", "peer_id": "abc"}
}
}
```
| Exit code | Meaning |
|-----------|---------|
| `0` | Success |
| `1` | Client error (bad input, resource not found) |
| `2` | Server error |
| `3` | Auth error (missing or invalid API key) |
CI pipelines and agent runtimes can branch on these without parsing stderr.
## Command reference
<CliCommands />
## Workflows
### Inspect an unfamiliar workspace
When you pick up a workspace and need to orient — start broad, narrow to the peer and session you care about.
<Steps>
<Step title="Survey the workspace">
```bash
honcho workspace inspect --json
honcho peer list --json
```
</Step>
<Step title="Inspect a specific peer">
```bash
honcho peer inspect <peer_id> --json
honcho peer card <peer_id> --json
```
</Step>
<Step title="Review the peer's memory">
```bash
honcho conclusion list --observer <peer_id> --json
honcho conclusion search "topic" --observer <peer_id> --json
```
</Step>
<Step title="Debug a session">
```bash
honcho session inspect <session_id> --json
honcho message list <session_id> --last 20 --json
honcho session context <session_id> --json
honcho session summaries <session_id> --json
```
</Step>
</Steps>
<Tip>
`honcho session context` shows exactly what an agent would receive at inference time — check it before `honcho peer chat` if a response surprises you.
</Tip>
### A peer isn't learning
If new messages aren't producing new conclusions, work down the diagnostic ladder.
```bash
# Is observation enabled for this peer?
honcho peer inspect <peer_id> --json | jq '.configuration'
# Is the deriver actually processing?
honcho workspace queue-status --json
# Do any conclusions exist at all? Any for the expected topic?
honcho conclusion list --observer <peer_id> --json
honcho conclusion search "expected topic" --observer <peer_id> --json
```
### Session context looks wrong
When an agent's responses don't reflect what you expect it to know.
```bash
honcho session context <session_id> --json
honcho session summaries <session_id> --json
honcho message list <session_id> --last 50 --json
```
### Dialectic returns bad answers
When `honcho peer chat` or the dialectic API is hallucinating or missing context.
```bash
# What does the peer card actually say?
honcho peer card <peer_id> --json
# Any conclusions for this topic?
honcho conclusion search "topic" --observer <peer_id> --json
# Reproduce the query against the CLI
honcho peer chat <peer_id> "what do you know about X?" --json
```
## Scripting & automation
Pipe commands into `jq` for inline transforms, or set `HONCHO_*` env vars for a CI/CD environment with no config file:
```bash
# Pipe to jq
honcho peer list --json | jq '.[].id'
honcho workspace inspect --json | jq '.peers'
# Machine-parseable health check — exit code for CI, details for logs
honcho doctor --json
# CI/CD — env vars only, no ~/.honcho/config.json
export HONCHO_API_KEY=hch-v3-xxx
export HONCHO_BASE_URL=https://api.honcho.dev
honcho workspace list
```
Non-interactive onboarding:
```bash
# Pre-seed via flags / env vars; init still prompts for anything missing
HONCHO_API_KEY=hch-v3-xxx honcho init --base-url https://api.honcho.dev
```

View File

@ -0,0 +1,261 @@
"""Generate ``docs/snippets/cli-commands.mdx`` from the Typer app.
Walks the ``honcho`` Typer app and emits a Mintlify snippet using native
Mintlify components: ``<AccordionGroup>`` / ``<Accordion>`` for subcommand
grouping and ``<ParamField>`` for each argument and option. The output is a
single snippet included by ``docs/v3/documentation/reference/cli.mdx``.
Usage::
uv run --package honcho-cli python honcho-cli/scripts/generate_cli_docs.py
# Or as a drift check (non-zero exit if the committed snippet is stale):
uv run --package honcho-cli python honcho-cli/scripts/generate_cli_docs.py --check
"""
from __future__ import annotations
import sys
from argparse import ArgumentParser
from pathlib import Path
import click
import typer.main
from honcho_cli.main import app
REPO_ROOT = Path(__file__).resolve().parents[2]
OUTPUT = REPO_ROOT / "docs" / "snippets" / "cli-commands.mdx"
HEADER = """{/*
GENERATED by honcho-cli/scripts/generate_cli_docs.py — do not edit.
Re-generate with: uv run --package honcho-cli python honcho-cli/scripts/generate_cli_docs.py
Source of truth: honcho-cli/src/honcho_cli/commands/
*/}
"""
# Documented once in cli.mdx's Configuration table. Skip at the per-command
# level so each Accordion only shows options specific to that subcommand.
GLOBAL_OPTIONS: set[tuple[str, str]] = {
("--workspace", "Override workspace ID"),
("--peer", "Override peer ID"),
("--session", "Override session ID"),
("--json", "Force JSON output"),
}
def _escape_mdx(text: str) -> str:
"""Escape MDX-sensitive characters in prose so Mintlify's parser doesn't
mistake ``{...}`` for a JSX expression or ``<x>`` for a JSX tag."""
return (
text.replace("\\", "\\\\")
.replace("{", "\\{")
.replace("}", "\\}")
.replace("<", "\\<")
)
def _attr(value: str) -> str:
"""Escape a string for use inside a JSX double-quoted attribute value."""
return value.replace("\\", "\\\\").replace('"', "'")
def _long_opt(param: click.Option) -> str | None:
return next((o for o in param.opts if o.startswith("--")), None)
def _short_opt(param: click.Option) -> str | None:
return next(
(o for o in param.opts if o.startswith("-") and not o.startswith("--")),
None,
)
def _is_global(param: click.Parameter) -> bool:
if not isinstance(param, click.Option) or not param.help:
return False
return (_long_opt(param), param.help) in GLOBAL_OPTIONS
def _param_type(param: click.Parameter) -> str:
if isinstance(param, click.Option) and param.is_flag:
return "boolean"
if isinstance(param.type, click.Choice):
return "string"
name = getattr(param.type, "name", "")
if name in ("integer", "int"):
return "number"
if name in ("float", "decimal"):
return "number"
if name == "boolean":
return "boolean"
return "string"
def _param_path(param: click.Parameter) -> str:
if isinstance(param, click.Argument):
return param.name or ""
return _long_opt(param) or (param.opts[0] if param.opts else "")
def _param_required(param: click.Parameter) -> bool:
if isinstance(param, click.Argument):
return param.required
if isinstance(param, click.Option):
return bool(param.required)
return False
def _default_attr(param: click.Parameter) -> str | None:
default = param.default
if default is None or default is False or callable(default):
return None
if isinstance(default, (list, tuple)) and not default:
return None
if default is True:
return "true"
return _attr(str(default))
def _ensure_period(text: str) -> str:
return text if text.endswith((".", "?", "!", ":")) else text + "."
def _param_body(param: click.Parameter) -> str:
parts: list[str] = []
if isinstance(param, click.Option):
if param.help:
parts.append(_ensure_period(_escape_mdx(param.help.strip())))
short = _short_opt(param)
if short:
parts.append(f"Short alias: `{short}`.")
if param.secondary_opts:
neg = " / ".join(f"`{o}`" for o in param.secondary_opts)
parts.append(f"Negate with {neg}.")
if isinstance(param.type, click.Choice):
choices = ", ".join(f"`{c}`" for c in param.type.choices)
parts.append(f"One of: {choices}.")
return " ".join(parts)
def _render_param(param: click.Parameter) -> list[str]:
props = [
f'path="{_attr(_param_path(param))}"',
f'type="{_param_type(param)}"',
]
if _param_required(param):
props.append("required")
default_attr = _default_attr(param)
if default_attr is not None:
props.append(f'default="{default_attr}"')
body = _param_body(param).strip()
open_tag = f"<ParamField {' '.join(props)}>"
if body:
return [open_tag, f" {body}", "</ParamField>"]
return [open_tag.replace(">", " />")]
def _params_of(
cmd: click.Command, *, strip_globals: bool
) -> list[click.Parameter]:
args = [p for p in cmd.params if isinstance(p, click.Argument)]
opts = [
p
for p in cmd.params
if isinstance(p, click.Option)
and not p.hidden
and not (strip_globals and _is_global(p))
]
return args + opts
def _invocation_line(cmd: click.Command, path: list[str]) -> str:
args = [p for p in cmd.params if isinstance(p, click.Argument)]
parts = [" ".join(path)]
for a in args:
placeholder = f"<{a.name}>"
if not a.required:
placeholder = f"[{placeholder}]"
parts.append(placeholder)
return " ".join(parts)
def _render_accordion(cmd: click.Command, path: list[str]) -> list[str]:
lines = [f'<Accordion title="{_attr(path[-1])}">']
if cmd.help:
lines.append(_escape_mdx(cmd.help.strip()))
lines.append("")
lines.append("```bash")
lines.append(_invocation_line(cmd, path))
lines.append("```")
lines.append("")
for p in _params_of(cmd, strip_globals=True):
lines.extend(_render_param(p))
lines.append("</Accordion>")
return lines
def _render_top(cmd: click.Command, path: list[str]) -> list[str]:
lines = [f"## {' '.join(path)}", ""]
if cmd.help:
lines.append(_escape_mdx(cmd.help.strip()))
lines.append("")
if isinstance(cmd, click.Group) and cmd.commands:
lines.append("<AccordionGroup>")
for sub_name in sorted(cmd.commands):
lines.extend(
_render_accordion(cmd.commands[sub_name], path + [sub_name])
)
lines.append("</AccordionGroup>")
lines.append("")
return lines
lines.append("```bash")
lines.append(_invocation_line(cmd, path))
lines.append("```")
lines.append("")
for p in _params_of(cmd, strip_globals=True):
lines.extend(_render_param(p))
lines.append("")
return lines
def build() -> str:
root: click.Command = typer.main.get_command(app)
if not isinstance(root, click.Group):
raise SystemExit("Expected root command to be a Group")
body: list[str] = []
for name in sorted(root.commands):
body.extend(_render_top(root.commands[name], ["honcho", name]))
return HEADER + "\n".join(body) + "\n"
def main() -> int:
parser = ArgumentParser()
parser.add_argument(
"--check",
action="store_true",
help="Exit non-zero if the committed snippet differs from generated output.",
)
ns = parser.parse_args()
generated = build()
if ns.check:
current = OUTPUT.read_text() if OUTPUT.exists() else ""
if current != generated:
print(
f"::error::{OUTPUT} is stale. Re-run without --check to regenerate.",
file=sys.stderr,
)
return 1
return 0
OUTPUT.parent.mkdir(parents=True, exist_ok=True)
OUTPUT.write_text(generated)
print(f"Wrote {OUTPUT}")
return 0
if __name__ == "__main__":
raise SystemExit(main())