Skills and Slash Commands
Evener has two kinds of reusable markdown prompts: skills and slash commands. Both are plain text templates. What differs is where they come from, how they are invoked, and — critically — whether they can execute shell commands.
Create and use a skill
Use a skill for instructions you want the agent to reuse. This example needs an Evener installation with a working provider and a project directory. Run the shell commands on the host where the session runs, from your project root.
Create
skills/change-summary/SKILL.md:markdown--- name: change-summary description: Summarize a code change and its verification. --- Read the diff relevant to the request. Report what changed, what checks ran, and what remains unverified. Do not edit files.Start a new session in that project. In the browser, type
/and selectchange-summary, or send this leading slash prompt as typed text:text/change-summary Summarize the current diff.Check that the catalog offers
change-summaryand that the session records its activation. A response that merely mentions the name is not proof of activation. Inspect discovery warnings if it is missing:nameanddescriptionmust be nonempty strings, andSKILL.mdmust be inside a skill directory that is an immediate child of a discovery root, such asskills/change-summary/SKILL.md. The format and discovery reference explains precedence and invocation controls.Edit the body and invoke it again to load current bytes. There is no live filesystem watcher. New names require another catalog discovery or session startup. To remove it, delete only the
SKILL.mdyou created and start a new session. Removing a file does not erase instructions already in context; later reloads of the missing source fail visibly.
The complete file is also in examples/extensions/skills/change-summary/SKILL.md. To get a local copy, use the git clone command in Optional disposable exercise; the file is under evener-docs/docs/examples/extensions/skills/change-summary/. No Evener build is needed: copy the skill into your project and use your installed executable. Skills are instructions, not a permission boundary. Even “Do not edit files” is guidance to the model, not an enforced read-only role.
Create a command with arguments
Use a command when you need a reusable prompt with explicit arguments. Create .evener/commands/summarize-change.md in your project:
---
description: Summarize a requested change.
argument-hint: change to summarize
---
Summarize this change: $ARGUMENTS
State the evidence and anything not verified. Do not edit files.Start a new session there and send /summarize-change the current diff as a leading typed prompt. The expanded instruction contains the current diff. Selecting a command chip instead invokes it with empty arguments; surrounding prose is not an argument. Check the command catalog and the expanded session input, not just the model's answer. If the name is absent, check the filename, project root, and load warnings. Avoid client built-in names such as help.
To update or remove a command, edit or delete that file and start a new session. Do not expect a running session's command inventory to refresh. See the command reference for user-global locations and precedence, and plugins for packaging executable commands.
Trust before invocation
Read extensions before loading them. Skills and automatically discovered commands supply untrusted prompt text. Skills never expand shell, file, or argument syntax. Project and user-global commands substitute arguments but do not execute shell or include files. Plugin commands can do both: configuring or installing a plugin is a code-trust decision, not just adding text.
| Source | Discovered from | $ARGUMENTS | !cmd`` | @file |
|---|---|---|---|---|
| Skill | bundled skills; home .agents/skills/; Evener user skills; project .agents/skills/ and skills/ (git root→cwd); skills_dirs; plugins | no | never | never |
| Evener-wide command | .evener/commands/ (git root→cwd), $XDG_CONFIG_HOME/evener/commands/ (~/.config fallback) | yes, inert text | never — stays literal | never — stays literal |
| Plugin command | plugins you installed or configured | yes, inert text | executes (10s timeout, output bounded) | inlines files at cwd-relative paths (symlinks followed) |
Argument substitution is safe in every row: $ARGUMENTS and $1..$9 are always substituted as inert text and can never become a live directive, even in plugin commands.
Skills
A skill is a directory containing a SKILL.md with YAML frontmatter. name and description are required strings. disable-model-invocation and user-invocable are optional strict YAML booleans, defaulting to false and true respectively. Quoted booleans and loose values such as yes are invalid; Evener marks the skill unavailable and reports a machine-readable diagnostic with its source and invalid field. Other descriptive metadata remains inert data. Unsupported behavioral metadata such as context: fork is diagnosed but not acted on. Compatibility diagnostics for well-formed metadata that Evener preserves but does not enforce are advisory and appear only at Full transcript detail. Invalid metadata and unreadable or unavailable skills remain visible at less verbose levels because they require action.
A SKILL.md whose frontmatter block is missing only its opening --- — it begins directly with a mapping entry such as name: and still closes on a whole --- line — is read tolerantly: Evener treats the leading block as frontmatter and reports a missing_frontmatter_delimiter compatibility diagnostic, advisory in the same way as the other preserved-metadata notes. A block that starts with a heading or prose, or that does not carry both a non-blank name and a non-blank description, is not recovered. A file saved with CRLF (or lone CR) line endings reads like an LF one either way, and its delivered body ends its lines in \n.
If ordinary YAML parsing fails, Evener also recovers a single top-level, single-line, unquoted description containing colon-space, such as description: LEGACY: use this skill. Recovery quotes only that description in memory and requires the complete metadata block to decode as one mapping. It preserves comments and refuses continuation lines, YAML syntax such as quotes or tags, duplicate keys, unrelated malformed content and trailing documents. Already-valid YAML keeps its ordinary interpretation. Invocation controls remain strict. Recovery reports an unquoted_description compatibility diagnostic at Full transcript detail.
Discovery and activation share these recoveries. Neither rewrites the source; activation delivers the complete body, and source digests cover the original bytes. Unrecoverable metadata leaves only that skill unavailable. The session emits a skill_diagnostic warning with source-specific guidance for malformed skills, invalid controls and collisions, rather than a session failure or daemon repair advice. CLI, web and native clients consume the shared warning fields. Correcting a source restores availability at the next catalog discovery or session startup. Retained descriptors revalidate current bytes when loaded; there is no live filesystem watcher.
allowed-tools may be one string or an ordered array of strings. Evener preserves it and diagnoses that it is not enforced: it neither grants nor restricts tool access.
Live sessions and cold client catalog reads share this discovery order, from lowest to highest precedence:
- Skills bundled with Evener.
~/.agents/skills/.$XDG_CONFIG_HOME/evener/skills/(~/.config/evener/skills/fallback).- Repository root through cwd, at each level
.agents/skills/thenskills/. - Explicit
skills_dirsentries, in their configured order. - Configured plugin skills, qualified as
plugin:skill.
Deeper project directories win over shallower ones; skills/ wins over .agents/skills/ at the same level. Without a repository, only cwd is scanned. Configured roots remain discoverable when a cold session has no recorded cwd. Each public root scans its immediate children, including readable directory symlinks. Absolute and relative links may point outside the root; discovery does not recurse into nested collections. Symlinked roots and linked SKILL.md files are also supported. Catalog sources and activation base_directory retain the configured, lexical paths, not the target's canonical paths. Links grant no new permissions or trust, and the private bundled-skill cache keeps its separate validation and publication policy.
A broken, looping or unreadable child link produces an unreadable_source diagnostic at that link without hiding healthy siblings. A directory without SKILL.md, or a link to a regular file instead of a directory, is not a candidate. Discovery is a snapshot: restoring a target makes it discoverable on the next catalog read or session startup, not through a new live refresh. A retained descriptor can load again after its target returns, provided the declared identity still matches; loading uses the current bytes. Discovery and loading do not alter the installed links or targets.
Plugins use first-valid-manifest reservation: later manifests with the same plugin name are skipped even if the selected plugin has malformed unrelated components. Skill discovery does not load those commands, agents, hooks, or MCP components. Plugin qualification preserves the declared name separately from the canonical catalog name. Exact names win; a bare suffix resolves only when it uniquely identifies a plugin skill. Ambiguous suffixes have sorted candidates.
Every collision reports the winner in diagnostic source and the displaced source in other_source. A known higher-priority name with invalid metadata reserves its key as unavailable; it never exposes a permissive lower-priority skill instead. Missing automatic directories are normal; unreadable sources, malformed existing skills, and absent configured roots produce diagnostics. Startup warnings and full session inspection expose diagnostics; source paths are excluded from completion and metadata inspection entries.
The model advertisement omits unavailable skills and those with disable-model-invocation: true, including the read_file fallback when use_skill is absent. User completion independently omits unavailable skills and those with user-invocable: false. Full metadata inspection retains hidden and unavailable entries, their controls, and both declared and canonical names. These are advertisement views, not the runtime catalog: lookup retains every known winner for runtime validation and authorization. Neither hiding nor advertising a skill grants permissions or establishes activation history.
Activation identity and persistence
Lifecycle metadata records future ordinary activations only. Existing sessions start with empty ordinary state when no lifecycle snapshot exists; old tool calls, copied history, transcript prose, and raw file reads are not evidence of activation. Metadata stores source identity, file/rendered digests, invocation controls, operation IDs, and delivery obligations, not ordinary skill bodies.
Preparation loads the current source and checks its current invocation flags. Only a server-created genuine user slash or selection route can authorize an ordinary source. That authorization is scoped to the canonical name and exact source: replacing a same-name catalog winner does not inherit it. Model/tool and compaction reload routes may reuse same-source authorization, but it never overrides user-invocable: false on a new user invocation. Role preloads retain separate frozen provenance and their permanent-prompt/frozen-delegate lifetime; they do not grant ordinary authorization. Legacy preload provenance remains unknown rather than being backfilled from a newly discovered skill.
Continuation reopens the recorded source and declared identity, even if that source is no longer the catalog winner. A missing source, including a vanished materialized builtin after restart, fails visibly rather than retargeting. Failed preparation preserves prior inventory. Preparation itself does not record delivery: already_present remains provisional until its delivery obligation is satisfied; unchanged-body satisfaction is not a new-body event. Snapshots preserve obligations and note generation across restart, while the existing pinned-note text and its generation remain authoritative.
Portable directories have the same trust policy as other skills: metadata is discovered, activation reads inert instructions, and subsequent actions still require normal tool permissions and sandbox access. Skills remain untrusted input. Evener does not automatically discover .claude/skills/, execute skill templates, substitute shell directives, or grant tools. Raw file reads do not become tracked skill activations.
When a skill is activated, Evener reads its recorded SKILL.md source, revalidates its current metadata, and delivers the complete instruction body in a structured, data-safe context. The context includes base_directory, the skill directory against which relative references to scripts, references, or other collateral are resolved. Referenced resources are loaded lazily with the ordinary permission-checked tools only when the task needs them; they are not eagerly included with the skill body. Activation does not grant directory access. Sandbox carve-outs cover the standard Evener plugin store and user skills location, including inside masked ~/.config/evener. Other discovered locations, such as arbitrary skills_dirs or ~/.agents/skills, need an existing readable root for collateral access in restricted mode. See sandboxing.
Skill bodies are inert instructions, not executable templates. Evener performs no expansion on them: no shell execution, no file inclusion, no argument substitution. Template-like syntax and context-delimiter text in the body are delivered verbatim as instruction data.
Complete delivery at dispatch
Every tracked route delivers the same complete rendered document: use_skill returns it as tool content, a leading slash or structured selection supplies it as separately identifiable typed context next to your preserved original text and arguments, and a role preload carries it in the permanent prompt. The activation event (SKILL_ACTIVATED) fires only after the complete body is admitted into an actual outgoing model request, not at resolution or tool execution time.
Delivery is complete-or-fail. use_skill has no default output truncation: a skill body is never silently shortened. A configured use_skill output limit produces an explicit complete-delivery failure instead of partial instructions, and the failure is recorded with the machine-readable output_limit code. Admission budgets through the existing token estimator, model context window, and output reservation, with mandatory prompt content and the current request admitted before any reload content. If the final request still cannot fit, the dispatch fails visibly with a context-budget error — it never truncates a protected body, claims success, or starts another compact/reload cycle. If a skill is that large, move conditional detail into reference files under the skill directory; the body should hold the core instructions and point at collateral the model reads lazily with read_file only when the task needs it.
The session inventory (loaded previously) is tracked separately from complete content currently present, and only the latter permits deduplication. A repeat use_skill for identical content returns a provisional already-present notice and keeps a pending delivery obligation. That obligation is revalidated against the final outgoing request: if compaction or projection removed the earlier carrier, the same recorded source is reloaded under the invocation's policy and re-admitted through a typed activation notification linked to the original invocation. Changed disk content produces an explicit change notice with the complete current instructions; a deleted or unreadable source produces a typed failure. Neither is ever reported as a false delivery. Obligations persist across transport retries and restart, and restored sessions reconcile receipts so a retained complete body is proven, not redelivered or double-reported. A failed reinvocation never erases an earlier successful record.
Explicit selection versus typed inline mentions
Guaranteed inline invocation comes from explicit selection. A typed inline /name mention in the middle of prose is preserved as ordinary text: the catalog prompt asks the model to recognize whitespace-bounded canonical slash tokens and call use_skill before acting — while ignoring quotations, fenced code, paths, URLs, and negations — but that interpretation is model behavior, not an enforced parser. When an invocation must be deterministic, select the skill explicitly instead. A leading /name expands in the runtime before the model turn, and a canonical skill selection (the AppWire skill item, or a composer chip) is prepared and admitted by the runtime at the input's actual consumption — independent of where the prose mentions anything. The original request is always preserved verbatim alongside the delivered body, so a selection never rewrites what you typed.
Every route a skill can take, and what each one means:
| Route | Trigger | Deterministic? | Records user authorization? | Result |
|---|---|---|---|---|
user_slash | Leading /name args typed input | yes — runtime expansion | yes | tracked ordinary activation |
user_selection | Canonical skill item selected on the input | yes — runtime preparation at consumption | yes | tracked ordinary activation |
model_tool | Model calls use_skill | no — model choice under current controls | no; a same-source continuation reuses the prior record's answer | tracked ordinary activation |
compaction_reload | Reload selection honored at the next dispatch after compaction | yes, once the selection is recorded | no; reuses the prior same-source answer | restores the recorded activation's body |
role_preload | Delegate role declaration | yes — loaded before the delegate starts | no — frozen provenance | permanent-prompt / frozen-delegate lifetime |
Canonical skill input on AppWire
AppWire's input-bearing turn mutations (turn/start, turn/steer, turn/queue, turn/drainAsSteer, and thread/start) accept skill selections as input items alongside text and images. A skill item is canonical-only: it names the catalog skill and carries nothing else. The user's original text travels as its own item, so a selection never replaces or edits prose:
{
"ref": "local:th_1",
"clientMutationId": "m-47",
"input": [
{ "type": "text", "text": "draft the release notes from the diff" },
{ "type": "skill", "name": "plugin:release-notes" }
]
}The wire rejects any other raw key on a skill item — body, path, and text included. A skill body always loads from the recorded SKILL.md source at activation; it is never carried on the input wire, and a client cannot smuggle one in a field ordinary JSON decoding would silently drop:
{ "type": "skill", "name": "plugin:release-notes", "body": "ignored?" } // rejected
{ "type": "skill", "name": "plugin:release-notes", "path": "/sk.md" } // rejected
{ "type": "skill", "name": "plugin:release-notes", "text": "" } // rejectedNames must be non-blank and are trimmed; duplicate selections are passed through for the runtime's identity and invocation policy to judge. Exact catalog identity and invocation policy remain consumption-time checks.
Selections are consumed at the input's actual claim, not at submission: the queued or started input keeps its selection across the durable queue, journal payload, queue returns, drains, and restarts, and the claimed input prepares all of its selections as one atomic group tied to the input's durable identity (its queue entry, or the stable turn a start or steering mutation reserved). Preparation resolves each name against the exact catalog identity — a bare suffix or unknown name fails rather than retargeting — loads the complete current bytes from the recorded SKILL.md, and checks the current invocation flags. Bytes changed on disk after queueing are what the consumption delivers.
Consumption is all-or-nothing. A group whose second selection cannot be prepared activates nothing and dispatches no dependent model work: the input is recorded as a visible failed input that keeps both the names and the original prose for correction and an explicit retry. A steering input whose selection fails is never downgraded to text: the unrelated in-flight turn keeps running with none of that steering input — not the bodies, not the prose — while a prominent failed-steering record persists before the pending execution clears, again keeping the names and prose for retry.
Submission is capability-gated. ThreadCapabilities.skillInput advertises whether a thread accepts skill items; a daemon-sourced thread advertises it exactly when its input-bearing turn mutations (turn/start, turn/steer, turn/queue, turn/drainAsSteer) are wired to consume selections, and anywhere it is false a skill item is an unsupported-input error rather than a silently degraded message. Diagnostics carry the catalog context clients need to build a selection UI: EvenerSkillInfo reports disableModelInvocation, userInvocable, available, and preserved allowedTools metadata, while EvenerDiagnostics.skillDiagnostics reports discovery problems (collisions, unreadable sources, invalid metadata) with their explicit sources. Completion offers only skills that are both available and userInvocable, and the composer still requires the target's skillInput capability before submitting a selection.
Mixed-version fail-closed and recovery
The Hub is a separate process from the sessions it forwards to, so it never assumes a daemon supports skill input: before any input-bearing mutation carrying a selection is forwarded, the Hub reads the target's advertised capability — on the same connection as the mutation for daemon-sourced threads, and through the relay's own read for turn/start — and rejects the request when the capability is false. This is what keeps a mixed-version deployment honest:
- Hub newer than daemon. An older daemon never sends
skillInput, so an absent capability reads exactly like a false one and every selection is rejected with anunsupported on this targetinvalid-params error. The daemon never sees the request, so no queue entry, journal payload, or turn is created for it. - Unreadable or unknown target. A capability read that fails — an unreachable endpoint, a dying daemon, a read error — is a rejection, never permission.
thread/start's initial input is gated on the spawned session's own read: when that read fails, the synthesized thread carries no capabilities and the selection is refused. The hub's synthesized capability sets (ended threads, roster projections) deliberately leaveskillInputfalse; a capability is only ever learned from a target that actually reported it. - Rejection shape. A rejection preserves what the caller composed: the selection is not degraded into
/skillslash prose, stripped to its text item, or partially delivered. The client keeps its input for an explicit retry. - Recovery. A rejection means the running target does not consume selections, so the fix is on the target side: upgrade or restart the session's daemon (for a stopped session, resume spawns a current daemon) and send the input again. The recheck runs on every attempt — including the automatic resume inside
turn/start, which re-reads the replacement daemon before forwarding — so the same request succeeds once the target that answers advertisesskillInput.
The web composers' canonical selections
The session composer and new-session launcher share the same atomic editor. They keep explicit skill and command selections as distinct canonical data:
- Selecting. The composer's inline slash menu lists skills (only those both
availableanduserInvocable) alongside commands. Choosing a skill row replaces the typed completion token with an indivisible chip carrying the skill's canonical name, in the sentence where it was typed; surrounding text and attachment anchors are untouched, and a pasted or typed inline/namemention that is never explicitly selected stays ordinary text. Completion adds a separating space whenever the text that follows would otherwise join the name, including at the end of the input; punctuation or whitespace that already bounds the reference is left as typed. Choosing a user or plugin command creates a command chip, not a skill chip. Built-in controls keep their existing completion and invocation behavior. The launcher reads the catalog for its selected host, directory, harness and plugins; the session composer filters plugin commands to that session's inventory. A chip is one unit: it is deleted with Backspace or Delete (never edited letter by letter), typing a name character directly against it separates the two rather than dissolving the selection, and undo and redo treat the chip and the edit that placed it as one step. Its details show the skill's description, or a note that the live catalog no longer backs the selection. - Drafts. Each session's sticky draft persists as one structured
{text, skillNames, commandNames?, mentions?}record. Mention locations distinguish command atoms, skill atoms and unselected same-spelling prose. Names alone suffice when every matching reference is a skill atom. Text-only edits map retained atoms to their new UTF-16 locations and remove atoms whose labels were deleted, without selecting same-spelling prose. Selections survive a reload, a thread switch, and a remount next to the text. Changing chips is a draft edit even when the text is byte-identical — a delayed commit clears a draft only when both halves still match what was submitted. On restore a selection is only kept while its complete/<name>reference is still visible in the text, so a name whose mention the user removed does not come back as a hidden activation; a queued entry that carries a selection with no prose of its own has that reference written out, so its chip is visible before it is sent. An existing plain-text draft migrates by reading the old value as literal text with an empty selection list: no old value is JSON-decoded to guess selections, and no slash mention in it is ever inferred as one. - Submission. Selections ride the existing input-bearing mutation as
{type: "skill", name}and{type: "command", name}items appended after the text and image items — there is no second wire shape, outbox, or recovery store for them. The client gates on the same capability the hub does: when a target'sskillInputorcommandInputis false or absent for that selection kind, submission and resend are refused before anything durable is written, the draft is retained, and the failure says the target does not accept selections. - Queue and recovery. The names live in the durable mutation record's own input, so queue drains, recovery edits and resends, and remounts all restore them. Text items also retain
{kind, name, offset}mention metadata, with UTF-16 offsets shifted across attachment translation. The authoritative queue projects these locations for a new client without the original outbox; restoring an entry does not guess kinds or select duplicate quoted prose. Editing locations do not authorize activation. Merging a recovered draft into a composer unions its selections with the currently staged ones, deduplicated by canonical name. The launcher's project-scoped draft retains text, both selection kinds and attachments through navigation, remounts and failed creation.
Explicit command selections
An explicit command item has exactly type and name. The name must be its exact catalog identity, such as pkg:review; a suffix or unknown identity is not retargeted to another command. Selections expand once per canonical name at consumption with empty arguments, wherever their chips appear in the original prompt. Surrounding prose is not $ARGUMENTS. The original prompt remains recorded separately from expanded bodies, and generated command text cannot select or recursively invoke another command.
Expansion keeps the command's source rules: project and user-global templates substitute arguments as inert text, while plugin templates use their existing shell and file expansion. A leading typed /name args keeps its argument behavior. Plain typed or pasted inline mentions remain prose. Command and skill selections with the same spelling still request their own distinct behavior. The daemon's commandInput capability gates the command kind independently of skillInput; refusal keeps the composed request available for correction.
Accepted inputs own prepared command results in the durable mutation journal. All unprepared names resolve before any command runs. Each plugin expansion records an in-progress marker before running its shell and saves its completed body before environment or user-input transcript admission. A returned claim, transcript-write retry or disk restore reuses those completed bytes rather than running the shell again. Queue promotion and draining carry that evidence into the new input owner, and uncertainty for any repeated name takes precedence over a completed result.
An interrupted expansion or missing completion save has an uncertain outcome. It is never automatically repeated: the original prompt and selections remain visible with a failure, and another healthy input can run. Correcting and resending creates a new intent and may run the shell again. External shell effects cannot commit atomically with the journal: a crash after an effect but before the completion save is uncertain, not an exactly-once guarantee. Only durably completed results are known and reusable.
Reload selection at compaction
Compaction can drop a loaded skill's instruction body, so both compaction paths accept a selection of skills to reload from disk afterward. The selection names exact canonical names from this session's successful-inventory records — never tool-call names or history text — and the runtime presents that inventory (names and descriptions) when asking.
- Explicit:
compact_contextaccepts an optionalreload_skillsarray of strings.note_to_selfremains required, and array elements validate as strings; a schema-invalid call is rejected by normal argument validation and schedules nothing. - Automatic: note elicitation asks for the same selection in exactly one
<skill-reload-selection>block containing a JSON object with areload_skillsfield, alongside its free-text note. Only a valid block is removed from the handed-forward note; a missing, multiple, or malformed block authorizes no reload and the note is preserved verbatim. Incidental skill mentions in the note or summary never count as a selection.
Presence distinguishes three outcomes:
| Selection | Meaning |
|---|---|
| Valid list | Reload those skills in listed order; duplicates collapse to first occurrence. An explicit empty array reloads none. |
Absent (omitted or null) | No selection was made; the all-loaded-skills reminder applies. |
| Invalid (malformed, or naming a skill outside the inventory) | Reported with invalid_selection/unknown_skill; no reload is authorized and the reminder applies. |
A present selection — including an explicit empty array — requests the compaction even with an empty note_to_self (which still clears any previous pinned note). Empty note, no instructions, and an absent/null selection keeps the plain clear-note behavior. An invalid selection in an accepted request never discards that request's valid note. A selection belongs to one compaction cycle and is consumed only by a compaction that actually publishes.
Accepted compaction requests survive restart. A failed metadata save returns a retryable error rather than accepting an unsaved request. A successful compaction consumes its request and skill selection after saving the result; interrupted delivery resumes after restart without repeating the compaction.
- Clearing or replacing a note cancels its automatic compaction request, not an explicit
compact_contextrequest. A second explicit request is rejected while the first is pending, leaving the first unchanged. - Later note elicitation cannot replace the pending cycle's skill selection.
- A fold that changes no content leaves the request pending. An unrelated manual compaction does not consume it. If an explicit compaction exhausts its retries without publishing, it cancels its request with a
forced_not_publishednotice. - Sessions saved before compaction lifecycle metadata existed start with fresh compaction state; Evener does not reconstruct requests from old tool calls.
The context-pressure nudge lists the loaded skill names either way: with compact_context available it asks for the selection through reload_skills; without the tool it lists the skills for awareness and keeps its existing note advice, never requesting a structured response the model cannot submit. It omits descriptions; automatic note elicitation still carries them.
Reload delivery after compaction
The next model request after a publication consumes its handoff receipt — and every other recorded, unconsumed handoff, whichever phase the publication or restart reconciliation left it in. A valid selection reloads exactly its named skills: each reload reopens the ordinary record's own recorded source — never a catalog winner, so a missing or identity-replaced source fails explicitly (source_missing / source_changed) rather than retargeting — and delivers the complete current bytes from disk through the shared loader and renderer. A changed source is reported with both the old and new digests and both flag generations in the typed outcome. A name held only by a preload needs no disk load: selecting it is a no-op.
An absent or invalid selection authorizes no body. Instead the session delivers one complete typed inventory notification listing every loaded skill — both provenances when a name holds a frozen preload and an ordinary activation — each classified from current source metadata and actual retained content:
| Availability | Meaning |
|---|---|
already_present | Complete current content is already in the retained tail or was restored by another activation; reusing it needs nothing. |
reloadable | The session can reload it: an authorized same-source continuation regardless of current flags, or current controls still admit the reload route. |
requires_user_activation | Hidden but user-invocable: current controls block the model's routes; only a genuine user invocation restores it. |
unavailable | Both flags block every ordinary route, or the recorded source can no longer be read (each unreadable source is diagnosed). |
permanent | A frozen role preload, which keeps its permanent-prompt lifetime. |
The full list is always delivered — never trimmed to fit. In sessions without the use_skill tool the reminder explains the untracked fallback: reading the skill's SKILL.md directly restores the text to the conversation but is not a tracked activation.
Reload bodies are admitted in selection order against the request's real remaining budget: a new explicit activation already in the conversation outranks them, each admitted reload consumes from the running total, and one that does not fit fails individually with a typed context_budget outcome — never a truncated body, never a second compaction or model-repair round. Complete content already present in the retained tail or restored by another activation is reused rather than duplicated, keeping a pending delivery obligation until final admission. A failed reload stays visible as its own typed outcome and never erases the earlier successful record.
After the reload carriers and obligations (or the reminder notification) are durably recorded, the consumed receipts are removed by publication identity — touching no other pending operation — and the snapshot save plus the transcript receipt reconciliation keep a restart from repeating delivery.
Evener-wide slash commands
An Evener-wide slash command is a markdown file — frontmatter optional — in one of two places:
<any dir from git root to cwd>/.evener/commands/name.md(project commands)$XDG_CONFIG_HOME/evener/commands/name.mdor~/.config/evener/commands/name.md(user-global commands)
The filename is the command name. Names cannot contain whitespace (invocation parses the name up to the first space, so a spaced name can never run) or colons (: is the plugin-namespace separator; evener skips such files with a warning). Invoke it by typing /name args in a session. Optional frontmatter: description, argument-hint, model, allowed-tools (the last two are parsed but not enforced; their compatibility advisory appears only at Full transcript detail).
Expansion substitutes $ARGUMENTS and $1..$9 as inert text. !cmd spans and `@file` references in an Evener-wide command body never execute or read anything — they remain in the expanded text verbatim except that argument substitution still applies inside them as inert text — and evener warns at load time if an Evener-wide command contains `! spans. If you want an executable template, package it as a plugin command instead.
Precedence: project > user-global > plugin. An Evener-wide command shadows a plugin command of the same bare name; the plugin command stays reachable as /plugin:name. Within project commands, the directory closest to your cwd wins.
Client caveats
- The browser intercepts its built-in slash controls before session input. Avoid names such as
/status,/model,/help,/steer, and/queue. Use distinct names for your commands. Headless input does not use that menu. - The web UI opens inline completion when you type
/in either composer. Mod+K opens the separate command palette. Selecting a command in inline completion stages an atomic empty-argument invocation. Leaving a leading/name argsas typed text retains normal command parsing; unmatched inline mentions are prose. The launcher reserves its built-in invocation names. - Live inline completion uses the owning session's loaded command inventory, including project commands for its cwd, host and harness.
thread/readexposes that path-free inventory asthread.evener.diagnostics.commands; absent or empty inventory never borrows controller commands. Switching sessions replaces the offered rows. The separate Mod+K palette retains controller-wide discovery, while the launcher discovers the target before creation. - Standalone skills are not command-file entries in the command catalog, but an exact
/skill-nametoken is recognized by the session when that skill is loaded and activates the skill body. Skill names and descriptions are shown in the model's skill catalog.
Plugin commands
Plugins (installed via the marketplace or configured via plugin_dirs) may ship commands/*.md files. In addition to $ARGUMENTS substitution, !`cmd` spans execute in the session environment and @file inlines files at working-directory-relative paths (the constraint is lexical; symlinks are followed). Only install plugins you trust — a plugin command's body runs shell commands with the same permissions as the session.
Plugin commands are namespaced: /plugin:name. The bare /name form resolves to the plugin command when no evener-wide command shadows it and no client built-in intercepts it (the client caveats above apply to plugin commands too). If two plugins define the same command name, the bare form resolves to one of them — which one is not guaranteed; use the qualified form to be sure.
Evener parses a plugin command's model and allowed-tools frontmatter but does not yet enforce either override per turn. The command runs with the session's default model and tools. Its load-time compatibility advisory appears only at Full transcript detail.
Security checklist for command authors
- Treat every
.evener/commands/file in a repo you did not write as untrusted text. Evener guarantees it cannot execute, but its contents still become prompt text for the model — read it before invoking it. - Never put secrets in command bodies; they are sent to the model verbatim.
- If you need shell output in a prompt, prefer a plugin command (explicit trust) over asking users to paste output manually.