Package Exports
- @robota-sdk/agent-cli
Readme
@robota-sdk/agent-cli
AI coding assistant CLI built on Robota SDK. Loads AGENTS.md/CLAUDE.md for project context and provides a tool-calling REPL with Claude Code-compatible permission modes.
Version: 3.0.0-beta.40
Installation
# Global install
npm install -g @robota-sdk/agent-cli
# Or run directly with npx
npx @robota-sdk/agent-climacOS users: Korean/CJK IME input may crash macOS Terminal.app. Use iTerm2 instead. This is a known Ink + Terminal.app issue shared with Claude Code.
After installing globally, the robota command is available system-wide:
robota # Interactive REPL
robota "prompt" # REPL with initial prompt
robota -p "List all files" # Print mode (one-shot, exit after response)Environment Variables
| Variable | Description | Required |
|---|---|---|
ANTHROPIC_API_KEY |
Anthropic API key | Yes |
Set your key before running:
export ANTHROPIC_API_KEY=sk-ant-...Development Setup (Monorepo)
# 1. Copy .env.example and add your Anthropic API key
cp packages/agent-cli/.env.example packages/agent-cli/.env
# Edit .env and set ANTHROPIC_API_KEY=sk-ant-...
# 2. Build dependencies and CLI
pnpm build:deps
pnpm --filter @robota-sdk/agent-cli buildUsage (Monorepo)
# From monorepo root
cd packages/agent-cli
# Development mode (no build needed, auto-loads .env)
pnpm dev
# Production mode (requires build)
pnpm start
# With arguments
pnpm dev -- --version
pnpm dev -- --permission-mode plan
pnpm dev -- -p "List all TypeScript files in src/"CLI Flags
robota # Interactive REPL (default mode)
robota "prompt" # REPL with initial prompt
robota -p "prompt" # Print mode (one-shot, exit after response)
robota -c # Continue last session
robota -r <session-id> # Resume session by ID
robota --model <model> # Model override (e.g., claude-sonnet-4-6)
robota --language <lang> # Response language (ko, en, ja, zh)
robota --permission-mode <mode> # plan | default | acceptEdits | bypassPermissions
robota --max-turns <n> # Limit agentic turns per interaction
robota --output-format <fmt> # text | json | stream-json (print mode)
robota --system-prompt <text> # Replace system prompt (print mode)
robota --append-system-prompt <text> # Append to system prompt (print mode)
robota --reset # Delete user settings and exit
robota --version # Show versionPrint Mode Output Formats
Print mode (-p) supports three output formats via --output-format:
| Format | Description |
|---|---|
text |
Plain text response to stdout (default) |
json |
Single JSON object: { type, result, session_id, subtype } |
stream-json |
Newline-delimited JSON with content_block_delta streaming events |
Stdin Pipe
When -p is used without a positional argument and stdin is piped, the CLI reads from stdin:
echo "Explain this error" | robota -p
cat file.ts | robota -p "Review this code" --output-format json
git diff | robota -p "Summarize changes" --output-format stream-jsonFirst-Run Setup
When no settings file exists, the CLI prompts for:
- Anthropic API key (input masked with asterisks)
- Response language (ko/en/ja/zh, default: en)
Creates ~/.robota/settings.json. Use robota --reset to return to first-run state.
Built-in Tools
The AI agent can invoke 6 tools:
| Tool | Description | Primary Argument |
|---|---|---|
Bash |
Execute shell commands | command |
Read |
Read file contents with line numbers | filePath |
Write |
Write content to a file | filePath |
Edit |
Replace a string in a file | filePath |
Glob |
Find files matching a pattern | pattern |
Grep |
Search file contents with regex | pattern |
Permission System
Every tool call passes through a three-step permission gate:
- Deny list — if any deny pattern matches, the action is blocked
- Allow list — if any allow pattern matches, the action is auto-approved
- Mode policy — the active permission mode determines the decision
Permission Modes
| Mode | Read/Glob/Grep | Write/Edit | Bash |
|---|---|---|---|
plan |
auto | deny | deny |
default |
auto | approve | approve |
acceptEdits |
auto | auto | approve |
bypassPermissions |
auto | auto | auto |
Changing Mode at Runtime
Use the /mode slash command:
> /mode # Show current mode
> /mode plan # Switch to plan (read-only)
> /mode bypassPermissions # Skip all promptsOr set it at startup:
robota --permission-mode planPermission Patterns
Configure in .robota/settings.json or .robota/settings.local.json:
{
"permissions": {
"allow": ["Bash(pnpm *)", "Bash(git status)", "Read(/src/**)"],
"deny": ["Bash(rm -rf *)", "Write(.env)"]
}
}Pattern syntax: ToolName matches any invocation; ToolName(pattern) matches on the primary argument with shell-style globs (*, **).
Keyboard Controls
| Key | Action |
|---|---|
| Enter | Submit input |
| ESC | Abort current execution (graceful — saves partial response) |
| Ctrl+C | Exit process immediately |
| Up/Down | Navigate visual lines in wrapped multi-line input |
| Arrow keys | Navigate slash command autocomplete, permission prompt |
Paste Handling
Bracketed paste mode (DECSET 2004) is enabled on startup. When pasting multiline text, the input area collapses it into a label: [Pasted text #1 +42 lines]. Multiple pastes are numbered sequentially. The full content is expanded on submit.
Single-line paste is inserted directly as typed text. Terminals without bracketed paste fall back to heuristic detection.
Edit Diff Display
After the Edit tool runs, a DiffBlock component renders the change inline:
✓ Edit(src/provider.ts)
│ src/provider.ts
│ - const DEFAULT_MAX_TOKENS = 4096;
│ + const maxTokens = getModelMaxOutput(modelId);Removed lines appear in red with -, added lines in green with +. Diffs longer than 10 lines show the first 8 + a ... and N more lines summary.
Session Management
The CLI supports continuing, resuming, forking, and naming sessions.
CLI Flags
| Flag | Description |
|---|---|
-c, --continue |
Continue the most recent session |
-r, --resume <id> |
Resume a specific session by ID |
--fork-session <id> |
Fork a session (new session with copied history) |
--name <name> |
Assign a name to the session at startup |
TUI Commands
| Command | Description |
|---|---|
/resume |
List recent sessions and resume one |
/rename <name> |
Rename the current session |
Session Name Display
When a session has a name, it appears in three places:
- Input border — session name shown in the input area border
- Terminal title — updated via ANSI escape sequences
- StatusBar — displayed alongside mode, model, and context usage
Slash Commands
| Command | Description |
|---|---|
/help |
Show available commands |
/clear |
Clear conversation history |
/mode [mode] |
Show or change permission mode |
/model [model] |
Select AI model (confirmation prompt, CLI restarts) |
/language [lang] |
Set response language (ko, en, ja, zh), saves and restarts |
/compact [instructions] |
Compress context window |
/cost |
Show session info |
/context |
Context window details |
/permissions |
Show permission rules |
/plugin [subcommand] |
Plugin management TUI |
/resume |
List recent sessions and resume one |
/rename <name> |
Rename the current session |
/exit |
Exit CLI |
Typing / triggers an autocomplete popup with arrow-key navigation and Esc to dismiss. Tab inserts the highlighted command into the input field without executing — continue typing args or press Enter to execute. Enter selects and executes immediately. Commands with subcommands (e.g., /mode, /model) show a nested submenu. Skill commands discovered from .agents/skills/ and .claude/commands/ appear alongside built-in commands.
Plugin Management
The /plugin command opens an interactive TUI for managing bundle plugins:
| Subcommand | Description |
|---|---|
/plugin install <name> |
Install a plugin from marketplace or local path |
/plugin uninstall <name> |
Remove an installed plugin |
/plugin enable <name> |
Enable a disabled plugin |
/plugin disable <name> |
Disable a plugin without uninstalling |
/plugin list |
List installed plugins with status |
/plugin marketplace |
Browse available plugins from configured sources |
Configuration
Settings are loaded from (highest priority first):
.robota/settings.local.json(local, gitignored).robota/settings.json(project, shared).claude/settings.json(project, Claude Code compatible)~/.robota/settings.json(user global)~/.claude/settings.json(user global, Claude Code compatible)
{
"defaultMode": "default",
"language": "en",
"provider": {
"name": "anthropic",
"model": "claude-sonnet-4-6",
"apiKey": "$ENV:ANTHROPIC_API_KEY"
},
"permissions": {
"allow": ["Bash(pnpm *)"],
"deny": ["Bash(rm -rf *)"]
}
}Context Discovery
The CLI automatically discovers and loads:
- AGENTS.md — walking up from cwd to filesystem root
- CLAUDE.md — same walk-up discovery
- Project metadata — from
package.json,tsconfig.json
All context is assembled into the system prompt.
Memory Management
- Message windowing — React state keeps the most recent 100 messages. Older messages are dropped from the render tree; full history remains in the session store.
- Tool state cleanup — Completed tool execution states are trimmed to the most recent 50 entries.
- React.memo —
MessageItemusesReact.memoto skip redundant re-renders.
Session Logging
Session logs are written to .robota/logs/{sessionId}.jsonl in JSONL format by default, capturing structured events for diagnostics and replay.
Architecture
The CLI is a pure TUI layer. All business logic lives in @robota-sdk/agent-sdk's InteractiveSession. useInteractiveSession is the sole React↔SDK bridge, converting SDK events to React state.
bin.ts → cli.ts (arg parsing)
└── ui/render.tsx → App.tsx (thin JSX shell)
├── useInteractiveSession (ONLY React↔SDK bridge)
│ ├── InteractiveSession (SDK)
│ ├── CommandRegistry (SDK, re-exported by CLI)
│ │ ├── BuiltinCommandSource (SDK)
│ │ ├── SkillCommandSource (SDK, discovers from 4 paths)
│ │ └── PluginCommandSource (CLI-local)
│ └── SystemCommandExecutor (SDK)
├── plugin-hooks-merger.ts (merges plugin hooks into SDK config)
├── MessageList.tsx
├── InputArea.tsx (CjkTextInput, bracketed paste, slash detection)
├── StatusBar.tsx (mode, model, context %, message count)
├── PermissionPrompt.tsx (arrow-key Allow/Deny)
├── SlashAutocomplete.tsx (command popup with scroll)
├── DiffBlock.tsx (Edit tool diff display)
├── MenuSelect.tsx (arrow-key menu, Plugin TUI)
├── PluginTUI.tsx (plugin management screen stack)
├── TextPrompt.tsx (text input for Plugin TUI)
└── ConfirmPrompt.tsx (reusable yes/no prompt)Dependencies
| Package | Purpose |
|---|---|
@robota-sdk/agent-sdk |
Session factory, query, config, context |
@robota-sdk/agent-core |
Types (TPermissionMode, TToolArgs) |
@robota-sdk/agent-transport-headless |
Headless runner for print mode (-p) |
ink, react |
TUI rendering |
ink-select-input |
Arrow-key selection (permission prompt) |
ink-spinner |
Loading spinner |
chalk |
Terminal colors |
ink-text-input |
Base text input (extended by CjkTextInput) |
marked, marked-terminal |
Markdown parsing and terminal rendering |
cli-highlight |
Syntax highlighting for code blocks |
string-width |
Unicode-aware string width (CJK support) |
Documentation
See docs/SPEC.md for the full specification, architecture details, and design decisions.
License
MIT