Zerg Terminal Client - CLI agent for continual AI systems
npm install zerg-ztcA full-screen terminal-based AI agent interface for interacting with the Zerg continual AI system and managing local development tasks.
``
◆ Zerg Terminal Client ◆ v0.1.0 Ctrl+C exit • /help
────────────────────────────────────────────────────────────────────────
● System • 14:23
Welcome to ZTC - Zerg Terminal Client.
Type a message to begin, or /help for commands.
❯ You • 14:24
Can you read the package.json and summarize it?
◆ Zerg • 14:24
I'll read that file for you.
⚙ read_file (a3f8b2c1) [0.2s]
path: package.json
→ {"name":"ztc","version":"0.1.0"...
This is ZTC v0.1.0, a Node.js CLI application using Ink for the
terminal UI and React 18. It has 5 tools available for file
operations, shell commands, and Zerg queries.
❯ _
● Ready ◉ ZTC v0.1.0 • a3f8b2c1
`
- Full-screen terminal UI - Built with Ink (React for CLIs)
- Agentic tool use - File I/O, shell commands, directory listing, Zerg integration
- Streaming responses - Real-time output with status indicators
- Session management - Unique session IDs, message history
- In-app configuration - Set API keys and model preferences without restarting
- Persistent config - Settings saved to ~/.ztc/config.json
- Debug mode - Toggle layout borders for development
- Web UI - Browser-based interface for easier debugging
`bashClone or create the project
mkdir ztc && cd ztc
$3
- Node.js >= 18
- npm or yarn
- Anthropic API key (can be configured in-app)
Usage
$3
`bash
Development (with hot reload via tsx)
npm run devProduction
npm run build
npm startOr install globally
npm link
ztc
`$3
`bash
npm run web
Opens at http://localhost:3000
`The web UI provides the same interface in a browser, making it easier to debug layouts and inspect state.
Configuration
ZTC stores configuration in
~/.ztc/config.json. You can manage it via commands:`bash
/config show # View current configuration
/config key sk-ant-... # Set Anthropic API key
/config model claude-opus-4-20250514 # Change model
`Or set via environment variable:
`bash
export ANTHROPIC_API_KEY=sk-ant-your-key-here
npm run dev
`$3
| Option | Description | Default |
|--------|-------------|---------|
|
apiKey | Anthropic API key | $ANTHROPIC_API_KEY |
| model | Claude model to use | claude-sonnet-4-20250514 |
| maxTokens | Max response tokens | 4096 |
| zergEndpoint | Zerg API endpoint | undefined |Commands
| Command | Description |
|---------|-------------|
|
/help | Show available commands |
| /config | Manage configuration |
| /status | Show current status |
| /clear | Clear message history |
| /debug | Toggle layout debug borders |
| /exit | Exit ZTC |Keyboard Shortcuts
| Shortcut | Action |
|----------|--------|
|
Enter | Submit message |
| Ctrl+C | Exit |
| Ctrl+L | Clear screen |
| ↑ / ↓ | Navigate command history |
| ← / → | Move cursor |
| Ctrl+← / Ctrl+→ | Move by word |
| Ctrl+A | Move to start of line |
| Ctrl+E | Move to end of line |
| Ctrl+U | Clear input line |
| Ctrl+W | Delete word before cursor |Available Tools
The agent has access to these tools:
$3
Read contents of a file.
`
Arguments:
path: string (required) - File path to read
encoding: string - File encoding (default: utf-8)
`$3
Write content to a file, creating directories if needed.
`
Arguments:
path: string (required) - File path to write
content: string (required) - Content to write
append: "true" | "false" - Append instead of overwrite
`$3
List contents of a directory.
`
Arguments:
path: string (required) - Directory path
recursive: "true" | "false" - List recursively (max 3 levels)
`$3
Execute a shell command.
`
Arguments:
command: string (required) - Shell command to execute
cwd: string - Working directory
timeout: string - Timeout in ms (default: 30000)
`$3
Query the Zerg continual AI system.
`
Arguments:
query: string (required) - Query for Zerg
context: string - Additional context
project: string - Project identifier
wait: "true" | "false" - Wait for completion
`Project Structure
`
ztc/
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
├── README.md
└── src/
├── cli.tsx # CLI entry point
├── App.tsx # Main application component
├── types.ts # TypeScript type definitions
├── config.ts # Configuration store (sync file I/O)
│
├── components/
│ ├── index.ts # Barrel export
│ ├── Header.tsx # Top header bar
│ ├── MessageList.tsx # Scrolling message area
│ ├── InputArea.tsx # Text input with cursor handling
│ └── StatusBar.tsx # Bottom status bar with spinner
│
├── agent/
│ ├── index.ts # Barrel export
│ ├── agent.ts # Agent loop, API calls, event emitter
│ └── tools.ts # Tool definitions and executors
│
└── web/
└── index.html # Standalone browser UI for debugging
`Architecture
$3
ZTC uses Ink which leverages Yoga (the same Flexbox layout engine used by React Native) to render React components to the terminal. This provides:
- Familiar React component model
- Flexbox-based layouts
- Hooks for input handling
- Efficient differential updates
$3
`
User Input → Agent.run() → API Call → Tool Use? → Execute Tools → Continue
↑ │ │
└─────────────────────────┴──────────────┘
`The agent implements a standard ReAct-style loop:
1. Send conversation to Claude API
2. If response contains tool calls, execute them
3. Append results and continue until no more tools
4. Return final response to UI
$3
The agent emits events for UI updates:
-
thinking_start / thinking_end
- tool_start / tool_end / tool_error
- stream_start / stream_delta / stream_end
- error$3
Terminal UIs can flicker during re-renders. ZTC prevents this by:
1. Loading config synchronously at startup
2. Capturing terminal dimensions once at module load
3. Avoiding hooks that cause re-renders (
useStdout)
4. Using useMemo for computed valuesDevelopment
$3
1. Define the tool in
src/agent/tools.ts:`typescript
export const myTool: Tool = {
definition: {
name: 'my_tool',
description: 'Does something useful',
parameters: {
type: 'object',
properties: {
arg1: { type: 'string', description: 'First argument' }
},
required: ['arg1']
}
},
execute: async (args) => {
// Implementation
return JSON.stringify({ result: 'done' });
}
};
`2. Add to
defaultTools array in the same file.$3
Add to the
commands array in src/App.tsx:`typescript
{
name: 'mycommand',
description: 'Does something',
usage: '',
handler: (args, ctx) => {
ctx.addMessage({
role: 'system',
content: You said: ${args.join(' ')}
});
}
}
`$3
`bash
npm run build # Compile TypeScript to dist/
npm run clean # Remove dist/
`Roadmap
- [ ] Streaming responses - Token-by-token output
- [ ] Session persistence - Save/load conversation history
- [ ] Multi-line input - Support for longer prompts
- [ ] Zerg integration - Connect to actual Zerg backend
- [ ] Git tools - Commit, diff, branch operations
- [ ] Search tools - Web search, codebase search
- [ ] Shared state module - Extract core logic for terminal + web UIs
- [ ] Plugin system - Dynamic tool loading
Troubleshooting
$3
Set your key with:
`
/config key sk-ant-your-key-here
`Or via environment:
`bash
export ANTHROPIC_API_KEY=sk-ant-...
`$3
Your API key may be invalid or expired. Update it with
/config key .$3
This shouldn't happen with current code. If it does:
1. Ensure you're using the latest source
2. Check terminal compatibility (works best with modern terminals)
3. Try the web UI for debugging:
npm run web$3
`bash
npm run build
``If you see type errors, ensure all files match the artifacts exactly.
MIT
---
Built for the Zerg continual AI system.