Nyzhi uses TOML configuration files with a two-layer merge system: global defaults plus optional per-project overrides.
Config File Locations
| File | Location | Purpose |
|---|---|---|
| Global | ~/.config/nyzhi/config.toml | Your personal defaults |
| Project | <project>/.nyzhi/config.toml | Project-specific overrides |
| Local | <project>/.nyzhi/config.local.toml | Machine-local overrides (gitignore this) |
When Nyzhi starts, it loads global first, then merges project config on top.
Tip: Run
nyz initinside any project to scaffold a.nyzhi/directory with a starter config.
Merge Rules
The merge is not a naive overwrite. Each section has specific semantics:
| Section | Merge behavior |
|---|---|
provider.providers | Merged per provider — project can override api_key, model, etc. |
provider.default | Project wins only if it differs from the built-in default (openai) |
mcp.servers | Project extends the global map |
agent.trust.deny_tools / deny_paths | Union + deduplicate |
agent.hooks / agent.commands | Concatenated (global first, then project) |
agent.agents.roles | Merged map — project can add or override roles |
browser.headless | AND — both must be true |
memory.auto_memory | OR — either can enable it |
update.enabled / index.enabled | AND — both must be true |
update.release_url | Global only (project cannot override — security) |
Quick Start Example
A minimal global config to get started:
# ~/.config/nyzhi/config.toml
[provider]
default = "openai"
[provider.openai]
model = "gpt-5.3-codex"
[agent.trust]
mode = "limited"
And a project config that tweaks behavior for a specific repo:
# <project>/.nyzhi/config.toml
[provider]
default = "anthropic"
[provider.anthropic]
model = "claude-sonnet-4-20250514"
[agent]
max_steps = 50
custom_instructions = "Always run tests before committing."
[agent.trust]
deny_paths = [".env", "secrets/"]
Full Schema Reference
[provider]
Controls which LLM provider and model to use.
[provider]
default = "openai" # provider ID to use by default
[provider.openai]
api_key = "" # or use OPENAI_API_KEY env var (recommended)
base_url = "" # override API endpoint
model = "gpt-5.3-codex"
api_style = "" # "openai" | "anthropic" | "gemini" — usually auto-detected
max_tokens = 4096
temperature = 0.7
You can define multiple providers and switch between them:
[provider.anthropic]
model = "claude-sonnet-4-20250514"
[provider.deepseek]
model = "deepseek-chat"
[provider.ollama]
base_url = "http://localhost:11434"
model = "codestral"
[models]
Global model defaults (applied when not set per-provider):
[models]
max_tokens = 4096
temperature = 0.7
[tui]
Terminal UI appearance and behavior.
[tui]
markdown = true # render markdown in responses
streaming = true # stream tokens as they arrive
theme = "dark" # "dark" | "light"
accent = "copper" # accent color name
show_thinking = true # show model reasoning blocks
output_style = "normal" # "normal" | "verbose" | "minimal" | "structured"
[tui.notify]
bell = true # terminal bell on completion
desktop = false # OS-level desktop notification
min_duration_ms = 5000 # only notify if turn took longer than this
[agent]
Core agent behavior.
[agent]
max_steps = 100 # max tool calls per turn
max_tokens = 200000 # context window budget
custom_instructions = "" # extra instructions injected into system prompt
auto_compact_threshold = 0.8 # compact context when this % of window is used
compact_instructions = "" # custom instructions for compaction
enforce_todos = false # require todo tracking
auto_simplify = false # auto-simplify when context is tight
auto_commit = false # auto-commit after each turn
model_profile = "" # model-specific tuning profile
subagent_model = "" # model for spawned subagents
[agent.trust]
Permission system that controls what the agent can do without asking.
[agent.trust]
mode = "limited" # "off" | "limited" | "autoedit" | "full"
allow_tools = [] # explicit allow list (empty = all allowed minus deny)
deny_tools = ["git_commit"] # tools that always need approval
allow_paths = [] # paths the agent can freely modify
deny_paths = [".env", "secrets/"] # paths the agent cannot touch
auto_approve = false # auto-approve all permission requests
always_ask = false # always ask, even for safe operations
remember_approvals = true # remember per-tool approvals for the session
Trust modes explained:
| Mode | Reads | Edits | Shell | Description |
|---|---|---|---|---|
off | Ask | Ask | Ask | Everything needs approval |
limited | Auto | Ask | Ask | Reads are free, writes need approval |
autoedit | Auto | Auto | Ask | File edits are free, shell needs approval |
full | Auto | Auto | Auto | Full autonomy — use with caution |
Aliases:
autoedit,auto_edit, andauto-editall work.
[agent.retry]
Automatic retry on transient failures.
[agent.retry]
max_retries = 3
initial_backoff_ms = 1000
max_backoff_ms = 30000
[agent.routing]
Automatic model routing based on prompt complexity.
[agent.routing]
enabled = false
low_keywords = ["fix typo", "rename"] # route to smaller model
high_keywords = ["refactor", "architect"] # route to larger model
[agent.verify]
Verification checks that run after the agent completes a task.
[[agent.verify.checks]]
kind = "command"
command = "npm test"
[[agent.verify.checks]]
kind = "command"
command = "cargo clippy"
[agent.agents]
Subagent settings.
[agent.agents]
max_threads = 4 # max concurrent subagents
max_depth = 2 # max nesting (agent spawning agent)
[agent.agents.roles.researcher]
description = "Read-only exploration agent"
read_only = true
allowed_tools = ["read", "grep", "glob", "semantic_search"]
max_steps = 30
[agent.sharing]
Session sharing via Cloudflare Pages.
[agent.sharing]
enabled = false
pages_project = ""
domain = ""
redact_patterns = ["API_KEY", "SECRET"]
[agent.voice]
Voice input support.
[agent.voice]
enabled = false
api_key_env = "OPENAI_API_KEY"
model = "whisper-1"
[agent.hooks]
Event-driven automation. See the Hooks guide for full details.
[[agent.hooks]]
event = "after_edit"
command = "prettier --write {file}"
timeout = 10
[[agent.hooks]]
event = "after_turn"
hook_type = "command"
command = "npm test"
block = true
Supported events: session_start, user_prompt_submit, pre_tool_use, post_tool_use, post_tool_use_failure, permission_request, notification, after_edit, after_turn, subagent_start, subagent_end, compact_context, worktree_create, worktree_remove, config_change, teammate_idle, task_completed.
[mcp]
Model Context Protocol server connections.
# stdio transport
[mcp.servers.my-tool]
command = "npx"
args = ["-y", "@my/mcp-server"]
env = { API_KEY = "..." }
# HTTP transport
[mcp.servers.remote-tool]
url = "https://mcp.example.com/sse"
headers = { Authorization = "Bearer ..." }
[shell]
Shell configuration and sandboxing.
[shell]
path = "/bin/zsh"
env = { NODE_ENV = "development" }
startup_commands = ["source ~/.nvm/nvm.sh"]
[shell.sandbox]
enabled = false
allow_network = true
allow_read = ["/usr/local", "/opt/homebrew"]
allow_write = []
block_dotfiles = true
[browser]
Browser automation settings.
[browser]
enabled = false
executable_path = "" # path to Chrome/Chromium
headless = true
[memory]
Persistent memory across sessions.
[memory]
auto_memory = true # automatically save and recall context
[index]
Semantic code index for auto-context.
[index]
enabled = true
embedding = "auto" # "auto" | "voyage" | "openai" | "perplexity" | "tfidf"
embedding_model = "" # override specific model
auto_context = true # inject relevant code into prompts
auto_context_chunks = 5 # how many chunks to inject
exclude = ["target/**", "node_modules/**", "dist/**"]
[update]
Self-update behavior.
[update]
enabled = true
check_interval_hours = 4
release_url = "https://get.nyzhi.com" # global only — cannot be overridden
[external_notify]
External notification integrations.
[external_notify]
webhook_url = ""
telegram_bot_token = ""
telegram_chat_id = ""
discord_webhook_url = ""
slack_webhook_url = ""
CLI Overrides
Some flags override config at runtime:
| Flag | Effect |
|---|---|
--trust full | Sets agent.trust.mode to full |
nyz exec --full-auto | Sets trust to full + sandbox to workspace-write |
nyz exec --sandbox | Sets runtime sandbox level |
--provider <id> | Overrides provider.default |
--model <name> | Overrides the model for the active provider |
File Locations Summary
| What | Path |
|---|---|
| Config directory | ~/.config/nyzhi/ |
| Data directory | ~/.local/share/nyzhi/ |
| Sessions | ~/.local/share/nyzhi/sessions/ |
| Auth store | ~/.local/share/nyzhi/auth.json |
Next Steps
- Authentication — API keys, OAuth, multi-account setup
- Providers — full provider list and model options
- Hooks — automate workflows with event-driven hooks