Skip to main content
Loom Core docs

What Is Ready Today

Loom Core User Guide

This guide is for day-to-day usage on a developer machine: setup, config sync, daemon operations, HUD visibility, and sandbox execution. The main shared HUD is the Kubernetes deployment loom-hub/mobile-hud, exposed at https://hud.flexinfer.ai. Run loom hud locally only for development, smoke tests, or isolated debugging.

For architecture details, see docs/ARCHITECTURE.md.

What Is Ready Today

For the latest shipped/in-progress snapshot, read docs/IMPLEMENTATION_STATUS.md.

Practical current state:

  • Stable local workflow: loom + loomd + loom proxy.
  • Multi-platform config sync in --loom-mode.
  • HUD visibility for servers, agents, tasks, and sandboxes.
  • Devbox sandbox execution via Docker or Kubernetes backend.

Core Concepts

  • loom: CLI for config generation/sync, daemon control, and utility commands.
  • loomd: local daemon that aggregates and routes MCP tool calls.
  • loom proxy: stdio MCP entrypoint used by AI clients in --loom-mode.

5-Minute First-Time Setup

From services/loom-core/:

make bootstrap-local
./bin/loom start
./bin/loom status

If you prefer manual startup without launchd:

make build
./bin/loom sync all --regen --loom-mode
./bin/loomd

Daily Commands

# Safe upgrade (restarts daemon only when idle)
make dev-upgrade

# Force upgrade + restart even when active
make dev-reload

# Health check
curl http://localhost:9876/health

# Launch local development HUD
./bin/loom hud --port 3333

# Local HUD launchd/service health (macOS)
./bin/loom hud status

make dev-upgrade now also attempts to restart a local development HUD when launchd service is installed or a HUD process is already bound to port 3333. It does not deploy the main shared HUD; use the Kubernetes rollout checks in the HUD section for that path.

Config Generation and Sync

Generate configs into generated/:

./bin/loom generate configs --target all --loom-mode

Sync to platform-specific destinations:

./bin/loom sync all --regen --loom-mode

Common targets: codex, vscode, kilocode, claude, claude_desktop, gemini, antigravity.

sync --regen resolves registries from the nearest workspace tree first (including ancestor platform/gitops/mcp/context/registry.yaml), then falls back to home defaults.

Claude Desktop uses the claude_desktop target and writes ~/Library/Application Support/Claude/claude_desktop_config.json. Its generated loom MCP entry includes --agent-hint claude-desktop, the shared llm-core tool profile, and LOOM_PROXY_IDLE_EXIT_SECONDS=0 so Claude Desktop can keep the MCP proxy process open without seeing a stale idle-exit disconnect.

