385 lines
11 KiB
TypeScript
385 lines
11 KiB
TypeScript
|
|
/** CLI reference — flags and subcommands for the huskies binary. */
|
||
|
|
import type { Metadata } from 'next'
|
||
|
|
|
||
|
|
/** Page metadata for the CLI reference. */
|
||
|
|
export const metadata: Metadata = {
|
||
|
|
title: 'CLI Reference — Huskies Docs',
|
||
|
|
description: 'Command-line reference for huskies, huskies init, and related subcommands.',
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Renders the CLI reference for huskies command-line flags. */
|
||
|
|
export default function CliPage() {
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
<h1 className="page-title">CLI Reference</h1>
|
||
|
|
<p className="page-subtitle">
|
||
|
|
Huskies ships as a single binary. Most interaction happens through the web UI or chat transports,
|
||
|
|
but the CLI is used for initial setup and server control.
|
||
|
|
</p>
|
||
|
|
|
||
|
|
<h2>huskies</h2>
|
||
|
|
<p>Start the huskies server.</p>
|
||
|
|
<pre>
|
||
|
|
<code>huskies [OPTIONS]</code>
|
||
|
|
</pre>
|
||
|
|
|
||
|
|
<h3>Options</h3>
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>Flag</th>
|
||
|
|
<th>Default</th>
|
||
|
|
<th>Description</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
<tr>
|
||
|
|
<td>--port <PORT></td>
|
||
|
|
<td>3000</td>
|
||
|
|
<td>
|
||
|
|
HTTP port to listen on. Set the <code>HUSKIES_PORT</code> environment variable as an
|
||
|
|
alternative.
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>--project <PATH></td>
|
||
|
|
<td>current dir</td>
|
||
|
|
<td>
|
||
|
|
Path to the project directory. Huskies looks for <code>.huskies/</code> here.
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>--help</td>
|
||
|
|
<td>—</td>
|
||
|
|
<td>Print help and exit.</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>--version</td>
|
||
|
|
<td>—</td>
|
||
|
|
<td>Print version and exit.</td>
|
||
|
|
</tr>
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
|
||
|
|
<h3>Examples</h3>
|
||
|
|
<pre>
|
||
|
|
<code>{`# Start on the default port
|
||
|
|
huskies
|
||
|
|
|
||
|
|
# Start on a custom port
|
||
|
|
huskies --port 3001
|
||
|
|
|
||
|
|
# Specify project directory explicitly
|
||
|
|
huskies --project /path/to/project --port 3000
|
||
|
|
|
||
|
|
# Using environment variable
|
||
|
|
HUSKIES_PORT=3002 huskies`}</code>
|
||
|
|
</pre>
|
||
|
|
|
||
|
|
<div className="note">
|
||
|
|
<strong>Multiple instances:</strong> Each worktree or project can run its own huskies instance on a
|
||
|
|
different port. Use <code>HUSKIES_PORT</code> to avoid conflicts when running several instances
|
||
|
|
simultaneously.
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<h2>huskies init</h2>
|
||
|
|
<p>
|
||
|
|
Initialise a project directory for use with huskies. Creates the <code>.huskies/</code> directory
|
||
|
|
structure, default configuration files, and <code>.mcp.json</code>.
|
||
|
|
</p>
|
||
|
|
<pre>
|
||
|
|
<code>huskies init [OPTIONS]</code>
|
||
|
|
</pre>
|
||
|
|
|
||
|
|
<h3>Options</h3>
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>Flag</th>
|
||
|
|
<th>Default</th>
|
||
|
|
<th>Description</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
<tr>
|
||
|
|
<td>--port <PORT></td>
|
||
|
|
<td>3000</td>
|
||
|
|
<td>
|
||
|
|
Port written into <code>.mcp.json</code> for MCP tool discovery.
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>--project <PATH></td>
|
||
|
|
<td>current dir</td>
|
||
|
|
<td>Directory to initialise. Must be a git repository.</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>--help</td>
|
||
|
|
<td>—</td>
|
||
|
|
<td>Print help and exit.</td>
|
||
|
|
</tr>
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
|
||
|
|
<h3>What it creates</h3>
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>Path</th>
|
||
|
|
<th>Description</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<code>.huskies/project.toml</code>
|
||
|
|
</td>
|
||
|
|
<td>Project-wide settings (QA mode, agent limits, timezone, etc.).</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<code>.huskies/agents.toml</code>
|
||
|
|
</td>
|
||
|
|
<td>Agent definitions for coder, QA, and mergemaster roles.</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<code>.huskies/work/1_backlog/</code>
|
||
|
|
</td>
|
||
|
|
<td>Pipeline stage directories (1 through 6).</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<code>.huskies/specs/00_CONTEXT.md</code>
|
||
|
|
</td>
|
||
|
|
<td>Placeholder project context file for the setup wizard.</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<code>.huskies/specs/tech/STACK.md</code>
|
||
|
|
</td>
|
||
|
|
<td>Placeholder tech stack file for the setup wizard.</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<code>.mcp.json</code>
|
||
|
|
</td>
|
||
|
|
<td>
|
||
|
|
MCP server config so Claude Code discovers huskies' tools automatically.
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
|
||
|
|
<div className="note">
|
||
|
|
<strong>Git required:</strong> The project directory must be a git repository. Run{' '}
|
||
|
|
<code>git init</code> first if needed.
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<h2>huskies agent</h2>
|
||
|
|
<p>
|
||
|
|
Spawn a single agent process directly from the command line. This is the command the server uses
|
||
|
|
internally when you run <code>start <number></code> in chat — you rarely need to invoke
|
||
|
|
it manually.
|
||
|
|
</p>
|
||
|
|
<pre>
|
||
|
|
<code>huskies agent [OPTIONS]</code>
|
||
|
|
</pre>
|
||
|
|
|
||
|
|
<h3>Options</h3>
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>Flag</th>
|
||
|
|
<th>Description</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
<tr>
|
||
|
|
<td>--story <ID></td>
|
||
|
|
<td>
|
||
|
|
Story ID slug to work on (e.g. <code>42_story_add_login</code>).
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>--agent <NAME></td>
|
||
|
|
<td>
|
||
|
|
Agent name from <code>agents.toml</code> to use (e.g. <code>coder-1</code>,{' '}
|
||
|
|
<code>qa</code>).
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>--worktree <PATH></td>
|
||
|
|
<td>Path to the git worktree the agent should work in.</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>--port <PORT></td>
|
||
|
|
<td>Huskies server port, so the agent can call MCP tools.</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>--help</td>
|
||
|
|
<td>Print help and exit.</td>
|
||
|
|
</tr>
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
|
||
|
|
<h2>Environment variables</h2>
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>Variable</th>
|
||
|
|
<th>Description</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<code>HUSKIES_PORT</code>
|
||
|
|
</td>
|
||
|
|
<td>
|
||
|
|
Server port. Overrides the <code>--port</code> flag.
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<code>ANTHROPIC_API_KEY</code>
|
||
|
|
</td>
|
||
|
|
<td>
|
||
|
|
Anthropic API key for agent sessions. Can also be set via the web UI on first use.
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<code>GITEA_TOKEN</code>
|
||
|
|
</td>
|
||
|
|
<td>
|
||
|
|
Gitea API token used by the <code>script/release</code> script when publishing releases.
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
|
||
|
|
<h2>Gateway event-push protocol</h2>
|
||
|
|
<p>
|
||
|
|
Project nodes can push pipeline status events to the gateway in real time over a WebSocket
|
||
|
|
connection. The gateway fans each event out to all connected local subscribers.
|
||
|
|
</p>
|
||
|
|
|
||
|
|
<h3>Connecting</h3>
|
||
|
|
<ol>
|
||
|
|
<li>
|
||
|
|
Obtain a one-time join token: <code>POST /gateway/tokens</code> →{' '}
|
||
|
|
<code>{'{"token":"…"}'}</code>
|
||
|
|
</li>
|
||
|
|
<li>
|
||
|
|
Open a WebSocket upgrade to{' '}
|
||
|
|
<code>GET /gateway/events/push?token=TOKEN&project=PROJECT_NAME</code>
|
||
|
|
</li>
|
||
|
|
<li>
|
||
|
|
The token is consumed on upgrade. The project name is attached to every event the server
|
||
|
|
broadcasts downstream.
|
||
|
|
</li>
|
||
|
|
</ol>
|
||
|
|
|
||
|
|
<h3>Sending events</h3>
|
||
|
|
<p>
|
||
|
|
Each message must be a JSON-encoded <code>StoredEvent</code> frame:
|
||
|
|
</p>
|
||
|
|
<pre>
|
||
|
|
<code>{`// Stage transition
|
||
|
|
{"type":"stage_transition","story_id":"42_story_login","from_stage":"2_current","to_stage":"3_qa","timestamp_ms":1700000000000}
|
||
|
|
|
||
|
|
// Merge failure
|
||
|
|
{"type":"merge_failure","story_id":"42_story_login","reason":"conflict in src/main.rs","timestamp_ms":1700000001000}
|
||
|
|
|
||
|
|
// Story blocked
|
||
|
|
{"type":"story_blocked","story_id":"42_story_login","reason":"retry limit exceeded","timestamp_ms":1700000002000}`}</code>
|
||
|
|
</pre>
|
||
|
|
<p>
|
||
|
|
The server does not send frames back. Any other frames received by the project node indicate an
|
||
|
|
error or server restart — treat them as a disconnect signal.
|
||
|
|
</p>
|
||
|
|
|
||
|
|
<h3>Reconnect with exponential back-off</h3>
|
||
|
|
<p>
|
||
|
|
Project nodes <strong>must</strong> reconnect on any disconnect. Use the following policy to avoid
|
||
|
|
thundering herds after a gateway restart:
|
||
|
|
</p>
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>Parameter</th>
|
||
|
|
<th>Value</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
<tr>
|
||
|
|
<td>Initial delay</td>
|
||
|
|
<td>1 s</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>Back-off multiplier</td>
|
||
|
|
<td>2× per attempt</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>Maximum delay</td>
|
||
|
|
<td>60 s</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>Jitter</td>
|
||
|
|
<td>±10 % of the computed delay</td>
|
||
|
|
</tr>
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
<p>Pseudocode:</p>
|
||
|
|
<pre>
|
||
|
|
<code>{`delay = 1.0 // seconds
|
||
|
|
max_delay = 60.0
|
||
|
|
|
||
|
|
loop:
|
||
|
|
token = POST /gateway/tokens
|
||
|
|
connect ws:/gateway/events/push?token=TOKEN&project=NAME
|
||
|
|
while connected:
|
||
|
|
send StoredEvent frames
|
||
|
|
// disconnected — wait and retry
|
||
|
|
jitter = delay * (random(0.9, 1.1))
|
||
|
|
sleep(min(jitter, max_delay))
|
||
|
|
delay = min(delay * 2, max_delay)`}</code>
|
||
|
|
</pre>
|
||
|
|
|
||
|
|
<div className="note">
|
||
|
|
<strong>New token per connection:</strong> Each WebSocket upgrade consumes the join token. Request a
|
||
|
|
fresh token for every reconnect attempt.
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<h2>Building from source</h2>
|
||
|
|
<h3>Standard release build</h3>
|
||
|
|
<pre>
|
||
|
|
<code>{`cargo build --release\n# Output: target/release/huskies`}</code>
|
||
|
|
</pre>
|
||
|
|
|
||
|
|
<h3>Static Linux binary (musl)</h3>
|
||
|
|
<p>
|
||
|
|
Requires <code>cross</code>: <code>cargo install cross</code>.
|
||
|
|
</p>
|
||
|
|
<pre>
|
||
|
|
<code>cross build --release --target x86_64-unknown-linux-musl</code>
|
||
|
|
</pre>
|
||
|
|
|
||
|
|
<h3>Docker image</h3>
|
||
|
|
<pre>
|
||
|
|
<code>docker compose -f docker/docker-compose.yml build</code>
|
||
|
|
</pre>
|
||
|
|
|
||
|
|
<h3>Release script</h3>
|
||
|
|
<p>
|
||
|
|
Builds macOS arm64 and Linux amd64 binaries, bumps the version, tags the repo, and publishes a
|
||
|
|
Gitea release with changelog and binaries attached.
|
||
|
|
</p>
|
||
|
|
<pre>
|
||
|
|
<code>script/release 0.8.0</code>
|
||
|
|
</pre>
|
||
|
|
</>
|
||
|
|
)
|
||
|
|
}
|