Skip to main content

Customization

Shape how the AI works in your repo with plain files in the .editvolt/ folder — versionable, reviewable, and shareable with your team.

.editvolt/
├── rules/ # house rules injected into every conversation
├── skills/ # repeatable multi-step workflows
├── subagents/ # specialized delegate agents
├── commands/ # your own slash commands
├── hooks/ # event hooks created in the Studio
├── hooks.json # hand-written hooks (merged with hooks/)
├── mcp.json # Model Context Protocol servers (project-scoped)
├── permissions.json # terminal + MCP allowlist
├── index/ # local vector index (generated)
└── grep-index/ # local text index (generated)

A fresh workspace is seeded with rules/, skills/, subagents/ and commands/ automatically (product.customization.seedDefaults). The generated index folders are git-ignored for you.

The Customization Studio

EditVolt Settings → Customization Studio is the UI over all of this — rules, skills, subagents, commands, hooks, and MCP servers in one place, with a + New form for each. The palette has direct entries too: EditVolt: Add Rule, Add Command, Add Hook, Add MCP Server.

See Settings for a full click-through walkthrough with screenshots of every tab. This page is the file-format reference — what to write if you're authoring a file by hand, scripting one, or just want to know exactly what each field does.

Shared frontmatter fields

Rules, skills, subagents, and commands are all a Markdown file with the same YAML-ish frontmatter shape:

---
name: Human-readable name
description: One line (or a multi-line block, see below)
activation: always | manual | intelligent | pathGlob
pathPattern: "**/*.ts" # only read when activation is pathGlob
slashName: short-name # optional; overrides the auto-derived /token
alias: another-name # optional; a second slash token
tags: quality, security # optional; free-form, shown in the Studio
enabled: false # optional; omit for enabled (the default)
---

The body. For a rule this is the guidance text; for a skill or command it's
the playbook the agent follows; for a subagent it's the persona/system prompt.

Only name is really required — everything else has a sensible default. Field notes:

FieldNotes
descriptionShown in the Studio list and (for intelligent skills) matched against the user's message each turn. Can be a single line, or a YAML block scalar (| preserves line breaks, > folds them into one paragraph) for something longer — see below.
activationSee Activation modes.
pathPatternA glob or comma-separated glob list, e.g. **/*.{ts,tsx}, src/**. Only meaningful when activation: pathGlob.
slashName / aliasWithout one, the short /token is derived from name or the folder slug. Set slashName when you want a specific, stable token regardless of how the name changes.
enabledAny value other than the literal false counts as enabled — this is what the Studio's Disable row action toggles.

A description longer than one line can use a block scalar instead of one giant line:

description: |
First sentence: what this is for.
Second sentence: when to reach for it instead of something else.

Activation modes

ModeWhen it firesApplies to
alwaysEvery single turn, unconditionally.Rules, skills
pathGlobTurns where the active file (or an attached file) matches pathPattern.Rules, skills
intelligentSkills only: auto-matched against the user's message each turn and its body is read in without being asked. Rules: never auto-matched by content — behaves like manual until explicitly invoked.Rules, skills, subagents, commands
manualNever automatic — only runs when invoked with /token (or the model calls it explicitly for a skill).Rules, skills, subagents, commands

Two things worth knowing before you pick a mode:

  • always costs a share of every prompt, forever. It's right for something small and universal ("cite the rule when you bend it"); for anything file-specific or topic-specific, prefer pathGlob or intelligent so it only shows up when relevant.
  • intelligent only auto-matches for skills. A rule set to intelligent is discoverable and slash-invocable, but — unlike a skill — its description is never matched against the conversation to pull it in automatically. If you want a rule to always apply to, say, every SQL file, use pathGlob, not intelligent.

Subagents accept the same activation field, but nothing currently reads it — a subagent is always listed and is only ever used when delegated to (see Subagents).

Rules

.editvolt/rules/<slug>/RULE.md — standing guidance injected into the system prompt. Good for constraints that should hold across the whole repo: "validate at trust boundaries, not in the middle", "cite the rule when you deliberately bend it".

---
name: Handle errors at boundaries
description: Validate and handle errors only at system boundaries -- never in the middle of business logic.
activation: always
---

Validate and handle errors at system boundaries only -- API handlers, file I/O,
network calls, and other entry points for untrusted input. Once a value is
inside the trust boundary, treat it as already valid. Never let an unhandled
exception reach the user: catch it, log enough context to debug, and return a
clear, actionable message.

A rule scoped to a subset of files uses pathGlob instead:

---
name: Parameterise data access
description: Never concatenate user-controlled values into a query.
activation: pathGlob
pathPattern: "**/*.{sql,ts,js,py,go,rb,java}"
---

Bind user-controlled values as parameters -- never concatenate them into a
query string, even when the input is "validated upstream".

Skills

