@robota-sdk/agent-cli 3.0.0-beta.7 → 3.0.0-beta.70

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.
Files changed (93) hide show
  1. package/README.md +414 -114
  2. package/bin/robota.cjs +47 -0
  3. package/dist/node/bin.d.ts +2 -1
  4. package/dist/node/bin.js +50 -10
  5. package/dist/node/bin.js.map +1 -0
  6. package/dist/node/child-process-subagent-ipc--Vp2dk1v.js +2 -0
  7. package/dist/node/child-process-subagent-ipc--Vp2dk1v.js.map +1 -0
  8. package/dist/node/child-process-subagent-ipc-Aitv2i6E.cjs +1 -0
  9. package/dist/node/child-process-subagent-ipc-CEy8bLN6.cjs +1 -0
  10. package/dist/node/child-process-subagent-ipc-DVpVp43R.js +2 -0
  11. package/dist/node/child-process-subagent-ipc-DVpVp43R.js.map +1 -0
  12. package/dist/node/cli.cjs +1 -0
  13. package/dist/node/cli.d.ts +7 -0
  14. package/dist/node/cli.d.ts.map +1 -0
  15. package/dist/node/cli.js +2 -0
  16. package/dist/node/cli.js.map +1 -0
  17. package/dist/node/constants.cjs +1 -0
  18. package/dist/node/constants.js +2 -0
  19. package/dist/node/constants.js.map +1 -0
  20. package/dist/node/index.cjs +42 -1257
  21. package/dist/node/index.d.ts +12 -47
  22. package/dist/node/index.d.ts.map +1 -0
  23. package/dist/node/index.js +43 -13
  24. package/dist/node/index.js.map +1 -0
  25. package/dist/node/init/init-command.cjs +32 -0
  26. package/dist/node/init/init-command.js +33 -0
  27. package/dist/node/init/init-command.js.map +1 -0
  28. package/dist/node/modes/print-mode.cjs +6 -0
  29. package/dist/node/modes/print-mode.js +7 -0
  30. package/dist/node/modes/print-mode.js.map +1 -0
  31. package/dist/node/modes/shell-exec.cjs +1 -0
  32. package/dist/node/modes/shell-exec.js +2 -0
  33. package/dist/node/modes/shell-exec.js.map +1 -0
  34. package/dist/node/modes/tui-mode.cjs +1 -0
  35. package/dist/node/modes/tui-mode.js +2 -0
  36. package/dist/node/modes/tui-mode.js.map +1 -0
  37. package/dist/node/provider-default-definitions-CKtxv2k0.js +2 -0
  38. package/dist/node/provider-default-definitions-CKtxv2k0.js.map +1 -0
  39. package/dist/node/provider-default-definitions-GFiYzACo.cjs +1 -0
  40. package/dist/node/provider-default-definitions-g0ZUDeii.cjs +1 -0
  41. package/dist/node/startup/append-system-prompt.cjs +3 -0
  42. package/dist/node/startup/append-system-prompt.js +4 -0
  43. package/dist/node/startup/append-system-prompt.js.map +1 -0
  44. package/dist/node/startup/args-to-options.cjs +1 -0
  45. package/dist/node/startup/args-to-options.js +2 -0
  46. package/dist/node/startup/args-to-options.js.map +1 -0
  47. package/dist/node/startup/command-setup.cjs +1 -0
  48. package/dist/node/startup/command-setup.d.ts +11 -0
  49. package/dist/node/startup/command-setup.d.ts.map +1 -0
  50. package/dist/node/startup/command-setup.js +2 -0
  51. package/dist/node/startup/command-setup.js.map +1 -0
  52. package/dist/node/startup/config-phase.cjs +1 -0
  53. package/dist/node/startup/config-phase.js +2 -0
  54. package/dist/node/startup/config-phase.js.map +1 -0
  55. package/dist/node/startup/preflight.cjs +1 -0
  56. package/dist/node/startup/preflight.js +2 -0
  57. package/dist/node/startup/preflight.js.map +1 -0
  58. package/dist/node/startup/provider-setup.cjs +1 -0
  59. package/dist/node/startup/provider-setup.js +2 -0
  60. package/dist/node/startup/provider-setup.js.map +1 -0
  61. package/dist/node/startup/provider-startup.cjs +2 -0
  62. package/dist/node/startup/provider-startup.js +3 -0
  63. package/dist/node/startup/provider-startup.js.map +1 -0
  64. package/dist/node/startup/reset-config.cjs +1 -0
  65. package/dist/node/startup/reset-config.js +2 -0
  66. package/dist/node/startup/reset-config.js.map +1 -0
  67. package/dist/node/startup/session-setup.cjs +1 -0
  68. package/dist/node/startup/session-setup.js +2 -0
  69. package/dist/node/startup/session-setup.js.map +1 -0
  70. package/dist/node/startup/subagent-setup.cjs +1 -0
  71. package/dist/node/startup/subagent-setup.js +2 -0
  72. package/dist/node/startup/subagent-setup.js.map +1 -0
  73. package/dist/node/startup/update-notice.cjs +1 -0
  74. package/dist/node/startup/update-notice.js +2 -0
  75. package/dist/node/startup/update-notice.js.map +1 -0
  76. package/dist/node/startup/version.cjs +1 -0
  77. package/dist/node/startup/version.js +2 -0
  78. package/dist/node/startup/version.js.map +1 -0
  79. package/dist/node/subagents/child-process-subagent-worker.cjs +1 -0
  80. package/dist/node/subagents/child-process-subagent-worker.d.ts +1 -0
  81. package/dist/node/subagents/child-process-subagent-worker.js +2 -0
  82. package/dist/node/subagents/child-process-subagent-worker.js.map +1 -0
  83. package/dist/node/user-local-direct-command.cjs +1 -0
  84. package/dist/node/user-local-direct-command.js +2 -0
  85. package/dist/node/user-local-direct-command.js.map +1 -0
  86. package/dist/node/utils/cli-args.cjs +35 -0
  87. package/dist/node/utils/cli-args.js +36 -0
  88. package/dist/node/utils/cli-args.js.map +1 -0
  89. package/package.json +52 -16
  90. package/dist/node/bin.cjs +0 -1240
  91. package/dist/node/bin.d.cts +0 -1
  92. package/dist/node/chunk-A2A66S6Q.js +0 -1219
  93. package/dist/node/index.d.cts +0 -49