Antigravity 2.0 sync writes .agents/mcp_config.json and .agents/hooks.json in workspaces, plus ~/.gemini/antigravity/mcp_config.json and ~/.gemini/config/hooks.json at home. The generated hooks keep Loom session tracking active and auto-allow the mcp(loom/*) tool namespace through Antigravity's native permission hook. PreToolUse hooks always return an explicit Antigravity decision JSON object, including telemetry-only hooks, and emit it as a parseable JSON line. Skills use Antigravity-specific registry overrides while emitting Gemini-style SKILL.md bundles under ~/.gemini/antigravity/skills/.

Daemon Operations

launchd commands (macOS)

./bin/loom start
./bin/loom status
./bin/loom reload
./bin/loom restart
./bin/loom stop

./bin/loom install now installs both daemon and HUD launchd plists when available.

Agent token sync (macOS)

./bin/loom sync agent-tokens install
./bin/loom sync agent-tokens status
./bin/loom sync agent-tokens run --apply

This installs the com.loom.agent-token-sync launchd job, which delegates to the GitOps-side bin/sync-agent-tokens helper and refreshes k3s/devbox/agent-auth-tokens.yaml from the local Codex and Gemini auth files on your Mac.

Claude is intentionally not part of this file sync. Cluster Claude agents use ANTHROPIC_API_KEY from k3s/devbox/agent-api-keys.yaml, and HUD/devbox worker launches consume that key-based path directly instead of a ~/.claude/auth.json blob.

Health and logs

curl http://localhost:9876/health

Default log files:

  • ~/.config/loom/logs/daemon.log
  • ~/.config/loom/logs/daemon.err

HUD (Agent Command Center)

The main shared HUD runs in Kubernetes:

kubectl -n loom-hub rollout status deployment/mobile-hud
kubectl -n loom-hub get pods -l app=mobile-hud
kubectl -n loom-hub get ingress mobile-hud

Operator URL: https://hud.flexinfer.ai

Use this Kubernetes deployment for normal fleet/session triage. The local command below is for HUD development, smoke testing, or offline debugging only:

./bin/loom hud --port 3333

Install/manage the local HUD launchd service (auto-start on login):

./bin/loom hud install
./bin/loom hud start
./bin/loom hud status
./bin/loom hud stop

loom hud install creates ~/.config/loom/hud.env (if missing) for launchd-loaded local HUD secrets such as FlexInfer, webhook, admin, and mobile operator tokens. The default local launchd HUD profile enables Redis cache (CACHE_BACKEND=redis, REDIS_URL=redis://localhost:6379).

Optional modes:

  • Dev CORS mode: ./bin/loom hud --port 3333 --dev
  • Terminal dashboard: ./bin/loom hud --tui
  • Native overlay (macOS): ./bin/loom hud --overlay --edge right --width 380 --opacity 0.92

Sandbox panel

HUD calls devbox_summary via /api/sandbox. If mcp-devbox is unavailable, HUD shows available=false.

Traces panel

HUD now includes a Traces activity view backed by GET /api/traces. It summarizes recent tool calls from the daemon audit log with status, server, tool name, total duration, and stage timing breakdowns (route, build, execute, send, recv). Use it to separate slow routing/pool acquisition from slow MCP execution when debugging latency or transport regressions. The shared Kubernetes HUD deployment enables the backing daemon audit log with LOOM_AUDIT_ENABLED=true, writing recent trace data to /home/mcp/.config/loom/audit.jsonl inside the loom-hub/mobile-hud pod. When opened from Fleet or Presence, the view is pre-filtered to the selected agent so you can jump from a live operator row straight to that agent's recent tool-call trail. Overview attention lanes and Lifecycle side-rail cards now use the same drilldown path: if the highlighted agent has a live session, the HUD opens Fleet session detail first; otherwise it falls back to the agent-filtered Traces view.

Fleet and Presence views

Desktop HUD agent surfaces now use one merged live-agent model:

  • Fleet focuses on live operational rows and merges presence heartbeats, active sessions, and spawned-agent metadata into a single table.
  • Fleet can group rows by root session so spawned subagents stay attached to the workflow that created them instead of appearing as unrelated flat entries.
  • Presence shows the same agent population, but keeps the broader coordination tabs for claims, worktrees, handoffs, and diagnostics.
  • Rows expose explicit evidence chips (presence, session, spawn) so you can see whether an agent is backed by a live session, only a heartbeat, or only a spawn record.
  • Session and Traces buttons are available directly from agent rows, which makes it easier to understand why an agent is visible even when session state and heartbeat state disagree.
  • Fleet session detail now includes a session-path breadcrumb and child-session list so you can traverse parent/root/current relationships without leaving the drawer.
  • Fleet session detail reads GET /api/sessions/{id}/trace, which composes session metadata, lifecycle events, context entries, and daemon audit traces. If context entries fail, for example because agent-context returns transport closed, the drawer still shows the available lifecycle/audit evidence and labels the partial source error inline.
  • Mobile clients can read the same resilient payload from GET /api/mobile/v1/sessions/{session_id}/trace, wrapped in the standard mobile envelope for bearer-token access.
  • Fleet session detail and Spawn detail now include recent trace previews inline, so you can inspect the last few routed tool calls before deciding whether to open the full Traces panel.
  • Overview and Lifecycle pressure cards are actionable now: attention agents jump into session detail or filtered traces, while namespace and relation hotspots jump into Dispatch.

Devbox Sandbox Workflows

mcp-devbox provides project-aware, persistent sandbox execution.

Weaver panel

The Infrastructure > Weaver HUD view now reads from dedicated Weaver status, history, and metrics endpoints.

  • Domain rows can render either legacy string-only domain payloads or richer domain objects with descriptions and tool counts.
  • Recent queries are ordered newest-first.
  • Metrics cards are backed by lifetime Weaver counters when the mcp-weaver server is available, instead of staying at placeholder zeroes.

Key tools:

  • devbox_detect: detect runtimes/dependencies for a project.
  • devbox_build: build/rebuild the sandbox image.
  • devbox_exec: run commands with bounded output.
  • devbox_exec_async + devbox_exec_poll: long-running command workflow.
  • devbox_status / devbox_stop: lifecycle operations.
  • devbox_summary / devbox_metrics: HUD + observability data.

Relevant environment variables:

  • DEVBOX_WORKSPACE_ROOT (default ~/workspace)
  • DEVBOX_BACKEND (docker or k8s)
  • DEVBOX_CACHE_DIR (default ~/.cache/loom/devbox)
  • DEVBOX_IDLE_TIMEOUT (default 30m)
  • DEVBOX_KUBECONFIG, DEVBOX_K8S_NAMESPACE, DEVBOX_K8S_STORAGE_CLASS (K8s backend)

Secrets and Template Variables

Registry env templates often use:

  • ${env:KEY}
  • ${keychain:KEY}
  • ${secret:KEY}

Set a Loom-managed secret:

./bin/loom secrets set GITLAB_TOKEN

Validate local setup:

./bin/loom check

Agent Hooks and Lifecycle (Advanced)

loom agent ... commands prefer HUD API calls (default port 3333) and fall back to daemon socket tool calls when HUD is unavailable.

Session lookup/list/prune, task-update, dispatch, context-inspect, and nudge-queue policy flows now share canonical request contracts from internal/hud/bridge/agent_contracts.go. That shared layer keeps CLI defaults, normalization, endpoint paths, and fallback payload shapes aligned between direct HUD HTTP calls and daemon bridge execution, which reduces transport-specific drift in hooks and wrapper scripts.

For hook-only clients that do not emit explicit session-start events (for example Codex notify), use heartbeat bootstrap mode:

loom agent heartbeat --agent-id codex --status active --ensure-session --agent-type codex --quiet

The generated Codex config now bootstraps a background keepalive wrapper from notify instead of relying on turn-completion heartbeats alone. For manual launches or custom wrappers, use:

loom agent keepalive-wrap --agent-id codex --session-id <session-id> --status active --ensure-session --agent-type codex -- codex

That wrapper keeps heartbeats flowing while the child process is running or idle, then deregisters when the wrapped command exits. The managed Codex TOML still cannot express a true top-level process wrapper, so Loom uses notify to start the background keepalive helper when needed.

When loom agent session-start runs with --auto-recall, the JSON response now includes a bounded startup_briefing field (and recalled_context as a compatibility alias) so hooks and wrappers can inject compressed recall instead of a full raw context dump. Startup recall now queries scope=all by default and includes memory tiers automatically: working + short_term for the fast strategy, and working + short_term + long_term for balanced and deep.

When callers use agent_context_add without an explicit durability, high-value entry types such as decision, finding, question, summary, error, and handoff are now mirrored into persistent memory while still remaining available as normal session context entries. Persistent context writes now land in the short_term memory tier first instead of skipping straight to long_term, which makes default recall more useful and gives later promotion/compaction policies something to work with. When the HUD coordinator is enabled, HUD and mobile session-end flows now treat the coordinator as the canonical summary owner: they disable agent_session_end summarization for that request and let the coordinator produce the post-session summary asynchronously. Coordinator-driven compaction now also inspects a small set of active sessions for high prompt estimates and can start memory compaction earlier when live context pressure is rising, instead of waiting only for tier token totals to grow large. Coordinator summary completion events now include before/after prompt estimates for the summarized session as well, which makes it easier to distinguish “summary stored successfully” from “summary materially changed live prompt pressure.” Compaction completion events now include before/after prompt estimates for the session that triggered pressure-aware compaction, so dashboards and alerts can distinguish “compaction ran” from “compaction actually reduced pressure.” Merge-only compaction runs now emit the same completion event, which keeps telemetry accurate when summaries are consolidated without needing per-item recompression. Coordinator Prometheus metrics now expose compaction effectiveness too: loom_coordinator_compaction_outcomes_total{trigger,effect} tracks reduced, flat_or_increased, and unmeasured outcomes, while loom_coordinator_compaction_prompt_delta_tokens{trigger} records positive prompt-token reductions for alerting and dashboards.

Optional environment overrides:

  • LOOM_HUD_PORT: HUD API port
  • LOOM_SOCKET: daemon socket path (fallback path)
  • LOOM_HUD_GIT_REMOTE_URL: upstream forge project URL (e.g. https://gitlab.flexinfer.ai/services/loom-core) used to build merge-queue deep links (Branch ↗ and New MR ↗) in the HUD Dispatch → Merge queue panel. When unset, the daemon auto-detects the URL by running git remote get-url origin from its working directory (2s timeout, fails gracefully when the daemon is not inside a git checkout). Embedded credentials (user:password@host and oauth2:token@host) are stripped before the URL reaches the frontend, and only http(s) schemes are emitted. Set this explicitly when the daemon runs outside a git checkout (e.g. in Kubernetes). Forge URL pattern is GitLab-style; GitHub support is a follow-up.

Context budget inspection:

loom agent context-inspect --agent-id codex --detail --limit 200

HUD agent context telemetry:

  • Scrape Prometheus-formatted samples from GET /api/agent/metrics.
  • Query the latest in-memory snapshots from GET /api/agent/context-telemetry.
  • Current gauges include prompt estimate, context-entry tokens, tool-schema tokens, file-injection tokens, system-prompt tokens, response-budget tokens, entry count, and total memory tokens.
  • Samples are labeled by low-cardinality dimensions: agent_type, session_status, and reason.
  • Sampling currently happens on session_start, context_add, and heartbeat; heartbeat samples are throttled to avoid noisy series.
  • Each successful sample also emits an agent.context.telemetry event into the HUD timeline stream for per-agent debugging.
  • Unified agent_recall responses now include recall_meta and _warnings fields, and Prometheus output includes backend-scoped agent_context_recall_duration_seconds summary series for context, memory, and graph.
  • Generated Claude Code and Codex loom-proxy configs now default to the reduced llm-core tool profile with --max-tools 160; operators can still opt back into the full surface by overriding --tool-profile or --max-tools.
  • ICC-focused sessions (the icc-* workflow skills) can opt into the dedicated icc-core profile (loom proxy --tool-profile icc-core), which pairs a slim developer core with the full icc, icc-capture, and pm surfaces inside a 100-tool ceiling — usable on Antigravity, whose default antigravity-core profile intentionally excludes the ICC block. Note the icc server must also be enabled in catalog-state.yaml for its tools to exist at all.
  • Repo-local proxy overrides (.loom/proxy.yaml): platforms whose MCP config is home-level (Antigravity reads a single ~/.gemini/config/mcp_config.json) pass the same --tool-profile for every repo. loom proxy therefore resolves <repo>/.loom/proxy.yaml from its working directory at startup (walking upward, bounded) and lets it shadow the CLI flags. Schema: optional top-level tool_profile/max_tools applying to every session, plus per---agent-hint entries under agents: (e.g. agents.antigravity.tool_profile: icc-core). Overridden profiles must be one of the known names (antigravity-core, llm-core, icc-core); unknown names are logged to stderr and ignored so a typo cannot expose the unfiltered tool list to a 100-tool-ceiling client. When an override applies, max_tools: 0 (or omitted) re-derives the new profile's default cap instead of carrying the CLI cap over. LOOM_PROXY_TOOL_PROFILE=<profile> overrides both file and flags for a single session. Example — private/icc-project-workspaces/.loom/proxy.yaml remaps only Antigravity sessions in that repo to icc-core, keeping antigravity-core everywhere else.

Hook reliability diagnostics:

loom agent hook-status --agent-id codex --window 5m
curl "http://127.0.0.1:3333/api/timeline?agent_id=codex&event_type=agent.heartbeat&limit=50"

For the main HUD, prefer the Kubernetes route and an operator token when querying HTTP endpoints directly:

curl "https://hud.flexinfer.ai/api/timeline?agent_id=codex&event_type=agent.heartbeat&limit=50"

Nudge queue status and policy:

curl "http://127.0.0.1:3333/api/agent/nudge-queue?agent_id=codex"
loom agent nudge-queue-policy
loom agent nudge-queue-policy --cap 96 --drop-policy summarize --debounce-ms 50 --lane-priority control,handoff,advice,default

Optional auth env for policy mutation:

  • LOOM_HUD_ADMIN_TOKEN (preferred)
  • HUD_ADMIN_TOKEN (fallback)

Response Size and Pagination

Many list/search tools support page + per_page (capped at 100). Several servers also enforce response-size limits.

Loom proxy inventory resources (loom-mode aware planning):

  • loom://tools/index
  • loom://tools/page/{page}
  • loom://tools/server/{server}/page/{page}

loom://tools is still supported for backward compatibility and may be truncated for large catalogs. Use the paged loom://tools/* URIs for deterministic full inventory.

CLI fallback for automation and scripts:

  • loom tools list --json
  • loom tools list --json --server <server> --page <n> --limit <n>

Selected env controls:

  • LOKI_MAX_RESPONSE_BYTES
  • PROMETHEUS_MAX_RESPONSE_BYTES
  • GRAFANA_MAX_RESPONSE_BYTES
  • TAVILY_MAX_RESPONSE_BYTES
  • ALERTMANAGER_MAX_RESPONSE_BYTES
  • LOOM_PROXY_TOOL_PAGE_SIZE (default 100, clamped 10..500)

Platform-Specific Quirks

Gemini CLI

Gemini CLI has several unique behaviors that Loom manages automatically:

  • Instruction Filename: Unlike Claude Code (instructions.md), Gemini CLI expects core instructions in GEMINI.md. Loom generates this file into ~/.gemini/GEMINI.md for instruction-type skills.
  • Skill Locations: Gemini CLI searches for skills in both workspace (.gemini/skills/) and user (~/.gemini/skills/) directories.
  • Duplicate Skills Error: A known quirk/bug in Gemini CLI causes it to error if the same skill name is discovered in both the workspace and user directories, even if the content is identical.
  • Loom Solution: To avoid duplication errors, the gemini profile in Loom sets SkillsDirectToHome: true. This ensures skills are only generated into the user directory (~/.gemini/skills/) and are automatically cleaned from the repository's .gemini/skills/ directory during sync operations.

Antigravity 2.0

Antigravity uses the same SKILL.md bundle shape as Gemini, but Loom treats antigravity as a distinct skill target. This lets targets.antigravity enable skills that Gemini disables and keeps generated skills in ~/.gemini/antigravity/skills/ instead of the Gemini CLI skill root.

Mobile Companion (iOS/iPadOS)

The Loom Companion app provides fleet monitoring, session management, and real-time alerts from an iPhone or iPad. For a full physical-device workflow, see docs/MOBILE_COMPANION_IPHONE_TESTING.md.

Connection Modes

ModeTransportWhen to Use
GatewayHTTPS through mcp.flexinfer.aiDefault path for the shared Kubernetes HUD
LANHTTP to local IPDevelopment only, when testing a local HUD server on the same network as the device

Pairing

  1. For normal use, rotate and publish the Kubernetes mobile token:
    make mobile-gateway-dev
    This patches loom-hub/loom-secrets, restarts deployment/mobile-hud, and verifies https://mcp.flexinfer.ai/api/mobile/v1/ping.
  2. Open Loom Companion on your device.
  3. Select Gateway mode.
  4. Enter the gateway URL https://mcp.flexinfer.ai.
  5. Enter the mobile operator bearer token.
  6. Tap Connect. The app probes /api/mobile/v1/ping to verify the connection.

For local development only, start a local HUD server with mobile auth enabled:

export HUD_MOBILE_OPERATOR_TOKEN="$(openssl rand -hex 32)"
export HUD_MOBILE_OPERATOR_SCOPES="mobile:read,mobile:session:create,mobile:session:end,mobile:push"
loom hud --bind 0.0.0.0 --port 3333 \
  --mobile-operator-token "$HUD_MOBILE_OPERATOR_TOKEN" \
  --mobile-operator-scopes "$HUD_MOBILE_OPERATOR_SCOPES"

Use make mobile-hud after exporting the token/scopes when you explicitly need the local LAN path.

Gateway bootstrap shortcut:

make mobile-gateway-dev

This is the preferred shared-system path because it updates the Kubernetes deployment instead of a local HUD process.

iOS Local Network Permission (LAN Mode)

When using LAN mode, iOS requires Local Network permission for the app to reach devices on your local network.

  • The permission dialog appears on the first connection attempt.
  • If denied, the app cannot reach the server and shows a "Local Network Access Required" banner.
  • To fix: Go to Settings > Privacy & Security > Local Network and enable Loom Companion.
  • The app distinguishes this error from other connection failures and provides targeted guidance.

Real-Time Updates

The app uses Server-Sent Events (SSE) for real-time dashboard and alert updates. If the SSE connection degrades (e.g., network switch), the app automatically falls back to 30-second polling and recovers SSE when the connection stabilizes.

Mobile API Scopes

The mobile operator token requires these scopes (configured via HUD_MOBILE_OPERATOR_SCOPES):

ScopeGrants
mobile:readDashboard, sessions, session detail, session events, session trace, audit, alerts policy
mobile:session:createCreate new agent sessions
mobile:session:endEnd active agent sessions
mobile:pushRegister/unregister push notification tokens

Troubleshooting Mobile Connection

SymptomLikely CauseFix
"Cannot reach server" in LAN modeLocal Network permission deniedSettings > Privacy & Security > Local Network
"Cannot reach server" in Gateway modeKubernetes HUD unavailable or ingress route brokenCheck kubectl -n loom-hub rollout status deployment/mobile-hud and verify https://mcp.flexinfer.ai/api/mobile/v1/ping
"Cannot reach server" in LAN modeWrong IP or portVerify server URL matches your local loom hud --bind ... --port ... settings
"[unauthorized]" errorToken mismatchVerify HUD_MOBILE_OPERATOR_TOKEN matches
"[forbidden]" errorMissing scopeAdd required scope to HUD_MOBILE_OPERATOR_SCOPES
Dashboard not updatingSSE disconnectedCheck Connection tab; polling fallback is active
[not_found] mobile API route not configured on gatewayGateway path split missingEnsure ingress routes /api/mobile/v1 to mobile-hud
unknown flag: --serveUsing an outdated commandUse loom hud --bind ... --port ... (there is no --serve flag)

Troubleshooting

  • Daemon offline: loom status, then loom restart
  • Binary drift after rebuild: make install-core, then loom restart
  • Stale tool list: loom reload
  • Client cannot find servers: loom sync all --regen --loom-mode
  • GUI apps miss shell env vars: run loom check and move secrets into loom secrets
  • Hook calls fail with both HUD and daemon errors: for the main system, verify loom-hub/mobile-hud rollout and ingress first; for local development, verify either loom hud is reachable (LOOM_HUD_PORT) or daemon socket exists (LOOM_SOCKET / ~/.config/loom/loom.sock)