huskies: merge 1113 story [huskies-server repo] Convert static website to Next.js with static rendering

This commit is contained in:
dave
2026-05-17 15:46:21 +00:00
parent 0695ad7ae6
commit 6e4fb7fd4b
23 changed files with 3849 additions and 1 deletions
+384
View File
@@ -0,0 +1,384 @@
/** 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 &lt;PORT&gt;</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 &lt;PATH&gt;</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>&mdash;</td>
<td>Print help and exit.</td>
</tr>
<tr>
<td>--version</td>
<td>&mdash;</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 &lt;PORT&gt;</td>
<td>3000</td>
<td>
Port written into <code>.mcp.json</code> for MCP tool discovery.
</td>
</tr>
<tr>
<td>--project &lt;PATH&gt;</td>
<td>current dir</td>
<td>Directory to initialise. Must be a git repository.</td>
</tr>
<tr>
<td>--help</td>
<td>&mdash;</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&apos; 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 &lt;number&gt;</code> in chat &mdash; 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 &lt;ID&gt;</td>
<td>
Story ID slug to work on (e.g. <code>42_story_add_login</code>).
</td>
</tr>
<tr>
<td>--agent &lt;NAME&gt;</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 &lt;PATH&gt;</td>
<td>Path to the git worktree the agent should work in.</td>
</tr>
<tr>
<td>--port &lt;PORT&gt;</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> &rarr;{' '}
<code>{'{"token":"…"}'}</code>
</li>
<li>
Open a WebSocket upgrade to{' '}
<code>GET /gateway/events/push?token=TOKEN&amp;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 &mdash; 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&times; per attempt</td>
</tr>
<tr>
<td>Maximum delay</td>
<td>60 s</td>
</tr>
<tr>
<td>Jitter</td>
<td>&plusmn;10&thinsp;% 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>
</>
)
}