Custom Modes: Code Review, Deploy, Lint
On this page
Lesson updated November 2, 2026. Example agent files now use keys documented by Vibe:
instructions(notsystem_prompt),active_model(notmodel),[tools.<tool>]blocks for approvals (theauto_approvekey does not exist in an agent file), and real tool names (edit, notedit_file; nolist_dirtool). Reminder from Lesson 3:safetyis a visual indicator, not a permission. Source: Configuration reference.
Create modes tailored to your workflow
The lesson on unified modes introduced the concept; now it’s time to put it to the test. We’ll build three custom modes that cover recurring needs for every developer: code review, deployment, and linting. Each is a .toml file placed in ~/.vibe/agents/, with tailored instructions. What distinguishes these three modes isn’t so much their instructions as the enabled_tools / [tools.<tool>] pair: this decides what Vibe can touch, and therefore what risk you face; safety is merely the visual label.
A reviewer that can’t break anything
The code review mode turns Vibe into a demanding reviewer that analyzes the quality, security, and maintainability of your code. Since it only reads, it’s marked safe, and its reading tools are set to permission = "always": it works without interrupting you, and without risk since no files will be modified. The tool list keeps this promise: no write_file, no edit, no bash.
# ~/.vibe/agents/review.toml
display_name = "Code Review"
description = "In-depth code review: security, performance, maintainability."
safety = "safe"
active_model = "mistral-medium-3.5" # model built into Vibe
instructions = """
You are a senior developer in code review mode.
Process:
1. Read modified files (git diff or specified files)
2. Analyze each change across 4 axes:
- Security (injection, XSS, CSRF, exposed secrets)
- Performance (N+1, nested loops, memory)
- Maintainability (naming, complexity, duplication)
- Correctness (logic, edge cases, types)
Output format:
## 🔴 Critiques (fix before merge)
## 🟡 Warnings (fix soon)
## 🟢 Suggestions (optional improvements)
For each point: file, line, problem, proposed fix.
"""
enabled_tools = [
"read_file",
"grep",
]
[tools.read_file]
permission = "always"
[tools.grep]
permission = "always"
The output format enforced in the prompt isn’t cosmetic: it lets you sort at a glance what blocks a pull request and what can wait. You launch the mode, then give it either a free-form instruction or a specific scope.
vibe --agent review
# > Analyze modified files in the current branch
# > /review src/api/
A deployment that refuses to improvise
The deploy mode is the exact opposite. It touches production, so it’s marked destructive, and its writing and bash tools remain at permission = "ask": every action requires your validation. The entire value of the mode lies in the fixed sequence of its prompt, and especially in its stop conditions. An improvised Friday night deployment always starts with a skipped step; here, a red test stops everything.
# ~/.vibe/agents/deploy.toml
display_name = "Deploy"
description = "Controlled deployment with tests, build, and verification."
safety = "destructive"
active_model = "codestral" # alias declared in config.toml (Lesson 2)
instructions = """
You are in deployment mode. Follow this sequence WITHOUT EXCEPTION:
1. VERIFY — clean git status, no uncommitted files
2. TEST — run the full test suite
3. BUILD — production build
4. VALIDATE — check the build (size, errors, warnings)
5. CONFIRM — ask the user before continuing
6. DEPLOY — run the deployment command
7. VERIFY — confirm the service responds correctly
If a step fails: STOP. Explain the problem and propose a solution.
Never deploy if tests fail.
Never deploy if the build contains critical warnings.
"""
enabled_tools = [
"read_file",
"write_file",
"bash",
"grep",
"ask_user_question"
]
[tools.write_file]
permission = "ask"
[tools.bash]
permission = "ask"
The presence of ask_user_question in the tools is essential: without it, step 5 would be wishful thinking, as the agent would have no technical way to question you.
vibe --agent deploy
# > Follows the sequence test → build → deploy → verification
Automatic but disciplined cleanup
Between the two sits the lint mode, which automates formatting, conventions, and import sorting. It modifies files, so it’s neutral, but its corrections are mechanical and reversible via Git: approving its tools outright (permission = "always") saves you from clicking fifty times. If its list includes bash, do so only in an isolated environment, or limit bash to an allowlist of lint commands only. The three rules at the end of the prompt are what keep it from going off the rails—a free-running agent will quickly install Biome in a project that lives perfectly well with ESLint.
# ~/.vibe/agents/lint.toml
display_name = "Lint & Fix"
description = "Automatic cleanup: lint, format, imports, conventions."
safety = "neutral"
active_model = "codestral" # alias declared in config.toml (Lesson 2)
instructions = """
You are in code cleanup mode.
Tasks:
1. Detect project tools (ESLint, Biome, Prettier, oxlint)
2. Run lint with auto-fix
3. Run formatting
4. Sort and clean up imports
5. Remove detectable dead code
6. Report errors that cannot be fixed automatically
Rules:
- Use tools already configured in the project
- Do not modify tool configuration
- Do not add new tools without asking
"""
enabled_tools = [
"read_file",
"edit",
"bash",
"grep",
]
[tools.read_file]
permission = "always"
[tools.edit]
permission = "always"
[tools.bash]
permission = "always" # reserve for isolated environments only
[tools.grep]
permission = "always"
Two more modes, and an organization rule
The same reasoning applies to other needs. A documentation mode remains neutral but keeps write_file and edit at "ask", because generating files in a repository deserves a look before writing.
# ~/.vibe/agents/docs.toml
display_name = "Documentation"
description = "Generates and updates technical documentation."
safety = "neutral"
active_model = "mistral-medium-3.5" # model built into Vibe
instructions = """
Generate technical documentation. For each file:
- JSDoc/TSDoc for public functions
- README with usage examples
- Documented environment variables
- API schemas if applicable
"""
enabled_tools = ["read_file", "write_file", "edit", "grep",]
[tools.write_file]
permission = "ask"
[tools.edit]
permission = "ask"
A migration mode, meanwhile, joins deploy in the destructive category: a botched schema migration can’t be undone with a git revert, hence the requirement for a systematic rollback script.
# ~/.vibe/agents/migrate.toml
display_name = "Migration"
description = "Handles database and dependency migrations."
safety = "destructive"
active_model = "mistral-medium-3.5" # model built into Vibe
instructions = """
You handle migrations. Absolute rules:
- Always generate a rollback script
- Test the migration on a copy before production
- Document every schema change
"""
enabled_tools = ["read_file", "write_file", "bash", "grep", "ask_user_question"]
[tools.write_file]
permission = "ask"
[tools.bash]
permission = "ask"
Finally, organize your agents directory so that criticality is readable in the tree structure itself. When you switch modes via keyboard mid-session, you need to know without thinking whether the mode you just activated can write to your disk.
~/.vibe/agents/
├── review.toml # safe — read-only
├── lint.toml # neutral — controlled modifications
├── docs.toml # neutral — file generation
├── deploy.toml # destructive — with confirmation
└── migrate.toml # destructive — with confirmation
Key takeaways
- Each mode is a
.tomlfile in~/.vibe/agents/designed for a specific workflow - The review mode has only reading tools, approved outright: it can only read
- The deploy mode keeps
bashand writing at"ask": it asks for confirmation - The lint mode approves its editing tools outright: it fixes automatically
- Adjust
active_modelbased on task complexity instructionsare key: be precise about the sequence and rules