package/README.md CHANGED
@@ -1,17 +1,72 @@
1
+ **Language:** [English](README.md) | [한국어](docs/README-KO.md)
2
+
3
+ > **Beta software** — currently `3.0.0-beta`. APIs and behavior may change before stable release.
4
+ > Please [report issues](https://github.com/woojubb/robota/issues) to help us improve.
5
+
1
6
  # @robota-sdk/agent-cli
2
7
 
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.
8
+ 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
9
 
5
- ## Installation
10
+ ## Why Robota?
11
+
12
+ | | Robota | Claude Code | Aider |
13
+ | ------------------------------------------------- | :----: | :---------: | :---: |
14
+ | Multi-provider (Anthropic, OpenAI, Gemini, Qwen…) | ✅ | ❌ | ✅ |
15
+ | Embed SDK in your own app | ✅ | ❌ | ❌ |
16
+ | Local models (LM Studio, Ollama via OpenAI API) | ✅ | ❌ | ✅ |
17
+ | Open source (MIT) | ✅ | partial | ✅ |
18
+ | Claude Code config compatible (CLAUDE.md, modes) | ✅ | — | ❌ |
19
+
20
+ ## Embed in Your App
21
+
22
+ ```typescript
23
+ import { createAgentRuntime } from '@robota-sdk/agent-framework';
24
+ import { createAnthropicProvider } from '@robota-sdk/agent-provider';
25
+
26
+ const runtime = createAgentRuntime({
27
+ provider: createAnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
28
+ });
29
+ const session = runtime.createSession({ permissionMode: 'bypassPermissions' });
30
+ const response = await session.submit('Explain this codebase');
31
+ ```
32
+
33
+ ## Prerequisites
34
+
35
+ Node.js **22 or higher** is required. The TUI renderer ([ink 7.x](https://github.com/vadimdemedes/ink)) requires Node.js 22+.
6
36
 
7
37
  ```bash
8
- # Global install
9
- npm install -g @robota-sdk/agent-cli
38
+ node --version # Must output v22.x.x or higher
39
+ ```
40
+
41
+ If your version is below 22, upgrade using one of:
42
+
43
+ ```bash
44
+ # nvm
45
+ nvm install 22 && nvm use 22
46
+
47
+ # Volta
48
+ volta install node@22
49
+ ```
50
+
51
+ ## Demo
52
+
53
+ <!-- TODO: Add demo GIF here -->
54
+ <!-- Run `pnpm demo:record` to capture a demo recording — see docs/demo-script.md for instructions -->
55
+
56
+ ![Demo](./docs/demo.gif)
57
+
58
+ ## Installation
10
59
 
11
- # Or run directly with npx
60
+ ```bash
61
+ # Try it now — no install needed
12
62
  npx @robota-sdk/agent-cli
63
+
64
+ # Install globally for persistent use
65
+ npm install -g @robota-sdk/agent-cli
13
66
  ```
14
67
 
68
+ > **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.
69
+
15
70
  After installing globally, the `robota` command is available system-wide:
16
71
 
17
72
  ```bash
@@ -22,9 +77,14 @@ robota -p "List all files" # Print mode (one-shot, exit after response)
22
77
 
23
78
  ### Environment Variables
24
79
 
25
- | Variable | Description | Required |
26
- | ------------------- | ----------------- | -------- |
27
- | `ANTHROPIC_API_KEY` | Anthropic API key | Yes |
80
+ | Variable | Description | Provider |
81
+ | ------------------- | -------------------------------------------------------- | --------- |
82
+ | `ANTHROPIC_API_KEY` | Anthropic API key | Anthropic |
83
+ | `OPENAI_API_KEY` | OpenAI API key | OpenAI |
84
+ | `GEMINI_API_KEY` | Google Gemini API key | Gemini |
85
+ | `DEEPSEEK_API_KEY` | DeepSeek API key | DeepSeek |
86
+ | `DASHSCOPE_API_KEY` | Alibaba Cloud Model Studio key | Qwen |
87
+ | `BRAVE_API_KEY` | Brave Search API key (optional — enables WebSearch tool) | WebSearch |
28
88
 
29
89
  Set your key before running:
30
90
 
@@ -35,11 +95,7 @@ export ANTHROPIC_API_KEY=sk-ant-...
35
95
  ## Development Setup (Monorepo)
36
96
 
37
97
  ```bash
38
- # 1. Copy .env.example and add your Anthropic API key
39
- cp packages/agent-cli/.env.example packages/agent-cli/.env
40
- # Edit .env and set ANTHROPIC_API_KEY=sk-ant-...
41
-
42
- # 2. Build dependencies and CLI
98
+ # Build dependencies and CLI
43
99
  pnpm build:deps
44
100
  pnpm --filter @robota-sdk/agent-cli build
45
101
  ```
@@ -50,7 +106,7 @@ pnpm --filter @robota-sdk/agent-cli build
50
106
  # From monorepo root
51
107
  cd packages/agent-cli
52
108
 
53
- # Development mode (no build needed, auto-loads .env)
109
+ # Development mode (no build needed)
54
110
  pnpm dev
55
111
 
56
112
  # Production mode (requires build)
@@ -70,74 +126,142 @@ robota "prompt" # REPL with initial prompt
70
126
  robota -p "prompt" # Print mode (one-shot, exit after response)
71
127
  robota -c # Continue last session
72
128
  robota -r <session-id> # Resume session by ID
73
- robota --model <model> # Model override (e.g., claude-sonnet-4-6)
129
+ robota --language <lang> # Response language (ko, en, ja, zh)
74
130
  robota --permission-mode <mode> # plan | default | acceptEdits | bypassPermissions
75
131
  robota --max-turns <n> # Limit agentic turns per interaction
132
+ robota --output-format <fmt> # text | json | stream-json (print mode)
133
+ robota --system-prompt <text> # Replace system prompt (print mode)
134
+ robota --append-system-prompt <text> # Append to system prompt (print mode)
135
+ robota --model claude-opus-4-7 # Override provider model for this session
136
+ robota --allowed-tools "Bash,Read" # Whitelist specific tools
137
+ robota --denied-tools "Bash,Write" # Blacklist specific tools (denied > allowed)
138
+ robota --reset # Delete user settings and exit
139
+ robota --check-update # Check npm for a newer CLI version and exit
140
+ robota --disable-update-check # Skip interactive startup update check for this run
76
141
  robota --version # Show version
77
142
  ```
78
143
 
79
- ## Built-in Tools
144
+ ### CLI Updates
80
145
 
81
- The CLI provides 6 tools that the AI agent can invoke:
146
+ Robota can check npm for a newer `@robota-sdk/agent-cli` version:
82
147
 
83
- | Tool | Description | Primary Argument |
84
- | ------- | ------------------------------------ | ---------------- |
85
- | `Bash` | Execute shell commands | `command` |
86
- | `Read` | Read file contents with line numbers | `filePath` |
87
- | `Write` | Write content to a file | `filePath` |
88
- | `Edit` | Replace a string in a file | `filePath` |
89
- | `Glob` | Find files matching a pattern | `pattern` |
90
- | `Grep` | Search file contents with regex | `pattern` |
148
+ ```bash
149
+ robota --check-update
150
+ ```
91
151
 
92
- ## Permission System
152
+ When an update is available, Robota prints the npm global install command:
93
153
 
94
- Every tool call passes through a three-step permission gate before execution:
154
+ ```bash
155
+ npm install -g '@robota-sdk/agent-cli@latest'
156
+ ```
95
157
 
96
- 1. **Deny list** — if any deny pattern matches, the action is blocked immediately
97
- 2. **Allow list** — if any allow pattern matches, the action is auto-approved
98
- 3. **Mode policy** — the active permission mode determines the decision
158
+ Robota does not implement its own updater and does not modify `~/.robota/settings.json` for update checks. Interactive startup checks use a user-level operational cache at `~/.robota/update-check.json` and can be skipped for one run with `--disable-update-check`. Print/headless mode (`robota -p`) does not perform automatic startup update checks so scripted stdout and stderr remain deterministic.
99
159
 
100
- When a tool requires approval, the user sees an interactive prompt:
160
+ ### Print Mode Output Formats
101
161
 
102
- ```
103
- [Permission Required] Tool: Bash
104
- Arguments: command: rm -rf dist
105
- Allow? [y/N]
162
+ Print mode (`-p`) supports three output formats via `--output-format`:
163
+
164
+ | Format | Description |
165
+ | ------------- | ------------------------------------------------------------------ |
166
+ | `text` | Plain text response to stdout (default) |
167
+ | `json` | Single JSON object: `{ type, result, session_id, subtype }` |
168
+ | `stream-json` | Newline-delimited JSON with `content_block_delta` streaming events |
169
+
170
+ ### Exit Codes (print mode)
171
+
172
+ | Code | Meaning |
173
+ | ---- | ---------------------------------------------- |
174
+ | 0 | Success |
175
+ | 1 | General error |
176
+ | 2 | Argument error |
177
+ | 3 | Configuration error (missing provider/API key) |
178
+ | 4 | API error |
179
+ | 5 | Tool execution error |
180
+
181
+ ### Stdin Pipe
182
+
183
+ When stdin is piped, the CLI reads it automatically. If a positional prompt is also given, the piped content is appended inside `<stdin>` tags:
184
+
185
+ ```bash
186
+ echo "Explain this error" | robota -p
187
+ cat file.ts | robota -p "Review this code" --output-format json
188
+ git diff | robota -p "Summarize changes" --output-format stream-json
106
189
  ```
107
190
 
108
- - Type `y` or `yes` to approve
109
- - Press Enter or type anything else to deny
191
+ ## First-Run Setup
110
192
 
111
- If denied, the AI agent receives a "Permission denied" error and can adjust its approach.
193
+ When no usable settings file exists, the CLI prompts for:
112
194
 
113
- ### Permission Modes
195
+ 1. **Provider selection** from the providers assembled into the CLI binary
196
+ 2. **Provider-specific setup fields** such as model, base URL, and masked API key
197
+ 3. **Response language** (ko/en/ja/zh, default: en)
114
198
 
115
- | Mode | Alias | Read/Glob/Grep | Write/Edit | Bash |
116
- | ------------------- | -------- | :------------: | :--------: | :-----: |
117
- | `plan` | safe | auto | deny | deny |
118
- | `default` | moderate | auto | approve | approve |
119
- | `acceptEdits` | full | auto | auto | approve |
120
- | `bypassPermissions` | — | auto | auto | auto |
199
+ Creates `~/.robota/settings.json`. Use `robota --reset` to return to first-run state.
121
200
 
122
- - **auto** — tool executes without prompting
123
- - **approve** — user is prompted to allow or deny
124
- - **deny** — tool is blocked silently (no prompt shown)
201
+ Provider setup is generated from provider definitions. The default CLI build includes Anthropic,
202
+ OpenAI-compatible, DeepSeek, Gemma, and Qwen providers; other embeddings can inject their own
203
+ provider definitions.
204
+ Interactive setup creates a readable profile key from the selected model id, such as
205
+ `claude-sonnet-4-6` or `gpt-4o`, and appends `-2`, `-3`, etc. when that key already exists. Generated
206
+ profile keys never include API keys or credential hints.
125
207
 
126
- Unknown tools default to `approve` in most modes, `deny` in `plan` mode.
208
+ Inside the TUI, `/provider` and `/provider list` show configured profiles as an interactive picker. Selecting a profile opens command-owned actions for switch, edit, test, duplicate, delete, and cancel. Headless mode prints the same profile list text without opening prompts.
127
209
 
128
- ### Changing Mode at Runtime
210
+ Non-interactive/headless mode never prompts. Configure a provider ahead of time with `robota --configure` in an interactive terminal, or use `robota --configure-provider <profile> --type <type> ... --set-current`.
129
211
 
130
- Use the `/mode` slash command in the REPL:
212
+ ## Built-in Tools
131
213
 
132
- ```
133
- > /mode # Show current mode
134
- Current permission mode: default
214
+ The AI agent can invoke 8 local tools:
215
+
216
+ | Tool | Description | Primary Argument |
217
+ | ----------- | ---------------------------------------------- | ---------------- |
218
+ | `Bash` | Execute shell commands | `command` |
219
+ | `Read` | Read file contents with line numbers | `filePath` |
220
+ | `Write` | Write content to a file | `filePath` |
221
+ | `Edit` | Replace a string in a file | `filePath` |
222
+ | `Glob` | Find files matching a pattern | `pattern` |
223
+ | `Grep` | Search file contents with regex | `pattern` |
224
+ | `WebFetch` | Fetch URL content as text | `url` |
225
+ | `WebSearch` | Search the internet (requires `BRAVE_API_KEY`) | `query` |
226
+
227
+ > **WebSearch** requires a `BRAVE_API_KEY` environment variable. Without it, the tool returns a setup message instead of results. Get a free key at [brave.com/search/api](https://brave.com/search/api/) (2,000 queries/month free tier).
135
228
 
136
- > /mode plan # Switch to plan (read-only)
137
- Permission mode set to: plan
229
+ ## Recent TUI Capabilities
230
+
231
+ - Provider setup and profile management are generated from provider definitions, so the default CLI
232
+ build can configure, switch, edit, test, duplicate, and delete Anthropic, OpenAI-compatible,
233
+ DeepSeek, Gemma, and Qwen profiles without provider-specific UI branches.
234
+ - Interactive startup can check npm for newer CLI versions; print/headless mode skips startup update checks to keep scripted output deterministic.
235
+ - Long-running sessions show provider usage summaries, status activity, background job tree rows, and collapsed command-output transcripts.
236
+ - Edit results render as context hunks with markdown-friendly diff blocks.
237
+ - Background subagents are real runtime jobs with transcripts and resumable task snapshots.
238
+ - Explicit multi-agent requests use the `/agent` command module batch path through the SDK runtime.
239
+
240
+ ## Permission System
241
+
242
+ Every tool call passes through a three-step permission gate:
243
+
244
+ 1. **Deny list** — if any deny pattern matches, the action is blocked
245
+ 2. **Allow list** — if any allow pattern matches, the action is auto-approved
246
+ 3. **Mode policy** — the active permission mode determines the decision
247
+
248
+ ### Permission Modes
249
+
250
+ | Mode | Read/Glob/Grep | Write/Edit | Bash |
251
+ | ------------------- | :------------: | :--------: | :-----: |
252
+ | `plan` | auto | deny | deny |
253
+ | `default` | auto | approve | approve |
254
+ | `acceptEdits` | auto | auto | approve |
255
+ | `bypassPermissions` | auto | auto | auto |
256
+
257
+ ### Changing Mode at Runtime
258
+
259
+ Use the `/permissions` slash command:
138
260
 
139
- > /mode bypassPermissions # Skip all prompts
140
- Permission mode set to: bypassPermissions
261
+ ```
262
+ > /permissions # Show current mode and session-approved tools
263
+ > /permissions plan # Switch to plan (read-only)
264
+ > /permissions bypassPermissions # Skip all prompts
141
265
  ```
142
266
 
143
267
  Or set it at startup:
@@ -146,7 +270,7 @@ Or set it at startup:
146
270
  robota --permission-mode plan
147
271
  ```
148
272
 
149
- ### Permission Patterns (allow/deny lists)
273
+ ### Permission Patterns
150
274
 
151
275
  Configure in `.robota/settings.json` or `.robota/settings.local.json`:
152
276
 
@@ -159,42 +283,167 @@ Configure in `.robota/settings.json` or `.robota/settings.local.json`:
159
283
  }
160
284
  ```
161
285
 
162
- **Pattern syntax:**
286
+ Pattern syntax: `ToolName` matches any invocation; `ToolName(pattern)` matches on the primary argument with shell-style globs (`*`, `**`).
287
+
288
+ ## Keyboard Controls
289
+
290
+ | Key | Action |
291
+ | ---------- | ----------------------------------------------------------- |
292
+ | Enter | Submit input |
293
+ | ESC | Abort current execution (graceful — saves partial response) |
294
+ | Ctrl+C | Exit process immediately |
295
+ | Up/Down | Navigate visual lines in wrapped multi-line input |
296
+ | Arrow keys | Navigate slash command autocomplete, permission prompt |
297
+
298
+ ## Paste Handling
163
299
 
164
- - `ToolName` — match any invocation of that tool (e.g., `Bash`)
165
- - `ToolName(pattern)` — match when the primary argument matches the glob (e.g., `Bash(pnpm *)`)
166
- - `*` — zero or more characters (shell-style)
167
- - `**` — one or more characters (recursive path matching)
300
+ 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.
168
301
 
169
- **Evaluation order:** deny patterns are checked first, then allow patterns, then the mode policy. Deny always wins.
302
+ Single-line paste is inserted directly as typed text. Terminals without bracketed paste fall back to heuristic detection.
303
+
304
+ ## Edit Diff Display
305
+
306
+ After the Edit tool runs, a `DiffBlock` component renders the change inline:
307
+
308
+ ```
309
+ ✓ Edit(src/provider.ts)
310
+ │ src/provider.ts
311
+ │ - const DEFAULT_MAX_TOKENS = 4096;
312
+ │ + const maxTokens = getModelMaxOutput(modelId);
313
+ ```
314
+
315
+ 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.
316
+
317
+ ## Session Management
318
+
319
+ The CLI supports continuing, resuming, forking, and naming sessions.
320
+
321
+ ### CLI Flags
322
+
323
+ | Flag | Description |
324
+ | --------------------- | ------------------------------------------------ |
325
+ | `-c`, `--continue` | Continue the most recent session |
326
+ | `-r`, `--resume <id>` | Resume a specific session by ID |
327
+ | `--fork-session <id>` | Fork a session (new session with copied history) |
328
+ | `--name <name>` | Assign a name to the session at startup |
329
+
330
+ ### TUI Commands
331
+
332
+ | Command | Description |
333
+ | ---------------- | ----------------------------------- |
334
+ | `/resume` | List recent sessions and resume one |
335
+ | `/rename <name>` | Rename the current session |
336
+
337
+ ### Session Name Display
338
+
339
+ When a session has a name, it appears in three places:
340
+
341
+ - **Input border** — session name shown in the input area border
342
+ - **Terminal title** — updated via ANSI escape sequences
343
+ - **StatusBar** — displayed alongside activity, model, and context usage
170
344
 
171
345
  ## Slash Commands
172
346
 
173
- | Command | Description |
174
- | -------------- | ------------------------------- |
175
- | `/help` | Show help |
176
- | `/clear` | Clear conversation history |
177
- | `/mode [mode]` | Show or change permission mode |
178
- | `/resume` | List and resume a saved session |
179
- | `/cost` | Show token usage |
180
- | `/model` | Show current model |
181
- | `/exit` | Exit CLI |
347
+ Typing `/` in the TUI opens an autocomplete popup. Arrow keys navigate, Tab inserts without executing, Enter executes. Subcommands (e.g., `/provider list`) show a nested submenu.
348
+
349
+ ### Session & Context
350
+
351
+ | Command | Description |
352
+ | ------------------------- | ---------------------------------------------------------------------- |
353
+ | `/clear` | Clear conversation history |
354
+ | `/compact [instructions]` | Compress context window |
355
+ | `/context` | Context window details, reference inventory, and auto-compact controls |
356
+ | `/cost` | Show session token usage and cost |
357
+ | `/resume` | List recent sessions and resume one |
358
+ | `/rename <name>` | Rename the current session |
359
+ | `/rewind` | List, inspect, restore, or rollback edit checkpoints |
360
+
361
+ ### Providers & Settings
362
+
363
+ | Command | Description |
364
+ | ------------------------ | -------------------------------------------------------------------- | ------- | -------------------------------------------------- |
365
+ | `/provider [subcommand]` | Manage provider profiles: `list`, `switch`, `add`, `test`, `current` |
366
+ | `/mode [mode]` | Show or switch permission mode |
367
+ | `/permissions [mode]` | Show permission rules or change permission mode |
368
+ | `/settings` | Open transport settings (enable/disable transports) |
369
+ | `/language [lang]` | Set response language (ko, en, ja, zh), saves and restarts |
370
+ | `/statusline [on | off | reset]` | Configure status-line fields (model, context, git) |
371
+
372
+ ### Tools & Memory
373
+
374
+ | Command | Description |
375
+ | ---------------------- | ---------------------------------------------- |
376
+ | `/memory [subcommand]` | Inspect, add, or review project memory entries |
377
+ | `/background` | List and control background tasks |
378
+ | `/agent` | Run and manage background subagent jobs |
379
+ | `/skills [name]` | List registered skills or activate one by name |
380
+ | `/plugin [subcommand]` | Plugin management |
381
+
382
+ ### Utility
383
+
384
+ | Command | Description |
385
+ | -------- | -------------------------------------------------- |
386
+ | `/help` | Show available commands |
387
+ | `/reset` | Delete user settings and return to first-run state |
388
+ | `/exit` | Exit CLI |
389
+
390
+ Skill commands discovered from `.agents/skills/` and `.claude/commands/` appear alongside built-in commands.
391
+
392
+ ## Plugin Management
393
+
394
+ The `/plugin` command opens an interactive TUI or runs plugin operations through the injected plugin command module:
395
+
396
+ | Subcommand | Description |
397
+ | ---------------------------------------- | ------------------------------------- |
398
+ | `/plugin` or `/plugin manage` | Open the plugin manager TUI |
399
+ | `/plugin install <name>@<marketplace>` | Install a plugin from a marketplace |
400
+ | `/plugin uninstall <name>@<marketplace>` | Remove an installed plugin |
401
+ | `/plugin enable <name>@<marketplace>` | Enable a disabled plugin |
402
+ | `/plugin disable <name>@<marketplace>` | Disable a plugin without uninstalling |
403
+ | `/plugin marketplace add <source>` | Add a marketplace source |
404
+ | `/plugin marketplace remove <name>` | Remove a marketplace source |
405
+ | `/plugin marketplace update <name>` | Update a marketplace source |
406
+ | `/plugin marketplace list` | List configured marketplace sources |
182
407
 
183
408
  ## Configuration
184
409
 
185
- Settings are loaded from (highest priority first):
410
+ Settings are merged in this order, from lowest to highest priority:
186
411
 
187
- 1. `.robota/settings.local.json` (local, gitignored)
188
- 2. `.robota/settings.json` (project, shared)
189
- 3. `~/.robota/settings.json` (user global)
412
+ 1. `~/.robota/settings.json` (user global)
413
+ 2. `~/.claude/settings.json` (user global, Claude Code compatible)
414
+ 3. `.robota/settings.json` (project, shared)
415
+ 4. `.robota/settings.local.json` (local, gitignored)
416
+ 5. `.claude/settings.json` (project, Claude Code compatible)
417
+ 6. `.claude/settings.local.json` (local, gitignored, Claude Code compatible)
190
418
 
191
419
  ```json
192
420
  {
193
421
  "defaultMode": "default",
194
- "provider": {
195
- "name": "anthropic",
196
- "model": "claude-sonnet-4-6",
197
- "apiKey": "$ENV:ANTHROPIC_API_KEY"
422
+ "language": "en",
423
+ "currentProvider": "qwen-plus",
424
+ "providers": {
425
+ "qwen-plus": {
426
+ "type": "qwen",
427
+ "model": "qwen-plus",
428
+ "apiKey": "$ENV:DASHSCOPE_API_KEY",
429
+ "baseURL": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
430
+ },
431
+ "supergemma4-26b-uncensored-v2": {
432
+ "type": "gemma",
433
+ "model": "supergemma4-26b-uncensored-v2",
434
+ "apiKey": "lm-studio",
435
+ "baseURL": "http://localhost:1234/v1"
436
+ },
437
+ "gpt-4o": {
438
+ "type": "openai",
439
+ "model": "gpt-4o",
440
+ "apiKey": "$ENV:OPENAI_API_KEY"
441
+ },
442
+ "claude-sonnet-4-6": {
443
+ "type": "anthropic",
444
+ "model": "claude-sonnet-4-6",
445
+ "apiKey": "$ENV:ANTHROPIC_API_KEY"
446
+ }
198
447
  },
199
448
  "permissions": {
200
449
  "allow": ["Bash(pnpm *)"],
@@ -203,13 +452,27 @@ Settings are loaded from (highest priority first):
203
452
  }
204
453
  ```
205
454
 
206
- ### Environment Variables
455
+ `currentProvider` selects a profile key from `providers`. The key is the stable profile identity, not
456
+ the provider type; multiple profile keys may use the same provider type and model when they represent
457
+ different credentials, endpoints, accounts, or operational defaults. Qwen Model Studio profiles use
458
+ `type: "qwen"` with a DashScope-compatible `baseURL`; the API key is usually stored as
459
+ `$ENV:DASHSCOPE_API_KEY`. DeepSeek profiles use `type: "deepseek"` with
460
+ `https://api.deepseek.com` and `$ENV:DEEPSEEK_API_KEY`. Gemma-family LM Studio models use
461
+ `type: "gemma"` so Robota can apply Gemma-specific channel-marker projection while still talking to
462
+ the OpenAI-compatible `/v1/chat/completions` API through `baseURL`. Generic OpenAI-compatible profiles use
463
+ `type: "openai"` and do not apply provider-specific projection. Use `--provider <profile>` for a
464
+ one-shot invocation override; add `--set-current` only when the selected profile should become the
465
+ persisted default. The legacy single-provider shape remains supported:
207
466
 
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.
467
+ ```json
468
+ {
469
+ "provider": {
470
+ "name": "anthropic",
471
+ "model": "claude-sonnet-4-6",
472
+ "apiKey": "$ENV:ANTHROPIC_API_KEY"
473
+ }
474
+ }
475
+ ```
213
476
 
214
477
  ## Context Discovery
215
478
 
@@ -219,36 +482,73 @@ The CLI automatically discovers and loads:
219
482
  - **CLAUDE.md** — same walk-up discovery
220
483
  - **Project metadata** — from `package.json`, `tsconfig.json`
221
484
 
222
- All context is assembled into the system prompt for the AI assistant.
485
+ All context is assembled into the system prompt.
486
+
487
+ Ordinary prompts may also reference workspace-local files with path-like `@file` tokens, for
488
+ example `@AGENTS.md` or `@docs/SPEC.md`. The CLI passes those prompts through unchanged; the SDK
489
+ resolves bounded file content under the active `cwd`, sends the enriched prompt to the model, and
490
+ records a structured file-reference event in the session history.
491
+
492
+ ## Memory Management
493
+
494
+ - **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.
495
+ - **Tool state cleanup** — Completed tool execution states are trimmed to the most recent 50 entries.
496
+ - **React.memo** — `MessageItem` uses `React.memo` to skip redundant re-renders.
497
+
498
+ ## Session Logging
499
+
500
+ Session logs are written to `.robota/logs/{sessionId}.jsonl` in JSONL format by default, capturing structured events for diagnostics and replay. Background task lifecycle/progress events are logged there as they happen. Child-process subagents also write append-only transcripts to `.robota/logs/{sessionId}/subagents/{agentId}.jsonl`, including streaming text deltas while the local provider request is still running.
501
+
502
+ Resumable session JSON is written to `.robota/sessions/{sessionId}.json` for the current project and includes messages, UI history, the exact system prompt, registered tool schemas, and background task snapshots. High-frequency streaming chunks stay in JSONL transcript files; the session JSON stores task state and transcript paths.
223
503
 
224
504
  ## Architecture
225
505
 
506
+ The CLI is a pure TUI layer. All business logic lives in `@robota-sdk/agent-framework`'s `InteractiveSession`. `useInteractiveSession` is the sole React↔SDK bridge, converting SDK events to React state.
507
+
226
508
  ```
227
- bin.ts → cli.ts (parseArgs, load config/context, create Session)
228
- ├── config/config-loader.ts — settings file discovery + Zod validation
229
- ├── context/context-loader.ts — AGENTS.md/CLAUDE.md walk-up discovery
230
- ├── context/project-detector.ts — package.json/tsconfig detection
231
- ├── context/system-prompt-builder.ts — system message assembly
232
- ├── session.ts — Robota agent wrapper + permission enforcement
233
- │ └── permissions/
234
- │ ├── permission-gate.ts — 3-step evaluation (deny → allow → mode)
235
- │ ├── permission-mode.ts — mode × tool policy matrix
236
- │ └── permission-prompt.ts — interactive [y/N] prompt
237
- ├── tools/ — 6 built-in tools (Bash, Read, Write, Edit, Glob, Grep)
238
- ├── session-store.ts — JSON file-based session persistence
239
- └── ui/ — Ink TUI components (App, MessageList, InputArea, etc.)
509
+ bin.ts → cli.ts (arg parsing)
510
+ └── ui/render.tsx → App.tsx (thin JSX shell)
511
+ ├── useInteractiveSession (ONLY React↔SDK bridge)
512
+ │ ├── InteractiveSession (SDK)
513
+ │ ├── CommandRegistry (SDK, re-exported by CLI)
514
+ │ │ ├── BuiltinCommandSource (SDK, empty by default)
515
+ │ │ ├── agent-command-skills (/skills command + virtual skill aliases)
516
+ │ │ ├── PluginCommandSource (SDK, plugin skills)
517
+ │ │ └── ICommandModule sources (/help, /compact, ...)
518
+ │ └── SystemCommandExecutor (SDK)
519
+ ├── plugin-hooks-merger.ts (merges plugin hooks into SDK config)
520
+ ├── MessageList.tsx
521
+ ├── InputArea.tsx (CjkTextInput, bracketed paste, slash detection)
522
+ ├── StatusBar.tsx (activity, conditional mode, model, context %)
523
+ ├── PermissionPrompt.tsx (arrow-key Allow/Deny)
524
+ ├── SlashAutocomplete.tsx (command popup with scroll)
525
+ ├── DiffBlock.tsx (Edit tool diff display)
526
+ ├── MenuSelect.tsx (arrow-key menu, Plugin TUI)
527
+ ├── PluginTUI.tsx (plugin management screen stack)
528
+ ├── TextPrompt.tsx (text input for Plugin TUI)
529
+ └── ConfirmPrompt.tsx (reusable yes/no prompt)
240
530
  ```
241
531
 
242
- Tool calls flow through the permission system:
532
+ ## Dependencies
243
533
 
244
- ```
245
- AI agent requests tool call
246
- → Session.wrapToolWithPermission() intercepts execute()
247
- → evaluatePermission(toolName, args, mode, allow/deny lists)
248
- → deny list match? → blocked
249
- → allow list match? → auto-approved
250
- → mode policy lookup → auto | approve | deny
251
- → if 'approve': promptForApproval() → user types y/N
252
- → if allowed: original tool.execute() runs
253
- → if denied: returns error result to AI agent
254
- ```
534
+ | Package | Purpose |
535
+ | -------------------------------------- | ------------------------------------------ |
536
+ | `@robota-sdk/agent-framework` | Session factory, query, config, context |
537
+ | `@robota-sdk/agent-core` | Types (TPermissionMode, TToolArgs) |
538
+ | `@robota-sdk/agent-transport-headless` | Headless runner for print mode (`-p`) |
539
+ | `ink` 7, `react` 19.2+ | TUI rendering |
540
+ | `ink-select-input` | Arrow-key selection (permission prompt) |
541
+ | `ink-spinner` | Loading spinner |
542
+ | `chalk` | Terminal colors |
543
+ | `ink-text-input` | Base text input (extended by CjkTextInput) |
544
+ | `marked`, `marked-terminal` | Markdown parsing and terminal rendering |
545
+ | `cli-highlight` | Syntax highlighting for code blocks |
546
+ | `string-width` | Unicode-aware string width (CJK support) |
547
+
548
+ ## Documentation
549
+
550
+ See [docs/SPEC.md](./docs/SPEC.md) for the full specification, architecture details, and design decisions.
551
+
552
+ ## License
553
+
554
+ MIT