@robota-sdk/agent-cli 3.0.0-beta.5 → 3.0.0-beta.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +195 -86
- package/dist/node/bin.js +11 -1
- package/dist/node/chunk-7EBJI2DW.js +2548 -0
- package/dist/node/index.cjs +2057 -719
- package/dist/node/index.d.cts +10 -23
- package/dist/node/index.d.ts +10 -23
- package/dist/node/index.js +1 -8
- package/package.json +16 -4
- package/dist/node/bin.cjs +0 -1217
- package/dist/node/bin.d.cts +0 -1
- package/dist/node/chunk-4DYVT4WI.js +0 -1196
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# @robota-sdk/agent-cli
|
|
2
2
|
|
|
3
|
-
AI coding assistant CLI built on Robota SDK. Loads AGENTS.md/CLAUDE.md for project context and provides tool-calling REPL with Claude Code-compatible permission modes.
|
|
3
|
+
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.
|
|
4
|
+
|
|
5
|
+
**Version**: 3.0.0-beta.40
|
|
4
6
|
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
@@ -12,6 +14,8 @@ npm install -g @robota-sdk/agent-cli
|
|
|
12
14
|
npx @robota-sdk/agent-cli
|
|
13
15
|
```
|
|
14
16
|
|
|
17
|
+
> **macOS users**: Korean/CJK IME input may crash macOS Terminal.app. Use **[iTerm2](https://iterm2.com/)** instead. This is a known Ink + Terminal.app issue shared with Claude Code.
|
|
18
|
+
|
|
15
19
|
After installing globally, the `robota` command is available system-wide:
|
|
16
20
|
|
|
17
21
|
```bash
|
|
@@ -71,14 +75,48 @@ robota -p "prompt" # Print mode (one-shot, exit after response)
|
|
|
71
75
|
robota -c # Continue last session
|
|
72
76
|
robota -r <session-id> # Resume session by ID
|
|
73
77
|
robota --model <model> # Model override (e.g., claude-sonnet-4-6)
|
|
78
|
+
robota --language <lang> # Response language (ko, en, ja, zh)
|
|
74
79
|
robota --permission-mode <mode> # plan | default | acceptEdits | bypassPermissions
|
|
75
80
|
robota --max-turns <n> # Limit agentic turns per interaction
|
|
81
|
+
robota --output-format <fmt> # text | json | stream-json (print mode)
|
|
82
|
+
robota --system-prompt <text> # Replace system prompt (print mode)
|
|
83
|
+
robota --append-system-prompt <text> # Append to system prompt (print mode)
|
|
84
|
+
robota --reset # Delete user settings and exit
|
|
76
85
|
robota --version # Show version
|
|
77
86
|
```
|
|
78
87
|
|
|
88
|
+
### Print Mode Output Formats
|
|
89
|
+
|
|
90
|
+
Print mode (`-p`) supports three output formats via `--output-format`:
|
|
91
|
+
|
|
92
|
+
| Format | Description |
|
|
93
|
+
| ------------- | ------------------------------------------------------------------ |
|
|
94
|
+
| `text` | Plain text response to stdout (default) |
|
|
95
|
+
| `json` | Single JSON object: `{ type, result, session_id, subtype }` |
|
|
96
|
+
| `stream-json` | Newline-delimited JSON with `content_block_delta` streaming events |
|
|
97
|
+
|
|
98
|
+
### Stdin Pipe
|
|
99
|
+
|
|
100
|
+
When `-p` is used without a positional argument and stdin is piped, the CLI reads from stdin:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
echo "Explain this error" | robota -p
|
|
104
|
+
cat file.ts | robota -p "Review this code" --output-format json
|
|
105
|
+
git diff | robota -p "Summarize changes" --output-format stream-json
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## First-Run Setup
|
|
109
|
+
|
|
110
|
+
When no settings file exists, the CLI prompts for:
|
|
111
|
+
|
|
112
|
+
1. **Anthropic API key** (input masked with asterisks)
|
|
113
|
+
2. **Response language** (ko/en/ja/zh, default: en)
|
|
114
|
+
|
|
115
|
+
Creates `~/.robota/settings.json`. Use `robota --reset` to return to first-run state.
|
|
116
|
+
|
|
79
117
|
## Built-in Tools
|
|
80
118
|
|
|
81
|
-
The
|
|
119
|
+
The AI agent can invoke 6 tools:
|
|
82
120
|
|
|
83
121
|
| Tool | Description | Primary Argument |
|
|
84
122
|
| ------- | ------------------------------------ | ---------------- |
|
|
@@ -91,53 +129,29 @@ The CLI provides 6 tools that the AI agent can invoke:
|
|
|
91
129
|
|
|
92
130
|
## Permission System
|
|
93
131
|
|
|
94
|
-
Every tool call passes through a three-step permission gate
|
|
132
|
+
Every tool call passes through a three-step permission gate:
|
|
95
133
|
|
|
96
|
-
1. **Deny list** — if any deny pattern matches, the action is blocked
|
|
134
|
+
1. **Deny list** — if any deny pattern matches, the action is blocked
|
|
97
135
|
2. **Allow list** — if any allow pattern matches, the action is auto-approved
|
|
98
136
|
3. **Mode policy** — the active permission mode determines the decision
|
|
99
137
|
|
|
100
|
-
When a tool requires approval, the user sees an interactive prompt:
|
|
101
|
-
|
|
102
|
-
```
|
|
103
|
-
[Permission Required] Tool: Bash
|
|
104
|
-
Arguments: command: rm -rf dist
|
|
105
|
-
Allow? [y/N]
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
- Type `y` or `yes` to approve
|
|
109
|
-
- Press Enter or type anything else to deny
|
|
110
|
-
|
|
111
|
-
If denied, the AI agent receives a "Permission denied" error and can adjust its approach.
|
|
112
|
-
|
|
113
138
|
### Permission Modes
|
|
114
139
|
|
|
115
|
-
| Mode |
|
|
116
|
-
| ------------------- |
|
|
117
|
-
| `plan` |
|
|
118
|
-
| `default` |
|
|
119
|
-
| `acceptEdits` |
|
|
120
|
-
| `bypassPermissions` |
|
|
121
|
-
|
|
122
|
-
- **auto** — tool executes without prompting
|
|
123
|
-
- **approve** — user is prompted to allow or deny
|
|
124
|
-
- **deny** — tool is blocked silently (no prompt shown)
|
|
125
|
-
|
|
126
|
-
Unknown tools default to `approve` in most modes, `deny` in `plan` mode.
|
|
140
|
+
| Mode | Read/Glob/Grep | Write/Edit | Bash |
|
|
141
|
+
| ------------------- | :------------: | :--------: | :-----: |
|
|
142
|
+
| `plan` | auto | deny | deny |
|
|
143
|
+
| `default` | auto | approve | approve |
|
|
144
|
+
| `acceptEdits` | auto | auto | approve |
|
|
145
|
+
| `bypassPermissions` | auto | auto | auto |
|
|
127
146
|
|
|
128
147
|
### Changing Mode at Runtime
|
|
129
148
|
|
|
130
|
-
Use the `/mode` slash command
|
|
149
|
+
Use the `/mode` slash command:
|
|
131
150
|
|
|
132
151
|
```
|
|
133
152
|
> /mode # Show current mode
|
|
134
|
-
Current permission mode: default
|
|
135
|
-
|
|
136
153
|
> /mode plan # Switch to plan (read-only)
|
|
137
|
-
Permission mode set to: plan
|
|
138
|
-
|
|
139
154
|
> /mode bypassPermissions # Skip all prompts
|
|
140
|
-
Permission mode set to: bypassPermissions
|
|
141
155
|
```
|
|
142
156
|
|
|
143
157
|
Or set it at startup:
|
|
@@ -146,7 +160,7 @@ Or set it at startup:
|
|
|
146
160
|
robota --permission-mode plan
|
|
147
161
|
```
|
|
148
162
|
|
|
149
|
-
### Permission Patterns
|
|
163
|
+
### Permission Patterns
|
|
150
164
|
|
|
151
165
|
Configure in `.robota/settings.json` or `.robota/settings.local.json`:
|
|
152
166
|
|
|
@@ -159,26 +173,97 @@ Configure in `.robota/settings.json` or `.robota/settings.local.json`:
|
|
|
159
173
|
}
|
|
160
174
|
```
|
|
161
175
|
|
|
162
|
-
|
|
176
|
+
Pattern syntax: `ToolName` matches any invocation; `ToolName(pattern)` matches on the primary argument with shell-style globs (`*`, `**`).
|
|
177
|
+
|
|
178
|
+
## Keyboard Controls
|
|
179
|
+
|
|
180
|
+
| Key | Action |
|
|
181
|
+
| ---------- | ----------------------------------------------------------- |
|
|
182
|
+
| Enter | Submit input |
|
|
183
|
+
| ESC | Abort current execution (graceful — saves partial response) |
|
|
184
|
+
| Ctrl+C | Exit process immediately |
|
|
185
|
+
| Up/Down | Navigate visual lines in wrapped multi-line input |
|
|
186
|
+
| Arrow keys | Navigate slash command autocomplete, permission prompt |
|
|
187
|
+
|
|
188
|
+
## Paste Handling
|
|
189
|
+
|
|
190
|
+
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.
|
|
191
|
+
|
|
192
|
+
Single-line paste is inserted directly as typed text. Terminals without bracketed paste fall back to heuristic detection.
|
|
193
|
+
|
|
194
|
+
## Edit Diff Display
|
|
195
|
+
|
|
196
|
+
After the Edit tool runs, a `DiffBlock` component renders the change inline:
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
✓ Edit(src/provider.ts)
|
|
200
|
+
│ src/provider.ts
|
|
201
|
+
│ - const DEFAULT_MAX_TOKENS = 4096;
|
|
202
|
+
│ + const maxTokens = getModelMaxOutput(modelId);
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
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.
|
|
206
|
+
|
|
207
|
+
## Session Management
|
|
208
|
+
|
|
209
|
+
The CLI supports continuing, resuming, forking, and naming sessions.
|
|
210
|
+
|
|
211
|
+
### CLI Flags
|
|
163
212
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
213
|
+
| Flag | Description |
|
|
214
|
+
| --------------------- | ------------------------------------------------ |
|
|
215
|
+
| `-c`, `--continue` | Continue the most recent session |
|
|
216
|
+
| `-r`, `--resume <id>` | Resume a specific session by ID |
|
|
217
|
+
| `--fork-session <id>` | Fork a session (new session with copied history) |
|
|
218
|
+
| `--name <name>` | Assign a name to the session at startup |
|
|
168
219
|
|
|
169
|
-
|
|
220
|
+
### TUI Commands
|
|
221
|
+
|
|
222
|
+
| Command | Description |
|
|
223
|
+
| ---------------- | ----------------------------------- |
|
|
224
|
+
| `/resume` | List recent sessions and resume one |
|
|
225
|
+
| `/rename <name>` | Rename the current session |
|
|
226
|
+
|
|
227
|
+
### Session Name Display
|
|
228
|
+
|
|
229
|
+
When a session has a name, it appears in three places:
|
|
230
|
+
|
|
231
|
+
- **Input border** — session name shown in the input area border
|
|
232
|
+
- **Terminal title** — updated via ANSI escape sequences
|
|
233
|
+
- **StatusBar** — displayed alongside mode, model, and context usage
|
|
170
234
|
|
|
171
235
|
## Slash Commands
|
|
172
236
|
|
|
173
|
-
| Command
|
|
174
|
-
|
|
|
175
|
-
| `/help`
|
|
176
|
-
| `/clear`
|
|
177
|
-
| `/mode [mode]`
|
|
178
|
-
| `/
|
|
179
|
-
| `/
|
|
180
|
-
| `/
|
|
181
|
-
| `/
|
|
237
|
+
| Command | Description |
|
|
238
|
+
| ------------------------- | ---------------------------------------------------------- |
|
|
239
|
+
| `/help` | Show available commands |
|
|
240
|
+
| `/clear` | Clear conversation history |
|
|
241
|
+
| `/mode [mode]` | Show or change permission mode |
|
|
242
|
+
| `/model [model]` | Select AI model (confirmation prompt, CLI restarts) |
|
|
243
|
+
| `/language [lang]` | Set response language (ko, en, ja, zh), saves and restarts |
|
|
244
|
+
| `/compact [instructions]` | Compress context window |
|
|
245
|
+
| `/cost` | Show session info |
|
|
246
|
+
| `/context` | Context window details |
|
|
247
|
+
| `/permissions` | Show permission rules |
|
|
248
|
+
| `/plugin [subcommand]` | Plugin management TUI |
|
|
249
|
+
| `/resume` | List recent sessions and resume one |
|
|
250
|
+
| `/rename <name>` | Rename the current session |
|
|
251
|
+
| `/exit` | Exit CLI |
|
|
252
|
+
|
|
253
|
+
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.
|
|
254
|
+
|
|
255
|
+
## Plugin Management
|
|
256
|
+
|
|
257
|
+
The `/plugin` command opens an interactive TUI for managing bundle plugins:
|
|
258
|
+
|
|
259
|
+
| Subcommand | Description |
|
|
260
|
+
| -------------------------- | ------------------------------------------------ |
|
|
261
|
+
| `/plugin install <name>` | Install a plugin from marketplace or local path |
|
|
262
|
+
| `/plugin uninstall <name>` | Remove an installed plugin |
|
|
263
|
+
| `/plugin enable <name>` | Enable a disabled plugin |
|
|
264
|
+
| `/plugin disable <name>` | Disable a plugin without uninstalling |
|
|
265
|
+
| `/plugin list` | List installed plugins with status |
|
|
266
|
+
| `/plugin marketplace` | Browse available plugins from configured sources |
|
|
182
267
|
|
|
183
268
|
## Configuration
|
|
184
269
|
|
|
@@ -186,11 +271,14 @@ Settings are loaded from (highest priority first):
|
|
|
186
271
|
|
|
187
272
|
1. `.robota/settings.local.json` (local, gitignored)
|
|
188
273
|
2. `.robota/settings.json` (project, shared)
|
|
189
|
-
3.
|
|
274
|
+
3. `.claude/settings.json` (project, Claude Code compatible)
|
|
275
|
+
4. `~/.robota/settings.json` (user global)
|
|
276
|
+
5. `~/.claude/settings.json` (user global, Claude Code compatible)
|
|
190
277
|
|
|
191
278
|
```json
|
|
192
279
|
{
|
|
193
280
|
"defaultMode": "default",
|
|
281
|
+
"language": "en",
|
|
194
282
|
"provider": {
|
|
195
283
|
"name": "anthropic",
|
|
196
284
|
"model": "claude-sonnet-4-6",
|
|
@@ -203,14 +291,6 @@ Settings are loaded from (highest priority first):
|
|
|
203
291
|
}
|
|
204
292
|
```
|
|
205
293
|
|
|
206
|
-
### Environment Variables
|
|
207
|
-
|
|
208
|
-
| Variable | Description | Required |
|
|
209
|
-
| ------------------- | ----------------- | -------- |
|
|
210
|
-
| `ANTHROPIC_API_KEY` | Anthropic API key | Yes |
|
|
211
|
-
|
|
212
|
-
Copy `.env.example` to `.env` and set your key. The CLI reads `.env` automatically in dev mode.
|
|
213
|
-
|
|
214
294
|
## Context Discovery
|
|
215
295
|
|
|
216
296
|
The CLI automatically discovers and loads:
|
|
@@ -219,36 +299,65 @@ The CLI automatically discovers and loads:
|
|
|
219
299
|
- **CLAUDE.md** — same walk-up discovery
|
|
220
300
|
- **Project metadata** — from `package.json`, `tsconfig.json`
|
|
221
301
|
|
|
222
|
-
All context is assembled into the system prompt
|
|
302
|
+
All context is assembled into the system prompt.
|
|
303
|
+
|
|
304
|
+
## Memory Management
|
|
305
|
+
|
|
306
|
+
- **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.
|
|
307
|
+
- **Tool state cleanup** — Completed tool execution states are trimmed to the most recent 50 entries.
|
|
308
|
+
- **React.memo** — `MessageItem` uses `React.memo` to skip redundant re-renders.
|
|
309
|
+
|
|
310
|
+
## Session Logging
|
|
311
|
+
|
|
312
|
+
Session logs are written to `.robota/logs/{sessionId}.jsonl` in JSONL format by default, capturing structured events for diagnostics and replay.
|
|
223
313
|
|
|
224
314
|
## Architecture
|
|
225
315
|
|
|
316
|
+
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.
|
|
317
|
+
|
|
226
318
|
```
|
|
227
|
-
bin.ts → cli.ts (
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
319
|
+
bin.ts → cli.ts (arg parsing)
|
|
320
|
+
└── ui/render.tsx → App.tsx (thin JSX shell)
|
|
321
|
+
├── useInteractiveSession (ONLY React↔SDK bridge)
|
|
322
|
+
│ ├── InteractiveSession (SDK)
|
|
323
|
+
│ ├── CommandRegistry (SDK, re-exported by CLI)
|
|
324
|
+
│ │ ├── BuiltinCommandSource (SDK)
|
|
325
|
+
│ │ ├── SkillCommandSource (SDK, discovers from 4 paths)
|
|
326
|
+
│ │ └── PluginCommandSource (CLI-local)
|
|
327
|
+
│ └── SystemCommandExecutor (SDK)
|
|
328
|
+
├── plugin-hooks-merger.ts (merges plugin hooks into SDK config)
|
|
329
|
+
├── MessageList.tsx
|
|
330
|
+
├── InputArea.tsx (CjkTextInput, bracketed paste, slash detection)
|
|
331
|
+
├── StatusBar.tsx (mode, model, context %, message count)
|
|
332
|
+
├── PermissionPrompt.tsx (arrow-key Allow/Deny)
|
|
333
|
+
├── SlashAutocomplete.tsx (command popup with scroll)
|
|
334
|
+
├── DiffBlock.tsx (Edit tool diff display)
|
|
335
|
+
├── MenuSelect.tsx (arrow-key menu, Plugin TUI)
|
|
336
|
+
├── PluginTUI.tsx (plugin management screen stack)
|
|
337
|
+
├── TextPrompt.tsx (text input for Plugin TUI)
|
|
338
|
+
└── ConfirmPrompt.tsx (reusable yes/no prompt)
|
|
240
339
|
```
|
|
241
340
|
|
|
242
|
-
|
|
341
|
+
## Dependencies
|
|
243
342
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
343
|
+
| Package | Purpose |
|
|
344
|
+
| -------------------------------------- | ------------------------------------------ |
|
|
345
|
+
| `@robota-sdk/agent-sdk` | Session factory, query, config, context |
|
|
346
|
+
| `@robota-sdk/agent-core` | Types (TPermissionMode, TToolArgs) |
|
|
347
|
+
| `@robota-sdk/agent-transport-headless` | Headless runner for print mode (`-p`) |
|
|
348
|
+
| `ink`, `react` | TUI rendering |
|
|
349
|
+
| `ink-select-input` | Arrow-key selection (permission prompt) |
|
|
350
|
+
| `ink-spinner` | Loading spinner |
|
|
351
|
+
| `chalk` | Terminal colors |
|
|
352
|
+
| `ink-text-input` | Base text input (extended by CjkTextInput) |
|
|
353
|
+
| `marked`, `marked-terminal` | Markdown parsing and terminal rendering |
|
|
354
|
+
| `cli-highlight` | Syntax highlighting for code blocks |
|
|
355
|
+
| `string-width` | Unicode-aware string width (CJK support) |
|
|
356
|
+
|
|
357
|
+
## Documentation
|
|
358
|
+
|
|
359
|
+
See [docs/SPEC.md](./docs/SPEC.md) for the full specification, architecture details, and design decisions.
|
|
360
|
+
|
|
361
|
+
## License
|
|
362
|
+
|
|
363
|
+
MIT
|
package/dist/node/bin.js
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
startCli
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7EBJI2DW.js";
|
|
5
5
|
|
|
6
6
|
// src/bin.ts
|
|
7
|
+
process.on("uncaughtException", (err) => {
|
|
8
|
+
const msg = err.message ?? "";
|
|
9
|
+
const isLikelyIME = msg.includes("string-width") || msg.includes("setCursorPosition") || msg.includes("getStringWidth") || msg.includes("slice") || msg.includes("charCodeAt");
|
|
10
|
+
if (isLikelyIME) {
|
|
11
|
+
process.stderr.write(`[robota] IME error suppressed: ${msg}
|
|
12
|
+
`);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
throw err;
|
|
16
|
+
});
|
|
7
17
|
startCli().catch((err) => {
|
|
8
18
|
const message = err instanceof Error ? err.message : String(err);
|
|
9
19
|
process.stderr.write(message + "\n");
|