Commit graph

42 commits

Author SHA1 Message Date
müde
411cf86632 nix fmt + rustfmt sweep 2026-05-17 01:40:28 +02:00
müde
0cf120e9e9 harness: default claudeMarketplaces to anthropics/claude-plugins-official
so every agent has the official Anthropic marketplace registered
out of the box and plugin specs like 'foo@claude-plugins-official'
resolve without per-agent.nix wiring. operators add more entries
(community marketplace, etc.) or override to [] to opt out.
2026-05-17 01:38:29 +02:00
müde
597351ca4e harness: declarative claude plugin marketplaces
new `hyperhive.claudeMarketplaces` option (list of strings — URL,
path, or github:owner/repo). harness boot adds each via
`claude plugin marketplace add` before updating + installing the
configured plugins, so specs like `foo@some-marketplace` resolve
on a fresh container. idempotent: 'already exists' stderr is
treated as success.
2026-05-17 01:36:18 +02:00
müde
608de57924 hive-forge: default to pkgs.forgejo (15.x), expose package option
nixpkgs's services.forgejo defaults to forgejo-lts (11.0.13 today);
LTS lags far enough behind that any prior non-LTS run against the
same state dir leaves the DB at a migration the LTS binary can't
read ('database newer than binary, refusing to start'). default to
the latest release line and let operators opt down to LTS by
overriding services.hive-forge.package.
2026-05-17 01:29:19 +02:00
müde
fed943a04e hive-forge: pin F3 PATH absolute (init runs even when disabled)
forgejo's F3 init resolves data-dir before checking ENABLED, so
`forgejo admin user create` still fataled on the RO nix-store
default. set [F3] PATH = /var/lib/forgejo/data/f3 alongside the
disable.
2026-05-17 00:25:55 +02:00
müde
3e3c27ac48 hive-forge: disable F3 (federation) — defaults to RO nix-store path
forgejo's F3 federation subsystem resolves its data dir relative to
the binary, which under nixos lands at /run/current-system/sw/bin/data/f3
(read-only nix store) and fatals the daemon at boot. we don't
federate; turn it off.
2026-05-17 00:03:41 +02:00
müde
4a06615c5c fix /state paths: sub-agents use /agents/<name>/state, not /state
sub-agent containers post-refactor bind their state at
/agents/<name>/state (manager keeps the legacy /state — see
lifecycle.rs:751). agent.md still said /state/forge-token; corrected
to /agents/{label}/state/forge-token (template-substituted at
boot). tea-login systemd unit now walks both candidates so the same
harness module works for the manager and sub-agents.
2026-05-16 23:37:49 +02:00
müde
787c058c71 harness: install tea + auto-login from /state/forge-token
agents get `pkgs.tea` (gitea/forgejo CLI) and a tea-login oneshot
that runs `tea login add --url <hyperhive.forge.url> --token
$(cat /state/forge-token)` before the harness starts. idempotent:
exits 0 when the token file is absent (hive-forge not on) or when
~/.config/tea/config.yml already exists. new
`hyperhive.forge.url` option (default http://localhost:3000) so
operators can point at a non-default forge port. claude can now
shell out to `tea repos create`, `tea pulls create`, etc.
2026-05-16 23:35:28 +02:00
müde
6e9c67dd94 hive-forge: wrap forgejo in a nixos-container
avoids fighting an operator-side `services.forgejo` over the
singleton module options. container shares host netns
(`privateNetwork = false`) so agents still dial the forge via
plain `localhost:<httpPort>` and the host firewall is the only
layer that matters. container name is `hive-forge` (no `h-`
prefix) so hive-c0re's lifecycle scanner ignores it — operator
manages it with the standard `nixos-container` CLI. state lives
at `/var/lib/nixos-containers/hive-forge/var/lib/forgejo/` and
survives restarts.
2026-05-16 20:52:36 +02:00
müde
c2d176ed13 add hive-forge module: private forgejo for agents
new `services.hive-forge.enable` (off by default) wraps
`services.forgejo` with hyperhive-friendly defaults: sqlite (no
extra db service), built-in ssh on 2222 so it doesn't fight the
host's openssh, http on 3000 (outside hyperhive's 7000/8000/8100-8999
ranges), registration off (operator seeds agent users), private
repos by default. exported as `nixosModules.hive-forge` — operator
imports it on the host alongside hive-c0re. container-side wiring
(MCP tools or a bind-mounted token) is deferred; containers already
share the host netns so they can reach http://localhost:3000 today.
2026-05-16 20:50:36 +02:00
müde
6dd17864ac auto-install claude plugins at harness boot
new hyperhive.claudePlugins NixOS option (list of strings) rendered
to /etc/hyperhive/claude-plugins.json. both hive-ag3nt and hive-m1nd
shell out 'claude plugin install <spec>' for each entry once at
startup before the turn loop opens. failures log a warning but don't
abort boot.
2026-05-16 15:17:34 +02:00
müde
67e4242b9f per-agent send allow-list via hyperhive.allowedRecipients
new NixOS option in harness-base.nix:
  hyperhive.allowedRecipients = [ 'alice' 'manager' ];  # whitelist
  hyperhive.allowedRecipients = [ ];                    # default = unrestricted

