Skip to content

Skills System & Multi-Agent Context

Skills are reusable instruction templates that extend the agent without touching source code. They live as SKILL.md files and are invoked in the TUI with a /skill-name [args] slash command.

~/.umbra/skills/ ← global skills (available in every project)
deploy/
SKILL.md
summarise/
SKILL.md
<project>/.umbra/skills/ ← project-local skills (override global on name collision)
test-watch/
SKILL.md

Each skill lives in its own named subdirectory. The subdirectory name becomes the skill name if the frontmatter omits name:. Project-local skills take precedence over global ones with the same name.

---
name: deploy
description: Deploy the project to the staging environment
argument-hint: <environment>
disable-model-invocation: false
---
Deploy $1 environment.
Current git status:
!`git status --short`
Run the deploy script and confirm the service is healthy.

Frontmatter fields:

FieldRequiredDescription
nameNo (falls back to dir name)Lowercase a–z, 0–9, hyphens; max 64 chars; no leading/trailing/consecutive hyphens
descriptionYesOne-line summary; shown in TUI autocomplete and injected into the system prompt
argument-hintNoPlaceholder shown in autocomplete, e.g. <branch-name>
disable-model-invocationNotrue → skill is user-invocable only; not listed in the LLM system prompt
PatternExpands to
$1, $2, $3First, second, third space-separated word
$ARGUMENTS or $@All arguments joined as a single string
${@:2}All args from position 2 onward
${@:2:3}Args 2 through 4 (bash-style slice)

Choosing between $1 and $ARGUMENTS: use $1/$2 only when the skill has clearly distinct positional flags (e.g. branch name + environment). For natural-language input (“find the bug in the auth module”), always use $ARGUMENTS — splitting a sentence into $1 $2 produces garbage.

Commands embedded in the skill body are executed at invocation time, before the content is sent to the model. The output replaces the injection marker.

Inline: !`command` — single-line output

Block:

```!
git log --oneline -10
```

Both forms run with the agent’s current cwd (10-second timeout). Errors produce [shell error: ...] inline instead of aborting.

User types: /deploy staging
1. Parse args: ["staging"]
2. substituteArgs(content, ["staging"]) → $1 → "staging"
3. expandShellInjections(content, cwd) → !`git status` → actual output
4. Prepend: "The user ran: /deploy staging\nExecute the following skill instructions now:\n\n..."
5. Send as the user message to the agent loop

At the start of each run, formatSkillsForPrompt() injects an <available_skills> XML block into the system prompt listing every skill where disable-model-invocation is not true. This lets the model know which skills exist and suggest them autonomously when relevant:

<available_skills>
<skill>
<name>deploy</name>
<description>Deploy the project to the staging environment</description>
<location>/home/user/.umbra/skills/deploy/SKILL.md</location>
</skill>
</available_skills>

Skills with disable-model-invocation: true are excluded from this block — they are user-only shortcuts and the model cannot suggest them.

Typing / in the TUI input field opens the skill picker. The argument-hint value is shown as a placeholder after the skill name. Skills are listed alphabetically with their description. The picker is fuzzy-searchable.