/** 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>
    </>
  )
}
