Loomcycle configure
Skill denn-gubsky/claude-code-plugin-loomcycle/skills/loomcycle-configure
Configure a loomcycle runtime — providers, model tiers, user tiers, fallbacks, per-agent sampling and context-compaction, environment variables, deployment profiles (brew/in-system, containerized, true sandbox, server, multi-tenant, cloud), filesystem Volumes, the Bashbox in-process sandbox, the Path VFS, chunked-graph Documents, encrypted per-tenant credentials (CredentialDef / $cred: / provider-key override), per-scope token budgets and usage/cost attribution, inbound webhooks, and third-party MCP servers. Use when the user wants to set up or tune loomcycle.yaml or its env, pick a deployment posture, wire provider routing/cost-cascades, gate plans, tune decoding (temperature/top_p) or compaction, lock down tool/sandbox/auth, enable or choose between Bash and the Bashbox sandbox (incl. its host-command fallback), name resources with Path, author chunked-graph Documents (and the SQL Memory they require), store tenant/user API keys or bring-your-own provider keys, set token budgets, receive webhooks, or connect external MCP tools.From its SKILL.md
npx -y skills add denn-gubsky/claude-code-plugin-loomcycle --skill loomcycle-configureAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
22.4 KB, as published. Nobody here has run it
Configure loomcycle
Help an operator write or tune their loomcycle.yaml (model routing) and
environment (posture: sandbox, auth, storage, scale). loomcycle splits its
configuration along one seam — keep it in mind throughout:
loomcycle.yamlowns routing —provider_priority,tiers,models:aliases,user_tiers:overlays,agents:overrides. Declarative model policy.- Environment owns posture — tool sandbox roots, the auth token, storage backend, multi-tenant pepper, replica id, observability. How and where it runs.
The six deployment profiles the operator may ask about are points on a trust × scale grid; each is a preset of env vars over the same yaml.
Hard safety rules (non-negotiable)
- Never read or write the secret env file
.env.local(*_API_KEY,LOOMCYCLE_AUTH_TOKEN, the operator-token pepper, trigger-secret values). It is git-ignored. To set a secret, print the exact line for the operator to add themselves. Its non-secret companion.env.insecure(v0.23.3 split, #399 — listen addr, sandbox roots, feature flags, allowlist names) carries no credentials and is safe to read and edit; only.env.localis off-limits. You may also read/writeloomcycle.yaml. (On a v0.23.0 binary there is only.env.local— treat it as secret-bearing.) - Never put a secret value in
loomcycle.yamlor any file. API keys andLOOMCYCLE_AUTH_TOKENare referenced by env-var name only. The yaml never holds a key. - Tools are default-deny — in two layers. (a) The built-ins
Read/Write/Edit/Bash/HTTP/WebFetchrefuse every call until their operator root/allowlist env var is set. (b) The capability toolsMemory/Channel/AgentDef/ScheduleDef/… additionally refuse until the agent carries an explicit scope list (memory_scopes,channels:,agent_def_scopes, …) — having the tool intoolsis necessary but not sufficient. An agent seesoperator-enabled ∩ tools ∩ per-tool-scope. Recommend the narrowest setting that works at every layer; never widen "to make it work." (v0.23.3 (F21/#389), loomcycle emits a bootWARNING:when a tool is intoolsbut its gate is unset —Memoryw/omemory_scopes,Channelw/ochannels,Evaluationw/oevaluation_scopes,Interruptionw/ointerruption.enabled— so this silent default-deny is now visible at startup, surfaced incfg.Warnings/loomcycle validate.) - Bash is not a sandbox. It is cwd-restricted + env-scrubbed only. If Bash is exposed to untrusted prompts, the runtime must be containerized — say so explicitly.
- Secrets at rest in the DB are redacted (v0.23.4, F32) — but keep them
off the cmdline anyway. loomcycle persists agent tool I/O (the full
Bashinput + result, etc.) in its store; before v0.23.4 a token an agent inlined on a command line (curl -H "Authorization: token <TOKEN>") was written to the DB in cleartext — and a tracked DB checkpoint could carry it into git. v0.23.4 masks secret-shaped values to[redacted:<ENV_NAME>]before persisting (value-based match — it catches the secret even renamed or inlined in a URL; the env-var name is kept for debuggability). Still advise agents to pass secrets out-of-band (env / stdin / a credential-helper script), never inline — so the secret never even transits a transcript. Redaction is an at-rest guard only: aBashchild still inherits the liveLOOMCYCLE_*process env, so an agent can read a secret at runtime (ties back to rule #4). - Validate before declaring done. Run
loomcycle validate <yaml>(andloomcycle doctorif an instance is reachable). Report the real outcome.
Workflow
- Discover. Ask for (or read) the current
loomcycle.yamland which providers the operator has keys for. Ask what they're building (personal automation? an app backend? a multi-customer SaaS?) — that picks the profile. - Pick the profile. Use the selector below. When unsure between two, pick the safer (lower-trust) one and say why.
- Author routing. Write/adjust
loomcycle.yamlper reference/routing.md — start at library defaults, push exceptions up the precedence stack only as needed. - Author posture. Emit the env lines for the chosen profile from reference/profiles.md; cross-check each var against reference/env-vars.md. Print env lines for the operator to add — never write the env file.
- Validate.
loomcycle validate <yaml>; if reachable,loomcycle doctorandGET /v1/_resolverto confirm providers probe green.
Profile selector
| Profile | Use when | Trust | Storage | Detail |
|---|---|---|---|---|
| 1. Brew + in-system agent | Personal workstation / local automation; you trust every prompt | Full host — all tools incl. Bash/Write/Edit on real dirs | SQLite | profiles.md §1 |
| 2. Containerized (in-container access) | Same power, contained blast radius; the recommended default for exposing Bash | Container-bounded | SQLite or PG | profiles.md §2 |
| 3. True sandbox | Untrusted/model-authored prompts; least privilege | Minimal — Bash off, default-deny roots, tight HTTP allowlist, code-js for any exec | SQLite or PG | profiles.md §3 |
| 4. Server | A single backend serving one app's agents | App-scoped tools, no Bash, callback allowlist | SQLite or PG | profiles.md §4 |
| 5. Multi-tenant | One instance fronting customers who don't trust each other | Per-principal tokens (RFC L), tenant isolation | Postgres | profiles.md §5 |
| 6. Cloud / multi-replica | Horizontal HA behind a load balancer | Server/multi-tenant + N replicas | Postgres | profiles.md §6 |
Profiles are cumulative: 5 builds on 4, 6 builds on 5. Read the matching section of reference/profiles.md before emitting config — each lists the exact env set, the yaml shape, and the sharp edges.
Volume primitive (RFC AH) — v1.0.3+
RFC AH replaces the env-var file jail with a volumes: block in loomcycle.yaml. The old
vars LOOMCYCLE_READ_ROOT, LOOMCYCLE_WRITE_ROOT, and LOOMCYCLE_BASH_CWD are retired
(Phase 3 — fatal config-load error in v1.0.3+). Remove them from env files before upgrading.
Quick migration (most configs)
In most configs all three vars pointed at the same directory. One block replaces all three:
volumes:
default:
path: ./work # relative to the dir run.sh cd's into
mode: rw # rw = Read+Write+Edit+Bash; ro = Read/Grep/Glob only
default: true # agents without an explicit `volumes:` list bind here
# Required only if any agent uses VolumeDef (mkdir -p ./work/dynamic first):
dynamic-root:
path: ./work/dynamic
mode: rw
dynamic_root: true
VolumeDef tool (Phase 2a/2b — agent-provisioned volumes)
Agents can provision volumes at runtime with VolumeDef op=create. Two gates required:
volume_def_scopes: [any]on the agent (per-agent capability gate)- A
dynamic_root: truevolume involumes:(backing store for provisioned volumes)
ephemeral: true makes the volume auto-purge when the creating run ends — no rm -rf needed.
Sub-agents inherit the dispatcher's volumes via spawn narrowing; address files with volume="name".
defaults: block — required for loomcycle validate
defaults:
provider: deepseek
model: deepseek-v4-pro
loomcycle validate uses a static dry-run resolver — it errors no provider resolved unless a
defaults: block is present. Inert at runtime (the tier resolver ignores it). Add it to every
config so validate works without a live provider environment.
Full reference: reference/volumes.md — migration table, field reference, VolumeDef op catalogue, spawn narrowing, validation errors.
Bashbox — a TRUE in-process sandbox (RFC AJ) — v1.3.0+
Bashbox is the isolated alternative to Bash: it runs commands in-process via gbash
(pure-Go) — no OS process, no network, every path rooted at the bound volume. Because the
isolation is real it honors read-only volumes (a ro binding mounts under an in-RAM overlay —
writes succeed in-run but never touch the host; Bash refuses ro). Opt-in like Bash:
LOOMCYCLE_BASHBOX_ENABLED=1 + tools:[Bashbox]. Prefer Bashbox over Bash for untrusted
prompts or read-only work; use Bash only when an agent needs a real host binary (in a contained
deployment). An operator can allowlist specific host commands gbash lacks (git, gh) to fall
through to the host shell via LOOMCYCLE_BASHBOX_FALLBACK_COMMANDS (off by default; only those names
escape; rw-only; creds via LOOMCYCLE_BASHBOX_FALLBACK_ALLOWED_ENV injected into the host child
only). Bashbox is in-band only — there is no mcp__loomcycle__bashbox meta-tool.
Full reference: reference/bashbox.md.
Path — a Unix-like VFS (RFC AL) — v1.4.0+
Path names Memory entries / Volume mounts / Documents by human-readable paths (/docs/launch)
over a dirents inode/dirent table. Six ops (resolve/ls/stat/mkdir(no-op)/mv/rm),
scope-aware (agent/user/tenant), .. rejected, tenant-isolated. Gate: tools: [Path] — no env flag, no separate scope policy (a dirent is a name, not an authority grant).
Resources opt into a name via Memory.set path: / VolumeDef.create mount_at: /
Document.create_document path:. Also a direct MCP meta-tool — call mcp__loomcycle__path
from the plugin without spawning a run (scope + tenant resolved server-side from the principal).
Full reference: reference/path.md.
Document — chunked-graph documents (RFC AK) — v1.4.0+
Document is a tree of chunks (UUID, hierarchy, type, fields, edges, Markdown body) that agents
and humans co-author. Bodies live in Memory; structure lives in SQL Memory (queryable). ~24 ops
(document/chunk lifecycle, edges, query_chunks, type defs, image assets, Markdown round-trip, and
the entity tier below), optimistic revision concurrency, atomic + orphan-free deletes. Two
gates: tools:[Document] AND LOOMCYCLE_SQLMEM_ENABLED=1 (the structure tables live in SQL
Memory — the #1 "Document refused" cause). Scope agent/user/tenant (v1.41.0+ — tenant is
shared across the tenant and needs tenant in both memory_scopes and sql_scopes, since a
document spans both planes). Also a direct MCP meta-tool — mcp__loomcycle__document.
Full reference: reference/document.md.
Entity memory — bi-temporal facts + the tenant ontology — v1.42.0+
Three Document ops make a document a fact store that can be corrected without losing what it
corrected. upsert_chunk writes by natural_key (unique per scope) so the same fact
extracted twice converges on one chunk instead of accumulating near-duplicates — the idempotency a
background consolidator needs; it takes no revision, and preserves any field you don't restate.
supersede_chunk retires a fact by stamping both end-timestamps and linking the replacement —
the retired fact stays readable, which is the point. graph_recall walks the relations
bidirectionally (≤2 hops) and is time-aware: as_of drops facts the store didn't believe at that
instant.
Two time axes, answering different questions: valid_at/invalid_at is world time (when the
fact was true), created_at/expired_at is system time (when the store believed it). Only the
world pair is caller-settable, so a retired fact cannot be un-retired — to retract a correction
you record another one, superseding the superseder. class
is derived or evidential — evidential material is exempt from retention pruning at any age,
because it's what everything else was distilled from.
The entity types are base seed ⊕ tenant layer (seed = POLE+O + preference/fact). The
tenant layer lives at /memory/ontology (tenant scope) and is inert until an operator confirms
it — the root chunk's status must be exactly confirmed, so flip it in the Web UI → Settings
→ Ontology tab rather than typing into the status field, where a typo leaves the layer silently
inactive.
Nesting in that document is a type hierarchy (v1.52.0): a child chunk is a subclass of its
parent, inheriting its fields, and a type filter on list_facts/query_chunks matches subtypes too
— so type=event returns incident rows. And since v1.53.0 your agent cannot edit that document:
on the ontology alone a run may only file a proposed entity, through propose_entity, which an
operator then accepts or rejects. Everything else there is refused.
Verified writes (v1.54.0). A fact can carry source_quote — the span of source text it was
drawn from — and a judge can be asked whether that span actually carries the claim. A fact that
fails is withheld from list_facts/graph_recall, never deleted (include_refuted: true reads
it back with the reason). Three things follow for an agent: pass the span when you write a fact;
never call judge_fact on your own writes, which is self-certification; and for a lookup question
try verbatim_answer before composing one, which returns the stored claim verbatim with its
citation, or a reason it will not. It refuses often, and a refusal means "answer normally", not
"there is nothing". Full reference:
reference/document.md.
⚠️ After upgrading the runtime, reload the plugin. The plugin ships no tool schemas — the thin client proxies the runtime's own
tools/list, and Claude Code caches it once, at connection. A session opened against an older deployment keeps the old schema, and arguments it doesn't declare get sent as strings (cannot unmarshal string into Go struct field …). Reload, don't debug.
Credentials — encrypted per-tenant secrets (RFC AR) — v1.10.0+
CredentialDef is an encrypted-at-rest store for named API secrets — a tenant (or a user)
stores its own provider/search/MCP keys and other Defs reference them by name, bound
server-side so the model never sees a value (get/list are metadata-only). One env gate:
LOOMCYCLE_SECRET_KEY (a base64 32-byte KEK) — fail-closed: unset ⇒ the store is disabled and
nothing is written (the #1 "credential refused" cause). AES-256-GCM + per-tenant HKDF key, AAD
row-binding, excluded from snapshots. Direct MCP meta-tool mcp__loomcycle__credentialdef (ops
create/get/list/delete; scope tenant/user/agent, scope_id derived from your identity,
never the wire; tenant-confined). Two consumption paths: $cred:<name> in an MCPServerDef
env:/headers: (per-user outbound channels — each user's own Telegram/Slack token), and a
provider/tool key override by env-var name (store ANTHROPIC_API_KEY / BRAVE_API_KEY → a
tenant's own key overrides the operator's host key, usage attributed to that scope).
Full reference: reference/credentials.md.
Token budgets + usage (RFC AW / RFC AV) — v1.10.0+ / v1.11.0+
Per-scope monthly token budgets — a soft warning and a hard cap (refuse new runs at
admission; an in-flight run that crosses hard warns-but-finishes) on operator/tenant/user
calendar-month token totals (UTC; no row = unlimited; most-restrictive-wins; advisory, per-replica,
fail-open). Budgets are set in the Web UI Limits console or over HTTP GET/PUT/DELETE /v1/_limits
(gRPC TokenLimit + TS/Python setLimit() too) — deliberately no MCP CRUD tool (like steering).
But you feel them on the run tools: spawn_run/spawn_runs return a limits array on a soft
crossing, and a hard-over run is refused at admission with token_limit_exceeded (429 /
ResourceExhausted). Budgets count what the RFC AV usage/cost ledger reports (GET /v1/_usage /
the Web UI Usage page — tokens + money by tenant/user/provider/model/source; reporting only, also
not an MCP tool). Full reference: reference/token-limits.md.
Reference files (read on demand)
- reference/routing.md — providers + API-key env
vars, the 4-layer resolver precedence,
tiers/user_tiers/models:aliases / per-agent overrides,fallback_on_error, the four cookbook patterns (single/multi provider × single/multi user-tier), and the per-agentsampling:(temperature/top_p/…) andcompaction:blocks. Read this for any routing, decoding, or compaction question. - reference/volumes.md — Volume primitive (RFC AH,
v1.0.3+):
volumes:block fields, per-agent binding, VolumeDef tool + gates, ephemeral volumes, spawn narrowing, migration from legacy jail vars, validation errors. Read this for any file-tool sandboxing,VolumeDef, or Phase 3 migration question. - reference/bashbox.md — Bashbox (RFC AJ, v1.3.0+):
the true in-process gbash sandbox vs
Bash, enablement (LOOMCYCLE_BASHBOX_ENABLED+tools), how it honorsrovolumes, the operator host-command fallback (LOOMCYCLE_BASHBOX_FALLBACK_*), and gbash coverage caveats. Read this for any sandboxed-shell orBash-vs-Bashboxquestion. - reference/path.md — Path primitive (RFC AL, v1.4.0+):
the dirent model, the six ops, scopes + grammar, how resources opt into a name,
the direct
mcp__loomcycle__pathmeta-tool, and v1 caveats. Read this for any resource-naming / VFS question. - reference/document.md — Document primitive (RFC AK,
v1.4.0+): chunked-graph documents, the content/structure split, the 13 ops, the
LOOMCYCLE_SQLMEM_ENABLEDprerequisite, optimistic concurrency, atomic deletes, and the directmcp__loomcycle__documentmeta-tool. Read this for any chunked-document / co-authoring question. - reference/credentials.md — CredentialDef (RFC AR,
v1.10.0+): the encrypted per-tenant/user secret store, the
LOOMCYCLE_SECRET_KEYfail-closed gate, thecreate/get/list/deleteops + scopes, the directmcp__loomcycle__credentialdefmeta-tool, and the two consumption paths ($cred:<name>in MCP env/headers, and the provider-key override by env-var name). Read this for any bring-your-own-key / per-user-token / secret-store question. - reference/token-limits.md — Token budgets (RFC AW,
v1.11.0+) + usage/cost (RFC AV, v1.10.0+): per-scope monthly soft/hard ceilings,
why there's no MCP CRUD tool (Web UI / HTTP
/v1/_limitsonly), how a crossing surfaces onspawn_run/spawn_runs(limitsarray +token_limit_exceededrefusal), and the/v1/_usagereporting split. Read this for any budget / spend-cap / usage-report question. - reference/profiles.md — the six deployment profiles in full: trust posture, exact env set, yaml skeleton, and sharp edges per profile.
- reference/env-vars.md — the grouped environment
variable catalogue (identity/listen, storage, tool sandboxes, providers,
memory, scheduler/webhooks/A2A, code-js, multi-tenant, observability,
cluster). Look up any
LOOMCYCLE_*here before recommending it. Note: three vars are retired (v1.0.3) — see the tool-sandboxes section. - reference/webhooks.md — inbound webhooks
(
webhooks:block — enable, theenabled+deliveryrequirement + v0.23.3 boot-validation, the webhook secret-resolution rules (LOOMCYCLE_*auto-allow / static-yaml auto-trust /LOOMCYCLE_WEBHOOKS_ENV_ALLOWLIST),auth.kind: nonetrusted-network ingress,payload_mapping.goal(raw-body default), triage endpoints, tailnet ingress) and third-party MCP servers (mcp_servers:— stdio/http,mcp__server__tool, the${}interpolation allowlist). Read this for any external-integration wiring.
Validation cheatsheet
loomcycle validate loomcycle.yaml # config-load checks (pin XOR tier, user_tiers default, alias cycles, unknown provider)
loomcycle doctor # config + env + providers + storage + listen; exit 0 = green
loomcycle init # bootstrap a starter loomcycle.yaml + README in the config dir
# Live resolver matrix — which providers probe green, which models each lists:
curl -s -H "Authorization: Bearer $LOOMCYCLE_AUTH_TOKEN" http://localhost:8787/v1/_resolver | jq .
# Force an immediate re-probe (unstick a transient outage without a restart):
curl -s -X POST -H "Authorization: Bearer $LOOMCYCLE_AUTH_TOKEN" http://localhost:8787/v1/_resolve/probe | jq .
Two resolver error classes to teach the operator: ErrTierUnavailable (every
candidate stalled/unreachable → retry, 503) vs ErrTierAgentNotAvailable
(agent providers: ∩ user_tier provider_priority is empty → policy
refusal, "upgrade your plan", do NOT retry).
This skill configures a self-hosted loomcycle the operator runs. It does not manage loomcycle's lifecycle (start/stop) — that stays the operator's job, and this plugin never auto-starts the binary.