module writes the list as JSON to /etc/hyperhive/send-allow
.json at activation. AgentServer::send reads the file before
issuing the broker request; if the list is non-empty and
`to` isn't on it, the tool returns a claude-readable refusal
string without touching the broker. the manager is always
implicitly permitted regardless of the list — otherwise a
misconfigured allow-list could strand a sub-agent without an
escalation path.

enforcement is in the in-container MCP server (not on the
host's per-agent socket) because the agent's nix config is the
trust boundary anyway — the operator audits agent.nix at
deploy time, the activation-time /etc/hyperhive/send-allow
.json is r/o under /nix/store, so the agent can't tamper at
runtime without going through a new approval.

agent prompt mentions the option + tells claude to route
through the manager when refused. retires the matching TODO
under Permissions / policy.
2026-05-16 03:59:28 +02:00
müde
66a69d0c7f harness-base: wrap config attributes after introducing options
mixing options.* with bare config-level attributes (boot.*, environment.*, etc.) at the same level isn't supported once the module declares any options — nix needs them under an explicit 'config = { ... }' block. error from the host: 'unsupported attribute boot. caused by introducing top-level options'. wrap accordingly.
2026-05-16 02:17:15 +02:00
müde
7d6d8e96c1 per-agent extra MCP servers via hyperhive.extraMcpServers
new NixOS option in harness-base.nix:
  hyperhive.extraMcpServers.<key> = {
    command = "/path/to/server";
    args = [ ... ];
    env = { KEY = "value"; };
    allowedTools = [ "send_message" "join_room" ];  # or ["*"]
  };

declared as attrsOf submodule so agents stack arbitrarily many.
the module writes the whole map as JSON to
/etc/hyperhive/extra-mcp.json at activation; the harness reads
that file in mcp::render_claude_config and merges each entry
into the rendered --mcp-config under its own mcpServers.<key>
block. allowed_mcp_tools(flavor) extends the --allowedTools
arg with mcp__<key>__<pattern> for every entry — "*" (the
default) becomes mcp__<key>__* so every tool from that server
is auto-approved, or pass a concrete list to tighten.

collision guard: an extra server keyed "hyperhive" is dropped
with a warn-log so user config can't shadow the built-in
surface. malformed JSON / missing file fall back to "no
extras" silently.

prompt note added: agents see "(some agents only) extra MCP
tools surfaced as mcp__<server>__<tool>" and learn they're
declared via agent.nix. retires the matching TODO under
Per-agent extension. matrix-chat agents + bitburner-agent
migration unblocked.
2026-05-16 02:10:11 +02:00
müde
50ef806266 operator pronouns: configurable free-text, threaded into prompts
new NixOS module option services.hive-c0re.operatorPronouns
(free text, default 'she/her', example 'they/them'). hive-c0re
takes it as a CLI flag (--operator-pronouns, lib.escapeShellArg'd
in the systemd unit), stores it on Coordinator, threads it into
the meta flake's mkAgent so each agent's systemd service gets
HIVE_OPERATOR_PRONOUNS set. the harness reads the env at boot
and substitutes {operator_pronouns} into the agent / manager
system prompt alongside {label}. nix string is escaped against
backslash + double-quote so non-ascii / quoted values
round-trip safely. prompt addendum: both agent.md and
manager.md mention the operator's pronouns up front so claude
uses them naturally in third-person reference. propagates on
next ↻ R3BU1LD (meta lock bump, no per-agent approval).
2026-05-16 02:05:22 +02:00
müde
62d1a74929 docs sync + revert auto-unfree removal
revert the earlier 'operator must set allowUnfree' move:
per-agent containers evaluate their own nixpkgs and the operator's
host-level allowUnfree doesn't propagate in. restoring the scoped
allowUnfreePredicate inside both the claude-unstable overlay and
harness-base.nix; documented in README + gotchas as 'nothing to
set on the operator side'.

docs:
- claude.md file map adds crash_watch.rs, kick_agent on coordinator,
  /api/model + journald viewer + bind-with-retry references.
- scratchpad rewritten to reflect the recent run.
- web-ui.md: notification row + browser notifications section,
  state row (badge + model chip + last-turn chip + cancel button),
  per-agent inbox, /model slash, /cancel-question + journald
  endpoints, focus-preservation on refresh.
- turn-loop.md: --model is read from Bus::model() per turn (runtime
  override via /model); recv(wait_seconds) up to 180s with the
  rationale; ask_operator gains ttl_seconds; new TurnState section;
  kick_agent inbox-on-startup hint.
- approvals.md: ttl/cancel resolution paths for operator questions.
- persistence.md: /state/hyperhive-model file.
- gotchas.md: web UI port collision policy (rename, don't probe);
  bind retry + SO_REUSEADDR shape; auto-unfree restored.
- todo.md: cleaned up empty sections and stale entries; /model
  shipped, dropped from the list.
2026-05-15 21:26:13 +02:00
müde
8b9f7d21b7 model persisted to /state; stop auto-allowing claude-code unfree
model persistence: /model <name> now writes to /state/hyperhive-model
(in-container), Bus::new reads it on init. operator override survives
harness restart and container rebuild; gone on --purge like every
other piece of agent state. path overridable via HYPERHIVE_MODEL_FILE
for tests. failure to persist is a warn, not fatal — runtime override
still applies, just won't survive a restart.

unfree opt-in: drop the auto-allowUnfreePredicate from
harness-base.nix and the claude-unstable overlay. operator now has to
set nixpkgs.config.allowUnfree (or a predicate listing claude-code)
in their own host config. silent unfree bypass was sketchy; this is
honest. readme + gotchas updated to spell out the snippet.

todo: drops model-persistence + container-crash + journald (all
shipped); adds per-agent send allow-list (constrain who an agent can
message).
2026-05-15 21:05:40 +02:00
müde
300be8afa9 operator control: /cancel slash command + cancel button
new POST /api/cancel on the per-agent web UI: shells out
pkill -INT claude (procps added to harness-base.nix). emits a Note
on the bus so the operator sees the cancel landed; state goes back
to idle when run_claude wakes and emits TurnEnd as usual.

frontend:
- /cancel slash command in the terminal input
- ■ cancel turn button in the state row, visible only while
  state === 'thinking' (driven from the same SSE-based state
  machine). disabled briefly during the POST.

claude gets SIGINT (not TERM) so it flushes anything in-flight and
emits a final result row before exiting.
2026-05-15 19:45:37 +02:00
müde
070b237d03 docs: SPA pattern noted, todo cleared; harness-base git config mkDefault
programs.git.config.user.{name,email} in harness-base.nix now mkDefault
so the per-agent applied flake's override merges without mkForce.
2026-05-15 17:17:48 +02:00
müde
e2aa40409e module: default hyperhiveFlake to self — operator no longer sets it 2026-05-15 16:54:05 +02:00
müde
4f91dfef99 module: thread hyperhive package directly — operators don't apply overlays 2026-05-15 16:51:18 +02:00
müde
0f0e242906 programs.git.enable + harness PATH tracks systemPackages
- harness-base.nix: switch to programs.git for declarative gitconfig.
- agent + manager service path = /run/current-system/sw → agents pick up
  new packages from their own agent.nix without harness edits.
- generated applied/<name>/flake.nix overrides programs.git.config.user
  (no more raw etc.gitconfig collision).
2026-05-15 16:16:14 +02:00
müde
e1289a3e4c nix templates: factor harness-base.nix (shared scaffolding incl. gitconfig) 2026-05-15 16:10:55 +02:00
müde
cb62e15d4f containers: install bashInteractive + set SHELL for claude's Bash tool 2026-05-15 16:06:32 +02:00
müde
1cbfacda20 agent + manager: put claude-code on the harness service PATH 2026-05-15 13:14:28 +02:00
müde
7c1ed07cf2 lifecycle: HYPERHIVE_GIT env override (bypass PATH); module sets it 2026-05-15 00:24:51 +02:00
müde
42e7761ea1 module: include pkgs.git directly in service path 2026-05-15 00:19:16 +02:00
müde
9133d9e1a3 Phase 7b: broker broadcast + dashboard SSE message-flow tail; pkgs.git in module 2026-05-15 00:13:34 +02:00
müde
8cf5d72798 Phase 6b: vibec0re-styled dashboard on hive-c0re + agent web UI restyled 2026-05-14 23:43:20 +02:00
müde
d0f954bbc1 Phase 6a: per-container web UI (axum); per-agent port hashed from name 2026-05-14 23:39:06 +02:00
müde
da655d31c8 manager: /etc/gitconfig so commits in /agents work out of the box 2026-05-14 23:11:57 +02:00
müde
433c0d212e Phase 5b: per-agent config flakes; approve validates + advances commit 2026-05-14 23:09:35 +02:00
müde
17092961a2 Phase 4: hive-m1nd harness + manager nixos template; devshell sqlite 2026-05-14 22:36:34 +02:00
müde
2a98e3ca87 fmt 2026-05-14 22:27:03 +02:00
müde
6e7fd2e897 Phase 3c: nixpkgs-unstable for claude-code; harness calls claude --print, falls back to echo 2026-05-14 22:26:14 +02:00
müde
af464e27f4 rebuild re-registers agent; preserve /run/hyperhive across restarts 2026-05-14 22:13:00 +02:00
müde
746132d41e agent-base: boot.isNspawnContainer (required on 25.11+) 2026-05-14 22:10:18 +02:00
müde
61407f41c9 hive-ag3nt: serve loop + send/recv CLI; template runs serve 2026-05-14 21:44:05 +02:00
müde
11e999ca93 module: add /run/current-system/sw to service path for nixos-container 2026-05-14 21:24:37 +02:00
müde
e541f2ac70 module: expose hive-c0re CLI in environment.systemPackages 2026-05-14 21:21:10 +02:00
müde
b1b11cf17c module: serve subcommand + runtime/state dirs 2026-05-14 20:52:44 +02:00
müde
c67584c7c1 flake: expose hyperhive package + nixos module + agent-base container 2026-05-14 20:33:25 +02:00