Reference
~1.8k tokens

Commands

Type / in the input box to open the command palette.

Built-in commands

CommandDescription
/compactSummarize and compact conversation history (optional guidance)
/newStart a new session
/forkFork this session and switch to the copy
/helpShow keybindings
/usageShow token usage breakdown
/queueRemove items from queue
/modelSwitch model
/themeSwitch color theme
/mcpConfigure MCP servers
/loginAuthenticate with an LLM provider
/cdChange working directory
/btwAsk a quick question (no tools, no history pollution)
/yoloToggle YOLO mode (skip all permission prompts)
/fastToggle fast mode (Anthropic Opus or Codex subscription models)
/workflowToggle workflow mode (task callable inside code_execution)
/exitExit the application
/reloadReload plugins and config
/trustTrust this folder and load its shared project config
/packupdateUpdate packages (++lockfile, ! skips review)
/packdelRemove undeclared packages (++all, or a name)
/memoryView, edit, and delete memory files
/renameRename the current session
/sessionsBrowse and switch sessions
/tasksBrowse and search tasks
/thinkingExtended thinking: pick an effort level, or set one directly

Sessions

Sessions run concurrently. /new starts a fresh session while the old one keeps working in the background, and /sessions shows the live status of each (working, needs input, idle) so you can jump between them. When a background session finishes or needs input, Maki flashes a note in the status bar. /rename renames the current session; in the session picker, Ctrl+N / Ctrl+R / Ctrl+D create, rename, and delete. Deleting the current session starts a fresh one and keeps the picker open.

Modes and toggles

  • /yolo: skip permission prompts for this session (deny rules still apply). The toggle survives a resume, and --yolo only sets the starting value. Config: always_yolo = true.
  • /thinking: extended thinking. Bare, or Alt+T, it opens a picker that shows what each level costs in tokens. With an argument it sets the level directly: off, adaptive, minimal to max, or a token budget. New sessions start at the last level you set, in -p, SDK and ACP too. Config: always_thinking pins a level.
  • /fast: faster responses on Anthropic Opus, and on eligible Codex models when you sign in with a ChatGPT subscription. OpenAI API keys and every other model ignore it. Config: always_fast = true.
  • /workflow: let code_execution call the task tool (and other workflow-only tools) from inside the Python sandbox. Config: always_workflow = true.
  • Plan / build: not a slash command. Press Tab in the input to toggle plan mode (plan-file writes only).
  • /reload: rebuild plugins and config without leaving the app.
  • /btw: one-shot side question with no tools and no history pollution.
  • /memory: open the memory file picker (view / edit / delete). See the memory tool under Tools.

Custom commands

You can define your own slash commands as Markdown files. Empty files are skipped.

Discovery and priority

Later sources override earlier ones when the command name matches (the stem of the file, or name in frontmatter):

  1. User config: ~/.config/maki/commands/ (and legacy ~/.maki/commands/ if present)
  2. User third-party: ~/.claude/commands/
  3. Project dirs, walking from the current working directory up to the nearest .git root. At each level: .maki/commands/, then .claude/commands/

Because the walk goes cwd → … → git root, a command at the repository root overrides the same name found only under a nested cwd. Project commands override user commands. Palette names are /project:<name> or /user:<name> depending on which scope won.

Skip all of the above with --no-commands (see CLI).

Metadata

You can add optional metadata at the top of the file between --- lines to set name, description, and argument-hint:

---
description: Review code for issues
argument-hint: <file>
---
Review $ARGUMENTS and suggest improvements.

Arguments

Use $ARGUMENTS in the command body. It gets replaced with whatever you type after the command name. The command is treated as accepting args if the body contains $ARGUMENTS or you set argument-hint.

For example, /project:review main.rs replaces $ARGUMENTS with main.rs.

Aliasing commands

Prefer a different name for a command? maki.api.run_command runs any slash command exactly as typing it would, so an alias is a one-line handler in your init.lua instead of a reimplementation.

-- ~/.config/maki/init.lua
local aliases = {
    { name = "/clear", target = "/new", description = "Alias for /new" },
    { name = "/resume", target = "/sessions", description = "Alias for /sessions" },
}

for _, alias in ipairs(aliases) do
    maki.api.register_command({
        name = alias.name,
        description = alias.description,
        handler = function()
            local ok, err = maki.api.run_command(alias.target)
            if not ok then
                maki.ui.flash("could not run " .. alias.target .. ": " .. err)
            end
        end,
    })
end

Aliasing adds a name, so both stay in the palette. Any command works as a target, including MCP prompts and other plugins' commands. See maki.api.run_command for matching and error handling, or maki.ui.action to bind a key instead of a name.

What a plugin may run

run_command only runs what the calling plugin's grants cover. Your init.lua counts as a plugin, and its grants come from ~/.config/maki/plugin.toml (see plugin permissions). Commands not listed here run for any plugin.

  • Needs fs_read, fs_write: /memory.
  • Needs fs_read, fs_write, net, run, env: /tasks.
  • Needs agent: /compact, /btw, custom commands, MCP prompts.
  • Needs what its owner holds: every other plugin command, as described below.
  • Only when you type it: /yolo, /trust, /packupdate, /packdel. These change permissions, folder trust, or installed packages.

A plugin command's handler runs with the grants of the plugin that registered it. The caller picks the arguments, so it must hold at least the same reach:

  • Every permission the owner holds.
  • Host access as wide as the owner's. A caller without net_hosts has it. A caller with a list needs the owner to have one too, and must contain each of its entries exactly as written, so *.example.com does not cover api.example.com.
  • Its own provider on the address of each provider the owner registered. That address may be on your LAN, which net_hosts cannot grant.

A caller granted run skips both address checks, since a process it starts can reach any host.

Related: CLI for shell flags and subcommands, Skills for on-demand playbooks.