A powerful tmux session management tool for orchestrating multiple AI coding agents in parallel.
Spawn, manage, and coordinate Claude Code, OpenAI Codex, and Google Gemini CLI agents across tiled tmux panes with simple commands and a stunning TUI featuring animated gradients, visual dashboards, and a beautiful command palette.
# One-line install
curl -fsSL https://raw.githubusercontent.com/Dicklesworthstone/ntm/main/install.sh | bash# Install NTM
curl -fsSL https://raw.githubusercontent.com/Dicklesworthstone/ntm/main/install.sh | bash
# Add shell integration
echo 'eval "$(ntm init zsh)"' >> ~/.zshrc && source ~/.zshrc
# Run the interactive tutorial
ntm tutorial
# Check dependencies
ntm deps -v
# Create your first multi-agent session
ntm spawn myproject --cc=2 --cod=1
# Send a prompt to all Claude agents
ntm send myproject --cc "Hello! Explore this codebase and summarize its architecture."
# Open the command palette
ntm palette myprojectModern AI-assisted development often involves running multiple coding agents simultaneously—Claude for architecture decisions, Codex for implementation, Gemini for testing. But managing these agents across terminal windows is painful:
- Window chaos: Each agent needs its own terminal, leading to cluttered desktops
- Context switching: Jumping between windows breaks flow and loses context
- No orchestration: Sending the same prompt to multiple agents requires manual copy-paste
- Session fragility: Disconnecting from SSH loses all your agent sessions
- Setup friction: Starting a new project means manually creating directories, initializing git, and spawning agents one by one
- Visual noise: Plain terminal output with no visual hierarchy or status indication
- No visibility: Hard to see agent status at a glance across many panes
NTM transforms tmux into a multi-agent command center:
- One session, many agents: All your AI agents live in a single tmux session with tiled panes
- Named panes: Each agent pane is labeled (e.g.,
myproject__cc_1,myproject__cod_2) for easy identification - Broadcast prompts: Send the same task to all agents of a specific type with one command
- Persistent sessions: Detach and reattach without losing any agent state
- Quick project setup: Create directory, initialize git, and spawn agents in a single command
- Stunning TUI: Animated gradients, visual dashboards, shimmering effects, and a beautiful command palette with Catppuccin themes
- Individual developers: Run multiple AI agents in parallel for faster iteration
- Researchers: Compare responses from different AI models side-by-side
- Power users: Build complex multi-agent workflows with scriptable commands
- Remote workers: Keep agent sessions alive across SSH disconnections
Create a new project with git initialization, VSCode settings, Claude config, and spawn agents in one command:
ntm quick myproject --template=go
ntm spawn myproject --cc=3 --cod=2 --gmi=1This creates ~/projects/myproject with all the scaffolding you need, then launches 6 AI agents in tiled panes.
Spawn specific combinations of agents:
ntm spawn myproject --cc=4 --cod=4 --gmi=2 # 4 Claude + 4 Codex + 2 Gemini = 10 agents + 1 user paneAdd more agents to an existing session:
ntm add myproject --cc=2 # Add 2 more Claude agentsSend the same prompt to all agents of a specific type:
ntm send myproject --cc "fix all TypeScript errors in src/"
ntm send myproject --cod "add comprehensive unit tests"
ntm send myproject --all "explain your current approach"Stop all running agents instantly:
ntm interrupt myproject # Send Ctrl+C to all agent panesntm list # List all tmux sessions
ntm status myproject # Show detailed status with agent counts
ntm attach myproject # Reattach to session
ntm view myproject # View all panes in tiled layout
ntm zoom myproject 2 # Zoom to specific pane
ntm dashboard myproject # Open interactive visual dashboard
ntm kill -f myproject # Kill session (force, no confirmation)ntm copy myproject:1 # Copy from specific pane
ntm copy myproject --all # Copy all pane outputs to clipboard
ntm copy myproject --cc # Copy Claude panes only
ntm copy myproject --pattern 'ERROR' # Filter lines by regex
ntm copy myproject --code # Extract only markdown code blocks
ntm copy myproject --output out.txt # Save output to file instead of clipboard
ntm save myproject -o ~/logs # Save all pane outputs to timestamped filesInvoke a stunning fuzzy-searchable palette of pre-configured prompts with a single keystroke:
ntm palette myproject # Open palette for session
# Or press F6 in tmux (after running ntm bind)The palette features:
- Animated gradient banner with shimmering title effects
- Catppuccin color theme with elegant gradients throughout
- Fuzzy search through all commands with live filtering
- Pinned + recent commands so you re-search less (pin/favorite with
Ctrl+P/Ctrl+F) - Live preview pane showing full prompt text + target metadata to reduce misfires
- Nerd Font icons (with Unicode/ASCII fallbacks for basic terminals)
- Visual target selector with animated color-coded agent badges
- Quick select: Numbers 1-9 for instant command selection
- Smooth animations: Pulsing indicators, gradient transitions
- Help overlay: Press
?(orF1) for key hints - Keyboard-driven: Full keyboard navigation with vim-style keys
Open a stunning visual dashboard for any session:
ntm dashboard myproject # Or use alias: ntm dash myprojectThe dashboard provides:
- Visual pane grid with color-coded agent cards
- Live agent counts showing Claude, Codex, Gemini, and user panes
- Token velocity badges showing real-time tokens-per-minute (tpm) for each agent
- Animated status indicators with pulsing selection highlights
- Quick navigation: Use 1-9 to select panes, z/Enter to zoom
- Real-time refresh: Press r to update pane status
- Context + mail shortcuts: Press
cfor context,mfor Agent Mail - Help overlay: Press
?for key hints (Esc closes) - Responsive layout: Adapts to terminal size automatically
Set up a convenient F6 hotkey to open the palette in a tmux popup:
ntm bind # Bind F6 (default)
ntm bind --key=F5 # Use different key
ntm bind --show # Show current binding
ntm bind --unbind # Remove the bindingAfter binding, press F6 inside any tmux session to open the palette in a floating popup.
Get started quickly with the built-in interactive tutorial:
ntm tutorial # Launch the animated tutorial
ntm tutorial --skip # Skip animations (accessibility mode)The tutorial walks you through:
- Core concepts (sessions, panes, agents)
- Essential commands with examples
- Multi-agent coordination strategies
- Power user tips and keyboard shortcuts
Keep NTM up-to-date with the built-in upgrade command:
ntm upgrade # Check for updates and prompt to install
ntm upgrade --check # Check only, don't install
ntm upgrade --yes # Auto-confirm installation
ntm upgrade --force # Force reinstall even if up-to-dateVerify all required tools are installed:
ntm deps # Quick check
ntm deps -v # Verbose output with versionscurl -fsSL https://raw.githubusercontent.com/Dicklesworthstone/ntm/main/install.sh | bashbrew install dicklesworthstone/tap/ntmgo install github.com/Dicklesworthstone/ntm/cmd/ntm@latestRun NTM in a container (useful for CI/CD or isolated environments):
# Pull the latest image
docker pull ghcr.io/dicklesworthstone/ntm:latest
# Run interactively
docker run -it --rm ghcr.io/dicklesworthstone/ntm:latest
# Or use a specific version
docker pull ghcr.io/dicklesworthstone/ntm:v1.0.0git clone https://github.com/Dicklesworthstone/ntm.git
cd ntm
go build -o ntm ./cmd/ntm
sudo mv ntm /usr/local/bin/After installing, add to your shell rc file:
# zsh (~/.zshrc)
eval "$(ntm init zsh)"
# bash (~/.bashrc)
eval "$(ntm init bash)"
# fish (~/.config/fish/config.fish)
ntm init fish | sourceThen reload your shell:
source ~/.zshrcShell integration adds:
| Category | Aliases | Description |
|---|---|---|
| Agent | cc, cod, gmi |
Launch Claude, Codex, Gemini |
| Session Creation | cnt, sat, qps |
create, spawn, quick |
| Agent Mgmt | ant, bp, int |
add, send, interrupt |
| Navigation | rnt, lnt, snt, vnt, znt |
attach, list, status, view, zoom |
| Dashboard | dash, d |
Interactive visual dashboard |
| Output | cpnt, svnt |
copy, save |
| Utilities | ncp, knt, cad |
palette, kill, deps |
Plus:
- Tab completions for all commands
- F6 keybinding support (run
ntm bindto configure)
Type ntm for a colorized help display with all commands.
| Command | Alias | Arguments | Description |
|---|---|---|---|
ntm create |
cnt |
<session> [--panes=N] |
Create empty session with N panes |
ntm spawn |
sat |
<session> --cc=N --cod=N --gmi=N |
Create session and launch agents |
ntm quick |
qps |
<project> [--template=go|python|node|rust] |
Full project setup with git, VSCode, Claude config |
Examples:
cnt myproject --panes=10 # 10 empty panes
sat myproject --cc=6 --cod=6 --gmi=2 # 6 Claude + 6 Codex + 2 Gemini
qps myproject --template=go # Create Go project scaffold| Command | Alias | Arguments | Description |
|---|---|---|---|
ntm add |
ant |
<session> --cc=N --cod=N --gmi=N |
Add more agents to existing session |
ntm send |
bp |
<session> [--cc|--cod|--gmi|--all] "prompt" |
Send prompt to agents by type |
ntm interrupt |
int |
<session> |
Send Ctrl+C to all agent panes |
Filter flags for send:
| Flag | Description |
|---|---|
--all |
Send to all agent panes (excludes user pane) |
--cc |
Send only to Claude panes |
--cod |
Send only to Codex panes |
--gmi |
Send only to Gemini panes |
Examples:
ant myproject --cc=2 # Add 2 Claude agents
bp myproject --cc "fix the linting errors" # Broadcast to Claude
bp myproject --all "summarize your progress" # Broadcast to all agents
int myproject # Stop all agents| Command | Alias | Arguments | Description |
|---|---|---|---|
ntm attach |
rnt |
<session> |
Attach (offers to create if missing) |
ntm list |
lnt |
List all tmux sessions | |
ntm status |
snt |
<session> |
Show pane details with type indicators (C/X/G) and agent counts |
ntm view |
vnt |
<session> |
Unzoom, tile layout, and attach |
ntm zoom |
znt |
<session> [pane-index] |
Zoom to specific pane |
ntm dashboard |
d, dash |
[session] |
Interactive visual dashboard |
Examples:
rnt myproject # Reattach to session
lnt # Show all sessions
snt myproject # Detailed status with icons
vnt myproject # View all panes tiled
znt myproject 3 # Zoom to pane 3
ntm dash myproject # Open interactive dashboard| Command | Alias | Arguments | Description |
|---|---|---|---|
ntm copy |
cpnt |
<session[:pane]> [--all|--cc|--cod|--gmi] [-l lines] [--pattern REGEX] [--code] [--output FILE] [--quiet] |
Copy pane output to clipboard or file with filters |
ntm save |
svnt |
<session> [-o dir] [-l lines] [--all|--cc|--cod|--gmi] |
Save outputs to files |
Examples:
cpnt myproject:1 # Copy specific pane
cpnt myproject --all # Copy all panes to clipboard
cpnt myproject --cc -l 500 # Copy last 500 lines from Claude panes
cpnt myproject --pattern 'ERROR' --output /tmp/errors.txt # Filter + save to file
svnt myproject -o ~/logs # Save all outputs to ~/logs
svnt myproject --cod # Save only Codex pane outputs| Command | Alias | Arguments | Description |
|---|---|---|---|
ntm palette |
ncp |
[session] |
Open interactive command palette |
ntm dashboard |
d, dash |
[session] |
Open visual session dashboard |
ntm bind |
[--key=F6] [--unbind] [--show] |
Configure tmux popup keybinding |
Examples:
ncp myproject # Open palette for session
ncp # Select session first, then palette
ntm dash myproject # Open dashboard for session
ntm bind # Set up F6 keybinding for palette popupPalette Navigation:
| Key | Action |
|---|---|
↑/↓ or j/k |
Navigate commands |
1-9 |
Quick select command |
Enter |
Select command |
Esc |
Back / Quit |
| Type | Filter commands |
Dashboard Navigation:
| Key | Action |
|---|---|
↑/↓ or j/k |
Navigate panes |
1-9 |
Quick select pane |
z or Enter |
Zoom to pane |
r |
Refresh pane data |
q or Esc |
Quit dashboard |
| Command | Alias | Arguments | Description |
|---|---|---|---|
ntm deps |
cad |
[-v] |
Check installed dependencies |
ntm kill |
knt |
<session> [-f] |
Kill session (with confirmation) |
ntm bind |
[--key=F6] [--unbind] [--show] |
Configure tmux F6 keybinding | |
ntm config init |
Create default config file | ||
ntm config show |
Display current configuration | ||
ntm tutorial |
[--skip] [--slide=N] |
Interactive tutorial | |
ntm upgrade |
[--check] [--yes] [--force] |
Self-update to latest version |
Examples:
ntm deps # Check all dependencies
knt myproject # Prompts for confirmation
knt -f myproject # Force kill, no prompt
ntm bind # Set up F6 popup keybinding
ntm config init # Create ~/.config/ntm/config.toml
ntm tutorial # Launch interactive tutorial
ntm upgrade # Check for and install updatesProfiles (also called personas) define agent behavioral characteristics including agent type, model, system prompts, and focus patterns. NTM includes built-in profiles for common roles like architect, implementer, reviewer, tester, and documenter.
| Command | Arguments | Description |
|---|---|---|
ntm profiles list |
[--agent TYPE] [--tag TAG] [--json] |
List available profiles |
ntm profiles show |
<name> [--json] |
Show detailed profile information |
ntm personas list |
[--agent TYPE] [--tag TAG] [--json] |
Alias for profiles list |
ntm personas show |
<name> [--json] |
Alias for profiles show |
Profile Sources (later overrides earlier):
- Built-in: Compiled into NTM (architect, implementer, reviewer, tester, documenter)
- User:
~/.config/ntm/personas.toml - Project:
.ntm/personas.toml
Profile Sets:
Profile sets are named groups of profiles for quick spawning:
# In ~/.config/ntm/personas.toml or .ntm/personas.toml
[[persona_sets]]
name = "backend-team"
description = "Full backend development team"
personas = ["architect", "implementer", "implementer", "tester"]Examples:
ntm profiles list # List all profiles
ntm profiles list --agent claude # Filter by agent type
ntm profiles list --tag review # Filter by tag
ntm profiles list --json # JSON output for scripts
ntm profiles show architect # Show profile details
ntm profiles show architect --json # JSON output with source infoUsing Profiles with Spawn:
ntm spawn myproject --profiles=architect,implementer,tester
ntm spawn myproject --profile-set=backend-teamNTM provides machine-readable output for integration with AI coding agents and automation pipelines. All robot commands output JSON by default and follow consistent exit codes (0=success, 1=error, 2=unavailable).
State Inspection:
ntm --robot-status # Sessions, panes, agent states
ntm --robot-context=SESSION # Context window usage per agent
ntm --robot-snapshot # Unified state: sessions + beads + alerts + mail
ntm --robot-tail=SESSION # Recent pane output (--lines=50 --panes=1,2)
ntm --robot-plan # bv execution plan with parallelizable tracks
ntm --robot-graph # Dependency graph insights
ntm --robot-dashboard # Dashboard summary (markdown or --json)
ntm --robot-terse # Single-line encoded state (minimal tokens)
ntm --robot-markdown # System state as markdown tables
ntm --robot-health # Project health summary
ntm --robot-version # Version info
ntm --robot-help # Full robot mode documentationAgent Control:
ntm --robot-send=SESSION --msg="Fix auth" --type=claude # Send to agents
ntm --robot-ack=SESSION --ack-timeout=30s # Watch for responses
ntm --robot-spawn=SESSION --spawn-cc=2 --spawn-wait # Create session
ntm --robot-interrupt=SESSION --interrupt-msg="Stop" # Send Ctrl+C
ntm --robot-assign=SESSION --assign-beads=bd-1,bd-2 # Assign work to agentsCASS Integration (Cross-Agent Search):
ntm --robot-cass-search="auth error" --cass-since=7d # Search past conversations
ntm --robot-cass-status # CASS health/stats
ntm --robot-cass-context="how to implement auth" # Get relevant contextSession State Management:
ntm --robot-save=SESSION --save-output=/path/state.json # Save session state
ntm --robot-restore=mystate --restore-dry # Restore (dry-run)
ntm --robot-history=SESSION --history-stats # Session history
ntm --robot-tokens --tokens-group-by=model # Token usage analyticsSupporting Flags:
| Flag | Use With | Description |
|---|---|---|
--panes=1,2,3 |
tail, send, ack, interrupt | Filter to specific pane indices |
--type=claude |
send, ack, interrupt | Filter by agent type (claude/cc, codex/cod, gemini/gmi) |
--all |
send, interrupt | Include user pane |
--lines=N |
tail | Lines per pane (default 20) |
--since=TIMESTAMP |
snapshot | RFC3339 timestamp for delta |
--track |
send | Combined send+ack mode |
--json |
dashboard, markdown | Force JSON output |
This enables AI agents to:
- Discover existing sessions and their agent configurations
- Plan multi-agent workflows programmatically
- Monitor context window usage across agents
- Search past agent conversations via CASS
- Assign beads/tasks to specific agents
- Save and restore session state
- Track token usage and history
Example JSON output (--robot-status):
{
"success": true,
"timestamp": "2025-01-15T10:30:00Z",
"sessions": [
{
"name": "myproject",
"attached": true,
"windows": 1,
"agents": [
{"type": "claude", "pane": "myproject__cc_1", "active": true},
{"type": "codex", "pane": "myproject__cod_1", "active": true}
]
}
],
"summary": {
"total_sessions": 1,
"total_agents": 2,
"by_type": {"claude": 1, "codex": 1}
}
}Example JSON output (--robot-context):
{
"success": true,
"session": "myproject",
"captured_at": "2025-01-15T10:30:00Z",
"agents": [
{
"pane": "myproject__cc_1",
"agent_type": "claude",
"model": "sonnet",
"estimated_tokens": 45000,
"with_overhead": 54000,
"context_limit": 200000,
"usage_percent": 27.0,
"usage_level": "Low",
"confidence": "estimated"
},
{
"pane": "myproject__cod_1",
"agent_type": "codex",
"model": "gpt4",
"estimated_tokens": 85000,
"with_overhead": 102000,
"context_limit": 128000,
"usage_percent": 79.7,
"usage_level": "High",
"confidence": "estimated"
}
],
"summary": {
"total_agents": 2,
"high_usage_count": 1,
"avg_usage": 53.35
},
"_agent_hints": {
"low_usage_agents": ["myproject__cc_1"],
"high_usage_agents": ["myproject__cod_1"],
"suggestions": ["1 agent(s) have high context usage", "1 agent(s) have room for additional work"]
}
}Exit Codes:
| Code | Meaning | JSON Field |
|---|---|---|
| 0 | Success | "success": true |
| 1 | Error | "success": false, "error_code": "..." |
| 2 | Unavailable | "success": false, "error_code": "NOT_IMPLEMENTED" |
Agent panes are named using the pattern: <project>__<agent>_<number>
Examples:
myproject__cc_1- First Claude agentmyproject__cod_2- Second Codex agentmyproject__gmi_1- First Gemini agentmyproject__cc_added_1- Claude agent added later viaadd
This naming enables targeted commands via filters (--cc, --cod, --gmi).
In status output and tables, agent types are shown with compact indicators:
- C = Claude
- X = Codex
- G = Gemini
- U = User pane
┌─────────────────────────────────────────────────────────────────┐
│ Session: myproject │
├─────────────────┬─────────────────┬─────────────────────────────┤
│ User Pane │ myproject__cc_1 │ myproject__cc_2 │
│ (your shell) │ (Claude #1) │ (Claude #2) │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ myproject__cod_1│ myproject__cod_2 │ myproject__gmi_1 │
│ (Codex #1) │ (Codex #2) │ (Gemini #1) │
└─────────────────┴─────────────────┴─────────────────────────────┘
- User pane (index 0): Always preserved as your command pane
- Agent panes (index 1+): Each runs one AI agent
- Tiled layout: Automatically arranged for optimal visibility
| Platform | Default Projects Base |
|---|---|
| macOS | ~/Developer |
| Linux | /data/projects |
Override with config or: export NTM_PROJECTS_BASE="/your/custom/path"
Each project creates a subdirectory: $PROJECTS_BASE/<session-name>/
The ntm quick command creates:
myproject/
├── .git/ # Initialized git repo
├── .gitignore # Language-appropriate ignores
├── .vscode/
│ └── settings.json # VSCode workspace settings
├── .claude/
│ ├── settings.toml # Claude Code config
│ └── commands/
│ └── review.md # Sample slash command
└── [template files] # main.go, main.py, etc.
NTM works out of the box with sensible defaults—no configuration file is required. When no config file exists, NTM uses built-in defaults appropriate for your platform.
Optional configuration lives in ~/.config/ntm/config.toml:
# Create default config (optional - NTM works without it)
ntm config init
# Show current config (shows effective config, including defaults)
ntm config show
# Edit config
$EDITOR ~/.config/ntm/config.toml# NTM (Named Tmux Manager) Configuration
# https://github.com/Dicklesworthstone/ntm
# Base directory for projects
projects_base = "~/Developer"
[agents]
# Commands used to launch each agent type
claude = 'NODE_OPTIONS="--max-old-space-size=32768" claude --dangerously-skip-permissions'
codex = "codex --dangerously-bypass-approvals-and-sandbox -m gpt-5.1-codex-max"
gemini = "gemini --yolo"
[tmux]
# Tmux-specific settings
default_panes = 10
palette_key = "F6"
# Command Palette entries
# Quick Actions
[[palette]]
key = "fresh_review"
label = "Fresh Eyes Review"
category = "Quick Actions"
prompt = """
Take a step back and carefully reread the most recent code changes.
Fix any obvious bugs or issues you spot.
"""
[[palette]]
key = "git_commit"
label = "Commit Changes"
category = "Quick Actions"
prompt = "Commit all changed files with detailed commit messages and push."
# Code Quality
[[palette]]
key = "refactor"
label = "Refactor Code"
category = "Code Quality"
prompt = """
Review the current code for opportunities to improve:
- Extract reusable functions
- Simplify complex logic
- Improve naming
- Remove duplication
"""
# Coordination
[[palette]]
key = "status_update"
label = "Status Update"
category = "Coordination"
prompt = """
Provide a brief status update:
1. What you just completed
2. What you're currently working on
3. Any blockers or questions
"""NTM also supports project-specific configuration when you run commands inside a repo that contains a .ntm/config.toml (NTM searches upward from your current directory).
Create a scaffold in the current directory:
ntm config project init
ntm config project init --force # overwrite .ntm/config.toml if it already existsProject config overrides the global config and is useful for:
- Default agent counts for
ntm spawn(when you don’t pass--cc/--cod/--gmi) - Project palette commands (
[palette].file, relative to.ntm/) - Project prompt templates (
[templates].dir, relative to.ntm/)
| Variable | Default | Description |
|---|---|---|
NTM_PROJECTS_BASE |
~/Developer (macOS) or /data/projects (Linux) |
Base directory for all projects |
NTM_THEME |
auto |
Color theme: auto (detect light/dark), mocha, macchiato, nord, latte, or plain (no-color) |
NTM_ICONS |
auto-detect | Icon set: nerd, unicode, ascii |
NTM_USE_ICONS |
auto-detect | Force icons: 1 (on) or 0 (off) |
NERD_FONTS |
auto-detect | Nerd Fonts available: 1 or 0 |
NTM supports pre- and post-command hooks that run custom scripts before and after key operations. This enables automation, logging, notifications, and integration with external tools.
Hooks are defined in ~/.config/ntm/hooks.toml (or in the main config.toml under [[command_hooks]]):
# ~/.config/ntm/hooks.toml
# Pre-spawn hook: runs before agents are spawned
[[command_hooks]]
event = "pre-spawn"
command = "echo 'Starting new session'"
name = "log-spawn-start"
description = "Log when a session starts"
# Post-spawn hook: runs after agents are spawned
[[command_hooks]]
event = "post-spawn"
command = "notify-send 'NTM' 'Agents spawned for $NTM_SESSION'"
name = "desktop-notify"
description = "Send desktop notification"
# Pre-send hook: runs before prompts are sent
[[command_hooks]]
event = "pre-send"
command = "echo \"$(date): Sending to $NTM_SEND_TARGETS\" >> ~/.ntm-send.log"
name = "log-sends"
description = "Log all send commands"
# Post-send hook: runs after prompts are delivered
[[command_hooks]]
event = "post-send"
command = "/path/to/my-webhook.sh"
name = "webhook"
timeout = "10s"
continue_on_error = true| Event | When It Runs | Use Cases |
|---|---|---|
pre-spawn |
Before creating session/agents | Validation, setup, cleanup |
post-spawn |
After agents are launched | Notifications, logging, auto-send initial prompts |
pre-send |
Before sending prompts | Logging, rate limiting, prompt validation |
post-send |
After prompts delivered | Webhooks, analytics, notifications |
pre-add |
Before adding agents | Validation |
post-add |
After adding agents | Notifications |
pre-create |
Before creating session | Validation |
post-create |
After creating session | Setup |
pre-shutdown |
Before killing session | Cleanup, backup |
post-shutdown |
After killing session | Cleanup |
[[command_hooks]]
event = "post-send" # Required: which event triggers this hook
command = "./my-script.sh" # Required: shell command to execute
# Optional settings
name = "my-hook" # Identifier for logging
description = "What this does" # Documentation
timeout = "30s" # Max execution time (default: 30s, max: 10m)
enabled = true # Set to false to disable without removing
continue_on_error = false # If true, NTM continues even if hook fails
workdir = "${PROJECT}" # Working directory (supports variables)
# Custom environment variables
[command_hooks.env]
MY_VAR = "custom_value"All hooks have access to these environment variables:
| Variable | Description | Available In |
|---|---|---|
NTM_SESSION |
Session name | All events |
NTM_PROJECT_DIR |
Project directory path | All events |
NTM_HOOK_EVENT |
Event name (e.g., "pre-send") | All events |
NTM_HOOK_NAME |
Hook name (if specified) | All events |
NTM_PANE |
Pane identifier | Pane-specific events |
NTM_MESSAGE |
Prompt being sent (truncated to 1000 chars) | Send events |
NTM_SEND_TARGETS |
Target description (e.g., "cc", "all", "agents") | Send events |
NTM_TARGET_CC |
"true" if targeting Claude | Send events |
NTM_TARGET_COD |
"true" if targeting Codex | Send events |
NTM_TARGET_GMI |
"true" if targeting Gemini | Send events |
NTM_TARGET_ALL |
"true" if targeting all panes | Send events |
NTM_PANE_INDEX |
Specific pane index (-1 if not specified) | Send events |
NTM_DELIVERED_COUNT |
Number of successful deliveries | Post-send only |
NTM_FAILED_COUNT |
Number of failed deliveries | Post-send only |
NTM_TARGET_PANES |
List of targeted pane indices | Post-send only |
NTM_AGENT_COUNT_CC |
Number of Claude agents | Spawn events |
NTM_AGENT_COUNT_COD |
Number of Codex agents | Spawn events |
NTM_AGENT_COUNT_GMI |
Number of Gemini agents | Spawn events |
NTM_AGENT_COUNT_TOTAL |
Total number of agents | Spawn events |
Log all sends to a file:
[[command_hooks]]
event = "pre-send"
name = "send-logger"
command = '''
echo "$(date -Iseconds) | Session: $NTM_SESSION | Targets: $NTM_SEND_TARGETS" >> ~/.ntm/send.log
echo "Message: $NTM_MESSAGE" >> ~/.ntm/send.log
echo "---" >> ~/.ntm/send.log
'''Desktop notification on spawn:
[[command_hooks]]
event = "post-spawn"
name = "spawn-notify"
command = "notify-send 'NTM' 'Session $NTM_SESSION ready with $NTM_AGENT_COUNT_TOTAL agents'"Webhook integration:
[[command_hooks]]
event = "post-send"
name = "slack-webhook"
timeout = "5s"
continue_on_error = true
command = '''
curl -s -X POST "$SLACK_WEBHOOK_URL" \
-H 'Content-type: application/json' \
-d "{\"text\": \"NTM: Sent prompt to $NTM_SEND_TARGETS in $NTM_SESSION\"}"
'''
[command_hooks.env]
SLACK_WEBHOOK_URL = "https://hooks.slack.com/services/..."Validate prompts before sending:
[[command_hooks]]
event = "pre-send"
name = "prompt-validator"
command = '''
# Block empty prompts
if [ -z "$NTM_MESSAGE" ]; then
echo "Error: Empty prompt not allowed" >&2
exit 1
fi
# Block prompts containing sensitive patterns
if echo "$NTM_MESSAGE" | grep -qiE "(password|secret|api.?key)"; then
echo "Warning: Prompt may contain sensitive data" >&2
exit 1
fi
'''Auto-save outputs before shutdown:
[[command_hooks]]
event = "pre-shutdown"
name = "auto-backup"
command = '''
mkdir -p ~/.ntm/backups
ntm save "$NTM_SESSION" -o ~/.ntm/backups 2>/dev/null || true
'''
continue_on_error = truePre-hooks:
- Run before the command executes
- If a pre-hook fails (non-zero exit), the command is aborted
- Set
continue_on_error = trueto run the command even if hook fails
Post-hooks:
- Run after the command completes
- Failures are logged but don't fail the overall command
- Useful for notifications and cleanup
Timeouts:
- Default: 30 seconds
- Maximum: 10 minutes
- Hooks that exceed timeout are killed
Execution:
- Hooks run in a shell (
sh -c "command") - Working directory defaults to project directory
- Standard output and errors are captured and displayed
CASS (Cross-Agent Search System) indexes past agent conversations across multiple tools (Claude Code, Codex, Cursor, Gemini, ChatGPT) so you can reuse solved problems and learn from prior sessions.
# Search for relevant past work
ntm --robot-cass-search="authentication error" --cass-since=7d
# Get context relevant to current task
ntm --robot-cass-context="how to implement rate limiting"
# Check CASS health and stats
ntm --robot-cass-statusThe NTM dashboard displays CASS context in a dedicated panel, showing:
- Relevant past sessions matching current project context
- Similarity scores for each match
- Quick access to session details
CASS works automatically when installed. Configure search behavior in your config:
[cass]
# Default search parameters
default_limit = 10
include_agents = ["claude", "codex", "gemini"]NTM monitors context window usage for each AI agent and automatically rotates agents before they exhaust their context, ensuring uninterrupted workflows during long sessions.
- Monitoring: Token usage is estimated using multiple strategies (message counts, cumulative tokens, session duration)
- Warning: When usage exceeds the warning threshold (default 80%), NTM alerts you
- Compaction: Before rotating, NTM tries to compact the context (using
/compactfor Claude or summarization prompts) - Rotation: If compaction doesn't reduce usage enough, a fresh agent is spawned with a handoff summary
Context rotation is enabled by default. Configure in ~/.config/ntm/config.toml:
[context_rotation]
enabled = true # Master toggle
warning_threshold = 0.80 # Warn at 80% usage
rotate_threshold = 0.95 # Rotate at 95% usage
summary_max_tokens = 2000 # Max tokens for handoff summary
min_session_age_sec = 300 # Don't rotate agents younger than 5 minutes
try_compact_first = true # Try compaction before rotation
require_confirm = false # Auto-rotate without confirmationntm --robot-context=SESSION # Get context usage for all agents
ntm --robot-context=SESSION --json # JSON output for automationExample output:
{
"success": true,
"session": "myproject",
"agents": [
{
"pane": "myproject__cc_1",
"estimated_tokens": 145000,
"context_limit": 200000,
"usage_percent": 72.5,
"usage_level": "Medium",
"needs_warning": false,
"needs_rotation": false
}
]
}When an agent is rotated, the old agent is asked for a structured summary containing:
- Current task being worked on
- Progress made so far
- Key decisions taken
- Active files being modified
- Any blockers or issues
This summary is passed to the fresh agent so it can continue seamlessly.
The dashboard displays context usage for each agent pane:
- Green: < 40% usage (plenty of room)
- Yellow: 40-60% usage (comfortable)
- Orange: 60-80% usage (approaching threshold)
- Red: > 80% usage (warning/needs attention)
NTM integrates with Agent Mail for multi-agent coordination across sessions and projects.
- Message routing: Send messages between agents in different sessions
- File reservations: Claim files to prevent conflicting edits
- Thread tracking: Organize discussions by topic or feature
- Human Overseer mode: Send high-priority instructions from the CLI
ntm mail send myproject --to GreenCastle "Review the API changes"
ntm mail send myproject --all "Checkpoint: sync and report status"
ntm mail inbox myproject # View agent inboxes
ntm mail read myproject --agent BlueLake # Read specific agent's mail
ntm mail ack myproject 42 # Acknowledge messagentm --robot-mail # Get mail state as JSONInstall the Agent Mail pre-commit guard to prevent commits that conflict with other agents' file reservations:
ntm hooks guard install
ntm hooks guard uninstall # Remove laterNTM uses the Catppuccin color palette by default, with support for multiple themes:
| Theme | Description |
|---|---|
auto |
Detects terminal background; dark → mocha, light → latte |
mocha |
Default dark theme, warm and cozy |
macchiato |
Darker variant with more contrast |
latte |
Light variant for light terminals |
nord |
Arctic-inspired, cooler tones |
plain |
No-color theme (uses terminal defaults; best for low-color terminals) |
Set via environment variable:
export NTM_THEME=autoEach agent type has a distinct color for visual identification:
| Agent | Color | Hex |
|---|---|---|
| Claude | Mauve (Purple) | #cba6f7 |
| Codex | Blue | #89b4fa |
| Gemini | Yellow | #f9e2af |
| User | Green | #a6e3a1 |
NTM auto-detects your terminal's capabilities:
| Set | Detection | Example Icons |
|---|---|---|
| Nerd Fonts | Powerlevel10k, iTerm2, WezTerm, Kitty | |
| Unicode | UTF-8 locale, modern terminals | ✓ ✗ ● ○ ★ ⚠ ℹ |
| ASCII | Fallback | [x] [X] * o |
Force a specific set:
export NTM_ICONS=nerd # Force Nerd Fonts
export NTM_ICONS=unicode # Force Unicode
export NTM_ICONS=ascii # Force ASCIIReduce motion (disable shimmer/pulse animations):
export NTM_REDUCE_MOTION=1Disable colors (respects the NO_COLOR standard, with an NTM override):
export NO_COLOR=1 # Any value disables colors
export NTM_NO_COLOR=1 # NTM-specific no-color toggle
export NTM_NO_COLOR=0 # Force colors ON (even if NO_COLOR is set)
export NTM_THEME=plain # Explicit no-color theme (escape hatch)- Width tiers: stacked layouts below 120 cols; split list/detail at 120+; richer metadata at 200+; tertiary labels/variants/locks at 240+; mega layouts at 320+.
- Give dashboard/status/palette at least 120 cols for split view; 200+ unlocks wider gutters and secondary columns; 240+ enables the full detail bars; 320+ enables mega layouts.
- Icons are ASCII-first by default. Switch to
NTM_ICONS=unicodeorNTM_ICONS=nerdonly if your terminal font renders them cleanly; otherwise stay on ASCII to avoid misaligned gutters. - Troubleshooting: if text wraps or glyphs drift, widen the pane, drop to
NTM_ICONS=ascii, and ensure a true monospace font (Nerd Fonts installed before usingNTM_ICONS=nerd).
| Tier | Width | Behavior |
|---|---|---|
| Narrow | <120 cols | Stacked layout, minimal badges |
| Split | 120-199 cols | List/detail split view |
| Wide | 200-239 cols | Secondary metadata, wider gutters |
| Ultra | 240-319 cols | Tertiary labels/variants/locks, max detail |
| Mega | ≥320 cols | Mega layouts, richest metadata |
# 1) Install + shell integration (zsh example)
curl -fsSL https://raw.githubusercontent.com/Dicklesworthstone/ntm/main/install.sh | bash
echo 'eval "$(ntm init zsh)"' >> ~/.zshrc && source ~/.zshrc
# 2) Sanity check + quick orientation
ntm deps -v
ntm tutorial
# 3) Spawn a session and bind the palette popup key (F6 by default)
ntm spawn myapi --cc=2 --cod=1
ntm bindntm attach myapi
# Inside the dashboard/palette: press ? for key hints
ntm dashboard myapi
ntm palette myapi
# Useful capture loop
ntm copy myapi --cc --last 200
ntm save myapi -o ~/logs/myapi
# Detach from tmux (agents keep running): Ctrl+B, then Dssh user@host
# Sessions persist on the server
ntm list
ntm attach myapi
# Inside tmux, these auto-select the current session:
ntm dashboard
ntm palette
# If clipboard isn't available on the remote, save to a file instead:
ntm copy myapi --cc --output out.txt- No sessions exist:
ntm spawn <name> - Icons drift/misaligned gutters:
export NTM_ICONS=ascii - Too much motion/flicker:
export NTM_REDUCE_MOTION=1 - Need plain output / low-color terminal:
export NTM_THEME=plain(orexport NO_COLOR=1) - Copy complains about non-interactive mode: pass a session explicitly (e.g.
ntm copy myapi --cc)
# 1. Check if agent CLIs are installed
ntm deps -v
# 2. Create project scaffold (optional)
ntm quick myapi --template=go
# 3. Spawn agents
ntm spawn myapi --cc=3 --cod=2
# 4. You're now attached to the session with 5 agents + 1 user pane# Send task to all Claude agents
ntm send myapi --cc "implement the /users endpoint with full CRUD operations"
# Send different task to Codex agents
ntm send myapi --cod "write comprehensive unit tests for the users module"
# Check status
ntm status myapi
# Zoom to a specific agent to see details
ntm zoom myapi 2
# View all panes
ntm view myapi# Open palette (or press F6 in tmux)
ntm palette myapi
# Use fuzzy search to find commands
# Type "fix" to filter to "Fix the Bug"
# Press 1-9 for quick select
# Press ? for key hints/help overlay
# Ctrl+P to pin/unpin a command; Ctrl+F to favorite/unfavorite
# Select target: 1=All, 2=Claude, 3=Codex, 4=Gemini# Need more Claude agents? Add 2 more
ntm add myapi --cc=2
# Interrupt all agents to give new instructions
ntm interrupt myapi
# Send new prompt to all
ntm send myapi --all "stop current work and focus on fixing the CI pipeline"# Save all agent outputs before ending session
ntm save myapi -o ~/logs/myapi
# Or copy specific agent output to clipboard
ntm copy myapi --cc# Detach (agents keep running)
# Press: Ctrl+B, then D
# Later, reattach
ntm attach myapi
# When done, kill session
ntm kill -f myapiDifferent problems call for different agent orchestration patterns. Here are proven strategies:
Assign different aspects of a task to different agent types based on their strengths:
# Start with architecture (Claude excels at high-level design)
ntm send myproject --cc "design the database schema for user management"
# Implementation (Codex for code generation)
ntm send myproject --cod "implement the User and Role models based on the schema"
# Testing (Gemini for comprehensive test coverage)
ntm send myproject --gmi "write unit and integration tests for the models"Best for: Large features with distinct phases (design → implement → test)
Have multiple agents solve the same problem independently, then compare approaches:
# Same prompt to all agents
ntm send myproject --all "implement a rate limiter middleware that allows 100 requests per minute per IP"
# View all panes side-by-side
ntm view myproject
# Compare implementations, pick the best one (or combine ideas)Best for: Problems with multiple valid solutions, learning different approaches
Create agents with specific responsibilities:
# Create session with specialists
ntm spawn myproject --cc=2 --cod=2 --gmi=2
# Claude team: architecture and review
ntm send myproject --cc "focus on code architecture and reviewing others' work"
# Codex team: implementation
ntm send myproject --cod "focus on implementing features and fixing bugs"
# Gemini team: testing and docs
ntm send myproject --gmi "focus on testing and documentation"Best for: Large projects with multiple concerns
Use agents to review each other's work:
# Implementation
ntm send myproject --cc "implement feature X with full error handling"
# Wait for completion, then peer review
ntm send myproject --cod "review the code Claude just wrote - look for bugs and improvements"
# Final validation
ntm send myproject --gmi "write tests that would catch the bugs mentioned in the review"Best for: Quality assurance, catching edge cases
Start simple, escalate when stuck:
# Start with one Claude agent
ntm spawn myproject --cc=1
# If stuck, add more perspectives
ntm add myproject --cc=1 --cod=1
# Still stuck? More agents
ntm add myproject --gmi=1
# Broadcast the problem to all
ntm send myproject --all "I'm stuck on X. Here's what I've tried: Y. What am I missing?"Best for: Debugging, breaking through blockers
Pre-commit: Save Agent Context
#!/bin/bash
# .git/hooks/pre-commit
SESSION=$(basename "$(pwd)")
if tmux has-session -t "$SESSION" 2>/dev/null; then
mkdir -p .agent-logs
ntm save "$SESSION" -o .agent-logs 2>/dev/null
fiPre-commit: Block Conflicting Commits (Agent Mail Guard)
Install the Agent Mail pre-commit guard so commits fail when you’re about to commit files reserved by other agents:
ntm hooks guard install
# Warn-only mode (doesn't block commits)
export AGENT_MAIL_GUARD_MODE=warnRemove it later:
ntm hooks guard uninstallAutomated Project Bootstrap:
#!/bin/bash
# bootstrap-project.sh
set -e
PROJECT="$1"
TEMPLATE="${2:-go}"
echo "Creating project: $PROJECT"
# Create project with template
ntm quick "$PROJECT" --template="$TEMPLATE"
# Spawn agents
ntm spawn "$PROJECT" --cc=2 --cod=2
# Give initial context
ntm send "$PROJECT" --all "You are working on a new $TEMPLATE project. Read any existing code and prepare to implement features."
echo "Project $PROJECT ready!"
echo "Run: ntm attach $PROJECT"Status Report:
#!/bin/bash
# status-all.sh
echo "=== Agent Status Report ==="
echo "Generated: $(date)"
echo ""
for session in $(tmux list-sessions -F '#{session_name}' 2>/dev/null); do
echo "## $session"
ntm status "$session"
echo ""
donetasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "NTM: Start Agents",
"type": "shell",
"command": "ntm spawn ${workspaceFolderBasename} --cc=2 --cod=2"
},
{
"label": "NTM: Send to Claude",
"type": "shell",
"command": "ntm send ${workspaceFolderBasename} --cc \"${input:prompt}\""
},
{
"label": "NTM: Open Palette",
"type": "shell",
"command": "ntm palette ${workspaceFolderBasename}"
}
],
"inputs": [
{
"id": "prompt",
"type": "promptString",
"description": "Enter prompt for agents"
}
]
}Add these to your ~/.tmux.conf for better agent management:
# Increase scrollback buffer (default is 2000)
set-option -g history-limit 50000
# Enable mouse support for pane selection
set -g mouse on
# Show pane titles in status bar
set -g pane-border-status top
set -g pane-border-format " #{pane_title} "
# Better colors for pane borders (Catppuccin-inspired)
set -g pane-border-style fg=colour238
set -g pane-active-border-style fg=colour39
# Faster key repetition
set -s escape-time 0Reload with: tmux source-file ~/.tmux.conf
If you're new to tmux, here are the key bindings (default prefix is Ctrl+B):
| Keys | Action |
|---|---|
Ctrl+B, D |
Detach from session |
Ctrl+B, [ |
Enter scroll/copy mode |
Ctrl+B, z |
Toggle zoom on current pane |
Ctrl+B, Arrow |
Navigate between panes |
Ctrl+B, c |
Create new window |
Ctrl+B, , |
Rename current window |
q |
Exit scroll mode |
F6 |
Open NTM palette (after shell integration) |
NTM will offer to help install tmux. If that fails:
# macOS
brew install tmux
# Ubuntu/Debian
sudo apt install tmux
# Fedora
sudo dnf install tmuxUse --force or attach to the existing session:
ntm attach myproject # Attach to existing
# OR
ntm kill -f myproject && ntm spawn myproject --cc=3 # Kill and recreateForce a re-tile:
ntm view myprojectInterrupt and restart:
ntm interrupt myproject
ntm send myproject --cc "continue where you left off"Check your terminal supports Nerd Fonts or force a fallback:
export NTM_ICONS=unicode # Use Unicode icons
export NTM_ICONS=ascii # Use ASCII onlyReload your shell configuration:
source ~/.zshrc # or ~/.bashrcUse the built-in upgrade command:
ntm upgradeQ: Does this work with bash?
A: Yes! NTM is a compiled Go binary that works with any shell. The shell integration (ntm init bash) provides aliases and completions for bash.
Q: Can I use this over SSH?
A: Yes! This is one of the primary use cases. Tmux sessions persist on the server:
- SSH to your server
- Start agents:
ntm spawn myproject --cc=3 - Detach:
Ctrl+B, D - Disconnect SSH
- Later: SSH back, run
ntm attach myproject
All agents continue running while you're disconnected.
Q: How many agents can I run simultaneously?
A: Practically limited by:
- Memory: Each agent CLI uses 100-500MB RAM
- API rate limits: Provider-specific throttling
- Screen real estate: Beyond ~16 panes, they become too small
Q: Does this work on Windows?
A: Not natively. Options:
- WSL2: Install in WSL2, works perfectly
- Git Bash: Limited support (no tmux)
Q: Why are agents run with "dangerous" flags?
A: The flags (--dangerously-skip-permissions, --yolo, etc.) allow agents to work autonomously without confirmation prompts. This is intentional for productivity. Only use in development environments.
Q: Can I add support for other AI CLIs?
A: Yes! Edit your config to add custom agent commands:
[agents]
claude = "my-custom-claude-wrapper"
codex = "aider --yes-always"
gemini = "cursor --accept-all"Q: Do agents share context with each other?
A: No, each agent runs independently. They:
- ✅ Can see the same filesystem
- ✅ Can read each other's file changes
- ❌ Cannot communicate directly
- ❌ Don't share conversation history
Use broadcast (ntm send) to coordinate.
Q: What happens if an agent crashes?
A: The pane stays open with a shell prompt. You can:
- Restart by typing the agent alias (
cc,cod,gmi) - Check what happened by scrolling up (
Ctrl+B, [) - The pane title remains, so filters still work
Q: How do I increase scrollback history?
A: Add to ~/.tmux.conf:
set-option -g history-limit 50000 # Default is 2000Q: What's the fastest way to learn NTM?
A: Run the interactive tutorial:
ntm tutorialIt walks you through all the core concepts with animated examples.
Q: How do I keep NTM updated?
A: Use the built-in upgrade command:
ntm upgrade # Check for updates and install
ntm upgrade --check # Just check, don't installThe agent aliases include flags that bypass safety prompts:
| Alias | Flag | Purpose |
|---|---|---|
cc |
--dangerously-skip-permissions |
Allows Claude full system access |
cod |
--dangerously-bypass-approvals-and-sandbox |
Allows Codex full system access |
gmi |
--yolo |
Allows Gemini to execute without confirmation |
These are intentional for productivity but mean the agents can:
- Read/write any files
- Execute system commands
- Make network requests
Recommendations:
- Only use in development environments
- Review agent outputs before committing code
- Don't use with sensitive credentials in scope
- Consider sandboxed environments for untrusted projects
| Component | Typical RAM | Notes |
|---|---|---|
| tmux server | 5-10 MB | Single process for all sessions |
| Per tmux pane | 1-2 MB | Minimal overhead |
Claude CLI (cc) |
200-400 MB | Node.js process |
Codex CLI (cod) |
150-300 MB | Varies by model |
Gemini CLI (gmi) |
100-200 MB | Lighter footprint |
Rough formula:
Total RAM ≈ 10 + (panes × 2) + (claude × 300) + (codex × 200) + (gemini × 150) MB
Example: Session with 3 Claude + 2 Codex + 1 Gemini + 1 user pane:
10 + (7 × 2) + (3 × 300) + (2 × 200) + (1 × 150) = 1,474 MB ≈ 1.5 GB
-
Start minimal, scale up
ntm spawn myproject --cc=1 ntm add myproject --cc=1 --cod=1 # Add more as needed -
Use multiple windows instead of many panes
tmux new-window -t myproject -n "tests" -
Save outputs before scrollback is lost
ntm save myproject -o ~/logs
| Approach | Pros | Cons |
|---|---|---|
| NTM | Purpose-built for AI agents, beautiful TUI, named panes, broadcast prompts | Requires tmux |
| Multiple Terminal Windows | Simple, no setup | No persistence, window chaos, no orchestration |
| Tmux (manual) | Full control | Verbose commands, no agent-specific features |
| Screen | Available everywhere | Fewer features, dated |
| Docker Containers | Full isolation | Heavyweight, complex |
✅ Good fit:
- Running multiple AI agents in parallel
- Remote development over SSH
- Projects requiring persistent sessions
- Workflows needing broadcast prompts
- Developers comfortable with CLI
❌ Consider alternatives:
- Single-agent workflows (just use the CLI directly)
- GUI-preferred workflows (use IDE integration)
- Windows without WSL
git clone https://github.com/Dicklesworthstone/ntm.git
cd ntm
go build -o ntm ./cmd/ntmgo test ./...# Build the container image
docker build -t ntm:local .
# Build with version info
docker build \
--build-arg VERSION=1.0.0 \
--build-arg COMMIT=$(git rev-parse HEAD) \
--build-arg DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ) \
-t ntm:local .NTM uses GitHub Actions for continuous integration:
- Lint: golangci-lint with 40+ linters
- Test: Unit tests with coverage on Linux and macOS
- Build: Cross-platform builds (Linux, macOS, Windows, FreeBSD)
- Security: Vulnerability scanning with govulncheck and gosec
- Release: Automated releases via GoReleaser with multi-arch Docker images
ntm/
├── cmd/ntm/ # Main entry point
├── internal/
│ ├── cli/ # Cobra commands and help rendering
│ ├── config/ # TOML configuration and palette loading
│ ├── palette/ # Command palette TUI with animations
│ ├── robot/ # Machine-readable JSON output for AI agents
│ ├── tmux/ # Tmux session/pane/window operations
│ ├── tutorial/ # Interactive tutorial with animated slides
│ ├── updater/ # Self-update from GitHub releases
│ ├── watcher/ # File watching utilities
│ └── tui/
│ ├── components/ # Reusable components (spinners, progress, banner)
│ ├── dashboard/ # Interactive session dashboard
│ ├── icons/ # Nerd Font / Unicode / ASCII icon sets
│ ├── styles/ # Gradient text, shimmer, glow effects
│ └── theme/ # Catppuccin themes (Mocha, Macchiato, Nord)
├── .github/workflows/ # CI/CD pipelines
├── .goreleaser.yaml # Release configuration
└── Dockerfile # Container image definition
MIT License. See LICENSE for details.
About Contributions: Please don't take this the wrong way, but I do not accept outside contributions for any of my projects. I simply don't have the mental bandwidth to review anything, and it's my name on the thing, so I'm responsible for any problems it causes; thus, the risk-reward is highly asymmetric from my perspective. I'd also have to worry about other "stakeholders," which seems unwise for tools I mostly make for myself for free. Feel free to submit issues, and even PRs if you want to illustrate a proposed fix, but know I won't merge them directly. Instead, I'll have Claude or Codex review submissions via
ghand independently decide whether and how to address them. Bug reports in particular are welcome. Sorry if this offends, but I want to avoid wasted time and hurt feelings. I understand this isn't in sync with the prevailing open-source ethos that seeks community contributions, but it's the only way I can move at this velocity and keep my sanity.
- tmux - The terminal multiplexer that makes this possible
- Bubble Tea - The TUI framework
- Catppuccin - The beautiful color palette
- Nerd Fonts - The icon fonts
- Cobra - The CLI framework
- Claude Code, Codex, Gemini CLI - The AI agents this tool orchestrates