Operator brief (#394): the header had thirteen distinct visual elements in one flex row with three different border-radius languages, four colour treatments, three label styles. Mara's direction: - agent icon bigger (full header height) as the identity anchor - title glow stays - nav links lose their default-anchor underline - overflow `⋯` absorbs `↻ R3BU1LD` + `↻ new session` (rare, destructive — both worth one extra click; rebuild is normally done from the dashboard) - accent stacking in the state strip stays — that's the vibe ## Layout shape Three flex columns in `.agent-header`: [icon · full height] [main column · 2 rows] [pills + ⋯] The main column carries row 1 (`◆ AGENT ◆` title + meta-nav) on top and row 2 (alive · state · model · ctx · cost · last-turn · cancel-turn) below. ## Changes ### `index.html` - Wrap title + nav in `.agent-header-row .agent-header-title-row`; wrap state-row siblings in `.agent-header-row .agent-state-row`; both go inside a new `.agent-header-main` column. - Right cluster `.agent-header-pills` contains the inbox + loose pills + a new `<button id="overflow-btn">⋯</button>` trigger. - Drop static `#new-session-btn` from `#state-row` — moved into the overflow menu, populated dynamically. - Add `<div id="overflow-menu" role="menu" hidden>` as a sibling of `<header>` (lives outside the header so its `position: fixed` popover isn't trapped by any header stacking context). ### `agent.css` - `--agent-header-h: 4.6em → 6em` so the icon can be square + full height without crowding the two-row main column. Terminal padding-top + status overlay top + tail-pill all derive from this variable, so they follow automatically. - `.agent-header { align-items: stretch }` lets the icon stretch to full height; `.agent-icon { height: 100%; aspect-ratio: 1 }` sizes it as a square off the stretched height. - `.agent-nav-link` rule added — `text-decoration: none`, cyan + soft glow, hover lights brighter (mara's spec). - `.overflow-btn` (round trigger) + `.overflow-menu` (frosted popover, fixed-position) + `.overflow-item` (rows with an icon column + label, hover ink matches per-action accent — cyan for dashboard, amber for rebuild/new-session). - Remove the old `#state-row` selector (layout now provided by `.agent-state-row` + `.agent-header-row`). ### `app.js` - `setHeader` no longer appends DASHB04RD / R3BU1LD chips into the title — title is just the identity glyph now. Both actions get rendered into the overflow menu by `populateOverflowMenu()`. - `populateOverflowMenu(label, dashUrl)` builds three rows: `↑ dashboard` (anchor), `↻ rebuild container` (button — same POST-form action as before), `↻ new claude session` (button — same `/api/new-session` call as the legacy header button). - Overflow toggle / outside-click / Escape dismissal — same pattern as the side-panel flyout (`Panel`). - Drop the static `new-session-btn` IIFE binder; the dynamically- rendered menu item owns its handler now. - Drop the per-nav-link inline `marginLeft` (layout gap comes from the new `.agent-nav { gap }` rule). ## Validation - `npm run build` clean. - Build deltas: agent.css 21.0kb → 23.6kb (overflow + nav rules + comments), app.js 117.4kb → 118.9kb (menu builder + toggle). - Browser smoke test isn't possible from inside iris's container. Worth eyeballing post-deploy: - Icon fills the full header height as a square - Title glow + uppercase styling preserved - Nav links render without underline; hover lights brighter - `⋯` opens a frosted popover with `↑ dashboard`, `↻ rebuild container`, `↻ new claude session` - Rebuild confirm + POST works the same as the legacy chip - New-session confirm + POST works the same as the legacy button - State strip still wraps when crowded (model/ctx/cost multi-line on narrow viewports) - Cancel-turn button still appears while thinking and clears on turn end - Terminal padding-top adjusts to the new 6em header height (no row hidden under the chrome) |
||
|---|---|---|
| branding | ||
| docs | ||
| frontend | ||
| hive-ag3nt | ||
| hive-c0re | ||
| hive-sh4re | ||
| nix | ||
| scripts | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CLAUDE.md | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
| TODO.md | ||
hyperhive
a swarm of claude-code agents, each in its own nspawn cage, gossiping over unix sockets. config changes flow as git commits, the operator approves them in a browser, every deploy is a tag. cyberpunk-themed dashboard included. 💜⚡
Claude code is great in one window, exponentielle across many — but only if you can keep the agents from stepping on each other, give them durable identity, and stop them from eating production. hyperhive is the substrate.
- identity = unix socket
- communication = sqlite-backed broker (
send/recv/ask/answer/remind) - config = git (manager proposes, operator approves, deploys land as tagged commits)
- blast radius = container
host (NixOS, runs hive-c0re.service)
│
├── operator
│ ├── browser → :7000 hive-c0re dashboard
│ ├── browser → :8000 / :8100-8999 per-agent web UIs
│ └── CLI → /run/hyperhive/host.sock admin protocol
│
├── hive-c0re (Rust daemon: lifecycle / broker / approvals /
│ auto-update / dashboard / sockets)
│
└── nixos-containers
├── hm1nd manager agent (privileged MCP surface)
└── h-<name> sub-agent (vanilla MCP surface + per-agent extras)
Depth lives in docs/ — pick the one matching your task:
| reading path | doc |
|---|---|
| dashboard layout + endpoints | docs/web-ui.md |
| claude turn loop + MCP tools | docs/turn-loop.md |
| config-edit + approval state machine | docs/approvals.md |
| what survives destroy / purge / restart | docs/persistence.md |
| naming, wire protocol, commit style | docs/conventions.md |
| NixOS / nspawn gotchas | docs/gotchas.md |
Host config
Minimal flake.nix for a host that runs hive-c0re:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
hyperhive.url = "git+https://git.berlin.ccc.de/vinzenz/hyperhive";
};
outputs = { nixpkgs, hyperhive, ... }: {
nixosConfigurations.my-host = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
hyperhive.nixosModules.default # hive-c0re + hive-forge in one import
({ ... }: {
services.hive-c0re.enable = true;
# services.hive-c0re.operatorPronouns = "they/them"; # default: "she/her"
# ... rest of your host config
system.stateVersion = "25.11";
})
];
};
};
}
hive-c0re opens its admin socket + dashboard, auto-creates the
manager container, and auto-rebuilds any container whose hyperhive
rev goes stale. claude-code is unfree — hyperhive scopes the
whitelist to itself, nothing for the operator to set.
Agent configuration
Per-agent settings live in each agent's agent.nix and are synced to
the container as environment variables. Common options:
hyperhive.model— Claude model for this agent (default:"haiku"). SetsHIVE_DEFAULT_MODELin the container; the harness applies it at boot and it takes priority over any persisted runtime override. The operator can still switch the model at runtime via the per-agent web UI, but that choice is reset by any rebuild that changes this option.hyperhive.allowedRecipients— List of agent names this agent can message (viasend). If unset, all agents are allowed. Useful to restrict an agent to talking only to the manager.hyperhive.forge.url— Base URL of the hyperhive-managed Forgejo (default:"http://localhost:3000"). Used to configure the agent's tea login at boot; no-op if/state/forge-tokenis missing.hyperhive.forge.keepSubscriptions— Boolean. Iftrue, the agent's forge repo subscriptions are never auto-cleaned during rebuild; useful for agents that want to watch specific repos. Rendered asHIVE_FORGE_KEEP_SUBSCRIPTIONS.hyperhive.forge.skipNotifyReasons— List of forge notificationreasonvalues to suppress (e.g.[ "subscribed" "participating" ]). Notifications matching these reasons are silently dropped; all others including direct mentions and reviews are delivered. Empty list (default) delivers all notifications. Rendered asHIVE_FORGE_NOTIFY_SKIP_REASONS(comma-separated).hyperhive.frontend.dist— Override the default frontend package (pkgs.hyperhive-frontend, built bynix/frontend.nix). Set to a custom derivation to ship a fully custom per-agent SPA. The JSON contract (/api/state,/events/stream, action endpoints) is the source of truth for any replacement.hyperhive.frontend.extraFiles— Attrset of extra files/directories to layer on top of the default agent dist. Each entry has asource(nix path) and an optionaltarget(URL prefix in the static tree, defaults to the attribute name). Example:{ bitburner.source = ./bitburner-dist; }serves that dist at/bitburner/. Pure additions only — overwriting an existing default file is a hard eval-time error; usefrontend.distto replace the whole dist. Paths with leading/or..segments are rejected at eval time.
See nix/templates/harness-base.nix for the full list of options and
their descriptions.
Build / deploy
nix develop -c cargo check
nix flake check # rust + nix + toml fmt + clippy
# deploy from a host config that imports hyperhive.nixosModules.hive-c0re
nix flake update --update-input hyperhive
sudo nixos-rebuild switch --flake .#<host>