Skip to content

Customization

Config files

smelt loads Lua from a fixed sequence of files. Each one is optional; if it doesn't exist, smelt moves on.

Order File What it's for
1 ~/.config/smelt/early.lua Runs before argv is parsed. Restricted API: smelt.cli, smelt.builtins, smelt.provider, and smelt.phase. See Early-phase config.
2 .smelt/early.lua Project-scoped early phase. Same restrictions; requires trust.
3 ~/.config/smelt/init.lua Your main config: providers, settings, permissions, MCP, keymaps, commands, custom tools.
4 ~/.config/smelt/plugins/*.lua Loaded after init.lua. One file per plugin.
5 .smelt/init.lua Project-local override. Requires trust.
6 .smelt/plugins/*.lua Project-local plugins. Requires trust.

~/.config/smelt honors $XDG_CONFIG_HOME. Override the init.lua path with --config <path>. If no config exists on first launch, the setup wizard creates one for you.

Project-local files (.smelt/*) are gated by the trust prompt; accept the directory the first time you open it. Use them for repo-specific keymaps, slash commands, permission rules, or MCP servers without polluting your global config. Project-local config is especially useful on teams: clone the repo and the agent already knows the project's conventions and tooling.

The Getting Started guide covers basic provider setup. See the Configuration Reference for every provider/setting field, and the Plugin Authoring guide for writing larger extensions against the smelt Lua API.

Settings and startup defaults

Set preferences in init.lua by assigning to smelt.settings:

smelt.settings.vim = true
smelt.settings.auto_compact = true
smelt.settings.redact_secrets = false
smelt.settings.file_icons = true

Use --set key=value when you only want a one-off override for a single launch. See the Configuration Reference for every key and default.

Model, mode, and reasoning effort have two layers: a cold-start default and the last value you picked in the TUI. Pin the cold-start defaults with smelt.defaults.set, and opt out of last-used recall with smelt.remember.set when you want a value to reset on every launch:

smelt.defaults.set({
  model = "openai/gpt-5.5",
  mode = "plan",
  reasoning_effort = "high",
})

smelt.remember.set({
  mode = false,
  reasoning_effort = false,
})

Providers and helper models

Register providers in init.lua so you can run smelt without long CLI flags:

smelt.provider.register("ollama", {
  type = "openai-compatible",
  api_base = "http://localhost:11434/v1",
  models = { "qwen3.6:27b" },
})

smelt.provider.register("openai", {
  type = "openai",
  api_base = "https://api.openai.com/v1",
  api_key_env = "OPENAI_API_KEY",
  models = { "gpt-5.5" },
})

Use the provider's base URL for api_base, not a full request path such as /chat/completions, /responses, or /messages.

Background features such as title generation, compaction, prediction, /btw, and web_fetch can use cheaper helper models while your main session uses a larger model:

smelt.model.preferred("title", "openai/gpt-5-mini")
smelt.model.preferred("compact", "anthropic/claude-haiku-4-5")
smelt.model.preferred("predict", "openai/gpt-5-mini")

The model must be registered under a provider. References use the same provider/model or unambiguous bare-model resolution as /model.

Themes

Use /color <preset> for a session-local slug color. For persistent theme changes, put Lua in init.lua.

Tweak one highlight group after the TUI is ready:

smelt.lifecycle.on_ready(function()
  smelt.theme.set("SmeltAccent", { fg = { ansi = 208 }, bold = true })
  smelt.theme.set("Comment", { fg = { ansi = 244 } })
end)

Or create a colorscheme at ~/.config/smelt/lua/smelt/colorschemes/mytheme.lua and load it:

-- ~/.config/smelt/lua/smelt/colorschemes/mytheme.lua
return {
  SmeltAccent  = { fg = { ansi = 208 } },
  SmeltProcess = { fg = { ansi = 117 } },
  SmeltMuted   = { fg = { ansi = 244 } },
  SmeltUserBg  = { bg = { dark = { ansi = 236 }, light = { ansi = 254 } } },
  Comment      = "SmeltMuted",
}
-- ~/.config/smelt/init.lua
smelt.lifecycle.on_ready(function()
  smelt.theme.use("mytheme")
end)

Color values support { ansi = N }, { rgb = { R, G, B } }, or a { dark = ..., light = ... } pair. The built-in reference is runtime/lua/smelt/colorschemes/default.lua.

Keymaps

Bind chords with smelt.keymap.set(mode, chord, handler). Modes are "n"|"i"|"v"|"" (or the long forms normal/insert/visual); "" binds in every mode.

smelt.keymap.set("n", "<C-s>", function()
  smelt.cmd.run("fork")
  smelt.notify.info("session forked")
end)

Built-in chords are listed in the Keybindings Reference. Deeper UI integration belongs in the Plugin Authoring guide.

Custom Commands

Markdown commands

Drop a .md file in ~/.config/smelt/commands/ and it becomes a slash command. Markdown commands are ideal for prompts you want to version-control or share with a team: anyone can edit the text and frontmatter without writing Lua. For example, ~/.config/smelt/commands/commit.md:

---
description: commit staged changes
model: openai/gpt-4o
temperature: 0.2
reasoning_effort: low
bash:
  allow: ["git *"]
---

Create a conventional commit for the staged changes.

Staged diff:

!`git diff --cached`

Recent commits for style reference:

!`git log --oneline -5`

Type /commit and the agent receives the evaluated prompt with shell outputs inlined. Arguments are appended: /commit fix typos.

To also expose a command as reusable agent context, see the smelt.skills reference.

See Custom Commands for all frontmatter fields and template syntax.

Lua commands

Register from init.lua with smelt.cmd.register:

smelt.cmd.register("hello", function(arg)
  local name = (arg and arg ~= "") and arg or "world"
  smelt.notify.info("hello, " .. name .. "!")
end, { desc = "say hi" })

Permissions

For common workflows, add a few narrow allow rules instead of switching to Yolo mode everywhere:

smelt.permissions.extend({
  default = {
    patterns = {
      bash = { allow = { "git status *", "git diff *", "git log *" } },
    },
  },
  apply = {
    patterns = {
      bash = { allow = { "cargo test *", "cargo clippy *" } },
    },
  },
})

Saved approvals from confirmation dialogs are workspace-scoped and managed with /permissions. See the Permissions Reference for the default matrix and rule grammar.

Skills

Skills are on-demand knowledge packs the agent can load during a conversation. They keep the system prompt lean: only the skills relevant to the current task are injected, so the agent stays focused and you save context tokens. Place a SKILL.md file in ~/.config/smelt/skills/<name>/ (global) or .smelt/skills/<name>/ (project-local). See the Configuration Reference for the full format.

External Tools (MCP)

Connect external tool servers via the Model Context Protocol. Servers run as child processes and their tools become available to the agent. MCP lets you extend smelt without writing Lua: if a server exists for Postgres, Slack, or your internal API, the agent can use it immediately. Register them in init.lua with smelt.mcp.register; see the Configuration Reference for setup.

Inspect connected servers at runtime with smelt.mcp.list(), smelt.mcp.tools(server?), and smelt.mcp.status(name). Useful for statusline indicators and conditional keymaps.

Early-phase config

early.lua runs before the binary parses argv, so it's the only place where you can declare new CLI flags or opt out of bundled modules. Use it when you need to change smelt's behaviour from the command line, for example, adding a --ci flag that switches to headless mode and disables interactive dialogs, or to prevent unwanted built-in tools from ever loading. The rest of init.lua runs as normal afterwards.

-- ~/.config/smelt/early.lua
smelt.cli.register_flag({ name = "experimental", kind = "boolean" })
smelt.builtins.disable({ tools = { "web_fetch" } })
-- ~/.config/smelt/init.lua
if smelt.cli.get("experimental") then
  -- ...
end

smelt.cli, smelt.builtins, smelt.provider, and smelt.phase are available here; most UI and runtime APIs are not. See smelt.cli and smelt.builtins for the common early-phase surfaces.

Custom Instructions (AGENTS.md)

Place an AGENTS.md file in your project root (or ~/.config/smelt/AGENTS.md for global instructions). Its contents are automatically appended to the system prompt for every conversation in that directory.

Use it for project conventions, coding standards, or any persistent context the agent should know. Keeping this in a file means the rules travel with the repo: a new teammate clones the project and the agent already knows the naming conventions, test patterns, and architectural constraints. Disable with --no-system-prompt.