Sigils & auto-injection
How `+skill` and `++agent` shorthand becomes injected content at submit time.
atrium ships two prompt-time shorthands that any in-pane agent (or human) can drop into a message:
+skill-name— auto-injects a skill's body into the current turn.++agent-slug— auto-injects a named agent's full body (system prompt + every attached skill).
UserPromptSubmit hook when you press Enter. The resolved bodies become additionalContext for the model's current turn, and a one-line systemMessage confirms what loaded.
+skill-name
The bare form auto-resolves against the skills registry using a caller-aware priority order:
- The caller's own harness, project scope.
- The caller's own harness, user scope.
atrium-project(cross-harness, this workspace).atrium-user(cross-harness, global).- Every other installed harness, in your configured adapter order.
vercel-labs/skills.
+skill-name@scope — for example +atrium@harness-claude-code to pull the canonical atrium skill from Claude Code's directory, or +code-review@atrium-project to force the workspace-scoped variant. Available scope tokens: atrium-user, atrium-project, harness-<adapter>, harness-project-<adapter>, vercel-labs-skills.
Sigils inside fenced code blocks (` ` ) or inline backtick spans are ignored, so prose like "use +atrium` in a code review" doesn't trigger resolution.
What the user sees
After submit, the agent's pane shows a status line:
↻ loaded `atrium` from Claude Code adapter — Interact with the atrium workspace
Multiple resolved sigils stack into a bulleted block. Failures surface as ⚠ unresolved: +typo, +missing-skill on a second line — the prompt still goes through, the model just doesn't get any extra context for the missing entries.
++agent-slug
++ is the agent shorthand. Agent slugs are globally unique within an atrium install, so there's no @scope form. When you submit ++qa explain the failing test, the hook:
- Looks up the agent profile by slug.
- Builds an expanded body from its system prompt + every attached skill, partitioned by mode (see below).
- Injects the body as
additionalContextfor the current turn. - Renders the
systemMessageconfirmation:↻ loaded \qa\from atrium agent.
Skill modes
A skill attached to an agent profile has one of three modes:
always-loaded— the full skill body is inlined into the agent's system prompt at launch. Counts against the model's context budget; use sparingly for short, high-value skills.discovery— only a one-line bullet (name, description, and the exactatrium skills load …command to fetch the body) goes into the system prompt. The model reads the bullet, decides whether the skill is relevant for the current turn, and pulls the full body on demand by running the command itself.disabled— the skill is in the profile but contributes nothing. Useful for staging a skill before you trust it enough to flip on.
The expanded body the agent receives on a ++slug injection looks like this:
You are a QA engineer reviewing automated test runs…
# Always-loaded skills (1)
--- BEGIN SKILL: atrium (atrium-user) ---
…full SKILL.md body…
--- END SKILL: atrium (atrium-user) ---
# Discovery-mode skills (2) — load on demand
- code-review (harness-claude-code) — Review a PR against project conventions
$ATRIUM_CLI_PATH skills load code-review --provenance harness-claude-code
- pipeline-report (atrium-user) — Generate weekly pipeline analysis
$ATRIUM_CLI_PATH skills load pipeline-report --provenance atrium-user
Always-loaded sections are delimited with --- BEGIN/END SKILL --- markers so the model can tell where each runbook starts and ends. Discovery rows give the model everything it needs to fetch the body when the turn actually warrants it.
How injection happens
Auto-injection is driven by the adapter's UserPromptSubmit hook (or its equivalent). atrium-adapters wires this on install:
- Claude Code, Codex, Gemini — the hook calls
atrium skills resolve-prompt-sigils --pane-id $ATRIUM_PANE_ID --adapter <name>, reads the harness's prompt payload from stdin, and writes a hook-response envelope to stdout. The envelope'shookSpecificOutput.additionalContextbecomes the model's extra turn context. - Cursor Agent — Cursor has no equivalent same-turn injection primitive, so the canonical atrium skill (installed into every adapter's tool-native skill directory) tells the agent to recognize
+name/++slugpatterns and fall back to runningatrium skills load <name>/atrium agents load <slug>from the Bash tool itself.
CLI fallback
Both halves of the system are reachable from the CLI for scripts, Bash-tool agents, and anyone outside the hook path:
# Load a skill body to stdout (frontmatter stripped).
"$ATRIUM_CLI_PATH" skills load atrium
# Pin a specific scope when the name is ambiguous.
"$ATRIUM_CLI_PATH" skills load code-review --provenance harness-claude-code
# Load an agent's expanded body (prompt + attached skill bodies).
"$ATRIUM_CLI_PATH" agents load qa
atrium skills load is what the discovery-mode bullet lines tell the model to run. atrium agents load is what the Cursor fallback (or any non-hook environment) uses to expand a ++slug mention.
Composite ids
Some surfaces (configuration files, telemetry, the Copy composite id menu action) need to address a skill by its full {scope}:{name} identifier. Examples:
atrium-user:atriumatrium-project:code-reviewharness-claude-code:pipeline-reportharness-project-codex:incident-postmortemvercel-labs-skills:typescript-pr-review
