How to package a skill into an artifact
A skill artifact packages a skill.md file — a Markdown document encoding domain knowledge, conventions, or structured guidance — into a .mur.zip the runtime installs alongside a capsule. Skills are callable: the agent invokes a skill by name (no arguments) and receives its full skill.md content as the tool result. No file-read capability is required. This lets you ship guidance independently of any particular capsule and install it into any capsule that benefits from it.
What is a skill artifact?
A skill artifact is a .mur.zip whose required payload is a single skill.md file. Unlike tool artifacts (WASM or native binaries), a skill artifact installs a static guidance file. The runtime writes it to workdir/tools/<name>/skill.md, lists it in MURMUR.md, and exposes it in the tool inventory as a zero-argument callable. When the agent calls the skill, the runtime reads skill.md and returns its content as the tool result — no file-read capability, no subprocess, no WASM. Content is loaded just-in-time, so it only consumes context tokens when the agent chooses to call it.
The relevant manifest options are:
| Option | Controls |
|---|---|
| artifacts[].runtime | Declares a skill artifact; set to skill to install skill.md at session start |
| artifacts[].source | Points at a local skill.md so the runtime installs it directly — no build, no publish. Skills get this for free (local_source defaults to true for runtime: skill); other roles must declare local_source: true to opt in. |
| inference.system_prompt_artifact | Bind a skill as the system prompt; reads its skill.md once at launch instead of on-demand |
There are two ways to get a skill into a capsule:
- Package and publish (Steps 1–6 below) — the distribution path.
mur build --skillproduces a.mur.zip,mur publishputs it in the registry, and the capsule declares it byname+version. Use this to share a skill across machines or pin a version. - Local source (Fast iteration) — the authoring path. The capsule points
source:at askill.mdon disk; the runtime reads it directly on every run. Edit the file, relaunch, the change is live. No build or publish step.
Fast iteration: source a skill from a local path
While you are still writing a skill, packaging and publishing on every edit is friction. Set source: on the artifact instead and the runtime reads skill.md straight from disk:
artifacts:
- name: code-review-conventions
source: ./skills/code-review-conventions/skill.md
runtime: skill
source: may point at the skill.md file directly, or at a directory containing it (the runtime finds skill.md case-insensitively):
artifacts:
- name: code-review-conventions
source: ./skills/code-review-conventions/
runtime: skill
Key points:
- No
version:needed. A local file has no registry version — the runtime labels itlocal. If you do setversion:, it is ignored with a warning. - Relative paths resolve against the manifest's directory, not your shell's working directory. Absolute paths work too.
source:is skill-only. Putting it on atool,driver, orhookartifact is a manifest error (E-MAN-003) caught before launch.- Everything downstream is unchanged. The skill installs to
workdir/tools/<name>/skill.mdand appears in the tool inventory andMURMUR.mdexactly as a registry skill would be — the agent calls it by name the same way (see Step 4).
Run mur install to fetch the driver and any other registry artifacts in your manifest:
mur install
Different ways to install artifacts
mur install needs to know where to fetch artifacts from. You have two options:
Option A — configure a registry source in ~/.murmur/config.yaml:
registry:
default: official
sources:
- name: official
type: github
repo: <owner>/<repo>
token: "${GITHUB_TOKEN}"
Then install by artifact name and version:
mur install <artifact-name@version>
Option B — pass a full GitHub reference and skip configuration entirely:
mur install github:<username>/<repo>@<tag>
See Installing artifacts to learn more.
Then run the capsule — there is nothing to build or publish first:
mur run
murmur: url localhost:52222
session: ses_019ed2af53da75c2aefee84ee10c34af
^C
If the path is wrong, the run fails before any workdir is created, naming what it could not find:
error[E-IO-001]: skill source path not found: /path/to/capsule/skills/code-review-conventions/skill.md
When you are ready to distribute the skill, switch to the packaged path below — build, publish, and replace source: with version:.
Step 1 — write skill.md
Create a skill.md file containing the guidance you want the agent to be able to read. Any Markdown structure works — use headings and lists to make the content easy to scan:
# Code Review Conventions
Guidance for reviewing pull requests in this project.
## What to check
- All public functions have doc comments
- Error types are described in the doc comment, not just the return type
- No `unwrap()` calls outside of tests
- No raw SQL strings — use the query builder
## How to structure feedback
Group findings by severity: blocking, non-blocking, nit.
Report each finding as: file · line · what · why.
The filename is case-insensitive at build time — SKILL.md, Skill.md, and skill.md are all accepted. The runtime always installs it as lowercase skill.md.
Step 2 — build the artifact
From an existing skill.md (no manifest required)
If you have a skill.md and want to wrap it immediately, use mur build --skill. No murmur.yaml is needed — one is generated for you:
mur build --skill my-skill/
Built artifact: ./my-skill-1.0.0.mur.zip
The output zip is always written to the current working directory. The artifact name is inferred from the folder name: lowercased, with non-alphanumeric characters (except hyphens) replaced by underscores. The version defaults to 1.0.0; pass --version to override:
To set an explicit name and version:
mur build --skill code-review-conventions --version 1.0.0 my-skill/
Built artifact: ./code-review-conventions-1.0.0.mur.zip
To add a one-line description (shown in the tool inventory and mur list):
mur build --skill code-review-conventions --summary "Project PR review conventions" my-skill/
The --summary text is written as description: in the generated manifest. You can update it later by re-running mur build --skill with a new --summary value — the existing manifest is updated in place.
The generated murmur.yaml inside the artifact contains three fields (four when --summary is given):
name: my-skill
version: '1.0.0'
runtime: skill
description: 'Project PR review conventions' # only present when --summary is passed
If the input folder already contains a murmur.yaml, it is used and the description field is set or overwritten when --summary is provided. The manifest must declare runtime: skill; any other runtime value is an error (E-MAN-003).
Agents with Bash or file-read tools will bypass the skill runtime
If your capsule exposes a Bash tool or a file-reader, the agent will almost always prefer a direct tool call to read the skill.md path rather than calling the skill through the runtime. The skill's tool-inventory entry is effectively invisible to it. If you need the agent to invoke the skill via the runtime (so the guidance is loaded on-demand and appears as a tool call in the trace), package and publish it first — then declare it by name and version in the manifest rather than via source:. See Step 3 onwards.
From a project folder with an explicit manifest
If you need control over the manifest — to pin a version or add a description — create a murmur.yaml alongside skill.md:
name: code-review-conventions
version: "1.0.0"
runtime: skill
Then build from the project directory:
mur build ./my-skill
Built artifact: ./my-skill/code-review-conventions-1.0.0.mur.zip
mur build validates that skill.md is present. If it is missing:
error[E-IO-003]: missing required file 'skill.md' in /path/to/my-skill
Step 3 — publish to the local registry
mur publish code-review-conventions-1.0.0.mur.zip
Choosing a registry target
Without --registry, the target is determined by your workspace config (registry.default / registry.remote_url in murmur.yaml). You can override it explicitly:
-
--registry local— writes to~/.murmur/artifacts/. No remote registry or API key needed. Use this when you are working locally or have no remote configured.mur publish --registry local code-review-conventions-1.0.0.mur.zip -
--registry <url>— publishes to a remote registry at that URL. RequiresNEXUS_API_KEYto be set.mur publish --registry https://registry.example.com code-review-conventions-1.0.0.mur.zip
Then install:
mur install
Step 4 — declare the skill in a capsule manifest
Create a murmur.yaml for the capsule that needs the skill. Add the skill artifact under artifacts: with runtime: skill. No special system prompt instruction is required — the agent sees the skill in its tool inventory and calls it by name when relevant:
name: pr-reviewer
version: "0.1.0"
artifacts:
- name: murmur-driver-anthropic
version: "1.0.0"
runtime: driver
- name: code-review-conventions
version: "1.0.0"
runtime: skill
capabilities:
network:
allow:
- https://api.anthropic.com
inference:
transport: http
endpoint: https://api.anthropic.com
model: claude-sonnet-5
api_key: ${ANTHROPIC_API_KEY}
driver:
artifact: murmur-driver-anthropic
system_prompt: |
You are a code review assistant.
name: pr-reviewer
version: "0.1.0"
artifacts:
- name: murmur-driver-openai
version: "1.0.0"
runtime: driver
- name: code-review-conventions
version: "1.0.0"
runtime: skill
capabilities:
network:
allow:
- https://api.openai.com
inference:
transport: http
endpoint: https://api.openai.com
model: o3-mini-high
api_key: ${OPENAI_API_KEY}
driver:
artifact: murmur-driver-openai
system_prompt: |
You are a code review assistant.
name: pr-reviewer
version: "0.1.0"
artifacts:
- name: murmur-driver-deepseek
version: "1.0.0"
runtime: driver
- name: code-review-conventions
version: "1.0.0"
runtime: skill
capabilities:
network:
allow:
- https://api.deepseek.com
inference:
transport: http
endpoint: https://api.deepseek.com
model: deepseek-r1
api_key: ${DEEPSEEK_API_KEY}
driver:
artifact: murmur-driver-deepseek
system_prompt: |
You are a code review assistant.
The skill appears in the agent's tool inventory as a zero-argument callable. When the agent calls code-review-conventions, the runtime reads tools/code-review-conventions/skill.md and returns the content as the tool result. No file-read capability is required.
If you want the skill's content pre-loaded as the system prompt instead of called on-demand, use inference.system_prompt_artifact instead.
Step 5 — install dependencies
mur install
Different ways to install artifacts
mur install needs to know where to fetch artifacts from. You have two options:
Option A — configure a registry source in ~/.murmur/config.yaml:
registry:
default: official
sources:
- name: official
type: github
repo: <owner>/<repo>
token: "${GITHUB_TOKEN}"
Then install by artifact name and version:
mur install <artifact-name@version>
Option B — pass a full GitHub reference and skip configuration entirely:
mur install github:<username>/<repo>@<tag>
See Installing artifacts to learn more.
Step 6 — run and verify
Create a task.md with the review request:
Review the diff in `/path/to/my-repo` against the project conventions.
Report findings grouped by severity: blocking, non-blocking, nit.
Run the capsule:
mur run
murmur: url localhost:52222
session: ses_019ed2af53da75c2aefee84ee10c34af
^C
At startup, the runtime installs the skill to:
workdir/
└── tools/
└── code-review-conventions/
└── skill.md
MURMUR.md at the workdir root lists all installed skills and tells the agent they are callable:
## Installed Skills
Skills are callable: invoke a skill by name (no input) to receive its full guidance
as the tool result. The content is returned just-in-time — it is not pre-injected
into context. No file-read capability is required.
- **code-review-conventions** — Project PR review conventions *(call by name to load guidance)*
The runtime returns the full skill.md content as the tool result.
Finding skill calls in the trace
After a session completes, run:
mur trace show
Different ways to identify a session
mur trace show locates a session three ways:
No argument — most recent session:
mur trace show
Finds the lexicographically largest ses_* entry in workdir/ — always the most recently created session, because session IDs are UUID v7 (time-ordered).
Short suffix — type the last few characters:
mur trace show 3e4b
Matches any session whose ID ends with the given string. Use 4 or more characters to avoid ambiguity. Matching is case-insensitive. If the suffix matches more than one session, mur lists the candidates and asks you to be more specific.
Full session ID:
mur trace show ses_6801f81dd28b4a9daf434e8324c4793e
Resolves the session directly without scanning workdir/.
Legacy file path:
mur trace show path/to/trace.jsonl
Any argument containing / or ending in .jsonl is treated as a literal file path. Kept for backward compatibility.
Use --workdir <path> if your session directory is not ./workdir.
Other trace exploration commands
mur trace has four subcommands for exploring session output:
mur trace show — print the full trace for a session to the terminal. Accepts a session ID, suffix, or no argument (most recent session).
mur trace steps — show a turn-by-turn summary of what the agent did in a session. Pass --verbose to include a truncated summary of each tool's input.
mur trace diff — compare the traces of two sessions side by side. Useful for spotting behavioural regressions between runs.
mur trace report — generate a structured summary report from a session's trace. Covers token usage, tool calls, latency, and other session-level metrics.
The summary includes a dedicated ── Skill calls ── section:
── Session ──────────────────────────────────────
session: ses_019ed2af53da75c2aefee84ee10c34af
capsule: pr-reviewer v0.1.0
model: deepseek-v4-flash
status: ok
duration: 4.1s
── Turns ────────────────────────────────────────
count: 2 (max: 10)
── Tokens ───────────────────────────────────────
input: 8,214 (avg 4,107/turn)
output: 612 (avg 306/turn)
total: 8,826
── Tool calls ───────────────────────────────────
count: 0
── Skill calls ──────────────────────────────────
count: 1 (1 ok, 0 error) success 100.0%
latency: avg 0ms
turn 0 code-review-conventions 0ms ✓
── Compaction ───────────────────────────────────
fired: no
── Tasks ────────────────────────────────────────
task 1 tsk_019ed2af turns: 2 in: 8,214 out: 612 ok 4.1s
The underlying event in trace.jsonl looks like this:
{"event_type":"skill_call","session_id":"ses_019ed2af53da75c2aefee84ee10c34af","timestamp":1782429237756,"turn":0,"skill_name":"code-review-conventions","output_bytes":6543,"duration_ms":0,"status":"ok"}
How skills differ from tools
| Tool artifact | Skill artifact | |
|---|---|---|
| Payload | WASM component or native binary | skill.md Markdown file |
| Model interaction | Agent calls it as a function with input | Agent calls it by name (no input); runtime returns skill.md content |
| Runs code | Yes | No — static file read by the runtime |
| Requires file-read capability | No | No |
| Injected into system prompt | No | No — unless declared as system_prompt_artifact |
Appears in tool inventory (%list()) |
Yes | Yes — shown as callable, zero-argument |
Appears in MURMUR.md |
Yes (## Installed Tools) |
Yes (## Installed Skills) |
| Consumes context tokens at start | No | No — only when called |
Skills do not run any code. They are static guidance files returned on-demand when the agent calls them by name.
Summary
| Step | What you produce |
|---|---|
skill.md with domain guidance |
The skill payload |
artifacts[].source: ./path/to/skill.md |
Authoring mode — runtime reads skill.md from disk; no build or publish |
mur build --skill <path> |
.mur.zip with generated manifest; output in CWD |
mur build --skill <name> --version <ver> <path> |
.mur.zip with explicit name and version |
mur build --skill --summary "<text>" <path> |
.mur.zip with description written to manifest |
mur build . (with murmur.yaml) |
.mur.zip with hand-authored manifest; output in source dir |
mur publish <zip> |
Skill available to any local capsule |
artifacts[].runtime: skill in capsule manifest |
Runtime installs skill.md; skill appears in tool inventory as callable |
inference.system_prompt_artifact: <name> |
Skill content read at launch and used as system prompt; not separately callable |