.editvolt/skills/<slug>/SKILL.md — a repeatable playbook. Set activation: intelligent and write a specific, distinctive description; that's what the agent matches your message against to decide whether to read the skill in on its own. You can also invoke any skill explicitly with /token, or by asking for it by name.

---
name: Summarize a long document
description: Read a document and produce a structured summary -- overview, key points, open questions.
activation: intelligent
tags: docs
---

Read the target document, then produce a summary with: a one-paragraph
overview, the key points as a bullet list, and any open questions or risks
called out separately. Preserve technical terms exactly; do not paraphrase
numbers, names, or version identifiers.

A more elaborate skill can walk through multiple steps and even reference sibling files in its own folder (.editvolt/skills/<slug>/references/*.md) for the agent to read on demand:

---
name: Scaffold a REST endpoint
description: Add a new REST endpoint -- route, handler, input validation, and a test -- following this repo's existing pattern.
activation: intelligent
tags: build
---

1. Find an existing endpoint in the same area and copy its shape (routing,
handler signature, validation, error responses).
2. Add the new route, then the handler, then validation for every input.
3. Write one test for the happy path and one for a validation failure.
4. Run the test suite for the changed package before saying you're done.

Subagents

.editvolt/subagents/<slug>/SUBAGENT.md — a focused delegate the main agent can hand a task to (via the subagent.delegate tool, or /delegate). The body is the persona/system prompt the delegate runs with; description is what the main agent sees when deciding whether this subagent fits a task.

---
name: API contract reviewer
description: Reviews changes to a public API surface for breaking changes.
activation: intelligent
---

You review changes to a public API surface (REST routes, function signatures,
exported types). Flag any breaking change -- a removed field, a renamed
parameter, a stricter validation rule -- and say what would break for
existing callers. Suggest a backward-compatible alternative when one exists.

A subagent runs as its own isolated turn against the same provider — it doesn't see the parent conversation, only the task description it's handed, so write its persona to be self-contained.

Hooks

Actions that fire on agent events — preToolUse, postToolUse, userPromptSubmit and a dozen more (the full list is in Settings). Hooks created in the Customization Studio are written to .editvolt/hooks/<name>/HOOK.md; hand-written .editvolt/hooks.json entries are merged with them at runtime. A hook either injects text into the turn or runs a shell command.

SettingDefaultDescription
product.hooks.enabledtrueMaster switch
product.hooks.shellEnabledfalsePermit hooks to run a command; each still asks once, showing the command
product.hooks.showInChattrueRender an inline marker when a hook fires

Commands

.editvolt/commands/<slug>/COMMAND.md — your own /slash workflow, alongside the built-ins (see Chat & modes). Commands default to activation: manual, since a command is something you choose to run, not something the agent should reach for on its own.

---
name: changelog-entry
description: Draft a Keep a Changelog style entry for the currently staged changes.
activation: manual
---

Look at the currently staged changes and draft one Keep a Changelog style
entry (Added / Changed / Fixed / Removed) describing them for an end user,
not a developer. Ask which section it belongs in if it is not obvious.

MCP servers

Connect a Model Context Protocol server to give the agent extra tools — databases, ticketing systems, internal APIs, anything with an MCP server. product.mcp.enabled is the master switch (on by default); there's no other opt-in — a server is live as soon as it's declared and trusted.

Config lives in .editvolt/mcp.json (project — shared with the repo) or ~/.editvolt/mcp.json (global — this machine only), both under a single mcpServers key:

{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/projects/my-app"]
}
}
}

That's a stdio server — EditVolt spawns command as a child process and speaks MCP over its stdin/stdout. A remote server instead gives a url:

{
"mcpServers": {
"internal-api": {
"type": "http",
"url": "https://mcp.internal.example.com",
"headers": {
"Authorization": "Bearer ${input:internal-api-token}"
}
}
}
}

Never write a credential directly into mcp.json — declare it as an input instead and reference it with ${input:id}; EditVolt prompts for it once and stores it in your OS keychain, not in the file:

{
"inputs": [
{ "id": "internal-api-token", "type": "promptString", "description": "Internal API token", "password": true }
],
"mcpServers": {
"internal-api": {
"type": "http",
"url": "https://mcp.internal.example.com",
"headers": { "Authorization": "Bearer ${input:internal-api-token}" }
}
}
}

A server's tools show up to the agent as mcp__<server>__<tool>, available in Agent mode. Every MCP tool call asks for consent the first time it runs, in the same allowlist as terminal commands (.editvolt/permissions.json); approving with Remember skips the prompt next time.

Project-scoped MCP servers are deliberately not honored in agent-created managed workspaces. A workspace the agent created and can freely write into must not be able to grant itself a new launchable executable — that would be the agent handing itself standing permissions it didn't have a moment ago. Point EditVolt at a real folder you opened yourself if you need a project-scoped MCP server.

Import what you already have

The Customization Studio imports your existing Cursor, Claude, and Copilot configurations and AGENTS.md files — including honoring .cursorignore. Keep this on with product.customization.includeForeign (default true).