huskies: merge 485_story_documentation_site_for_huskies_dev
This commit is contained in:
@@ -0,0 +1,174 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>CLI Reference — Huskies Docs</title>
|
||||||
|
<meta name="description" content="Command-line reference for huskies, huskies init, and related subcommands.">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600;700;800&family=Karla:ital,wght@0,300;0,400;0,500;1,300;1,400&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="docs.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<header class="reveal r1">
|
||||||
|
<a href="/" class="logo">huskies</a>
|
||||||
|
<nav>
|
||||||
|
<a href="/#how">How it works</a>
|
||||||
|
<a href="/#features">Features</a>
|
||||||
|
<a href="/docs/" class="active">Docs</a>
|
||||||
|
<a href="https://code.crashlabs.io/crashlabs/huskies">Source</a>
|
||||||
|
<a href="https://code.crashlabs.io/crashlabs/huskies/releases">Releases</a>
|
||||||
|
<a href="mailto:hello@huskies.dev" class="nav-cta">Get in touch</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<div class="docs-layout">
|
||||||
|
<aside class="sidebar reveal r2">
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Getting started</div>
|
||||||
|
<nav>
|
||||||
|
<a href="/docs/">Overview</a>
|
||||||
|
<a href="quickstart.html">Quickstart</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Reference</div>
|
||||||
|
<nav>
|
||||||
|
<a href="configuration.html">Configuration</a>
|
||||||
|
<a href="commands.html">Bot commands</a>
|
||||||
|
<a href="cli.html" class="active">CLI</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Guides</div>
|
||||||
|
<nav>
|
||||||
|
<a href="pipeline.html">Pipeline stages</a>
|
||||||
|
<a href="transports.html">Chat transports</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<main class="docs-main reveal r3">
|
||||||
|
<h1 class="page-title">CLI Reference</h1>
|
||||||
|
<p class="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 class="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 class="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>Building from source</h2>
|
||||||
|
<h3>Standard release build</h3>
|
||||||
|
<pre><code>cargo build --release
|
||||||
|
# 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>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="reveal r3">
|
||||||
|
<span>© 2026 Libby Labs Ltd.</span>
|
||||||
|
<a href="/privacy.html">Privacy Policy</a>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Bot Commands — Huskies Docs</title>
|
||||||
|
<meta name="description" content="Full reference of huskies bot commands available in Matrix, Slack, WhatsApp, Discord, and the web UI.">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600;700;800&family=Karla:ital,wght@0,300;0,400;0,500;1,300;1,400&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="docs.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<header class="reveal r1">
|
||||||
|
<a href="/" class="logo">huskies</a>
|
||||||
|
<nav>
|
||||||
|
<a href="/#how">How it works</a>
|
||||||
|
<a href="/#features">Features</a>
|
||||||
|
<a href="/docs/" class="active">Docs</a>
|
||||||
|
<a href="https://code.crashlabs.io/crashlabs/huskies">Source</a>
|
||||||
|
<a href="https://code.crashlabs.io/crashlabs/huskies/releases">Releases</a>
|
||||||
|
<a href="mailto:hello@huskies.dev" class="nav-cta">Get in touch</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<div class="docs-layout">
|
||||||
|
<aside class="sidebar reveal r2">
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Getting started</div>
|
||||||
|
<nav>
|
||||||
|
<a href="/docs/">Overview</a>
|
||||||
|
<a href="quickstart.html">Quickstart</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Reference</div>
|
||||||
|
<nav>
|
||||||
|
<a href="configuration.html">Configuration</a>
|
||||||
|
<a href="commands.html" class="active">Bot commands</a>
|
||||||
|
<a href="cli.html">CLI</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Guides</div>
|
||||||
|
<nav>
|
||||||
|
<a href="pipeline.html">Pipeline stages</a>
|
||||||
|
<a href="transports.html">Chat transports</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<main class="docs-main reveal r3">
|
||||||
|
<h1 class="page-title">Bot Commands</h1>
|
||||||
|
<p class="page-subtitle">Commands available in every chat transport (Matrix, Slack, WhatsApp, Discord) and the built-in web UI. Commands are case-insensitive. Run <code>help</code> in any chat to see the list.</p>
|
||||||
|
|
||||||
|
<div class="note">
|
||||||
|
<strong>How to invoke:</strong> In chat rooms, address the bot first (e.g. <code>@huskies start 42</code>) or enable ambient mode so it responds to all messages. In the web UI, type commands directly.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Pipeline management</h2>
|
||||||
|
<div class="cmd-grid">
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">status</div>
|
||||||
|
<div class="cmd-desc">Show pipeline status and agent availability. Use <code>status <number></code> for a detailed triage dump on a specific story.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">start</div>
|
||||||
|
<div class="cmd-desc">Start an agent on a story: <code>start <number></code>. To use the opus model: <code>start <number> opus</code>.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">move</div>
|
||||||
|
<div class="cmd-desc">Move a work item to a pipeline stage: <code>move <number> <stage></code>. Stages: <code>backlog</code>, <code>current</code>, <code>qa</code>, <code>merge</code>, <code>done</code>.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">show</div>
|
||||||
|
<div class="cmd-desc">Display the full text of a work item: <code>show <number></code>.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">delete</div>
|
||||||
|
<div class="cmd-desc">Remove a work item from the pipeline: <code>delete <number></code>.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">unblock</div>
|
||||||
|
<div class="cmd-desc">Reset a blocked story: <code>unblock <number></code>. Clears the blocked flag and resets the retry count.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">assign</div>
|
||||||
|
<div class="cmd-desc">Pre-assign a model to a story before starting: <code>assign <number> <model></code> (e.g. <code>assign 42 opus</code>).</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">depends</div>
|
||||||
|
<div class="cmd-desc">Set story dependencies: <code>depends <number> [dep1 dep2 ...]</code>. Call with no deps to clear all dependencies.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">timer</div>
|
||||||
|
<div class="cmd-desc">Schedule a deferred agent start: <code>timer <number> HH:MM</code>. List all timers: <code>timer list</code>. Cancel: <code>timer cancel <number></code>. Times are interpreted in the project timezone.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Worktrees</h2>
|
||||||
|
<div class="cmd-grid">
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">rmtree</div>
|
||||||
|
<div class="cmd-desc">Delete the worktree for a story without removing the story from the pipeline: <code>rmtree <number></code>. Useful for freeing disk space on a story that needs to be restarted.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Observability</h2>
|
||||||
|
<div class="cmd-grid">
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">cost</div>
|
||||||
|
<div class="cmd-desc">Show token spend: 24h total, top stories, breakdown by agent type, and all-time total.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">coverage</div>
|
||||||
|
<div class="cmd-desc">Show test coverage from the cached baseline. Use <code>coverage run</code> to rerun the full test suite and regenerate the report.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">git</div>
|
||||||
|
<div class="cmd-desc">Show git status for the main repository: current branch, uncommitted changes, and ahead/behind remote.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">htop</div>
|
||||||
|
<div class="cmd-desc">Live system and agent process dashboard. Use <code>htop</code> to start, <code>htop 10m</code> to run for 10 minutes, <code>htop stop</code> to stop.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">loc</div>
|
||||||
|
<div class="cmd-desc">Show top source files by line count: <code>loc</code> (top 10), <code>loc <N></code> for N files, or <code>loc <filepath></code> for a specific file.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">overview</div>
|
||||||
|
<div class="cmd-desc">Show an implementation summary for a merged story: <code>overview <number></code>.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">unreleased</div>
|
||||||
|
<div class="cmd-desc">Show stories merged to master since the last release tag.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Server management</h2>
|
||||||
|
<div class="cmd-grid">
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">rebuild</div>
|
||||||
|
<div class="cmd-desc">Rebuild the huskies server binary and restart the process.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">reset</div>
|
||||||
|
<div class="cmd-desc">Clear the current Claude Code session and start a fresh context window.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Setup & configuration</h2>
|
||||||
|
<div class="cmd-grid">
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">setup</div>
|
||||||
|
<div class="cmd-desc">Show setup wizard progress. Drive the wizard from chat: <code>setup generate</code>, <code>setup confirm</code>, <code>setup skip</code>, <code>setup retry</code>.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">ambient</div>
|
||||||
|
<div class="cmd-desc">Toggle ambient mode for the current room: <code>ambient on</code> or <code>ambient off</code>. In ambient mode the bot responds to all messages, not just addressed ones.</div>
|
||||||
|
</div>
|
||||||
|
<div class="cmd-row">
|
||||||
|
<div class="cmd-name">help</div>
|
||||||
|
<div class="cmd-desc">Show the list of available commands.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="reveal r3">
|
||||||
|
<span>© 2026 Libby Labs Ltd.</span>
|
||||||
|
<a href="/privacy.html">Privacy Policy</a>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,230 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Configuration — Huskies Docs</title>
|
||||||
|
<meta name="description" content="Reference for project.toml, agents.toml, and bot.toml configuration files.">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600;700;800&family=Karla:ital,wght@0,300;0,400;0,500;1,300;1,400&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="docs.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<header class="reveal r1">
|
||||||
|
<a href="/" class="logo">huskies</a>
|
||||||
|
<nav>
|
||||||
|
<a href="/#how">How it works</a>
|
||||||
|
<a href="/#features">Features</a>
|
||||||
|
<a href="/docs/" class="active">Docs</a>
|
||||||
|
<a href="https://code.crashlabs.io/crashlabs/huskies">Source</a>
|
||||||
|
<a href="https://code.crashlabs.io/crashlabs/huskies/releases">Releases</a>
|
||||||
|
<a href="mailto:hello@huskies.dev" class="nav-cta">Get in touch</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<div class="docs-layout">
|
||||||
|
<aside class="sidebar reveal r2">
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Getting started</div>
|
||||||
|
<nav>
|
||||||
|
<a href="/docs/">Overview</a>
|
||||||
|
<a href="quickstart.html">Quickstart</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Reference</div>
|
||||||
|
<nav>
|
||||||
|
<a href="configuration.html" class="active">Configuration</a>
|
||||||
|
<a href="commands.html">Bot commands</a>
|
||||||
|
<a href="cli.html">CLI</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Guides</div>
|
||||||
|
<nav>
|
||||||
|
<a href="pipeline.html">Pipeline stages</a>
|
||||||
|
<a href="transports.html">Chat transports</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<main class="docs-main reveal r3">
|
||||||
|
<h1 class="page-title">Configuration</h1>
|
||||||
|
<p class="page-subtitle">Huskies is configured via three TOML files in your <code>.huskies/</code> directory. All files are created by <code>huskies init</code> with sensible defaults.</p>
|
||||||
|
|
||||||
|
<h2 id="project-toml">project.toml</h2>
|
||||||
|
<p>Project-wide settings. Lives at <code>.huskies/project.toml</code>.</p>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Key</th><th>Type</th><th>Default</th><th>Description</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>default_qa</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td><code>"server"</code></td>
|
||||||
|
<td>Default QA mode. One of <code>"server"</code> (automated gate run), <code>"agent"</code> (spawn a QA agent), or <code>"human"</code> (manual approval).</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>default_coder_model</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td><code>"sonnet"</code></td>
|
||||||
|
<td>Default model for coder agents. Only agents matching this model are auto-assigned. Use <code>"opus"</code> on individual stories for complex tasks.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>max_coders</td>
|
||||||
|
<td>integer</td>
|
||||||
|
<td><code>3</code></td>
|
||||||
|
<td>Maximum concurrent coder agents. Stories wait in <code>2_current/</code> when all slots are full.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>max_retries</td>
|
||||||
|
<td>integer</td>
|
||||||
|
<td><code>3</code></td>
|
||||||
|
<td>Maximum retries per story per pipeline stage before marking it as blocked. Set to <code>0</code> to disable.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>base_branch</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>auto-detected</td>
|
||||||
|
<td>Base branch for merges and agent prompts. When unset, huskies reads the current HEAD branch.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>rate_limit_notifications</td>
|
||||||
|
<td>bool</td>
|
||||||
|
<td><code>false</code></td>
|
||||||
|
<td>Send chat notifications when API soft rate limits are hit. Hard blocks and story-blocked notifications are always sent.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>timezone</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td><code>"UTC"</code></td>
|
||||||
|
<td>IANA timezone for timer scheduling (e.g. <code>"Europe/London"</code>, <code>"America/New_York"</code>). Timer HH:MM inputs are interpreted in this timezone.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3>Component setup</h3>
|
||||||
|
<p>The <code>[[component]]</code> sections define how to build and verify each part of your project. The server runs setup commands before accepting a story's QA and teardown commands after merging.</p>
|
||||||
|
<pre><code>[[component]]
|
||||||
|
name = "frontend"
|
||||||
|
path = "frontend"
|
||||||
|
setup = ["npm ci", "npm run build"]
|
||||||
|
teardown = []
|
||||||
|
|
||||||
|
[[component]]
|
||||||
|
name = "server"
|
||||||
|
path = "."
|
||||||
|
setup = ["mkdir -p frontend/dist", "cargo check"]
|
||||||
|
teardown = []</code></pre>
|
||||||
|
|
||||||
|
<h3>Story front matter overrides</h3>
|
||||||
|
<p>Individual stories can override project defaults using YAML front matter:</p>
|
||||||
|
<pre><code>---
|
||||||
|
name: "My Complex Story"
|
||||||
|
qa: agent # override default_qa
|
||||||
|
agent: opus # use the opus coder agent
|
||||||
|
---</code></pre>
|
||||||
|
|
||||||
|
<h2 id="agents-toml">agents.toml</h2>
|
||||||
|
<p>Agent definitions. Lives at <code>.huskies/agents.toml</code>. Each <code>[[agent]]</code> block defines one agent slot.</p>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Key</th><th>Description</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>name</td>
|
||||||
|
<td>Unique identifier for this agent slot (e.g. <code>"coder-1"</code>, <code>"qa"</code>).</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>stage</td>
|
||||||
|
<td>Pipeline stage this agent handles. One of <code>"coder"</code>, <code>"qa"</code>, or <code>"mergemaster"</code>.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>role</td>
|
||||||
|
<td>Human-readable description of the agent's responsibilities (shown in status output).</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>model</td>
|
||||||
|
<td>Claude model to use. One of <code>"sonnet"</code> (claude-sonnet-4-6) or <code>"opus"</code> (claude-opus-4-6).</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>max_turns</td>
|
||||||
|
<td>Maximum conversation turns before the agent is forcefully stopped.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>max_budget_usd</td>
|
||||||
|
<td>Maximum API spend in USD before the agent is stopped.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>prompt</td>
|
||||||
|
<td>The initial user-turn prompt sent to the agent. Supports template variables (see below).</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>system_prompt</td>
|
||||||
|
<td>The system prompt sent to the agent session.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3>Template variables</h3>
|
||||||
|
<p>The following variables are interpolated into <code>prompt</code> and <code>system_prompt</code> at agent start time:</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Variable</th><th>Description</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>{{story_id}}</td><td>The story's ID slug (e.g. <code>42_story_add_login</code>).</td></tr>
|
||||||
|
<tr><td>{{worktree_path}}</td><td>Absolute path to the agent's git worktree.</td></tr>
|
||||||
|
<tr><td>{{base_branch}}</td><td>The base branch name from <code>project.toml</code>.</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3>Example: adding an opus coder</h3>
|
||||||
|
<pre><code>[[agent]]
|
||||||
|
name = "coder-opus"
|
||||||
|
stage = "coder"
|
||||||
|
role = "Senior engineer for complex tasks."
|
||||||
|
model = "opus"
|
||||||
|
max_turns = 80
|
||||||
|
max_budget_usd = 20.00
|
||||||
|
prompt = "You are working on story {{story_id}} ..."
|
||||||
|
system_prompt = "You are a senior full-stack engineer ..."</code></pre>
|
||||||
|
<p>To use this agent for a specific story, add <code>agent: opus</code> to the story's front matter, or run <code>start <number> opus</code> in chat.</p>
|
||||||
|
|
||||||
|
<h2 id="bot-toml">bot.toml</h2>
|
||||||
|
<p>Chat transport configuration. Lives at <code>.huskies/bot.toml</code>. This file is gitignored as it contains credentials. Copy the appropriate example file to get started:</p>
|
||||||
|
<pre><code>cp .huskies/bot.toml.matrix.example .huskies/bot.toml</code></pre>
|
||||||
|
<p>Only one transport can be active at a time. See the <a href="transports.html">Chat transports</a> guide for setup instructions for each platform.</p>
|
||||||
|
|
||||||
|
<h3>Common fields</h3>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Key</th><th>Description</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>enabled</td><td>Set to <code>true</code> to activate the bot. Set to <code>false</code> to disable without removing the file.</td></tr>
|
||||||
|
<tr><td>transport</td><td>Transport type: <code>"matrix"</code>, <code>"whatsapp"</code>, <code>"slack"</code>, or <code>"discord"</code>.</td></tr>
|
||||||
|
<tr><td>display_name</td><td>Optional. Bot display name in chat messages.</td></tr>
|
||||||
|
<tr><td>history_size</td><td>Optional. Maximum conversation turns to remember per room/user (default: 20).</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="reveal r3">
|
||||||
|
<span>© 2026 Libby Labs Ltd.</span>
|
||||||
|
<a href="/privacy.html">Privacy Policy</a>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,447 @@
|
|||||||
|
:root {
|
||||||
|
--bg: #080c15;
|
||||||
|
--surface: #0e1420;
|
||||||
|
--surface-hover: #131a28;
|
||||||
|
--border: #1a2235;
|
||||||
|
--text: #e8ecf4;
|
||||||
|
--text-secondary: #8892a8;
|
||||||
|
--text-dim: #4a5568;
|
||||||
|
--cyan: #22d3ee;
|
||||||
|
--cyan-dim: rgba(34, 211, 238, 0.07);
|
||||||
|
--cyan-glow: rgba(34, 211, 238, 0.15);
|
||||||
|
--display: 'Bricolage Grotesque', sans-serif;
|
||||||
|
--body: 'Karla', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
html { scroll-behavior: smooth; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: var(--body);
|
||||||
|
background: var(--bg);
|
||||||
|
color: var(--text);
|
||||||
|
line-height: 1.6;
|
||||||
|
min-height: 100vh;
|
||||||
|
overflow-x: hidden;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
a { color: var(--cyan); text-decoration: none; transition: opacity 0.2s; }
|
||||||
|
a:hover { opacity: 0.7; }
|
||||||
|
|
||||||
|
/* Animations */
|
||||||
|
@keyframes fadeUp {
|
||||||
|
from { opacity: 0; transform: translateY(18px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal {
|
||||||
|
opacity: 0;
|
||||||
|
animation: fadeUp 0.7s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
||||||
|
}
|
||||||
|
.r1 { animation-delay: 0.05s; }
|
||||||
|
.r2 { animation-delay: 0.15s; }
|
||||||
|
.r3 { animation-delay: 0.3s; }
|
||||||
|
|
||||||
|
/* Outer shell */
|
||||||
|
.shell {
|
||||||
|
max-width: 1100px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.shell { padding: 0 1.25rem; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
header {
|
||||||
|
padding: 2rem 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-family: var(--display);
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: -0.03em;
|
||||||
|
color: var(--text) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
header nav {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
header nav a {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
header nav a:hover { color: var(--text); opacity: 1; }
|
||||||
|
header nav a.active { color: var(--cyan); }
|
||||||
|
|
||||||
|
.nav-cta {
|
||||||
|
color: var(--cyan) !important;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Docs layout */
|
||||||
|
.docs-layout {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 220px 1fr;
|
||||||
|
gap: 0;
|
||||||
|
min-height: calc(100vh - 80px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sidebar */
|
||||||
|
.sidebar {
|
||||||
|
border-right: 1px solid var(--border);
|
||||||
|
padding: 2.5rem 0 2.5rem 0;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
height: 100vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-section {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-heading {
|
||||||
|
font-family: var(--display);
|
||||||
|
font-size: 0.6rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.14em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--text-dim);
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar nav a {
|
||||||
|
display: block;
|
||||||
|
padding: 0.4rem 1.5rem;
|
||||||
|
font-size: 0.83rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
transition: color 0.15s, background 0.15s;
|
||||||
|
border-left: 2px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar nav a:hover {
|
||||||
|
color: var(--text);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar nav a.active {
|
||||||
|
color: var(--cyan);
|
||||||
|
border-left-color: var(--cyan);
|
||||||
|
background: var(--cyan-dim);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main content */
|
||||||
|
.docs-main {
|
||||||
|
padding: 2.5rem 3rem 4rem;
|
||||||
|
max-width: 780px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.docs-layout { grid-template-columns: 1fr; }
|
||||||
|
.sidebar {
|
||||||
|
position: static;
|
||||||
|
height: auto;
|
||||||
|
border-right: none;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
padding: 1.5rem 0;
|
||||||
|
}
|
||||||
|
.docs-main { padding: 2rem 0 3rem; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Typography */
|
||||||
|
.page-title {
|
||||||
|
font-family: var(--display);
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: -0.03em;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-subtitle {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-weight: 300;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
max-width: 560px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-family: var(--display);
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
margin: 3rem 0 1rem;
|
||||||
|
padding-top: 1rem;
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
scroll-margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2:first-of-type {
|
||||||
|
margin-top: 0;
|
||||||
|
padding-top: 0;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-family: var(--display);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 1.8rem 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
line-height: 1.8;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p strong {
|
||||||
|
color: var(--text);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul, ol {
|
||||||
|
padding-left: 1.4rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
line-height: 1.8;
|
||||||
|
margin-bottom: 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
li strong {
|
||||||
|
color: var(--text);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code */
|
||||||
|
code {
|
||||||
|
font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0.1em 0.4em;
|
||||||
|
color: var(--cyan);
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 1.2rem 1.4rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin: 1rem 0 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre code {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 0.82rem;
|
||||||
|
color: var(--text);
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tables */
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 1rem 0 1.5rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align: left;
|
||||||
|
font-family: var(--display);
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--text-dim);
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 0.65rem 1rem;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
color: var(--text-secondary);
|
||||||
|
vertical-align: top;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:first-child {
|
||||||
|
font-family: 'SF Mono', 'Fira Code', monospace;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--cyan);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:last-child td { border-bottom: none; }
|
||||||
|
|
||||||
|
/* Callout / note box */
|
||||||
|
.note {
|
||||||
|
background: var(--cyan-dim);
|
||||||
|
border: 1px solid rgba(34, 211, 238, 0.2);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 1rem 1.2rem;
|
||||||
|
margin: 1.2rem 0;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note strong {
|
||||||
|
color: var(--cyan);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step list */
|
||||||
|
.step-list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
counter-reset: steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-list li {
|
||||||
|
counter-increment: steps;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 40px 1fr;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1.2rem 0;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-list li:first-child { border-top: 1px solid var(--border); }
|
||||||
|
|
||||||
|
.step-list li::before {
|
||||||
|
content: counter(steps, decimal-leading-zero);
|
||||||
|
font-family: var(--display);
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-dim);
|
||||||
|
padding-top: 0.15rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Command cards */
|
||||||
|
.cmd-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1px;
|
||||||
|
background: var(--border);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 1rem 0 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 160px 1fr;
|
||||||
|
background: var(--surface);
|
||||||
|
transition: background 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-row:hover { background: var(--surface-hover); }
|
||||||
|
|
||||||
|
.cmd-name {
|
||||||
|
padding: 0.9rem 1.1rem;
|
||||||
|
font-family: 'SF Mono', 'Fira Code', monospace;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--cyan);
|
||||||
|
border-right: 1px solid var(--border);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-desc {
|
||||||
|
padding: 0.9rem 1.1rem;
|
||||||
|
font-size: 0.84rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
line-height: 1.6;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Docs index cards */
|
||||||
|
.doc-cards {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 1px;
|
||||||
|
background: var(--border);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-card {
|
||||||
|
background: var(--surface);
|
||||||
|
padding: 1.6rem;
|
||||||
|
transition: background 0.2s;
|
||||||
|
text-decoration: none;
|
||||||
|
display: block;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-card:hover { background: var(--surface-hover); opacity: 1; }
|
||||||
|
|
||||||
|
.doc-card-title {
|
||||||
|
font-family: var(--display);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text);
|
||||||
|
margin-bottom: 0.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-card-desc {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.doc-cards { grid-template-columns: 1fr; }
|
||||||
|
.cmd-row { grid-template-columns: 130px 1fr; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Footer */
|
||||||
|
footer {
|
||||||
|
padding: 2rem 0;
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--text-dim);
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
color: var(--text-dim);
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a:hover { color: var(--text-secondary); }
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Documentation — Huskies</title>
|
||||||
|
<meta name="description" content="Huskies documentation: quickstart, configuration, bot commands, pipeline, and more.">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600;700;800&family=Karla:ital,wght@0,300;0,400;0,500;1,300;1,400&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="docs.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<header class="reveal r1">
|
||||||
|
<a href="/" class="logo">huskies</a>
|
||||||
|
<nav>
|
||||||
|
<a href="/#how">How it works</a>
|
||||||
|
<a href="/#features">Features</a>
|
||||||
|
<a href="/docs/" class="active">Docs</a>
|
||||||
|
<a href="https://code.crashlabs.io/crashlabs/huskies">Source</a>
|
||||||
|
<a href="https://code.crashlabs.io/crashlabs/huskies/releases">Releases</a>
|
||||||
|
<a href="mailto:hello@huskies.dev" class="nav-cta">Get in touch</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<div class="docs-layout">
|
||||||
|
<aside class="sidebar reveal r2">
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Getting started</div>
|
||||||
|
<nav>
|
||||||
|
<a href="/docs/" class="active">Overview</a>
|
||||||
|
<a href="quickstart.html">Quickstart</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Reference</div>
|
||||||
|
<nav>
|
||||||
|
<a href="configuration.html">Configuration</a>
|
||||||
|
<a href="commands.html">Bot commands</a>
|
||||||
|
<a href="cli.html">CLI</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Guides</div>
|
||||||
|
<nav>
|
||||||
|
<a href="pipeline.html">Pipeline stages</a>
|
||||||
|
<a href="transports.html">Chat transports</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<main class="docs-main reveal r3">
|
||||||
|
<p class="hero-kicker" style="font-family:var(--display);font-size:0.68rem;font-weight:600;letter-spacing:0.18em;text-transform:uppercase;color:var(--cyan);margin-bottom:1rem;">Documentation</p>
|
||||||
|
<h1 class="page-title">Huskies Docs</h1>
|
||||||
|
<p class="page-subtitle">Everything you need to set up and run huskies — a story-driven development pipeline that turns coding agents into a disciplined team.</p>
|
||||||
|
|
||||||
|
<div class="doc-cards">
|
||||||
|
<a class="doc-card" href="quickstart.html">
|
||||||
|
<div class="doc-card-title">Quickstart</div>
|
||||||
|
<div class="doc-card-desc">Install huskies, run the server, create your first story, and watch an agent implement it.</div>
|
||||||
|
</a>
|
||||||
|
<a class="doc-card" href="configuration.html">
|
||||||
|
<div class="doc-card-title">Configuration</div>
|
||||||
|
<div class="doc-card-desc">Reference for <code>project.toml</code>, <code>agents.toml</code>, and <code>bot.toml</code>.</div>
|
||||||
|
</a>
|
||||||
|
<a class="doc-card" href="commands.html">
|
||||||
|
<div class="doc-card-title">Bot commands</div>
|
||||||
|
<div class="doc-card-desc">Full list of commands available in Matrix, Slack, WhatsApp, and the web UI.</div>
|
||||||
|
</a>
|
||||||
|
<a class="doc-card" href="pipeline.html">
|
||||||
|
<div class="doc-card-title">Pipeline stages</div>
|
||||||
|
<div class="doc-card-desc">How work items move from backlog through QA and merge to done.</div>
|
||||||
|
</a>
|
||||||
|
<a class="doc-card" href="transports.html">
|
||||||
|
<div class="doc-card-title">Chat transports</div>
|
||||||
|
<div class="doc-card-desc">Connect huskies to Matrix, WhatsApp, Slack, Discord, or the built-in web UI.</div>
|
||||||
|
</a>
|
||||||
|
<a class="doc-card" href="cli.html">
|
||||||
|
<div class="doc-card-title">CLI reference</div>
|
||||||
|
<div class="doc-card-desc">Command-line flags for <code>huskies</code>, <code>huskies init</code>, and <code>huskies agent</code>.</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>What is huskies?</h2>
|
||||||
|
<p>Huskies is a story-driven development server. You write stories (feature requests) with acceptance criteria; huskies spawns coding agents in isolated git worktrees, runs them through quality gates, and squash-merges the result to your main branch — all without you writing a line of code.</p>
|
||||||
|
<p>It ships as a single Rust binary with an embedded React frontend. No separate database or build infrastructure required.</p>
|
||||||
|
|
||||||
|
<h2>How it works</h2>
|
||||||
|
<ol class="step-list">
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
<strong>Write a story.</strong> Describe the change with acceptance criteria via the web UI, a chat room (Matrix, WhatsApp, Slack), or by dropping a Markdown file in <code>.huskies/work/1_backlog/</code>.
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
<strong>Agent picks it up.</strong> Run <code>start <number></code> (or configure auto-start). A coder agent creates a feature branch, implements the code, and writes tests against your criteria.
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
<strong>Quality gates run.</strong> Linters, tests, and compilation checks run automatically when the agent exits. Nothing moves forward until everything passes.
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
<strong>QA review.</strong> A QA agent verifies each acceptance criterion, runs your test suite, and either approves or rejects with detailed findings.
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
<strong>Merge & land.</strong> A merge agent resolves conflicts and squash-merges to your main branch. The worktree is cleaned up automatically.
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2>Key concepts</h2>
|
||||||
|
<p><strong>Stories</strong> are Markdown files with YAML front matter. They live in <code>.huskies/work/</code> and move through pipeline stages as work progresses.</p>
|
||||||
|
<p><strong>Agents</strong> are Claude Code sessions that run autonomously in git worktrees. Each story gets its own isolated worktree so multiple stories can be in flight simultaneously.</p>
|
||||||
|
<p><strong>MCP tools</strong> give Claude Code sessions programmatic access to the pipeline: creating stories, starting agents, checking status, recording test results.</p>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="reveal r3">
|
||||||
|
<span>© 2026 Libby Labs Ltd.</span>
|
||||||
|
<a href="/privacy.html">Privacy Policy</a>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Pipeline Stages — Huskies Docs</title>
|
||||||
|
<meta name="description" content="How work items move through the huskies pipeline: backlog, current, QA, merge, done.">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600;700;800&family=Karla:ital,wght@0,300;0,400;0,500;1,300;1,400&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="docs.css">
|
||||||
|
<style>
|
||||||
|
.pipeline-stages {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1px;
|
||||||
|
background: var(--border);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
}
|
||||||
|
.stage-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 48px 140px 1fr;
|
||||||
|
gap: 0;
|
||||||
|
background: var(--surface);
|
||||||
|
transition: background 0.2s;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
.stage-row:hover { background: var(--surface-hover); }
|
||||||
|
.stage-num {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-family: var(--display);
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-dim);
|
||||||
|
border-right: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
.stage-name {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 1rem 1.1rem;
|
||||||
|
font-family: var(--display);
|
||||||
|
font-size: 0.88rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text);
|
||||||
|
border-right: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
.stage-desc {
|
||||||
|
padding: 1rem 1.2rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.stage-row.active .stage-name { color: var(--cyan); }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<header class="reveal r1">
|
||||||
|
<a href="/" class="logo">huskies</a>
|
||||||
|
<nav>
|
||||||
|
<a href="/#how">How it works</a>
|
||||||
|
<a href="/#features">Features</a>
|
||||||
|
<a href="/docs/" class="active">Docs</a>
|
||||||
|
<a href="https://code.crashlabs.io/crashlabs/huskies">Source</a>
|
||||||
|
<a href="https://code.crashlabs.io/crashlabs/huskies/releases">Releases</a>
|
||||||
|
<a href="mailto:hello@huskies.dev" class="nav-cta">Get in touch</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<div class="docs-layout">
|
||||||
|
<aside class="sidebar reveal r2">
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Getting started</div>
|
||||||
|
<nav>
|
||||||
|
<a href="/docs/">Overview</a>
|
||||||
|
<a href="quickstart.html">Quickstart</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Reference</div>
|
||||||
|
<nav>
|
||||||
|
<a href="configuration.html">Configuration</a>
|
||||||
|
<a href="commands.html">Bot commands</a>
|
||||||
|
<a href="cli.html">CLI</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Guides</div>
|
||||||
|
<nav>
|
||||||
|
<a href="pipeline.html" class="active">Pipeline stages</a>
|
||||||
|
<a href="transports.html">Chat transports</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<main class="docs-main reveal r3">
|
||||||
|
<h1 class="page-title">Pipeline Stages</h1>
|
||||||
|
<p class="page-subtitle">Work items move through six stages from idea to archive. Each stage is a directory under <code>.huskies/work/</code>. Moving a file between directories advances the story.</p>
|
||||||
|
|
||||||
|
<div class="pipeline-stages">
|
||||||
|
<div class="stage-row">
|
||||||
|
<div class="stage-num">1</div>
|
||||||
|
<div class="stage-name">Backlog</div>
|
||||||
|
<div class="stage-desc"><code>1_backlog/</code> — New work items awaiting prioritisation. Stories sit here until you decide to start them.</div>
|
||||||
|
</div>
|
||||||
|
<div class="stage-row active">
|
||||||
|
<div class="stage-num">2</div>
|
||||||
|
<div class="stage-name">Current</div>
|
||||||
|
<div class="stage-desc"><code>2_current/</code> — Work in progress. Run <code>start <number></code> to assign a coder agent. Multiple stories can be in current simultaneously (up to <code>max_coders</code>).</div>
|
||||||
|
</div>
|
||||||
|
<div class="stage-row">
|
||||||
|
<div class="stage-num">3</div>
|
||||||
|
<div class="stage-name">QA</div>
|
||||||
|
<div class="stage-desc"><code>3_qa/</code> — Quality review. The server automatically moves stories here when the coder agent passes all quality gates. A QA agent (or a human) verifies each acceptance criterion.</div>
|
||||||
|
</div>
|
||||||
|
<div class="stage-row">
|
||||||
|
<div class="stage-num">4</div>
|
||||||
|
<div class="stage-name">Merge</div>
|
||||||
|
<div class="stage-desc"><code>4_merge/</code> — Ready to merge. Stories reach here after QA approval. Run <code>start <number></code> to trigger the mergemaster agent, which squash-merges to your base branch.</div>
|
||||||
|
</div>
|
||||||
|
<div class="stage-row">
|
||||||
|
<div class="stage-num">5</div>
|
||||||
|
<div class="stage-name">Done</div>
|
||||||
|
<div class="stage-desc"><code>5_done/</code> — Merged and complete. The mergemaster moves stories here after a successful merge. Auto-swept to archive after 4 hours.</div>
|
||||||
|
</div>
|
||||||
|
<div class="stage-row">
|
||||||
|
<div class="stage-num">6</div>
|
||||||
|
<div class="stage-name">Archived</div>
|
||||||
|
<div class="stage-desc"><code>6_archived/</code> — Long-term storage. Stories land here automatically from done. Use <code>overview <number></code> to see the implementation summary for any archived story.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Work item types</h2>
|
||||||
|
<p>All work item types move through the same pipeline. They differ in naming convention and workflow:</p>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead><tr><th>Type</th><th>Filename pattern</th><th>When to use</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>story</td>
|
||||||
|
<td><code>42_story_add_login.md</code></td>
|
||||||
|
<td>New functionality. Requires acceptance criteria and tests.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>bug</td>
|
||||||
|
<td><code>43_bug_login_crashes.md</code></td>
|
||||||
|
<td>Defect in existing functionality. Write a failing test first.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>spike</td>
|
||||||
|
<td><code>44_spike_auth_options.md</code></td>
|
||||||
|
<td>Time-boxed research to reduce uncertainty. No production code.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>refactor</td>
|
||||||
|
<td><code>45_refactor_extract_auth.md</code></td>
|
||||||
|
<td>Code quality improvement. Behaviour must not change.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2>Story file format</h2>
|
||||||
|
<p>Every work item is a Markdown file with YAML front matter:</p>
|
||||||
|
<pre><code>---
|
||||||
|
name: "Short human-readable name"
|
||||||
|
qa: agent # optional: override default_qa
|
||||||
|
agent: opus # optional: request specific agent model
|
||||||
|
---
|
||||||
|
|
||||||
|
# Story 42: Add login endpoint
|
||||||
|
|
||||||
|
## User Story
|
||||||
|
As a user, I want to log in with email and password so that I can access my account.
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
- [ ] POST /auth/login accepts email and password
|
||||||
|
- [ ] Returns a JWT token on success
|
||||||
|
- [ ] Returns 401 on invalid credentials
|
||||||
|
- [ ] Rate-limited to 5 attempts per minute per IP
|
||||||
|
|
||||||
|
## Out of Scope
|
||||||
|
- OAuth / social login
|
||||||
|
- Password reset flow</code></pre>
|
||||||
|
|
||||||
|
<h2>Acceptance criteria tracking</h2>
|
||||||
|
<p>Acceptance criteria use Markdown checkboxes (<code>- [ ]</code>). The QA agent reviews each criterion against the code diff and marks passing criteria as <code>- [x]</code> in the story file. Criteria that fail are noted in the QA report.</p>
|
||||||
|
|
||||||
|
<div class="note">
|
||||||
|
<strong>Golden rule:</strong> No code is written until acceptance criteria are captured in the story. The agent reads the story file to understand what to build and what to test.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Filesystem watcher</h2>
|
||||||
|
<p>The server watches <code>.huskies/work/</code> for changes. When a file is created, moved, or modified, the watcher auto-commits with a deterministic message and broadcasts a WebSocket update to the frontend. This means:</p>
|
||||||
|
<ul>
|
||||||
|
<li>You can drag a story between stage folders in your IDE and it advances automatically.</li>
|
||||||
|
<li>MCP tools only need to write or move files — the watcher handles git commits.</li>
|
||||||
|
<li>The pipeline board updates in real time without a manual refresh.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Blocked stories</h2>
|
||||||
|
<p>A story is marked <strong>blocked</strong> when it fails the same pipeline stage more than <code>max_retries</code> times (default: 3). Blocked stories require manual intervention:</p>
|
||||||
|
<ol>
|
||||||
|
<li>Run <code>status <number></code> to see the failure log.</li>
|
||||||
|
<li>Fix the underlying issue (update the story, fix a build problem, etc.).</li>
|
||||||
|
<li>Run <code>unblock <number></code> to reset the retry counter.</li>
|
||||||
|
<li>Run <code>start <number></code> to try again.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2>Dependencies</h2>
|
||||||
|
<p>Stories can declare dependencies using the <code>depends</code> command. A story with unresolved dependencies waits in <code>2_current/</code> until all its dependencies have reached <code>5_done/</code>.</p>
|
||||||
|
<pre><code>depends 45 42 43 # story 45 waits for 42 and 43 to finish
|
||||||
|
depends 45 # clear all dependencies</code></pre>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="reveal r3">
|
||||||
|
<span>© 2026 Libby Labs Ltd.</span>
|
||||||
|
<a href="/privacy.html">Privacy Policy</a>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Quickstart — Huskies Docs</title>
|
||||||
|
<meta name="description" content="Get huskies running in minutes: Docker setup, first story, first agent run.">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600;700;800&family=Karla:ital,wght@0,300;0,400;0,500;1,300;1,400&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="docs.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<header class="reveal r1">
|
||||||
|
<a href="/" class="logo">huskies</a>
|
||||||
|
<nav>
|
||||||
|
<a href="/#how">How it works</a>
|
||||||
|
<a href="/#features">Features</a>
|
||||||
|
<a href="/docs/" class="active">Docs</a>
|
||||||
|
<a href="https://code.crashlabs.io/crashlabs/huskies">Source</a>
|
||||||
|
<a href="https://code.crashlabs.io/crashlabs/huskies/releases">Releases</a>
|
||||||
|
<a href="mailto:hello@huskies.dev" class="nav-cta">Get in touch</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<div class="docs-layout">
|
||||||
|
<aside class="sidebar reveal r2">
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Getting started</div>
|
||||||
|
<nav>
|
||||||
|
<a href="/docs/">Overview</a>
|
||||||
|
<a href="quickstart.html" class="active">Quickstart</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Reference</div>
|
||||||
|
<nav>
|
||||||
|
<a href="configuration.html">Configuration</a>
|
||||||
|
<a href="commands.html">Bot commands</a>
|
||||||
|
<a href="cli.html">CLI</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Guides</div>
|
||||||
|
<nav>
|
||||||
|
<a href="pipeline.html">Pipeline stages</a>
|
||||||
|
<a href="transports.html">Chat transports</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<main class="docs-main reveal r3">
|
||||||
|
<h1 class="page-title">Quickstart</h1>
|
||||||
|
<p class="page-subtitle">Get huskies running in your project in a few minutes. This guide covers Docker setup, running from a binary, your first story, and your first agent run.</p>
|
||||||
|
|
||||||
|
<h2>Option A: Docker (recommended)</h2>
|
||||||
|
<p>The easiest way to run huskies is with Docker Compose. This requires Docker and a Claude API key.</p>
|
||||||
|
<ol class="step-list">
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
<strong>Get the compose file.</strong> Download <code>docker-compose.yml</code> from the <a href="https://code.crashlabs.io/crashlabs/huskies/releases">releases page</a> or copy it from the repository's <code>docker/</code> directory.
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
<strong>Set your API key.</strong> Create a <code>.env</code> file next to the compose file:
|
||||||
|
<pre><code>ANTHROPIC_API_KEY=sk-ant-...</code></pre>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
<strong>Mount your project.</strong> Edit the compose file to mount your project directory:
|
||||||
|
<pre><code>volumes:
|
||||||
|
- /path/to/your/project:/workspace</code></pre>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
<strong>Start the server.</strong>
|
||||||
|
<pre><code>docker compose up</code></pre>
|
||||||
|
Open <a href="http://localhost:3000">http://localhost:3000</a> to see the pipeline board.
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2>Option B: Binary</h2>
|
||||||
|
<p>Download the pre-built binary for your platform from the <a href="https://code.crashlabs.io/crashlabs/huskies/releases">releases page</a> and place it somewhere on your <code>PATH</code>.</p>
|
||||||
|
|
||||||
|
<h3>macOS (Apple Silicon)</h3>
|
||||||
|
<pre><code>curl -L https://code.crashlabs.io/crashlabs/huskies/releases/download/latest/huskies-aarch64-apple-darwin \
|
||||||
|
-o /usr/local/bin/huskies
|
||||||
|
chmod +x /usr/local/bin/huskies</code></pre>
|
||||||
|
|
||||||
|
<h3>Linux (x86-64)</h3>
|
||||||
|
<pre><code>curl -L https://code.crashlabs.io/crashlabs/huskies/releases/download/latest/huskies-x86_64-unknown-linux-musl \
|
||||||
|
-o /usr/local/bin/huskies
|
||||||
|
chmod +x /usr/local/bin/huskies</code></pre>
|
||||||
|
|
||||||
|
<h2>Option C: Build from source</h2>
|
||||||
|
<p>Requires Rust (stable), Node.js, and npm.</p>
|
||||||
|
<pre><code>git clone https://code.crashlabs.io/crashlabs/huskies
|
||||||
|
cd huskies
|
||||||
|
cargo build --release
|
||||||
|
# Binary is at target/release/huskies</code></pre>
|
||||||
|
|
||||||
|
<h2>Initialise your project</h2>
|
||||||
|
<p>From your project directory, run the init command. This creates the <code>.huskies/</code> directory with the pipeline structure and configuration files.</p>
|
||||||
|
<pre><code>cd /path/to/your/project
|
||||||
|
huskies init --port 3000</code></pre>
|
||||||
|
<p>This creates:</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>.huskies/project.toml</code> — project-wide settings</li>
|
||||||
|
<li><code>.huskies/agents.toml</code> — agent definitions (coder, QA, mergemaster)</li>
|
||||||
|
<li><code>.huskies/work/</code> — the 6-stage pipeline directory</li>
|
||||||
|
<li><code>.mcp.json</code> — MCP server config for Claude Code integration</li>
|
||||||
|
<li><code>.huskies/specs/</code> — placeholder spec files for your project context</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="note">
|
||||||
|
<strong>Claude Code integration:</strong> The <code>.mcp.json</code> file automatically registers huskies' MCP tools with Claude Code. Open a Claude Code session in your project and it will discover tools like <code>create_story</code>, <code>start_agent</code>, and <code>get_pipeline_status</code> automatically.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Start the server</h2>
|
||||||
|
<pre><code>huskies --port 3000</code></pre>
|
||||||
|
<p>Open <a href="http://localhost:3000">http://localhost:3000</a> to see the pipeline board, agent status, and chat interface.</p>
|
||||||
|
|
||||||
|
<h2>Run the setup wizard</h2>
|
||||||
|
<p>Open a Claude Code session in your project directory (or use the web chat UI), and tell Claude:</p>
|
||||||
|
<pre><code>help me set up this project with huskies</code></pre>
|
||||||
|
<p>Claude will walk you through the setup wizard — generating project context (<code>specs/00_CONTEXT.md</code>), tech stack docs (<code>specs/tech/STACK.md</code>), and test/release scripts. Review each step and confirm or ask to retry.</p>
|
||||||
|
|
||||||
|
<h2>Create your first story</h2>
|
||||||
|
<p>In the chat UI or via a chat transport, type:</p>
|
||||||
|
<pre><code>I want to add a health check endpoint to the API</code></pre>
|
||||||
|
<p>Claude will create a story file in <code>.huskies/work/1_backlog/</code> with a user story and acceptance criteria. Review it, then move it to current:</p>
|
||||||
|
<pre><code>move <story-number> current</code></pre>
|
||||||
|
|
||||||
|
<h2>Start an agent</h2>
|
||||||
|
<p>Once a story is in <code>2_current/</code>, start a coding agent:</p>
|
||||||
|
<pre><code>start <story-number></code></pre>
|
||||||
|
<p>The agent creates an isolated git worktree, implements the feature against the acceptance criteria, runs quality gates (clippy, tests, biome), and exits. The server automatically advances the story to QA if all gates pass.</p>
|
||||||
|
|
||||||
|
<h2>Review and merge</h2>
|
||||||
|
<p>Once QA passes, the story moves to <code>4_merge/</code>. To merge:</p>
|
||||||
|
<pre><code>start <story-number></code></pre>
|
||||||
|
<p>The mergemaster agent resolves any conflicts and squash-merges to your main branch. The worktree is cleaned up automatically.</p>
|
||||||
|
|
||||||
|
<div class="note">
|
||||||
|
<strong>Tip:</strong> Use <code>status</code> in the chat at any time to see the current pipeline state, active agents, and their progress.
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="reveal r3">
|
||||||
|
<span>© 2026 Libby Labs Ltd.</span>
|
||||||
|
<a href="/privacy.html">Privacy Policy</a>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Chat Transports — Huskies Docs</title>
|
||||||
|
<meta name="description" content="Connect huskies to Matrix, WhatsApp, Slack, Discord, or the built-in web UI.">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600;700;800&family=Karla:ital,wght@0,300;0,400;0,500;1,300;1,400&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="docs.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<header class="reveal r1">
|
||||||
|
<a href="/" class="logo">huskies</a>
|
||||||
|
<nav>
|
||||||
|
<a href="/#how">How it works</a>
|
||||||
|
<a href="/#features">Features</a>
|
||||||
|
<a href="/docs/" class="active">Docs</a>
|
||||||
|
<a href="https://code.crashlabs.io/crashlabs/huskies">Source</a>
|
||||||
|
<a href="https://code.crashlabs.io/crashlabs/huskies/releases">Releases</a>
|
||||||
|
<a href="mailto:hello@huskies.dev" class="nav-cta">Get in touch</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<div class="docs-layout">
|
||||||
|
<aside class="sidebar reveal r2">
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Getting started</div>
|
||||||
|
<nav>
|
||||||
|
<a href="/docs/">Overview</a>
|
||||||
|
<a href="quickstart.html">Quickstart</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Reference</div>
|
||||||
|
<nav>
|
||||||
|
<a href="configuration.html">Configuration</a>
|
||||||
|
<a href="commands.html">Bot commands</a>
|
||||||
|
<a href="cli.html">CLI</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-section">
|
||||||
|
<div class="sidebar-heading">Guides</div>
|
||||||
|
<nav>
|
||||||
|
<a href="pipeline.html">Pipeline stages</a>
|
||||||
|
<a href="transports.html" class="active">Chat transports</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<main class="docs-main reveal r3">
|
||||||
|
<h1 class="page-title">Chat Transports</h1>
|
||||||
|
<p class="page-subtitle">Huskies can be controlled via bot commands in any of five transports. Only one external transport can be active at a time. The web UI is always available regardless.</p>
|
||||||
|
|
||||||
|
<div class="note">
|
||||||
|
<strong>Configuration:</strong> Copy the relevant example file to <code>.huskies/bot.toml</code> and fill in your credentials. The file is gitignored. Restart huskies after changes.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Web UI</h2>
|
||||||
|
<p>The built-in web interface is always available at <code>http://localhost:<port></code>. No configuration required. It provides:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Pipeline board showing all work items and their stages</li>
|
||||||
|
<li>Agent status panel with live output streaming</li>
|
||||||
|
<li>Chat interface for running commands and talking to Claude</li>
|
||||||
|
<li>Coverage and cost dashboards</li>
|
||||||
|
</ul>
|
||||||
|
<p>No <code>bot.toml</code> is required for the web UI. If no transport is configured, huskies runs in web-only mode.</p>
|
||||||
|
|
||||||
|
<h2>Matrix</h2>
|
||||||
|
<p>Matrix uses the Matrix Client-Server API with long-polling sync. No public webhook URL is required — the bot connects outbound to your homeserver.</p>
|
||||||
|
|
||||||
|
<h3>Setup</h3>
|
||||||
|
<ol class="step-list">
|
||||||
|
<li><div>Register a Matrix account for the bot on your homeserver (e.g. <code>@huskies:example.com</code>).</div></li>
|
||||||
|
<li><div>Invite the bot account to the rooms you want it to monitor.</div></li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
Copy the example config and fill in your credentials:
|
||||||
|
<pre><code>cp .huskies/bot.toml.matrix.example .huskies/bot.toml</code></pre>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h3>bot.toml fields</h3>
|
||||||
|
<table>
|
||||||
|
<thead><tr><th>Key</th><th>Description</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>homeserver</td><td>Your Matrix homeserver URL (e.g. <code>https://matrix.example.com</code>).</td></tr>
|
||||||
|
<tr><td>username</td><td>Bot account Matrix ID (e.g. <code>@huskies:example.com</code>).</td></tr>
|
||||||
|
<tr><td>password</td><td>Bot account password.</td></tr>
|
||||||
|
<tr><td>room_ids</td><td>List of room IDs to listen in (e.g. <code>["!roomid:example.com"]</code>).</td></tr>
|
||||||
|
<tr><td>allowed_users</td><td>Matrix IDs allowed to interact. Empty list means nobody — always set this.</td></tr>
|
||||||
|
<tr><td>ambient_rooms</td><td>Rooms where the bot responds to all messages (not just addressed ones). Updated automatically by <code>ambient on/off</code>.</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2>Slack</h2>
|
||||||
|
<p>Slack uses event subscriptions over a webhook. You'll need a public HTTPS URL pointing to your huskies server.</p>
|
||||||
|
|
||||||
|
<h3>Setup</h3>
|
||||||
|
<ol class="step-list">
|
||||||
|
<li><div>Create a Slack App at <a href="https://api.slack.com/apps">api.slack.com/apps</a>.</div></li>
|
||||||
|
<li><div>Add OAuth scopes: <code>chat:write</code>, <code>chat:update</code>.</div></li>
|
||||||
|
<li><div>Subscribe to bot events: <code>message.channels</code>, <code>message.groups</code>, <code>message.im</code>.</div></li>
|
||||||
|
<li><div>Install the app to your workspace and copy the bot token.</div></li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
Set your webhook URL in Event Subscriptions:
|
||||||
|
<code>https://your-server/webhook/slack</code>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
Copy the example config:
|
||||||
|
<pre><code>cp .huskies/bot.toml.slack.example .huskies/bot.toml</code></pre>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h3>bot.toml fields</h3>
|
||||||
|
<table>
|
||||||
|
<thead><tr><th>Key</th><th>Description</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>slack_bot_token</td><td>OAuth bot token starting with <code>xoxb-</code>.</td></tr>
|
||||||
|
<tr><td>slack_signing_secret</td><td>Signing secret from the app's Basic Information page.</td></tr>
|
||||||
|
<tr><td>slack_channel_ids</td><td>List of channel IDs to listen in (e.g. <code>["C01ABCDEF"]</code>).</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2>WhatsApp (Meta Cloud API)</h2>
|
||||||
|
<p>Connects huskies to WhatsApp Business via the Meta Cloud API. Requires a Meta Business account and a public webhook URL.</p>
|
||||||
|
|
||||||
|
<h3>Setup</h3>
|
||||||
|
<ol class="step-list">
|
||||||
|
<li><div>Create a Meta Business App at <a href="https://developers.facebook.com">developers.facebook.com</a>.</div></li>
|
||||||
|
<li><div>Add the WhatsApp product and get a Phone Number ID.</div></li>
|
||||||
|
<li><div>Generate a permanent access token.</div></li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
Register your webhook URL in Meta's dashboard:
|
||||||
|
<code>https://your-server/webhook/whatsapp</code>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
Copy the example config:
|
||||||
|
<pre><code>cp .huskies/bot.toml.whatsapp-meta.example .huskies/bot.toml</code></pre>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h3>bot.toml fields</h3>
|
||||||
|
<table>
|
||||||
|
<thead><tr><th>Key</th><th>Description</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>whatsapp_provider</td><td>Set to <code>"meta"</code> for the Meta Cloud API.</td></tr>
|
||||||
|
<tr><td>whatsapp_phone_number_id</td><td>Phone Number ID from the Meta dashboard.</td></tr>
|
||||||
|
<tr><td>whatsapp_access_token</td><td>Permanent access token.</td></tr>
|
||||||
|
<tr><td>whatsapp_verify_token</td><td>Webhook verify token — must match what you set in Meta's dashboard.</td></tr>
|
||||||
|
<tr><td>whatsapp_allowed_phones</td><td>Optional. List of phone numbers allowed to interact (e.g. <code>["+15551234567"]</code>). When absent, all numbers are allowed.</td></tr>
|
||||||
|
<tr><td>whatsapp_notification_template</td><td>Optional. Name of the approved Meta message template for out-of-window notifications (default: <code>"pipeline_notification"</code>).</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2>WhatsApp (Twilio)</h2>
|
||||||
|
<p>An alternative WhatsApp integration using Twilio's WhatsApp API. Requires a Twilio account.</p>
|
||||||
|
<pre><code>cp .huskies/bot.toml.whatsapp-twilio.example .huskies/bot.toml</code></pre>
|
||||||
|
<p>Set <code>whatsapp_provider = "twilio"</code> and fill in your Twilio account SID, auth token, and phone numbers. The webhook URL is the same: <code>https://your-server/webhook/whatsapp</code>.</p>
|
||||||
|
|
||||||
|
<h2>Discord</h2>
|
||||||
|
<p>Connects huskies to Discord using the Discord Gateway WebSocket. No public webhook URL required — the bot connects outbound.</p>
|
||||||
|
|
||||||
|
<h3>Setup</h3>
|
||||||
|
<ol class="step-list">
|
||||||
|
<li><div>Create a Discord Application at <a href="https://discord.com/developers/applications">discord.com/developers/applications</a>.</div></li>
|
||||||
|
<li><div>Go to Bot, create a bot, and copy the token.</div></li>
|
||||||
|
<li><div>Enable <strong>Message Content Intent</strong> under Privileged Gateway Intents.</div></li>
|
||||||
|
<li><div>Go to OAuth2 → URL Generator, select the <code>bot</code> scope with permissions: Send Messages, Read Message History, Manage Messages.</div></li>
|
||||||
|
<li><div>Use the generated URL to invite the bot to your server.</div></li>
|
||||||
|
<li><div>Right-click target channels → Copy Channel ID (requires Developer Mode enabled in Discord settings).</div></li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
Copy the example config:
|
||||||
|
<pre><code>cp .huskies/bot.toml.discord.example .huskies/bot.toml</code></pre>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h3>bot.toml fields</h3>
|
||||||
|
<table>
|
||||||
|
<thead><tr><th>Key</th><th>Description</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>discord_bot_token</td><td>Bot token from the Discord developer portal.</td></tr>
|
||||||
|
<tr><td>discord_channel_ids</td><td>List of channel IDs to listen in (e.g. <code>["123456789012345678"]</code>).</td></tr>
|
||||||
|
<tr><td>discord_allowed_users</td><td>Optional. Discord user IDs allowed to interact. When absent, all users in configured channels can interact.</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="reveal r3">
|
||||||
|
<span>© 2026 Libby Labs Ltd.</span>
|
||||||
|
<a href="/privacy.html">Privacy Policy</a>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
<nav>
|
<nav>
|
||||||
<a href="#how">How it works</a>
|
<a href="#how">How it works</a>
|
||||||
<a href="#features">Features</a>
|
<a href="#features">Features</a>
|
||||||
|
<a href="/docs/">Docs</a>
|
||||||
<a href="https://code.crashlabs.io/crashlabs/huskies">Source</a>
|
<a href="https://code.crashlabs.io/crashlabs/huskies">Source</a>
|
||||||
<a href="https://code.crashlabs.io/crashlabs/huskies/releases">Releases</a>
|
<a href="https://code.crashlabs.io/crashlabs/huskies/releases">Releases</a>
|
||||||
<a href="mailto:hello@huskies.dev" class="nav-cta">Get in touch</a>
|
<a href="mailto:hello@huskies.dev" class="nav-cta">Get in touch</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user