Skip to content

Latest commit

 

History

History
172 lines (161 loc) · 12.8 KB

AGENTS.md

File metadata and controls

172 lines (161 loc) · 12.8 KB

AGENTS.md — IceDOS ai-tools

Utilizes the IceDOS framework. The full bible — module structure, config flow, the icedos rebuild --build test loop, validate.* helpers, dep loading — lives in core: https://github.com/IceDOS/core/blob/main/AGENTS.md — this file only covers what is specific to ai-tools.

Non-negotiable rules (full detail in core)

  • Build/test only via the icedos CLI — never sudo nixos-rebuild.
  • Never git commit/stash/reset/pull — the user manages git.
  • Every option uses a validate.*/mk*Option helper; no untyped options.
  • Option-path segments that hold other options are kebab-case (agent-bridge); only leaf value keys are camelCase (remoteLookup).
  • A module's config.toml defaults must mirror its icedos.nix defaults.
  • Format with icedos nixf . after editing any .nix.

Purpose

AI agents, local model servers and their glue: claude-code, antigravity, opencode, prime-agent (agents), llamacpp, ollama (model servers), peon-ping (agent-event audio), mcp-server (icedos mcp serve), one module per MCP server (basic-memory-mcp, chrome-devtools-mcp, context7-mcp, ddev-mcp, kwin-mcp, nixos-mcp, opencart-mcp, pagespeed-insights-mcp, plesk-mcp, rea-mcp, signal-mcp), alimit (usage limits for every agent and provider), ai-accounts (several accounts per agent), agent-launch (fzf agent picker) and code-intelligence (per-language LSP skills).

Namespace

Every option here lives under icedos.ai-tools: the shared rules, skills and mcp-servers, and one attrset per module (icedos.ai-tools.prime-agent, ...).

Layout

modules/<category>/<name>/{icedos.nix,config.toml}; flake.nix exposes them via icedosLib.scanModules { path = ./modules; filename = "icedos.nix"; }, which recurses, and meta.name (not the folder) names the module. The categories are agents (antigravity, claude-code, opencode, prime-agent), models (llamacpp, ollama), mcp (one folder per MCP server: icedos-mcp, whose module name is mcp-server, and basic-memory, chrome-devtools, context7, ddev, kwin, nixos, opencart, pagespeed-insights, plesk, rea, signal, each named <folder>-mcp except kwin-mcp; mcp/lib holds their shared Nix helpers) and integrations (agent-launch, ai-accounts, alimit, code-intelligence, peon-ping). modules/default loads whenever the repo is listed and owns the shared options.

Shared options (icedos.ai-tools.*)

  • icedos.ai-tools.rules — name = markdown. prime-agent writes them all to <dataDir>/APPEND_SYSTEM.md, which 0.10.0 appends to every system prompt, antigravity writes ~/.gemini/config/rules/<name>.md, opencode writes ~/.config/opencode/rules/<name>.md and lists it in instructions, and claude-code sets programs.claude-code.rules (mkDefault per entry).
  • icedos.ai-tools.skills — name = full SKILL.md. Same fan-out: prime-agent skills.extra-builtin, antigravity ~/.gemini/antigravity-cli/skills/, opencode programs.opencode.skills, Claude Code programs.claude-code.skills. prime-agent bakes them into a wrapper layer over prime-agent.unwrapped, so skill edits never recompile Rust.
  • Per-agent options of the same name win over the shared entry (antigravity.{rules,skills}, opencode.skills, prime-agent.extensions.rules, prime-agent.skills.extra-builtin).
  • Non-agent modules (llamacpp, ollama, peon-ping and the mcp modules) have a skills option that adds to icedos.ai-tools.skills, so a skill ships with the module it documents.
  • icedos.ai-tools.mcp-servers — name = programs.mcp.servers entry. default gives every hm user these servers (mkDefault per entry, so a same-named programs.mcp.servers entry wins), which every agent module reads, and writes /etc/mcp/servers.json ({"mcpServers": ...}, remote ones with type = "http") for agents outside Home Manager.

