feat(#2012): ship hyperhive docs as a nix asset + opt-in ~/.claude pointer

This commit is contained in:
damocles 2026-06-27 14:12:19 +02:00 committed by mara
commit 3fb5cb863b
3 changed files with 57 additions and 5 deletions

View file

@ -12,21 +12,28 @@
# Output layout: # Output layout:
# $out/share/hyperhive/branding/{hyperhive,agent-configs}.{svg,png} # $out/share/hyperhive/branding/{hyperhive,agent-configs}.{svg,png}
# $out/share/hyperhive/prompts/{system.md, claude-settings.json} # $out/share/hyperhive/prompts/{system.md, claude-settings.json}
# $out/share/hyperhive/docs/ — the repo docs/ tree
stdenv.mkDerivation { stdenv.mkDerivation {
pname = "hyperhive-assets"; pname = "hyperhive-assets";
version = "0.1.0"; version = "0.1.0";
# Narrow `srcs` (branding/ + hive-ag3nt/prompts/) is what decouples # Narrow `srcs` (branding/ + hive-ag3nt/prompts/ + docs/) is what
# this derivation's input hash from the rest of the tree. # decouples this derivation's input hash from the rest of the tree.
# Including docs/ surfaces the reference docs in-container at
# `$HIVE_ASSETS_DIR/docs/` (no host mount, pulled from the nix store);
# a docs/ edit re-hashes this asset, the accepted tradeoff for shipping
# the docs declaratively.
srcs = [ srcs = [
../branding ../branding
../hive-ag3nt/prompts ../hive-ag3nt/prompts
../docs
]; ];
unpackPhase = '' unpackPhase = ''
runHook preUnpack runHook preUnpack
cp -r ${../branding} branding cp -r ${../branding} branding
cp -r ${../hive-ag3nt/prompts} prompts cp -r ${../hive-ag3nt/prompts} prompts
chmod -R u+w branding prompts cp -r ${../docs} docs
chmod -R u+w branding prompts docs
runHook postUnpack runHook postUnpack
''; '';
@ -47,6 +54,7 @@ stdenv.mkDerivation {
mkdir -p $out/share/hyperhive mkdir -p $out/share/hyperhive
cp -r branding $out/share/hyperhive/branding cp -r branding $out/share/hyperhive/branding
cp -r prompts $out/share/hyperhive/prompts cp -r prompts $out/share/hyperhive/prompts
cp -r docs $out/share/hyperhive/docs
runHook postInstall runHook postInstall
''; '';
@ -54,7 +62,7 @@ stdenv.mkDerivation {
dontFixup = true; dontFixup = true;
meta = { meta = {
description = "hyperhive static assets (branding + claude prompts)"; description = "hyperhive static assets (branding + claude prompts + docs)";
homepage = "https://forge.darkest.space/hyperhive/hyperhive"; homepage = "https://forge.darkest.space/hyperhive/hyperhive";
license = lib.licenses.mit; license = lib.licenses.mit;
}; };

View file

@ -70,6 +70,24 @@ let
iconPng = pkgs.runCommand "hive-agent-icon.png" { nativeBuildInputs = [ pkgs.librsvg ]; } '' iconPng = pkgs.runCommand "hive-agent-icon.png" { nativeBuildInputs = [ pkgs.librsvg ]; } ''
rsvg-convert -f png -w 512 -h 512 ${config.hyperhive.icon} -o $out rsvg-convert -f png -w 512 -h 512 ${config.hyperhive.icon} -o $out
''; '';
# Generic, agent-agnostic `~/.claude/CLAUDE.md` installed when
# `hyperhive.docs.enable` is on (root/manager default-on; see
# `manager.nix`). claude auto-loads this user-global memory file every
# session, so it's the discovery hook for the docs asset — no
# per-agent prompt injection. It references the STABLE `$HIVE_ASSETS_DIR`
# env var (not the hashed nix-store path) which the agent resolves at
# read time.
docsClaudeMd = pkgs.writeText "hive-docs-claude.md" ''
# Hyperhive reference docs
The hyperhive subsystem docs ship read-only inside this container at
`$HIVE_ASSETS_DIR/docs/` (resolve the env var, e.g.
`ls "$HIVE_ASSETS_DIR/docs"`).
On a fresh deploy, read `$HIVE_ASSETS_DIR/docs/setup.md` first for the
first-run hive bootstrap commands (forge / gateway / matrix
provisioning, spawning the first sub-agents).
'';
in in
{ {
# Shared scaffolding for every hyperhive harness container. # Shared scaffolding for every hyperhive harness container.
@ -210,6 +228,18 @@ in
''; '';
}; };
options.hyperhive.docs.enable = lib.mkEnableOption ''
install a generic `~/.claude/CLAUDE.md` pointing this agent at the
hyperhive reference docs shipped read-only at `$HIVE_ASSETS_DIR/docs/`
(the repo `docs/` tree, packaged into the assets derivation). claude
auto-loads the file every session, so the docs are discoverable
without any per-agent prompt injection. The docs themselves are
always present at `$HIVE_ASSETS_DIR/docs/`; this option only controls
the auto-loaded pointer. Default-on for the root/manager agent (see
`manager.nix`), off elsewhere; any agent can flip it from its
`agent.nix`.
'';
options.hyperhive.allowedBashPatterns = lib.mkOption { options.hyperhive.allowedBashPatterns = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
default = [ ]; default = [ ];
@ -1011,6 +1041,14 @@ in
[ -d "$configDir" ] || continue [ -d "$configDir" ] || continue
chown -hR "$userName:$userName" "$configDir" 2>/dev/null || true chown -hR "$userName:$userName" "$configDir" 2>/dev/null || true
done done
${lib.optionalString config.hyperhive.docs.enable ''
# hyperhive.docs.enable: point this agent at the hyperhive docs
# via a managed `~/.claude/CLAUDE.md` (claude auto-loads it every
# session). Symlink → always reflects the current flake; the
# chown -h below sets the link's ownership.
mkdir -p "$homeDir/.claude"
ln -sfn ${docsClaudeMd} "$homeDir/.claude/CLAUDE.md"
''}
if [ -d "$homeDir/.claude" ]; then if [ -d "$homeDir/.claude" ]; then
chown -hR "$userName:$userName" "$homeDir/.claude" 2>/dev/null || true chown -hR "$userName:$userName" "$homeDir/.claude" 2>/dev/null || true
# 0755 so hive-core (a different unix user) can list the dir and # 0755 so hive-core (a different unix user) can list the dir and

View file

@ -1,7 +1,13 @@
{ ... }: { lib, ... }:
{ {
# Entry-point for the privileged root agent (ruth). Referenced from # Entry-point for the privileged root agent (ruth). Referenced from
# `flake.nix` (`nixosConfigurations.ruth`) and the meta-flake's # `flake.nix` (`nixosConfigurations.ruth`) and the meta-flake's
# `applied/ruth/flake.nix`. # `applied/ruth/flake.nix`.
imports = [ ./harness-base.nix ]; imports = [ ./harness-base.nix ];
# The root/manager bootstraps a fresh hive, so it gets the hyperhive
# reference docs surfaced by default (the `~/.claude/CLAUDE.md` pointer
# → `$HIVE_ASSETS_DIR/docs/setup.md`). `mkDefault` so a manager's own
# `agent.nix` can still turn it off. Other agents default off.
hyperhive.docs.enable = lib.mkDefault true;
} }