170 lines
5.9 KiB
Markdown
170 lines
5.9 KiB
Markdown
# Huskies
|
|
|
|
A story-driven development server that manages work items, spawns coding agents, and runs them through a pipeline from backlog to done. Ships as a single Rust binary with an embedded React frontend.
|
|
|
|
## Getting started with Claude Code
|
|
|
|
1. Download the huskies binary (or build from source — see below).
|
|
|
|
2. From your project directory, scaffold and start the server:
|
|
|
|
```bash
|
|
huskies init --port 3000
|
|
```
|
|
|
|
This creates a `.huskies/` directory with the pipeline structure, `project.toml`, and `.mcp.json`. The `.mcp.json` file lets Claude Code discover huskies' MCP tools automatically.
|
|
|
|
Huskies also ships an embedded React frontend. Once the server is running, open `http://localhost:3000` to see the pipeline board, agent status, and chat interface.
|
|
|
|
3. Open a Claude Code session in the same project directory, or visit http://localhost:3000/.
|
|
|
|
4. Tell Claude: "help me set up this project with huskies." Claude will walk you through the setup wizard — generating project context, tech stack docs, and test/release scripts. Review each step and confirm or ask to retry.
|
|
|
|
Once setup is complete, Claude can create stories, start agents, check status, and manage the full pipeline via MCP tools — no commands to memorize.
|
|
|
|
## Chat transports
|
|
|
|
Huskies can be controlled via bot commands in **Matrix**, **WhatsApp**, and **Slack**. Configure a transport in `.huskies/bot.toml` — see the example files:
|
|
|
|
- `.huskies/bot.toml.matrix.example`
|
|
- `.huskies/bot.toml.whatsapp-meta.example`
|
|
- `.huskies/bot.toml.whatsapp-twilio.example`
|
|
- `.huskies/bot.toml.slack.example`
|
|
|
|
## Prerequisites for building
|
|
|
|
- Rust (2024 edition)
|
|
- Node.js and npm
|
|
- Docker (for Linux cross-compilation and container deployment)
|
|
- `cross` (`cargo install cross`) optional, for Linux static builds. Only needed if you are building for a different architecture, e.g. if you want to build a Linux binary from a Mac.
|
|
|
|
You only need these installed if you want to build Huskies yourself. Alternately, you can just download and run the `huskies` binary for your system from https://code.crashlabs.io/crashlabs/huskies/releases
|
|
|
|
## Building for production
|
|
|
|
```bash
|
|
cargo build --release
|
|
```
|
|
|
|
The release binary embeds the frontend via `rust-embed`. Output: `target/release/huskies`.
|
|
|
|
For a static Linux binary (musl, zero dynamic deps):
|
|
|
|
```bash
|
|
cross build --release --target x86_64-unknown-linux-musl
|
|
```
|
|
|
|
Docker:
|
|
|
|
```bash
|
|
script/docker_rebuild
|
|
|
|
# or
|
|
|
|
script/docker_restart
|
|
```
|
|
|
|
## Running in development
|
|
|
|
```bash
|
|
# Run tests
|
|
script/test
|
|
|
|
# Run the server
|
|
cargo run -- --port 3000
|
|
|
|
# In another terminal, run the frontend dev server
|
|
cd frontend && npm install && npm run dev
|
|
```
|
|
|
|
Configuration lives in `.huskies/project.toml`. See `.huskies/bot.toml.*.example` for transport setup.
|
|
|
|
## Releasing
|
|
|
|
Requires a Gitea API token in `.env` (`GITEA_TOKEN=your_token`).
|
|
|
|
```bash
|
|
script/release 0.7.1
|
|
```
|
|
|
|
This bumps version in `Cargo.toml` and `package.json`, builds macOS arm64 and Linux amd64 binaries, tags the repo, and publishes a Gitea release with changelog and binaries attached.
|
|
|
|
## Startup reconcile pass
|
|
|
|
On startup, after CRDT replay and database initialisation, huskies runs a
|
|
**reconcile pass** that compares pipeline state across three sources:
|
|
|
|
1. **In-memory CRDT** — the primary source of truth, reconstructed from
|
|
`crdt_ops` on startup.
|
|
2. **`pipeline_items` table** — a shadow/materialised view written alongside
|
|
CRDT updates, used for fast DB queries.
|
|
3. **Filesystem shadows** (`.huskies/work/N_stage/*.md`) — legacy rendering
|
|
still written by some paths and read by agent worktrees.
|
|
|
|
Any disagreement between these sources is **drift**. The reconcile pass logs a
|
|
structured line for each drifted item:
|
|
|
|
```
|
|
[reconcile] DRIFT story=X crdt_stage=Y db_stage=Z fs_stage=W
|
|
```
|
|
|
|
(`MISSING` is used where a source has no record for that story.)
|
|
|
|
### Drift types
|
|
|
|
| Type | Meaning |
|
|
|------|---------|
|
|
| `CRDT-only` | Story present in CRDT but absent from `pipeline_items` |
|
|
| `DB-only` | Story present in `pipeline_items` but absent from CRDT |
|
|
| `FS-only` | Story on the filesystem but absent from both CRDT and DB |
|
|
| `stage-mismatch` | Story present in both CRDT and DB but with different stage values |
|
|
|
|
Note: a filesystem shadow that lags behind the CRDT/DB stage (both of which
|
|
agree) is **not** treated as drift — the FS is a best-effort rendering and is
|
|
allowed to lag.
|
|
|
|
If any drift is detected, the Matrix/Slack/WhatsApp bot startup announcement
|
|
includes a count and a suggestion to check the server logs.
|
|
|
|
### Opt-out
|
|
|
|
Set `reconcile_on_startup = false` in `.huskies/project.toml` to disable the
|
|
pass during the migration window if it produces noise.
|
|
## Debugging
|
|
|
|
### Inspecting the in-memory CRDT state
|
|
|
|
When diagnosing state issues, use the `dump_crdt` MCP tool or the `/debug/crdt` HTTP endpoint to inspect the raw in-memory CRDT state directly. These surfaces show the ground truth that the running server holds — not a summarised pipeline view and not the persisted SQLite ops.
|
|
|
|
**MCP tool** (from Claude Code or any MCP client):
|
|
|
|
```
|
|
mcp__huskies__dump_crdt
|
|
# dump everything
|
|
{}
|
|
|
|
# restrict to a single item
|
|
{"story_id": "42_story_my_feature"}
|
|
```
|
|
|
|
**HTTP endpoint** (browser or curl):
|
|
|
|
```bash
|
|
# dump everything
|
|
curl http://localhost:3001/debug/crdt
|
|
|
|
# restrict to a single item
|
|
curl "http://localhost:3001/debug/crdt?story_id=42_story_my_feature"
|
|
```
|
|
|
|
Both return a JSON document with:
|
|
|
|
- **`metadata`** — `in_memory_state_loaded`, `total_items`, `total_ops_in_list`, `max_seq_in_list`, `persisted_ops_count`, `pending_persist_ops_count`
|
|
- **`items`** — one entry per CRDT list item (including tombstoned/deleted entries), each with `story_id`, `stage`, `name`, `agent`, `retry_count`, `blocked`, `depends_on`, `content_index` (hex OpId for cross-referencing with `crdt_ops`), and `is_deleted`
|
|
|
|
> **This is a debug tool.** For normal pipeline introspection use `get_pipeline_status` or `GET /api/pipeline` instead.
|
|
|
|
## License
|
|
|
|
GPL-3.0. See [LICENSE](LICENSE).
|