How do I create a command extension?
A command extension is a prefix-triggered shortcut in the chat UI that dispatches a handler prompt when invoked.
When would I use a command?
Use a command when you want a repeatable action that’s faster to invoke than typing a full request. Good candidates:
- Repetitive prompts —
/summarize,/translate,/diffthat you run several times a week - Workflow shortcuts —
/standupthat assembles your daily update from recent context - Team conventions —
/reviewthat applies your code review checklist to whatever you paste - Agent routing —
@researcherto address a message directly to a specific agent
Commands are not for long-running autonomous work — use a job extension for that.
How do I create one by chatting?
Tell Daemion what you want. The agent writes the extension record for you:
You: Create a /deploy command that runs my deploy script
Daemion: I’ll create that command extension for you.
The
/deploycommand is ready. When you type/deployin chat, I’ll prompt you to confirm and then execute your deploy script. Want to add any arguments — like an environment flag (/deploy staging)?
You: Yes, add an optional env argument that defaults to production
Daemion: Updated —
/deploynow accepts an optionalenvargument. Defaults toproductionif omitted. Try/deploy stagingto test it.
The extension is created in SQLite immediately. No restart needed.
How do I create one via the API?
The API is the programmatic path — for scripts, CI pipelines, or agents creating commands at runtime. Chat is the primary path for humans.
curl -X POST http://localhost:3001/extensions
-H “Authorization: Bearer $DAEMION_TOKEN”
-H “Content-Type: application/json”
-d ’{
“type”: “command”,
“name”: “deploy”,
“description”: “Trigger a deployment with an optional environment argument.”,
“definition”: {
“prefix”: ”/”,
“args”: “env?”,
“handler”: “The user wants to deploy. If an env argument was provided use it, otherwise default to production. Confirm the target environment with the user before proceeding, then execute the deploy script.”
},
“source”: “user”,
“enabled”: true
}’
The gateway validates definition against CommandDefinitionSchema and returns the created extension with its assigned id.
What does the command schema look like?
Defined in src/schema/extension.ts:24-28:
// CommandDefinitionSchema — the shape of definition for type: “command” interface CommandDefinition { prefix: ”/” | ”@” | ”!” | ”#”; // which prefix triggers this command args?: string; // optional argument descriptor, e.g. “env?” or “query” handler: string; // prompt string dispatched when the command fires }
The top-level extension envelope (shared across all 12 types):
interface Extension { id: string; // e.g. “ext_09def789” — assigned by gateway on creation type: “command”; name: string; // unique per type, kebab-case, 1-100 chars description: string; // human-readable, max 500 chars definition: CommandDefinition; source: “built-in” | “user” | “agent” | “community”; enabled: boolean; created_at: string; // ISO 8601 updated_at: string; // ISO 8601 }
Frequently asked questions
/ is the conventional slash-command style. @ is conventionally used to address a specific agent (@researcher). ! and # are available for your own conventions. The prefix is displayed in the UI autocomplete and is part of how the command is invoked.args in the definition. The value is a descriptor string (e.g. "env?" for an optional env flag, "query" for a required search term). The handler receives whatever the user typed after the command name as part of its invocation context./extensions with source: "agent". Agent-created extensions start disabled — the user enables them. This is the pattern for letting Daemion build its own toolset during a conversation.PATCH /extensions/:id to update fields or DELETE /extensions/:id to remove it. See the Extensions API for the full reference.POST /reseed to sync without restarting.What can go wrong
400 {"error": "validation failed"} — The definition failed CommandDefinitionSchema validation. The most common cause is an invalid prefix value — only /, @, !, and # are accepted. Check that handler is a non-empty string.
401 {"error": "unauthorized"} — The Authorization header is missing or the bearer token doesn’t match the gateway token. The token is in ~/.daemion/.gateway-token. Use $DAEMION_TOKEN in your shell.
403 {"error": "cannot disable essential extensions"} — Essential built-in commands cannot be disabled. Create a new command with source: "user" and a different name to add custom behavior.
403 {"error": "cannot delete essential extensions"} — Essential commands cannot be deleted.
What’s next?
- How do I create an agent extension? — give Claude a persistent identity and system prompt
- How do I create a job extension? — scheduled autonomous work units
- Extensions API — full CRUD reference