MCP modules

  • Each one packages its server as a real derivation, puts it on the system PATH, registers it in mcp-servers under the server name agents already use (basic-memory, chrome-devtools, context7, ddev, icedos, kwin-mcp, nixos, opencart, pagespeed-insights, rea, signal-mcp) and ships its skills. plesk-mcp instead registers one plesk-<name> entry per servers.<name>, and its wrapper sources the credentials from PLESK_ENV_FILE, so they stay out of the store. opencart-mcp sources OPENCART_ENV_FILE (envFile) the same way, and pagespeed-insights-mcp reads GOOGLE_API_KEY from GOOGLE_API_KEY_FILE (apiKeyFile).
  • Skills that upstream ships come from the package source: upstreamSkills lists the names, lib/upstream-skills.nix reads SKILL.md and appends references/*.md. They read ${package.src} (pkgs.context7-mcp.src for context7), an IFD that only needs the fetch, so skills always match the packaged version. basic-memory builds from its GitHub release for this, since its wheel leaves out skills/. The module's own skills replaces an upstream skill of the same name.
  • lib/python.nix is Python 3 with the MCP Python SDK 2.x (nixpkgs ships 1.x), used by kwin-mcp and basic-memory-mcp; basic-memory-mcp adds the FastMCP release it pins on top. lib/python-bin.nix runs an entry point through python.withPackages, since kwin-mcp re-runs sys.executable -m kwin_mcp.* and needs its packages in the child.
  • rea-mcp, ddev-mcp and pagespeed-insights-mcp build the npm tarball with package-lock.json generated from the trimmed package.json their postPatch writes (rea drops frida, ddev drops its build tools). Each update.sh regenerates the lock with the same jq trim, so keep the two filters identical.
  • Pins not in nixpkgs live in JSON next to the package: source.json per server and lib/python-sdk.json for the SDK wheels. Each has an update.sh (lib/update-python-sdk.sh for the SDK) and an update-<module>.yml workflow over module-update.yml. kwin-mcp, opencart-mcp and signal-mcp track upstream main, which runs ahead of their tags; basic-memory follows its latest release and the exact FastMCP version its pyproject.toml pins.

Agent registry

agent-launch owns icedos.ai-tools.agent-launch.agents.<name> (command, label, resumeArgs, locator) and the agent-launch fzf picker. Every agent module lists it in meta.dependencies and registers itself there. Don't set zed.terminalInitCommand from an agent module: zed's agent bridge extends agent-launch and reads this registry.

Cross-repo checks

zed stays in apps, so hasModule calls for it pass url = "github:icedos/apps" instead of repoUrl.

Test a change to this repo

Point this repo's overrideUrl at the local checkout in the config root (path:/home/ice/Projects/icedos/ai-tools), then icedos rebuild --build.

Notable modules / gotchas

  • peon-ping — Warcraft-peon-style agent-event audio. Standalone module: owns icedos.ai-tools.peon-ping.users.<name> (self-materialised via genDefaults). Claude Code integration is upstream's own programs.peon-ping.claudeCodeIntegration (per-user opt-in, claudeCodeIntegration = true), and opencode consumes the user settings for its own peon plugin. See core's Per-user (users) options.
  • prime-agent — mirrors the bundled models.dev catalog into models.json. Only models in that snapshot show up today (it lags upstream). To add a newly released model without waiting for a prime-agent bump, define it under icedos.ai-tools.prime-agent.settings.providers.<name>.models: prime-agent's models[] merges with the catalog — an unknown id is added (inheriting the built-in provider's api/baseUrl), a known id replaces the bundled definition. Use the model's real dot id (e.g. glm-5.3-flash, not glm-5-3-flash) and the same id in modelOverrides.
  • claude-code — owns icedos.ai-tools.claude-code.users.<name> (mkSubmoduleAttrsOption, filled per normal user via genDefaults) and enables programs.claude-code for every hm user (enable = lib.mkDefault true, enableMcpIntegration = true). It feeds the shared icedos.ai-tools.{rules,skills} into programs.claude-code.{rules,skills} with mkDefault per entry. settings and per-user skills go through the raw passthrough ([home-manager.users.<name>.programs.claude-code.*]). MCP servers come from the shared programs.mcp.servers registry.
    • marketplaces — fetcher results are not TOML-expressible, so list them under [[icedos.ai-tools.claude-code.users.<name>.marketplaces]] with a source enum (fetchFromGitHub/fetchFromGitLab/fetchgit/path) and that source's fields. path is copied into the store at eval time, and pure eval forbids host paths there.
    • It declares no hooks. peon-ping registers its own via icedos.ai-tools.peon-ping.users.<u>.claudeCodeIntegration.
  • ai-accounts — standalone module that owns icedos.ai-tools.ai-accounts.users.<name> (self-materialised via genDefaults). ai-account exec <agent> -- picks an account (flag, AI_ACCOUNT_<AGENT>, sticky, alimit headroom, default) and execs the real binary with per-account env. Agent modules wrap their package through lib/wrap.nix only when lib/has-accounts.nix finds declared accounts; opencode also counts as declaring when ollama does, because it passes its key in.
    • State lives in ~/.local/state/ai-accounts/<agent>/<account>/. Shared mode links the real dir except adapters.*_PRIVATE (never linked) and adapters.*_SEED (copied once, then owned by the account, because agents rewrite those files by renaming over the target).
    • A logged-out account fails with exit 3 when stdin is not a tty. On a tty the launch signs in first: ollama prompts for the key, opencode runs opencode auth login, the other agents start and show their own sign-in. An opencode launch also prompts for the key of the ollama account it tags, when that account has no key.
    • alimit keys for non-default accounts are <provider>@<tag>/<window>. Status lines read AI_ACCOUNT_TAGS, and alimit headroom feeds auto-pick.
    • Per-account settings merge over the agent module's icedos.managed-settings.<agent> into the account's own settings file on each launch, recorded in .ai-account-settings.json so removing an override restores the value it replaced.
    • Antigravity accounts run behind xdg-dbus-proxy, which hides org.freedesktop.secrets so agy stores its token in the account's ~/.gemini. antigravity.busTalk lists the reachable names.
  • alimit — standalone module that owns icedos.ai-tools.alimit.users.<name> (self-materialised via genDefaults). One SQLite DB at ~/.local/share/alimit/usage.db holds usage windows keyed <provider>/<window> (Claude keeps bare keys). Status lines record samples while agents run, and a user timer polls the providers in providers (claude, opencode-go, ollama, openrouter) for idle periods. Antigravity has no quota API, so only its status line records it.
    • Every bar shows only its own agent's usage: Claude Code's status line shows claude, antigravity's shows antigravity, prime-agent's footer and opencode's sidebar show the provider of the current model.
    • Weekly and monthly windows (config.period_of) project their end from the average burn since the window opened (reset minus 7 days, or one calendar month), blended with the previous period's for its first 2/7 (rates.paced). A backtest on a week of samples put it closest to the final weekly usage; the last hour's rate and a 5h-derived rate did worse. Antigravity opens its week at first use, so its reset only drifts while usage is 0%. 5h and daily windows keep the last hour's rate.
    • Every weekly window paired with a 5h one (config.weekly_of; Claude, Antigravity families, opencode-go rolling) carries exchange, the 5h percent per 1% weekly (rates.exchange): rises both report at the same instants, polls only when any exist, idle-session redraws skipped, and a missing resets_at (an idle 5h window) counts as a reset. Agent bars and opencode's sidebar print it as 1%=X% 5h, the dashboard one line per pair. Ollama's session is unpaired: its length is undocumented, and current Ollama plans only have a monthly allowance.
    • alimit headroom ranks accounts by each window's peak (rates.compute), not its last row.
    • API keys come from env, then prime-agent's auth.json, then opencode's; alimit never refreshes Claude Code's OAuth token.
    • icedos ai limits opens the full dashboard. widget installs the Plasma applet org.icedos.alimit.
  • code-intelligence — ships one code-intelligence-<lang> skill per folder listed in icedos.ai-tools.code-intelligence.languages, plus a code-intelligence rule pointing agents at them. Both land in the shared skills and rules with mkDefault.