### Quick Start Commands Source: https://maki.sh/docs/quick-start Installation commands for Linux/macOS, Windows, Nix, and Cargo; provider authentication; first session; default model configuration; project structure. ```bash curl -fsSL https://maki.sh/install.sh -o install.sh cat install.sh # Then run. chmod +x install.sh && sh install.sh ``` ```bash curl -fsSL https://maki.sh/install.sh | sh ``` ```powershell irm https://maki.sh/install.ps1 -OutFile install.ps1 Get-Content install.ps1 ``` ```bash cargo install --locked --git https://github.com/tontinton/maki.git maki ``` ```bash nix run github:tontinton/maki ``` ```bash maki auth login # interactive picker (OAuth or API key) export ANTHROPIC_API_KEY=... # or just export a key ``` ```bash maki ``` ```lua -- ~/.config/maki/init.lua maki.setup({ provider = { default_model = "anthropic/claude-sonnet-4-6", }, }) ``` ```text .maki/ ├── init.lua # overrides global config ├── permissions.toml # permission rules ├── mcp.toml # MCP server config ├── commands/ # custom slash commands (.md files) └── skills/ # project skills (each dir has a SKILL.md) AGENTS.md # always in context AGENTS.local.md # personal per-project instructions (gitignored) ``` -------------------------------- ### Install a package by hand into pack directory Source: https://maki.sh/docs/packages Shows the directory layout for manually installing a package into a Neovim-style package directory. Use any group name except core, which Maki reserves and never scans. A start package loads at startup; an opt package stays installed until activated. Manual placement grants the package exactly the permissions its plugin.toml requests without an approval step. ```text /site/pack//start// /site/pack//opt// ``` -------------------------------- ### Instruction file loading example Source: https://maki.sh/docs/context Shows which instruction files are loaded at session start. Maki walks from the git root down to the working directory, loading one project file per directory (first match wins) plus AGENTS.local.md if present. Closer directories win on conflicts, and a global ~/.config/maki/AGENTS.md is always loaded. ```text ~/repo/AGENTS.md loaded (root) ~/repo/AGENTS.local.md loaded (yours, gitignored) ~/repo/api/CLAUDE.md loaded when cwd is ~/repo/api, wins over root ~/repo/web/AGENTS.md not loaded yet... ~/.config/maki/AGENTS.md loaded (global) ``` -------------------------------- ### Everyday maki CLI usage examples Source: https://maki.sh/docs/cli A set of everyday command-line examples for the maki CLI, covering TUI usage, one-shot prompts, session continuation, model listing, authentication, and tool inspection. ```bash # TUI on a project cd ~/code/my-app && maki # One-shot with YOLO and a model pin maki -p --yolo -m anthropic/claude-sonnet-4-6 "summarize the architecture" # Resume yesterday's session maki --continue # List models, then log in maki models maki auth login # Inspect tools without starting a session maki prompt --tools --names ``` -------------------------------- ### Telemetry configuration example in init.lua Source: https://maki.sh/docs/telemetry Example of setting up telemetry in maki.setup with enabled flag, exporters, protocol, endpoint, headers, and resource attributes. All durations are in milliseconds and floored at 100ms. Exporter values can be otlp, console, none, or a comma-separated mix. Protocols are grpc, http/protobuf, and http/json. ```lua maki.setup({ telemetry = { enabled = true, metrics_exporter = "otlp", logs_exporter = "otlp", protocol = "grpc", endpoint = "http://localhost:4317", headers = { ["x-api-key"] = "secret" }, resource_attributes = { team = "core", env = "dev" }, }, }) ``` -------------------------------- ### Start ACP server Source: https://maki.sh/docs/acp Command to start the Maki ACP server over stdio. ```bash maki acp ``` -------------------------------- ### Configure bundled plugins in maki.setup Source: https://maki.sh/docs/configuration Example of configuring the `plugins` table in `maki.setup`. Shows disabling `websearch` and setting a custom `timeout_secs` for `bash`. All bundled plugins are on by default; set `enabled = false` to turn one off. ```lua maki.setup({ plugins = { bash = { timeout_secs = 180 }, websearch = { enabled = false }, }, }) ``` -------------------------------- ### Install packages from Git with maki.pack.add Source: https://maki.sh/docs/packages Declares managed packages in the global init.lua, normally ~/.config/maki/init.lua. Each entry is a source string or a table with src, version, name, and data. Maki shows all new packages in one install prompt and writes the selected commit to pack-lock.json. ```lua maki.pack.add({ "https://github.com/example/maki-goal", { src = "https://github.com/example/maki-review", version = "v1.2.0", }, }) ``` -------------------------------- ### Example skill directory path Source: https://maki.sh/docs/skills Shows the directory layout for a skill named 'git-release' under the project's .maki/skills folder. ```text .maki/skills/git-release/SKILL.md ``` -------------------------------- ### Complete Configuration Example Source: https://maki.sh/docs/configuration Shows the full set of optional settings for maki.setup() in init.lua. All fields are optional; typos cause an immediate error. A project init.lua runs only after folder trust is granted. The provider policy with allowed and excluded models applies to selectors, CLI/API changes, delegation, and the `maki models` command. maki.setup() can only be called once per init.lua. ```lua maki.setup({ ui = { splash_animation = true, mouse_scroll_lines = 5, theme = "tokyonight", tool_output_lines = { bash = 8, read = 5, }, }, agent = { max_output_lines = 3000, }, provider = { default_model = "anthropic/claude-sonnet-4-6", allowed_models = { "anthropic/*", "openai/gpt-5" }, excluded_models = { "*/*-preview" }, }, storage = { max_log_files = 5, }, plugins = { bash = { timeout_secs = 180 }, index = { max_file_size_mb = 4 }, }, }) ``` -------------------------------- ### Install package with confirm = false Source: https://maki.sh/docs/packages Sets confirm = false to skip the install prompt when the package source is already trusted and Maki must run without a terminal. This option does not approve package permissions. Maki rejects HTTP sources with credentials. ```lua maki.pack.add({ "https://github.com/example/maki-goal" }, { confirm = false, }) ``` -------------------------------- ### maki acp: start ACP server Source: https://maki.sh/docs/cli Start an ACP server on stdio for editors like Zed. Subcommand flags are only `-m`/`--model` and `--yolo`. Global flags like `--no-jit` must come before the subcommand. ```bash maki acp maki acp -m anthropic/claude-sonnet-4-6 maki acp --yolo maki --no-jit acp ``` -------------------------------- ### Example SKILL.md for git-release Source: https://maki.sh/docs/skills A complete SKILL.md file with optional frontmatter providing name and description, followed by the skill steps. The frontmatter is optional; without it the directory name becomes the name and the whole file is the body. ```markdown --- name: git-release description: Cut a tagged release and open the changelog PR --- ## Steps 1. Read `CHANGELOG.md` and the commits since the last tag. 2. Propose a semver bump and a short release summary. 3. Only tag after the user confirms. ``` -------------------------------- ### maki index: print file skeleton Source: https://maki.sh/docs/cli Run the `index` tool on a file and print the skeleton, so you can see what the agent will get before a session. Builtin plugins always load here; `--no-plugins` only skips user `init.lua`. ```bash maki index path/to/file.rs ``` -------------------------------- ### MCP prompt slash command examples Source: https://maki.sh/docs/mcp Examples of Maki slash commands for MCP prompts. Use /server:prompt-name syntax. Prompts can have no arguments, one argument, or multiple positional arguments. Skipping a required argument shows a usage hint. ```plaintext /github:create-pr # no arguments /analytics:report monthly # one argument /review:code src tests # multiple, positional ``` -------------------------------- ### Configure allowed_private_hosts in maki.setup Source: https://maki.sh/docs/configuration Configure the net guard to allow specific private hosts. The example lists localhost:8080, nas.lan, and the CIDR range 10.0.0.0/8. An entry without a port covers every port; a listed name is allowed whatever it resolves to, and every redirect hop is checked against the same list. ```lua maki.setup({ net = { allowed_private_hosts = { "localhost:8080", "nas.lan", "10.0.0.0/8" }, }, }) ``` -------------------------------- ### Send stream-json user message with --max-turns Source: https://maki.sh/docs/headless Quick example of sending a stream-json user message to Maki with --max-turns 3. One-shot --print always starts a new session in build mode; plan mode and session resume need the SDK path or the TUI. ```bash echo '{"type":"user","message":{"content":"explain this repo"}}' \ | maki --print --input-format stream-json --max-turns 3 ``` -------------------------------- ### Install package with custom load function Source: https://maki.sh/docs/packages Sets load to a function when the package needs a custom entry point. The function runs as the package owner and receives the package spec and its installed path. The data field can contain any Lua value. ```lua maki.pack.add({ { src = "https://github.com/example/maki-review", data = { module = "review" }, }, }, { load = function(package) require(package.spec.data.module).setup() end, }) ``` -------------------------------- ### maki update and rollback Source: https://maki.sh/docs/cli Update to the latest release or roll back to the previous version. `-y` skips confirmation, `--no-color` disables colored output. Uses the same install locations as the install scripts. ```bash maki update # install latest release maki update -y # skip confirmation maki update --no-color maki rollback # previous version ``` -------------------------------- ### index vs read: skeleton then targeted read Source: https://maki.sh/docs/token-economy Compares reading a whole file versus using the index tool to get a tree-sitter skeleton (imports, types, signatures, line numbers) and then reading only the needed ranges. ```text read main.rs index main.rs ──────────── ───────────────────────────── 1400 lines in context 60 lines of signatures + read offset=812 limit=40 ``` -------------------------------- ### Enable YOLO mode always in init.lua Source: https://maki.sh/docs/permissions Configure Maki to start in YOLO mode every time by setting always_yolo = true in the init.lua configuration file. This skips prompts on gated tools, but explicit deny rules still apply. ```lua -- ~/.config/maki/init.lua maki.setup({ always_yolo = true, }) ``` -------------------------------- ### Activate a package with maki.packadd Source: https://maki.sh/docs/packages Activates an installed package or a managed package declared with load = false. Call it from init.lua or from another package; Maki loads the named package after the calling Lua task returns. ```lua maki.packadd("my-package") ``` -------------------------------- ### Model identifier examples Source: https://maki.sh/docs/providers Shows the provider/model_id format used to reference models in Maki. The prefix can be omitted if the model name is unique across providers. ```text anthropic/claude-sonnet-4-6 openai/gpt-4.1 xai/grok-4.6 zai/glm-4.7 ``` -------------------------------- ### Remove all undeclared packages with /packdel ++all Source: https://maki.sh/docs/packages Removes every installed package that is no longer declared. Maki displays the packages it is about to remove and waits for acceptance. Packages still active in this or another Maki process are refused. Use /packdel! to skip the review; refusals still apply. ```text /packdel ++all ``` -------------------------------- ### permissions.toml with per-tool allow/deny lists Source: https://maki.sh/docs/permissions Example permissions.toml showing per-tool allow/deny lists and the default key. The [bash] section allows cargo and git commands while denying rm -rf and sudo. The [read] section sets default to allow, and MCP sections use allow/deny arrays. Note that in MCP sections, boolean allow/deny forms are deprecated; use default = "allow" or "deny" instead. ```toml default = "deny" [bash] allow = [ "cargo *", "git *", ] deny = [ "rm -rf *", "sudo *", ] [read] default = "allow" [mcp.deepwiki] allow = ["search", "fetch"] [mcp.github] deny = ["admin_delete"] ``` -------------------------------- ### Declare and wrap a custom plugin slot Source: https://maki.sh/docs/hooks Defines a custom extension point with declare_slot and wraps it with set_slot. The declaring plugin owns the name and supplies the default; anyone can wrap it. Names starting with tool. are reserved for maki, which fires them at guaranteed ordering points. ```lua -- owner local render = maki.api.declare_slot("myplugin.render", function(text) return text:upper() end) -- anyone maki.api.set_slot("myplugin.render", function(prev, text) return "[" .. prev(text) .. "]" end) -- render("hi") now returns "[HI]" ``` -------------------------------- ### Manage folder trust with maki trust commands Source: https://maki.sh/docs/folder-trust Manage folder trust decisions. PATH defaults to the current directory. None of these commands start the Lua host, so they are safe to run in a folder you have not read yet. Decisions are stored outside the project and follow the checkout path. ```bash maki trust add [PATH] # asks before recording maki trust add [PATH] --yes # records a yes maki trust remove [PATH] # clears a yes or a no maki trust list # shows both kinds of decision ``` -------------------------------- ### Restore an archived session with shell commands Source: https://maki.sh/docs/context Commands to restore an archived session file. Move the live log aside, copy the archive into place, then start Maki with the session ID. This drops the session's current state, so back it up first. ```bash cd ~/.local/state/maki/sessions mv .jsonl .jsonl.bak cp archive//.jsonl .jsonl maki -s ``` -------------------------------- ### Get JSON output with --output-format json Source: https://maki.sh/docs/headless Requests JSON output from a headless Maki run. The JSON object includes type, subtype, is_error, duration_ms, num_turns, result, stop_reason, session_id, total_cost_usd, and usage. Add --verbose to include full turn-by-turn messages. ```bash maki "fix the tests" --print --output-format json ``` -------------------------------- ### Rewrite bash command with maki.api.set_slot Source: https://maki.sh/docs/hooks Rewrites a bash command in place before it runs. If the command starts with `grep -r`, it is replaced with `rg`; otherwise the call is left unchanged. The rewritten command is passed to the next layer via `prev(input, ctx)`. Maki does not do this automatically because `rg` and `grep -r` do not search the same files. ```lua maki.api.set_slot("tool.bash.input", function(prev, input, ctx) local rewritten = input.command:gsub("^grep %-r ", "rg ") if rewritten == input.command then return end input.command = rewritten return prev(input, ctx) end) ``` -------------------------------- ### Complete 'glob' tool plugin in Lua (register_options and register_tool) Source: https://maki.sh/docs/plugins Full implementation of the bundled 'glob' tool. Opens with maki.api.register_options, which bundled plugins use but your own plugins skip. It demonstrates tool registration (name, kind, description, schema, header, restore), (value, err) handling from maki.fs.glob, error reporting via { llm_output = ```lua local truncate = require("maki.truncate") local ToolView = require("maki.tool_view") local shorten_path = require("maki.shorten_path") local output_limits = require("maki.output_limits") local NO_FILES_FOUND = "No files found" local opts = maki.api.register_options(output_limits.extend({ search_result_limit = { default = 100, min = 10, desc = "Max files returned per search." }, })) local function glob_view_opts(ctx) local tol = ctx:tool_output_lines() return { max_lines = (tol and tol.other) or 3, keep = "head" } end maki.api.register_tool({ name = "glob", kind = "search", description = [[Find files by glob pattern. - Respects .gitignore. - Returns absolute paths sorted by modification time (newest first). - Prefer speculative parallel searches over sequential rounds of glob+grep.]], schema = { type = "object", properties = { pattern = { type = "string", description = "Glob pattern (e.g. **/*.rs, src/**/*.ts)", required = true }, path = { type = "string", description = "Directory to search in (default: cwd)" }, }, }, header = function(input) local buf = maki.ui.buf() local spans = { { shorten_path(input.pattern or ""), "tool" } } if input.path then spans[#spans + 1] = { " in ", "dim" } spans[#spans + 1] = { shorten_path(input.path), "path" } end buf:line(spans) return buf end, restore = function(_input, output, _is_error, ctx) return ToolView.restore(output, glob_view_opts(ctx)) end, handler = function(input, ctx) local pattern = input.pattern if not pattern then return { llm_output = "error: pattern is required", is_error = true } end local limit = opts.search_result_limit local max_lines, max_bytes = output_limits.resolve(opts, ctx) local files, err = maki.fs.glob(pattern, { path = input.path, gitignore = true, sort = "mtime", limit = limit, }) if not files then return { llm_output = "error: " .. err, is_error = true } end if #files == 0 then return { llm_output = NO_FILES_FOUND } end local lines = {} for i, f in ipairs(files) do lines[i] = shorten_path(f) end local text = table.concat(lines, "\n") local llm_output = truncate(text, max_lines, max_bytes) local buf = maki.ui.buf() local view = ToolView.new(buf, glob_view_opts(ctx)) for _, line in ipairs(lines) do view:append(line) end view:finish() buf:on("click", function() view:toggle() end) return { llm_output = llm_output, body = buf, } end, }) ``` -------------------------------- ### CLI usage syntax Source: https://maki.sh/docs/cli Shows the two top-level CLI forms: running the TUI with optional options and prompt, or invoking a subcommand. Use this as a quick reference for the command syntax. ```text maki [OPTIONS] [PROMPT] maki ``` -------------------------------- ### maki prompt: inspect prompt and tools Source: https://maki.sh/docs/cli Debug helper for inspecting the prompt and tool surface the agent sees. `--plan` is rejected on non-system variants. ```bash maki prompt # rendered system prompt (default: system variant) maki prompt research maki prompt general maki prompt --plan # system prompt + plan-mode reminder (system only) maki prompt --tools # tool definitions as JSON maki prompt --tools --names # tool names only, one per line ``` -------------------------------- ### Boot without user init.lua using maki --no-plugins Source: https://maki.sh/docs/keybindings Use this command to recover from a bad keymap that leaves Maki stuck, such as a rebound Ctrl+C or a plugin that throws on load. It skips user init.lua files (global and project) but keeps the Lua host and builtin plugins running, so tools still work. The default keymap lives in Rust, so it is never dropped. ```bash maki --no-plugins ``` -------------------------------- ### Load plugin with require Source: https://maki.sh/docs/plugins Loads the plugin module from init.lua. The module name is the path under lua/ without the extension. ```lua require("hello") ``` -------------------------------- ### maki models: list models and refresh catalog Source: https://maki.sh/docs/cli List models. One spec per line, warnings on stderr. Built-in and script providers are listed live; catalog-backed providers come from the models.dev cache, which expires after 24 hours and supplies pricing and context windows. `--refresh` refetches the catalog; if the refetch fails, the cached catalog stays in place, the list still prints, and the command exits non-zero. ```bash maki models maki models --refresh # refetch the models.dev catalog ``` -------------------------------- ### maki auth: login, logout, status Source: https://maki.sh/docs/cli Manage authentication for providers. `login` stores credentials under the state directory and can write plan/base URL choices into `providers.toml`. OpenAI and Copilot have dedicated flows; other providers prompt for a key (and a plan when the provider has more than one). `status` shows each provider as configured (key on disk), env-only, or missing. ```bash maki auth login [provider] # interactive picker if omitted maki auth logout maki auth status ``` -------------------------------- ### Register a tool with maki.api.register_tool Source: https://maki.sh/docs/plugins Registers a tool named 'hello' that the LLM can call. The handler returns an llm_output string. Place this in a plugin file under the config dir. ```lua maki.api.register_tool({ name = "hello", description = "Say hello to a name.", parameters = { type = "object", properties = { name = { type = "string" } }, required = { "name" } }, handler = function(args) return { llm_output = "hello " .. args.name } end, }) ``` -------------------------------- ### index Source: https://maki.sh/docs/tools Returns a compact overview of a source file, including imports, type definitions, and function signatures with line numbers. ```APIDOC ## index ### Description Return a compact overview of a source file: imports, type definitions, function signatures, and structure with their line numbers surrounded by []. ~70-90% more efficient than reading the full file. ### Parameters - **path** (string) - Required - Absolute path to the file ``` -------------------------------- ### Configure HTTP MCP server with headers Source: https://maki.sh/docs/mcp Defines an HTTP MCP server using a URL and optional headers. Header values expand ${VAR} from the environment; an unset or empty variable fails the server with the variable named in its status. ```toml [mcp.analytics] url = "https://mcp.example.com/mcp" headers = { Authorization = "Bearer ${ANALYTICS_TOKEN}" } ``` -------------------------------- ### Context loading overview: fixed vs on-demand Source: https://maki.sh/docs/context Shows the fixed overhead loaded every request versus on-demand content. The left column is paid every request, the right column only when used. Maki keeps the fixed part small: skills contribute one description line, memories one tag list, and large MCP servers one search tool. ```text session start (paid every request) on demand (paid when used) ────────────────────────────────── ───────────────────────────────── system prompt file contents read / index / grep tool definitions skill bodies skill tool instruction files (AGENTS.md, ...) memory notes memory tool memory tag names subdir rules first read there skill names + descriptions MCP tool defs tool_search ``` -------------------------------- ### Run Maki with --trust in containers or CI Source: https://maki.sh/docs/folder-trust Run Maki with --trust to load project configuration for that run in containers or CI. Records no decision, so a state directory shared by many containers collects no grants. There is no environment variable that does the same. ```bash maki --trust -p "run the test suite" ``` -------------------------------- ### Trim bash output with maki.api.set_slot Source: https://maki.sh/docs/hooks Trims the output of a bash tool before it becomes part of the conversation. Drops lines that start with optional whitespace followed by `Compiling ` and keeps at most 200 lines. The trimmed text is passed to the next layer via `prev(out, ctx)`. The replacement table must carry `text`; without it the output is left alone and the reason is logged. ```lua local MAX = 200 maki.api.set_slot("tool.bash.output", function(prev, out, ctx) local lines = {} for line in out.text:gmatch("[^\n]+") do if not line:match("^%s*Compiling ") then table.insert(lines, line) end end out.text = table.concat(lines, "\n", 1, math.min(#lines, MAX)) return prev(out, ctx) end) ``` -------------------------------- ### Configure telemetry export in init.lua Source: https://maki.sh/docs/telemetry Enables OpenTelemetry export to a collector using gRPC on the default port. Set protocol to "http/protobuf" and endpoint to "http://localhost:4318" for HTTP, or use metrics_exporter = "console" to write OTLP/JSON to the maki log file instead. ```lua maki.setup({ telemetry = { enabled = true, metrics_exporter = "otlp", logs_exporter = "otlp", protocol = "grpc", endpoint = "http://localhost:4317", }, }) ``` -------------------------------- ### Migrate API across files with --allowed-tools Source: https://maki.sh/docs/headless Migrates an API across many files by looping over files containing old_api_call and running Maki with --yolo and --allowed-tools Read,Edit to keep behavior identical. ```bash grep -rl 'old_api_call' src/ | while read file; do maki "In $file, migrate old_api_call() to new_api_call(). \ Keep behavior identical." -p --yolo --allowed-tools Read,Edit done ``` -------------------------------- ### Configure Zed agent_servers Source: https://maki.sh/docs/acp Add Maki as a custom agent in Zed's settings.json file. ```json "agent_servers": { "Maki": { "default_config_options": { "model": "deepseek/deepseek-flash" }, "type": "custom", "command": "maki", "args": ["acp"], "env": {} } } ``` -------------------------------- ### Run Maki headless with --print Source: https://maki.sh/docs/headless Runs Maki non-interactively with the --print flag. Useful for scripts, CI, and automation. A headless run never asks about folder trust; a project .maki directory with no stored answer is skipped and reported on standard error. ```bash maki "explain this codebase" --print ``` -------------------------------- ### Set defer_tools threshold Source: https://maki.sh/docs/mcp TOML configuration showing how to set the top-level defer_tools key to 30, which moves the threshold for when to defer tools. With 30, servers with more than 30 tools will defer; otherwise all load upfront. ```toml defer_tools = 30 [mcp.github] url = "https://api.githubcopilot.com/mcp/" ``` -------------------------------- ### Add MCP server with default deferral Source: https://maki.sh/docs/mcp TOML configuration for adding an MCP server (Datadog) without any deferral configuration. The server is added as usual, and Maki defers its tools by default. ```toml [mcp.datadog] url = "https://mcp.datadoghq.com/api/unstable/mcp-server/mcp?toolsets=all" ``` -------------------------------- ### maki session: list and delete sessions Source: https://maki.sh/docs/cli Manage stored sessions. `list` prints a table (id, title, project directory with `$HOME` collapsed to `~`, last update as a relative age), newest first; a listed id works with `maki --session ` to resume it. `delete` removes the session log along with its archives and index entries, asks for confirmation first unless you pass `-f`/`--force`, and refuses outright without a terminal. A maki that already has the session open will not notice the delete and will lose the rest of that conversation, so close it first. Inside the TUI the same data lives behind `/sessions` (`Ctrl+P`), where `Ctrl+D` deletes. ```bash maki session list # sessions for the current directory maki session list --global # sessions from all projects maki session delete # asks first, -f skips ``` -------------------------------- ### Configure HTTP MCP server with OAuth static client Source: https://maki.sh/docs/mcp Defines an HTTP MCP server that requires OAuth but lacks dynamic client registration. Provides a static client with client_id, client_secret, and callback settings. ```toml [mcp.acme] url = "https://mcp.acme.example.com/mcp" oauth = { client_id = "acme-client", client_secret = "s3cret", callback_port = 3118, callback_path = "/callback", callback_hostname = "localhost" } ``` -------------------------------- ### Track cost with jq '.total_cost_usd' Source: https://maki.sh/docs/headless Cost tracking: runs Maki with JSON output and pipes to jq to extract the total_cost_usd field. ```bash maki "refactor the database layer" -p --output-format json | jq '.total_cost_usd' ``` -------------------------------- ### MCP tool permissions in permissions.toml Source: https://maki.sh/docs/permissions Configure MCP tool permissions in a global permissions.toml file. Server names are table keys under [mcp], tool names are array values. The default = "allow" setting is ignored in project files and only applies globally. ```toml # Global permissions.toml (default = "allow" is ignored in project files) [mcp.deepwiki] allow = ["search", "fetch"] [mcp.github] deny = ["admin_delete"] [mcp.lean-lsp] default = "allow" # allow all tools on this server (global only) ``` -------------------------------- ### Update a single package with /packupdate Source: https://maki.sh/docs/packages Run /packupdate with a package name to update only that package. Maki fetches the source, shows old and proposed commits, and compares permission requests with approved permissions. ```text /packupdate maki-review ``` -------------------------------- ### tool_search deferral flow diagram Source: https://maki.sh/docs/mcp ASCII diagram showing the decision flow for deferring MCP tools. If the server has more than defer_tools (default 10) tools, only tool_search is loaded; otherwise all tools load upfront. When the model searches, a few matches load and stay for the session. ```text server ships 117 tool definitions │ more than defer_tools (10)? │ no │ yes ▼ ▼ all load context gets one small tool: tool_search upfront │ │ model: tool_search("logs") ▼ 3 matches load, stay for the session 114 definitions never enter context ``` -------------------------------- ### Maki config directory layout Source: https://maki.sh/docs/plugins Shows the layout of the maki config directory, listing the three file types and their roles. ```text init.lua the only file maki runs; require()s plugins, calls maki.setup() lua/.lua plugin modules, loaded by require("") plugin.toml permission grants for every Lua file in the dir ``` -------------------------------- ### Set provider plans in TOML config Source: https://maki.sh/docs/providers Configure the plan for Mistral and Z.AI providers in a TOML file. The plan determines the base URL and default model. The environment variable _BASE_URL overrides both the plan and any base_url in this file. ```toml [mistral] plan = "coding" [zai] plan = "coding" ``` -------------------------------- ### Configure stdio MCP servers Source: https://maki.sh/docs/mcp Defines MCP servers using the stdio transport. Each server specifies a command array and optional environment variables, timeout, and enabled flag. Environment values expand ${VAR} from the environment. ```toml [mcp.filesystem] command = ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/tmp"] [mcp.github] command = ["gh", "mcp-server"] environment = { GITHUB_TOKEN = "ghp_xxxx" } timeout = 10000 enabled = false ``` -------------------------------- ### Wrap all tool output slots with redaction Source: https://maki.sh/docs/hooks Wraps every tool's output slot with a redaction layer. The loop only affects tools registered so far, so run it from init.lua after builtin plugins load; MCP tools are missed because they arrive later. Without every permission, most builtins declare no capability and the layer is skipped. ```lua local function redact(prev, out, ctx) out.text = out.text:gsub("sk%-%w+", "[redacted]") return prev(out, ctx) end for _, tool in ipairs(maki.api.get_tools()) do maki.api.set_slot("tool." .. tool.name .. ".output", redact) end ``` -------------------------------- ### Configure ui.notifications in init.lua Source: https://maki.sh/docs/notifications Set the notification behavior in the Maki configuration file. The value "auto" uses OSC 9 in supported terminals and BEL otherwise. ```lua maki.setup({ ui = { notifications = "auto", }, }) ``` -------------------------------- ### maki trust: add, remove, list trusted folders Source: https://maki.sh/docs/cli Manage folder trust. Records whether a folder's `.maki` configuration may load. `PATH` defaults to the current directory, `--yes` skips the confirmation, and `list` shows trusted and rejected folders. See Folder Trust for what is gated and for the `--trust` flag that grants trust for a single run. ```bash maki trust add [PATH] maki trust add [PATH] --yes maki trust remove [PATH] maki trust list ``` -------------------------------- ### Register command aliases in init.lua Source: https://maki.sh/docs/commands Define a list of aliases mapping new names to existing commands, then register each with maki.api.register_command. The handler calls maki.api.run_command(target) and flashes an error message if it fails. Both the alias and original name remain in the palette. ```lua -- ~/.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 ``` -------------------------------- ### Opt out a server with always_load Source: https://maki.sh/docs/mcp TOML configuration for opting a server out of the search step entirely by setting always_load = true. This is good for small servers used every turn, but on a big server it defeats the purpose. ```toml [mcp.linear] command = ["linear-mcp-server"] always_load = true ``` -------------------------------- ### bash Source: https://maki.sh/docs/tools Executes a bash command with configurable timeout and working directory. ```APIDOC ## bash ### Description Execute a bash command. Commands run in the default working directory. ### Parameters - **command** (string) - Required - The bash command to execute - **description** (string) - Optional - Short description (3-5 words) of what the command does - **timeout** (integer) - Optional - Timeout in seconds (default: 120) - **workdir** (string) - Optional - Working directory (default: cwd) ``` -------------------------------- ### maki mcp: auth and logout for MCP servers Source: https://maki.sh/docs/cli Manage MCP server authentication. Server names come from your MCP config. On a machine without a browser, `auth` prints a URL you open elsewhere and paste back. ```bash maki mcp auth # OAuth for an HTTP MCP server maki mcp logout # drop stored tokens ``` -------------------------------- ### default key with per-tool override for bash Source: https://maki.sh/docs/permissions Shows the default key set to "deny" globally, with bash overridden to "prompt" and cargo commands allowed. This configuration denies everything by default except bash which still prompts, and cargo * commands which are allowed. Project files cannot set default = "allow". ```toml default = "deny" [bash] default = "prompt" allow = ["cargo *"] ``` -------------------------------- ### Custom command with frontmatter metadata Source: https://maki.sh/docs/commands Defines a custom slash command with frontmatter metadata. The `description` and `argument-hint` fields are optional; the body uses `$ARGUMENTS` to receive user input after the command name. ```markdown --- description: Review code for issues argument-hint: --- Review $ARGUMENTS and suggest improvements. ``` -------------------------------- ### Request guarded APIs in plugin.toml Source: https://maki.sh/docs/packages Declares guarded API permissions in plugin.toml. Maki asks about new permissions in a separate prompt. A package without plugin.toml asks for nothing and every guarded call fails. Approvals apply only to the same package name and source and are stored in /site/pack-approvals.json. ```toml [permissions] fs_read = true fs_write = true net = true run = true env = true ``` -------------------------------- ### write Source: https://maki.sh/docs/tools Writes content to a file, replacing any existing content. ```APIDOC ## write ### Description Write content to a file, replacing existing content. ### Parameters - **content** (string) - Required - The complete file content to write - **path** (string) - Required - Absolute path to the file ``` -------------------------------- ### Grant permissions in plugin.toml Source: https://maki.sh/docs/plugins Grants permissions for the plugin in plugin.toml. Without this file, every gated call is denied. ```toml [permissions] fs_read = true run = true ``` -------------------------------- ### maki migrate xdg Source: https://maki.sh/docs/cli Move data from `~/.maki/` into platform directories. Safe to re-run. See Configuration. ```bash maki migrate xdg ``` -------------------------------- ### Return custom models from dynamic provider Source: https://maki.sh/docs/providers Output of the `models` subcommand for a dynamic provider. Only `id` is required; optional fields include tier, context_window, max_output_tokens, pricing, and feature flags. The first model per tier is used for sub-agents. ```json [{"id": "my-model-v2", "tier": "strong", "context_window": 200000, "max_output_tokens": 16384}] ``` -------------------------------- ### list Source: https://maki.sh/docs/tools Lists the contents of a directory, returning entry names sorted alphabetically with directories first. ```APIDOC ## list ### Description List directory contents. Returns entry names sorted alphabetically, directories first with a trailing slash. ### Parameters - **path** (string) - Required - Absolute path to the directory ``` -------------------------------- ### Pipe stdin to Maki with -p Source: https://maki.sh/docs/headless Pipes input via stdin to Maki in headless mode using the -p shorthand for --print. In a container, add --trust to load a project .maki directory for that run. ```bash echo "list all TODO comments" | maki -p ``` -------------------------------- ### webfetch Source: https://maki.sh/docs/tools Fetches a URL and returns its contents. Supports output formats of markdown, text, or html, with configurable timeout. ```APIDOC ## webfetch ### Description Fetch a URL and return its contents. ### Parameters | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | `format` | string | no | | Output format: markdown (default), text, or html | | `timeout` | integer | no | 30, max 120 | Timeout in seconds | | `url` | string | yes | | URL to fetch (http:// or https://) | ``` -------------------------------- ### Enable tmux passthrough for OSC 9 Source: https://maki.sh/docs/notifications Enable OSC 9 passthrough in tmux. Use "all" instead of "on" to allow passthrough even when the Maki pane is not visible. ```tmux set -g allow-passthrough all ``` -------------------------------- ### Replace Claude Code with Maki --print Source: https://maki.sh/docs/headless Shows Maki's --print as a drop-in replacement for Claude Code. Same JSON fields, same --output-format options, same --verbose behavior, so scripts that parse Claude Code output work unchanged. ```bash # Before claude "fix the bug" --print --output-format json # After maki "fix the bug" --print --output-format json ``` -------------------------------- ### websearch Source: https://maki.sh/docs/tools Searches the web for real-time information using Exa AI. Returns a configurable number of results. ```APIDOC ## websearch ### Description Search the web for real-time information using Exa AI. ### Parameters | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | `num_results` | integer | no | 8 | Number of results to return | | `query` | string | yes | | Search query | ``` -------------------------------- ### Tool Call Check Flow Source: https://maki.sh/docs/permissions Visual representation of the permission resolution process for every tool call, showing the priority of deny rules, allow rules, YOLO mode, and plan file writes. ```text tool call │ deny rule matches? ── yes ──► blocked. no exceptions │ no allow rule matches? ── yes ──► runs │ no YOLO active? ── yes ──► runs │ no plan file write? ── yes ──► runs │ no ▼ default: prompt / allow / deny ``` -------------------------------- ### view_image Source: https://maki.sh/docs/tools Views an image file, returning it as vision input alongside the tool result. ```APIDOC ## view_image ### Description View an image file (png, jpeg, gif, webp) so you can actually see it; it is returned as vision input alongside the tool result. Use instead of `read` for images. ### Parameters - **path** (string) - Required - Path to the image file ``` -------------------------------- ### Agent loop re-sends context each turn Source: https://maki.sh/docs/token-economy Shows how the full conversation is re-sent to the model on every turn, so each tool result is re-priced until the session ends or history is compacted. ```text turn 1 [system + prompt] ─► model ─► tool call turn 2 [system + prompt + result 1] ─► model ─► tool call turn 3 [system + prompt + result 1 + 2] ─► model ─► ... ``` -------------------------------- ### Manage MCP Authentication via CLI Source: https://maki.sh/docs/mcp Commands to manually trigger the authentication flow for a specific server or remove stored tokens. ```bash maki mcp auth # manually trigger auth maki mcp logout # remove stored tokens ``` -------------------------------- ### grep Source: https://maki.sh/docs/tools Searches file contents using a regex pattern, with optional context and filtering. ```APIDOC ## grep ### Description Search file contents using regex. ### Parameters - **context_after** (integer) - Optional - Context lines after match - **context_before** (integer) - Optional - Context lines before match - **include** (string) - Optional - File glob filter (e.g. *.c) - **limit** (integer) - Optional - Max match groups to return - **path** (string) - Optional - Directory to search in (default: cwd) - **pattern** (string) - Required - Regex pattern ``` -------------------------------- ### Restore lockfile revision with /packupdate ++lockfile Source: https://maki.sh/docs/packages Pass ++lockfile to restore the commit already recorded in the lockfile instead of resolving the declared version. ```text /packupdate ++lockfile maki-review ``` -------------------------------- ### Remove a package with /packdel Source: https://maki.sh/docs/packages Removes the inactive package named maki-review after its declaration has been removed from init.lua and Maki has been reloaded. Maki shows what it will remove and waits for acceptance; active packages are refused. ```text /packdel maki-review ``` -------------------------------- ### Override built-in and declare custom provider in providers.toml Source: https://maki.sh/docs/providers Shows how to override a built-in provider (anthropic) with a proxy base_url and how to declare a full custom provider (my-proxy) with protocol, base_url, api_key_env, default_model, discover_models, and two model entries. Env vars still win over this file for built-in overrides. Custom slugs must not reuse a built-in provider name. ```toml # Point a built-in at a proxy. Env vars still win over this file. [anthropic] base_url = "https://my-proxy.internal" # Full custom provider. Slug becomes the `provider/` prefix in model specs. [my-proxy] display_name = "My Proxy" protocol = "openai" # openai | openai-responses | anthropic | google base_url = "https://llm.example.com/v1" api_key_env = "MY_PROXY_API_KEY" default_model = "my-proxy/fast-v1" discover_models = true # also list models via the provider's /models endpoint [[my-proxy.models]] id = "fast-v1" tier = "weak" context_window = 128000 max_output_tokens = 16384 pricing_input = 0.5 pricing_output = 1.5 [[my-proxy.models]] id = "smart-v1" tier = "strong" context_window = 200000 max_output_tokens = 32000 supports_thinking = true supports_vision = false ``` -------------------------------- ### Telemetry data flow diagram Source: https://maki.sh/docs/telemetry ASCII diagram showing the flow from call sites through bounded queues to a background task and collector. Call sites use try_send to emit events; measurements are aggregated and batched, with retry on failure. ```text call sites --try_send --> bounded queues --> background task --> collector emit() events aggregate (one atomic load measurements batch when disabled) retry ``` -------------------------------- ### Automated PR summary with gh pr edit Source: https://maki.sh/docs/headless Automated PR summaries in CI: captures Maki's summary of git diff main..HEAD into a shell variable and passes it to gh pr edit --body. ```bash SUMMARY=$(git diff main..HEAD | maki "Write a 2-3 sentence \ summary of this change for a PR description." --print) gh pr edit --body "$SUMMARY" ```