Customization
Mastra Code is designed as a composable library. The createMastraCode() factory function accepts configuration overrides, and the returned AgentController can drive any frontend, not just the built-in TUI.
Programmatic usage
Import createMastraCode to bootstrap Mastra Code in your own application:
import { createMastraCode } from 'mastracode'
const { controller, session, mcpManager, authStorage } = await createMastraCode({
cwd: '/path/to/project',
initialState: {
yolo: false,
},
})
session.subscribe(event => {
if (event.type === 'message_update') {
const text = event.message.content
.filter(p => p.type === 'text')
.map(p => p.text)
.join('')
process.stdout.write(text)
}
})
await session.sendMessage({ content: 'Explain the auth module' })createMastraCode boots the controller and returns a ready-to-use session. Subscribe to events and send messages on the session; use the controller to switch modes, configure tools, and manage shared resources.
Custom modes
Override the default Build/Plan/Fast modes by passing a modes array:
import { createMastraCode } from 'mastracode'
import { Agent } from '@mastra/core/agent'
const reviewAgent = new Agent({
id: 'review-agent',
name: 'Review Agent',
instructions:
'You are a code review specialist. Analyze code for bugs, security issues, and best practices.',
model: 'anthropic/claude-sonnet-4-6',
})
const { controller } = await createMastraCode({
modes: [
{
id: 'review',
name: 'Review',
default: true,
defaultModelId: 'anthropic/claude-sonnet-4-6',
color: '#f59e0b',
agent: reviewAgent,
},
{
id: 'build',
name: 'Build',
defaultModelId: 'anthropic/claude-opus-4-7',
color: '#7c3aed',
agent: reviewAgent,
},
],
})Each mode requires an id and an agent. The name, defaultModelId, and color fields control how the mode appears in the TUI.
Extra tools
Add custom tools to the agent's tool set without replacing the built-in tools:
import { createMastraCode } from 'mastracode'
import { createTool } from '@mastra/core/tools'
import { z } from 'zod'
const deployTool = createTool({
id: 'deploy',
description: 'Deploy the current branch to staging',
inputSchema: z.object({
environment: z.enum(['staging', 'production']),
}),
execute: async ({ environment }) => {
return { content: `Deployed to ${environment}` }
},
})
const { controller } = await createMastraCode({
extraTools: { deploy: deployTool },
})Extra tools are merged with the dynamic tool set and are available to the agent in all modes.
Custom subagents
Override the default Explore/Plan/Execute subagents. Each subagent receives its own set of tools, scoping what it can do:
import { createMastraCode } from 'mastracode'
import { createTool } from '@mastra/core/tools'
const { controller } = await createMastraCode({
subagents: [
{
id: 'explore',
name: 'Explore',
description: 'Read-only codebase exploration',
instructions:
'You are an expert code explorer. Use read-only tools to answer questions about the codebase.',
},
{
id: 'test-writer',
name: 'Test Writer',
description: 'Write tests for the specified module',
instructions:
'You are a test-writing specialist. Generate comprehensive tests for the given module.',
},
],
})Custom storage
Connect to a remote database instead of the default local SQLite:
import { createMastraCode } from 'mastracode'
const { controller } = await createMastraCode({
storage: {
url: 'libsql://my-db.turso.io',
authToken: 'my-auth-token',
},
})This is equivalent to setting .mastracode/database.json but allows configuration at the code level.
Custom interval handlers
Replace or extend the default background tasks:
import { createMastraCode } from 'mastracode'
const { controller } = await createMastraCode({
intervalHandlers: [
{
id: 'sync-config',
intervalMs: 60_000,
handler: async () => {
await syncConfigFromRemote()
},
},
],
})Interval handlers run on a fixed interval. They start when controller.init() is called and stop when controller.destroy() is called.
Building a custom TUI
Mastra Code exports the MastraTUI class from mastracode/tui for building custom terminal interfaces. The TUI is driven by the AgentController event system:
import { createMastraCode } from 'mastracode'
import { MastraTUI } from 'mastracode/tui'
const { controller, mcpManager, hookManager, authStorage } = await createMastraCode()
const tui = new MastraTUI({
controller,
hookManager,
authStorage,
mcpManager,
appName: 'My Coding Agent',
version: '1.0.0',
})
tui.run()The TUI subscribes to controller events and renders messages, tool calls, approvals, and status information in real time.
Initial state overrides
Control default behavior through initialState:
import { createMastraCode } from 'mastracode'
const { controller } = await createMastraCode({
initialState: {
yolo: false,
thinkingLevel: 'high',
smartEditing: true,
notifications: 'system',
permissionRules: {
categories: {
read: 'allow',
edit: 'ask',
execute: 'ask',
mcp: 'deny',
},
tools: {},
},
},
})Available state fields
| Field | Type | Default | Description |
|---|---|---|---|
yolo | boolean | true | Auto-approve all tool calls |
thinkingLevel | string | "off" | Extended thinking depth for Anthropic models |
smartEditing | boolean | true | Use AST-based analysis for code edits |
notifications | "bell" | "system" | "both" | "off" | "off" | Alert when the TUI needs attention |
permissionRules | object | Default policies | Per-category and per-tool approval policies |
observerModelId | string | "google/gemini-2.5-flash" | Model for observational memory observer |
reflectorModelId | string | "google/gemini-2.5-flash" | Model for observational memory reflector |
observationThreshold | number | 30000 | Token count triggering observation pass |
reflectionThreshold | number | 40000 | Token count triggering reflection pass |