@pithosai/pithosai 1.0.0 → 1.0.2

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 CHANGED
@@ -1,451 +1,151 @@
1
- # Pithosai (pi-agent)
1
+ # Pithosai (`@pithosai/pithosai`)
2
2
 
3
- Pithosai is a CLI that implements code or projects from a natural-language request. Role prompts are loaded from the SQLite DB at runtime (with optional fallback to `.pithosai/<role>/*.md`). A project-local `.pithosai/` directory holds role-specific prompt files when used and persists conversation sessions under `.pithosai/sessions/`.
4
-
5
- **Requirements:** Node.js (ESM), and a model provider — Cursor CLI (browser auth, no API key), DeepSeek API key, or OpenRouter API key.
3
+ **Multi-role AI CLI** for coding and product work: natural-language requests, pluggable models (Cursor, DeepSeek, OpenRouter), and role-based prompts stored in SQLite. **Current version: 1.0.1** — see [CHANGELOG.md](CHANGELOG.md).
6
4
 
7
5
  ---
8
6
 
9
7
  ## Install
10
8
 
11
- ```bash
12
- npm install
13
- ```
14
-
15
- Set up at least one model provider:
16
-
17
- - **Cursor CLI** (recommended — no API key needed):
18
- ```bash
19
- curl https://cursor.com/install -fsS | bash
20
- cursor-agent login
21
- export CURSOR_MODEL=auto # or: sonnet-4.6, opus-4.6, gpt-5.2
22
- ```
23
- - **DeepSeek:** `export DEEPSEEK_API_KEY=sk-...`
24
- - **OpenRouter:** `export OPENROUTER_API_KEY=sk-or-...`
25
-
26
- Provider priority: `CURSOR_MODEL` / `--cursor` > `DEEPSEEK_API_KEY` > `OPENROUTER_API_KEY`.
27
-
28
- ---
29
-
30
- ## Docker
31
-
32
- If you want to build the Docker image, please git clone a new project from the repo, then run the following command:
9
+ **Node.js ≥ 18.12** required.
33
10
 
34
11
  ```bash
35
- docker build --no-cache -t pithosai .
12
+ npm install -g @pithosai/pithosai
36
13
  ```
37
14
 
38
- **Important:** Never share the project directory that is used by the non-Docker runtime.
15
+ On a **global** install, the package runs a one-time step: if `~/.pithosai/pithosai.db` does not exist, it is created from the bundled schema. Override the path anytime with `PITHOSAI_DB_PATH`.
39
16
 
40
17
  ---
41
18
 
42
- ## Quick start
43
-
44
- 1. **Create a project**
45
-
46
- ```bash
47
- pithosai init
48
- # or: pithosai init my-app --type js
49
- # or: pithosai init ./backend --type ts --lang zh --role RD
50
- ```
51
-
52
- This creates the target directory (if needed), scaffolds by project type (`--type js|ts|python`) and role (`--role RD|PM|QA|CO|SRE` and other template roles), creates `.pithosai/sessions/`, and writes `.settings.json` (lang, project, supportedRoles, tools). Role prompts are loaded from the SQLite DB at runtime; no prompt files are copied into the project by default. For PM, QA, CO, MKT, or SRE roles, a starter `rules/requirements.md` is created for you to fill in.
53
-
54
- 2. **Run a request**
55
-
56
- ```bash
57
- pithosai "Add a REST endpoint that returns the current time"
58
- pithosai -C ./my-app "Run tests and fix failures"
59
- pithosai "Refactor the auth module" --cursor # use Cursor models (auto)
60
- pithosai --cursor sonnet-4.6 "Explain this codebase" # specific Cursor model
61
- ```
62
-
63
- By default, after the agent replies you get an interactive session to type more requests. Type `exit` or `quit` to leave.
64
-
65
- 3. **Interactive-only mode (no initial request)**
19
+ ## What you get
66
20
 
67
- ```bash
68
- pithosai -i
69
- ```
70
-
71
- **Terminal UI (TTY):** When both stdin and stdout are TTYs, the default run command uses **`@mariozechner/pi-tui`**: the **input area stays at the bottom** in a **boxed Editor** (no `You:` prefix on the prompt), **assistant output streams above**, and a **loading row** sits **just above the input box** while the model is working. When output hits the transcript, that row **switches to a simpler running indicator** (same idea as the stderr spinner in non-TUI mode) and **stays until the run finishes**, instead of disappearing immediately. While the TUI is up, **CWD/request banners and run status go through the transcript sink** (and the **log file** via the file-only logger), not raw stdout, so **extra `process.stdout` traffic does not paint over the full-screen layout**; **Ctrl+S** and **Ctrl+P** notices are **appended to the transcript** instead of raw stdout. **Run failures** (including guard timeouts), **dialog/plan `success: false` errors**, and **failed result previews** are **appended to the transcript in red** so they stay visible without corrupting the layout. Slash-command output, `/list` tables, and `/shell` results are drawn in the same transcript (multi-line `/list` output is split into real rows and the view **scrolls to the table header**; use the **mouse wheel**, **arrow keys**, **PgUp/PgDn**, or **Ctrl+U / Ctrl+F** (page) to scroll long output, **including while the agent is running** (**Ctrl+U/Ctrl+F** scroll the log instead of the editor’s usual line-edit shortcuts; **Ctrl+D** remains EOF / exit on an empty line). Set **`PITHOSAI_NO_TUI=1`** to use the classic readline **`You:`** line instead (e.g. scripts or SSH without a proper terminal).
72
-
73
- In **`agent`** mode (default), prints CWD and short tips (full tools, task-scoped history in the local DB, `/new`, `/shell`, `/list`, `/show`, `/show-task [index]`, `/show-prompt`, **`/list-skill`**, **`/install-skill`**, **`/remove-skill`** — same behavior as `pithosai skills list`, `install`, and `remove` — keyboard controls), then prompts for input. **`dialog`** and **`plan`** show their own tips. After the banner, all three modes start the same input loop when interactive is enabled (plan keeps transcript output minimal until each plan file is written). **Tab** completes slash commands (e.g. `/list`, `/list-skill`, `/show`, `/show-prompt`, `/show-task`, `/install-skill`, `/remove-skill`) and `exit` / `quit` in both the pi-tui **Editor** prompt (dropdown + Enter to apply) and **readline** mode; **`/shell`** is only offered in **agent** mode. Typing **`/`** also opens the slash menu as you continue the command. The pause sub-prompt still uses readline **Tab** for `continue` / `c` and `exit` / `e`.
74
-
75
- While an agent run is in progress, keyboard controls are available:
76
- - `Ctrl+S` — stop current run and return to prompt
77
- - `Ctrl+P` — pause current run and enter pause sub-prompt
78
- - `continue` / `c` resumes with current request
79
- - `exit` / `e` exits the CLI
80
- - any other non-empty input replaces the pending request
81
-
82
- 4. **One-shot (no follow-up prompt)**
83
-
84
- ```bash
85
- pithosai --no-interactive "One request only"
86
- ```
87
-
88
- 5. **Run variant (`--mode`)**
89
-
90
- The default command supports a run variant:
91
-
92
- | Mode | Behavior |
93
- |------|----------|
94
- | `agent` (default) | Answer and use tools (implement, run commands via tools, etc.). |
95
- | `dialog` | Answer-focused mode with **read-only tools only** (`read`, `list_files`, `read_pdf`, `web_fetch`, `web_search`, `proxy_downloader`, `read_email`). `/shell` is disabled; `/list`, `/select`, `/show`, `/show-prompt`, `/show-task [index]`, `/list-skill`, `/install-skill`, and `/remove-skill` still work. |
96
- | `plan` | Writes the model reply only to `<slug>-plan.md` in the **project root** (`-C` / cwd). Same **read-only tools** as dialog; `/shell` is disabled. `/list`, `/select`, `/show`, `/show-prompt`, `/show-task [index]`, `/list-skill`, `/install-skill`, and `/remove-skill` work like dialog. With `-i`, the follow-up prompt runs another plan per line (output stays minimal in the UI until each run completes). |
97
-
98
- **Note:** In `plan` mode the run uses a **discard output sink** by default, so you often will not see streamed tokens in the terminal until the model finishes (or times out). While waiting, a **spinner on stderr** shows progress; when anything writes to **stdout**, the line **switches to a lighter running spinner** (TTY) until the run completes, instead of being cleared immediately. On a non-TTY stderr, the spinner **stops** on first stdout as before. The default max run time is **30 minutes** (`AGENT_RUN_TIMEOUT_MS`); pass `--timeout <seconds>` for a shorter cap.
99
-
100
- **Dialog / plan result preview:** After each run completes, **dialog** and **plan** open a full-screen terminal viewer built on **`@mariozechner/pi-tui`** (`Markdown` with the same themed styling as **pi** via **`@mariozechner/pi-coding-agent`**’s `getMarkdownTheme`): scroll with **↑↓** or **j**/**k**, **PgUp**/**PgDn** or **Ctrl+U**/**Ctrl+D**, **Home**/**End**, **gg** (top), or **G** (bottom); press **q**, **Esc**, or **Ctrl+C** to close. While the preview is open, the interactive agent TUI is suspended so those keys only affect the viewer. If stdin/stdout are not both TTY (e.g. CI), the raw markdown is printed to stdout instead. If you set `PITHOSAI_RESULT_BROWSER=chrome`, preview switches to the browser viewer implemented with Playwright and rendered as **WeChat-style HTML** (inline styles, same pipeline as the `markdown_to_html` tool with `forWechat: true`). In Chrome mode the page includes a **Copy markdown** button (copies the raw markdown via the Clipboard API, with a textarea fallback) and **Close** (closes the whole preview browser via Playwright, not only the tab—needed so Chrome does not keep an empty window after the last tab closes). Content is passed in memory via `page.setContent` (no temp file). The Chrome window is opened with **Chromium app mode** (`--app=about:blank` plus a few flags) using Playwright’s **`launchPersistentContext`** so the omnibox and tab strip stay hidden—plain `browser.newPage()` would open a normal Chrome window and ignore app mode. Only your page content and the in-page toolbar are shown (standard window title bar may still appear). Chrome mode defaults to **Google Chrome stable** (`channel: chrome`) and falls back to bundled Chromium if Chrome is missing (install with `npm run playwright:install` / `npx playwright install chromium`). To always use the bundled browser in Chrome mode, set `PITHOSAI_PLAYWRIGHT_CHANNEL=bundled`. Other channels (e.g. `msedge`, `chrome-beta`) are supported via the same variable. To disable preview (e.g. CI), set `PITHOSAI_SKIP_RESULT_BROWSER=1`.
101
-
102
- In **`agent`** mode the model may call the **`playwright_view_markdown`** tool to open the same Playwright preview from **either** raw `markdown` **or** a project `path` to a `.md` file (exactly one of the two). The tool blocks until the user closes the preview window and respects `PITHOSAI_SKIP_RESULT_BROWSER` and `PITHOSAI_PLAYWRIGHT_CHANNEL`. It is **not** available in `dialog` / `plan` read-only toolsets.
103
-
104
- ```bash
105
- pithosai --mode dialog "Explain this stack trace"
106
- pithosai -C ./my-app --mode plan "Sprint plan for the API work"
107
- pithosai -l zh --mode plan --timeout 120 "迭代计划"
108
- ```
109
-
110
- 6. **Shell commands in interactive mode**
111
-
112
- ```bash
113
- pithosai -i
114
- You: /shell ls -la
115
- You: /shell git status
116
- You: /shell npm test
117
- ```
21
+ | You run | Purpose |
22
+ |--------|---------|
23
+ | `pithosai` | Main CLI: `init`, interactive agent, `task`, `heartbeat`, `skills`, `memorize`, and more. |
24
+ | `rdsai`, `pmsai`, `qasai`, `cosai`, `mktai`, `wrsai` | Same CLI with a **default role** (e.g. RD, PM, QA). |
25
+ | `email-monitor` | Heartbeat / email-driven task loop (`heartbeat` bundle). |
26
+ | `render-markdown` | Render Markdown files in the terminal. |
27
+ | `pithosai-init-db` | Manually initialize `~/.pithosai/pithosai.db` if needed (usually automatic after global install). |
118
28
 
119
- Prefix commands with `/shell` to execute shell commands directly.
120
-
121
- The same prompt also supports **task-scoped commands** (conversation rows live in the local SQLite DB): `/list` lists persisted tasks as a markdown table (`index`, `task id`, `task title`, `description`, `createTime`); `/select <index>` selects the active task id, prints a selected-task line, and then shows current task stats (`/show`); `/show` prints current task stats; **`/show-prompt`** builds the system prompt for the current `--mode`, language, and role (same logic as `pithosai show-prompt`) and opens it in the same result viewer as dialog/plan, with the prompt body rendered as **markdown** (not a fenced code block); **`/show-task`** shows Q&A for the current task, and **`/show-task <index>`** shows Q&A for that persisted task index. Q&A and **`/show-prompt`** use the same configured result viewer (**pi-tui** terminal viewer by default, Playwright preview when `PITHOSAI_RESULT_BROWSER=chrome`); if `PITHOSAI_SKIP_RESULT_BROWSER=1`, markdown is printed to the terminal instead.
122
-
123
- **Skill commands (ClawHub):** **`/list-skill`** lists installed skills under `.pithosai/skills` (like `pithosai skills list`). **`/install-skill`** with no name installs all remote skills from `clawhub list`; **`/install-skill <name>`** installs one skill; add **`--force`** to reinstall. **`/remove-skill <name>`** removes an installed skill (like `pithosai skills remove`). These use the same implementation as the `pithosai skills` CLI; `clawhub install` still uses inherited stdio when run from the REPL.
124
-
125
- 7. **Add another role**
126
-
127
- ```bash
128
- pithosai add-role CO
129
- ```
29
+ ---
130
30
 
131
- Creates `.pithosai/<role>/` if it does not exist and adds the role to `supportedRoles` in project settings. If `.pithosai/<role>/` already exists, the command returns without overwriting. Prompts are loaded from the SQLite DB at runtime (with file fallback). Use `-r CO` or project settings to select the role.
31
+ ## Choose a model provider
132
32
 
133
- 8. **Task mode (watch and process tasks from markdown)**
33
+ Configure **at least one** of:
134
34
 
35
+ 1. **Cursor CLI** (recommended — subscription auth, no separate API key)
135
36
  ```bash
136
- pithosai task --file prompts.md
137
- pithosai task -C ./my-app --file prompts.md --model deepSeekCoder
37
+ curl https://cursor.com/install -fsS | bash
38
+ cursor-agent login
39
+ export CURSOR_MODEL=auto
138
40
  ```
41
+ Use **`pithosai "your request" --cursor`** or set `CURSOR_MODEL`.
139
42
 
140
- The task runner watches the task file and processes one task at a time (prioritizing `processing` tasks first, then `pending` tasks). During a running task:
141
- - `Ctrl+S` stops the current task run
142
- - `Ctrl+P` pauses and enters the same pause sub-prompt as interactive mode
143
- - If you edit request text in pause sub-prompt, the resumed task run uses the edited text as the task request
43
+ 2. **DeepSeek** — `export DEEPSEEK_API_KEY=sk-...`
144
44
 
145
- 9. **Memorize (role memory file from persisted tasks)**
45
+ 3. **OpenRouter** — `export OPENROUTER_API_KEY=sk-or-...`
146
46
 
147
- ```bash
148
- pithosai memorize --start 2026-01-01 --end 2026-01-31 -r RD
149
- pithosai -r PM memorize --start 2026-04-01 --end 2026-04-10 -C ./my-app
150
- ```
151
-
152
- Reads the local SQLite task store (`~/.pithosai/pithosai.db` unless `PITHOSAI_DB_PATH` is set), finds tasks where the **role** has persisted task messages whose timestamps fall in the inclusive date range, and writes **`.pithosai/<role>/memory.md`** with a short summary per task (title, status, contribution excerpt from assistant output, and a suggested improvement line). Dates are **YYYY-MM-DD** (whole UTC days) or full ISO datetimes. LLM summarization uses the same model selection as the default **`pithosai`** run: **`--reasoner`**, **`--chat`**, **`--cursor [model]`**, and optional **`--model <key>`** (same `KEY_TO_MODEL` keys as **`pithosai task`**). The optional LLM tightening step uses **Chinese** instructions when global **`--lang`** (or project **`lang`** in settings) is Chinese (`zh`…), and **English** otherwise. Use **`--no-llm`** or **`PITHOSAI_MEMORIZE_SKIP_LLM=1`** to write only the structured file without an LLM pass, or if the model is unavailable the command falls back to the structured markdown and prints a notice.
47
+ **Precedence:** `CURSOR_MODEL` / `--cursor` → DeepSeek → OpenRouter.
153
48
 
154
49
  ---
155
50
 
156
- ## Role-specific commands
157
-
158
- Besides `pithosai`, you can use role-specific entry points. Each one runs the same CLI with a default **role** (and, for some, the **chat** model). All support the same subcommands and options as `pithosai`.
159
-
160
- | Command | Default role | Model | Use case |
161
- |--------|----------------|-------|----------|
162
- | **pithosai** | RD | Coder | General coding; implement from natural language. |
163
- | **rdsai** | RD | Coder | Same as `pithosai`; RD (e.g. R&D) coding agent. |
164
- | **pmsai** | PM | Chat | Product/project management; uses PM templates + chat model. |
165
- | **qasai** | QA | Chat | QA; uses QA templates + chat model. |
166
- | **cosai** | CO | Chat | CO role; uses CO templates + chat model. |
167
- | **mktai** | MKT | Chat | Professional marketing (positioning, GTM, campaigns); uses MKT templates + chat model. |
168
-
169
- Examples:
51
+ ## Quick start
170
52
 
171
53
  ```bash
172
- rdsai "Refactor the auth module"
173
- pmsai "Draft a sprint plan for the API work"
174
- qasai "Generate test cases for the login flow"
175
- cosai -i
176
- mktai "Pressure-test our positioning vs two named competitors; output a matrix, proof gaps, and homepage narrative fixes"
54
+ cd your-project
55
+ pithosai init
56
+ pithosai "Describe what you want done"
177
57
  ```
178
58
 
179
- You can still override role or model (e.g. `pmsai -r QA`, `qasai --reasoner`, or `rdsai --cursor`). Add a role's templates with `pithosai add-role PM` (or QA, CO, MKT, SRE, etc.) before using that role.
180
-
181
- ---
182
-
183
- ## Cursor CLI Integration
59
+ - **`pithosai -i`** — interactive session with no initial prompt.
60
+ - **`pithosai --no-interactive "…"`** — one shot, then exit.
61
+ - **`pithosai -C ./other-dir "…"`** — use another project directory.
184
62
 
185
- Use models from your Cursor subscription (Claude Sonnet/Opus, GPT-5.2, etc.) without separate API keys. Authentication is handled by the Cursor CLI's browser-based login.
63
+ Prompts load from the **local SQLite database** (default `~/.pithosai/pithosai.db`). Optional overrides live under `.pithosai/<role>/` in your project.
186
64
 
187
- **Setup (one-time):**
188
-
189
- ```bash
190
- # Install the Cursor agent CLI
191
- curl https://cursor.com/install -fsS | bash
192
-
193
- # Log in via browser
194
- cursor-agent login
65
+ ---
195
66
 
196
- # Verify auth
197
- cursor-agent status
198
- ```
67
+ ## Run modes (`--mode`)
199
68
 
200
- **Usage:**
69
+ | Mode | Use case |
70
+ |------|----------|
71
+ | **`agent`** (default) | Full tools: edit files, run commands, etc. |
72
+ | **`dialog`** | Answers and read-only tools (no shell tool). |
73
+ | **`plan`** | Writes a plan file (`<slug>-plan.md`) in the project root; read-only tools. |
201
74
 
202
75
  ```bash
203
- # Environment variable
204
- export CURSOR_MODEL=auto
205
- pithosai "Build a REST API"
206
-
207
- # CLI flag (overrides env)
208
- # Note: `--cursor` has an optional value. To avoid parsing the request as model id,
209
- # put request before `--cursor`, or use `--` as separator.
210
- pithosai "Explain this code" --cursor
211
- pithosai --cursor -- "Explain this code"
212
- pithosai --cursor sonnet-4.6 "Refactor auth module"
213
- pithosai --cursor opus-4.6 "Design a database schema"
214
- pithosai --cursor gpt-5.2 "Write unit tests"
76
+ pithosai --mode dialog "Explain this error"
77
+ pithosai --mode plan "Outline the next sprint"
215
78
  ```
216
79
 
217
- **Available models:**
218
-
219
- | Model id | Description |
220
- |----------|-------------|
221
- | `auto` | Cursor's default model selection |
222
- | `sonnet-4.6` | Claude Sonnet 4.6 |
223
- | `sonnet-4.6-thinking` | Claude Sonnet 4.6 with extended thinking |
224
- | `opus-4.6` | Claude Opus 4.6 |
225
- | `gpt-5.2` | GPT 5.2 |
226
-
227
- Any model id supported by `cursor-agent --list-models` can be used; the above are pre-defined with metadata. Unknown ids are passed through to `cursor-agent` as-is.
80
+ Result previews (terminal or optional Chrome via Playwright) can be tuned with `PITHOSAI_SKIP_RESULT_BROWSER`, `PITHOSAI_RESULT_BROWSER`, and `PITHOSAI_PLAYWRIGHT_CHANNEL`. Details: [Configuration](https://gitee.com/sihuic/pithosai/blob/master/docs/Configuration.md) (repository).
228
81
 
229
82
  ---
230
83
 
231
- ## Heartbeat
232
-
233
- Heartbeat polls the role's email inbox for **task emails** (subjects starting with `task:` or `任务:`), enqueues them, and runs the agent on one task per tick. State (processed IDs and unprocessed queue) is stored in `~/.pithosai/heartbeat-state.json` and is keyed by role and optionally by project.
84
+ ## Common commands
234
85
 
235
- **Requirements:** The role must have IMAP/SMTP configured in `.settings.json` (see `roles.<role>.imap` and `roles.<role>.smtp`). After each task the agent sends a reply email: on success to the task sender; on failure to the support address (see `SUPPORT_EMAIL` below).
86
+ | Command | What it does |
87
+ |---------|----------------|
88
+ | `pithosai init [dir]` | Scaffold project, `.pithosai/sessions/`, settings. |
89
+ | `pithosai add-role <role>` | Add a role to the project. |
90
+ | `pithosai task --file <md>` | Watch a task file and run tasks sequentially. |
91
+ | `pithosai memorize --start … --end … -r <role>` | Build `.pithosai/<role>/memory.md` from stored tasks. |
92
+ | `pithosai heartbeat` / `heartbeat --once` | Email-driven task pipeline (needs IMAP/SMTP in settings). |
93
+ | `pithosai skills …` | Install / list / remove skills (see repo docs). |
94
+ | `pithosai show-prompt` | Print or preview the system prompt for debugging. |
95
+ | `pithosai shell "cmd"` | Run a shell command via the CLI. |
236
96
 
237
- - **One tick (fetch + process one task, then exit):**
238
- ```bash
239
- pithosai heartbeat --once
240
- ```
241
- - **Continuous loop (poll every N seconds):**
242
- ```bash
243
- pithosai heartbeat
244
- pithosai heartbeat --interval 120
245
- ```
246
-
247
- You can pass `-C`, `-r`, `-l`, `--reasoner`, `--chat`, `--cursor`, `--timeout`, etc. as with other commands. Programmatic API: `heartbeatTick(cwd, runOpts)` runs one tick and returns `{ processedCount, ranOne, unprocessedCount }`; `heartbeatLoop(cwd, opts)` runs the loop with `opts.intervalSeconds` (default 60).
97
+ Use **`pithosai --help`** and **`pithosai <command> --help`** for flags (`--timeout`, `--lang`, `--role`, `--log-path`, etc.).
248
98
 
249
99
  ---
250
100
 
251
- ## Skills Management
252
-
253
- Install, list, and remove AI skills from Clawhub AI. Skills are stored in `.pithosai/skills/` and can be used by agents via the `read_skill` tool. `clawhub install` output and install/list status messages are written to **stdout** / **stderr** in the terminal (not only to the log file).
254
-
255
- **Requirements:** ScraperAPI account and API key (set as `SCRAPERAPI_API_KEY` environment variable).
101
+ ## Interactive session (short)
256
102
 
257
- - **Install skills:**
258
- ```bash
259
- pithosai skills install
260
- pithosai skills install greet --api-key your_key
261
- pithosai skills install --force --url https://custom-skills.example.com
262
- ```
263
- - **List installed skills:**
264
- ```bash
265
- pithosai skills list
266
- pithosai skills list -l zh
267
- ```
268
- - **Remove skill:**
269
- ```bash
270
- pithosai skills remove greet
271
- ```
272
-
273
- See [Skills CLI Documentation](docs/SKILLS-CLI.md) for complete usage.
103
+ In a normal terminal, the default UI uses a **full-screen TUI** (bottom input, scrolling transcript). **`Ctrl+S`** stops a run; **`Ctrl+P`** pauses. Slash commands include `/shell`, `/list`, `/show-task`, `/show-prompt`, and skill helpers. Set **`PITHOSAI_NO_TUI=1`** for a classic line-based prompt (e.g. scripts or minimal terminals).
274
104
 
275
105
  ---
276
106
 
277
- ## Skill Conversion
278
-
279
- Automatically convert frequently used skills into permanent tools for better performance and reliability. The system monitors skill usage, analyzes patterns, and generates optimized tool implementations.
280
-
281
- **Features:**
282
- - **Usage Tracking**: Automatically records skill executions, parameters, and success rates
283
- - **Pattern Analysis**: Identifies common parameter combinations and usage patterns
284
- - **Smart Conversion**: Suggests when skills are ready for conversion based on usage statistics
285
- - **Tool Generation**: Creates optimized JavaScript tools with proper parameter validation
286
- - **Performance Boost**: Converted tools run 50-80% faster than skill-based execution
287
-
288
- **Usage:**
289
-
290
- - **List convertible skills:**
291
- ```bash
292
- pithosai skill-convert list
293
- pithosai skill-convert list --threshold 70
294
- ```
295
-
296
- - **Convert a skill:**
297
- ```bash
298
- pithosai skill-convert convert screenshot
299
- pithosai skill-convert convert screenshot --dry-run # Preview conversion
300
- pithosai skill-convert convert screenshot --force # Force re-conversion
301
- ```
302
-
303
- - **View statistics:**
304
- ```bash
305
- pithosai skill-convert stats
306
- pithosai skill-convert stats --skill screenshot
307
- ```
308
-
309
- - **Manage converted tools:**
310
- ```bash
311
- pithosai skill-convert tools list
312
- pithosai skill-convert tools remove screenshot_tool
313
- pithosai skill-convert tools enable/disable screenshot_tool
314
- ```
315
-
316
- - **Clear records:**
317
- ```bash
318
- pithosai skill-convert clear screenshot
319
- pithosai skill-convert clear --all
320
- ```
321
-
322
- **How it works:**
323
- 1. When you use skills via `read_skill`, the system tracks each execution
324
- 2. After sufficient usage (minimum 3 successful executions), skills become eligible for conversion
325
- 3. The system analyzes parameter patterns and generates optimized tool code
326
- 4. Converted tools are stored in `.pithosai/custom-tools/` and automatically loaded
327
- 5. Future requests use the optimized tool instead of reading skill documentation
328
-
329
- **Example workflow:**
330
- ```bash
331
- # 1. Use a skill multiple times
332
- pithosai "Take a screenshot of the terminal"
333
- pithosai "Capture the browser window after 2 seconds"
334
- pithosai "Take a screenshot of a specific region"
335
-
336
- # 2. Check if it's ready for conversion
337
- pithosai skill-convert list
107
+ ## Environment variables (essentials)
338
108
 
339
- # 3. Convert to permanent tool
340
- pithosai skill-convert convert screenshot
341
-
342
- # 4. Use the optimized tool directly
343
- # (The agent will now use screenshot_tool instead of read_skill screenshot)
344
- pithosai "Take another screenshot with delay"
345
- ```
109
+ | Variable | Role |
110
+ |----------|------|
111
+ | `CURSOR_MODEL`, `CURSOR_AGENT_BIN` | Cursor CLI integration |
112
+ | `DEEPSEEK_API_KEY`, `OPENROUTER_API_KEY` | API providers |
113
+ | `PITHOSAI_DB_PATH` | SQLite DB path (default `~/.pithosai/pithosai.db`) |
114
+ | `PITHOSAI_SKIP_RESULT_BROWSER` | Skip markdown preview (e.g. CI) |
115
+ | `PITHOSAI_RESULT_BROWSER` | `chrome` for Playwright browser preview |
116
+ | `PITHOSAI_TIMEOUT_MS` / `--timeout` | Run time limits |
117
+ | `SCRAPERAPI_API_KEY` | Used by skills / some tools |
346
118
 
347
- See [Skill-to-Tool Design](docs/SKILL-TO-TOOL-DESIGN.md) for technical details.
119
+ A longer list (history limits, security hooks, debug) lives in the [Configuration](https://gitee.com/sihuic/pithosai/blob/master/docs/Configuration.md) doc in the repository.
348
120
 
349
121
  ---
350
122
 
351
- ## Shell Command
123
+ ## Documentation and source
352
124
 
353
- Execute shell commands directly or from interactive mode. Useful for file operations, git commands, and system tasks.
125
+ The **npm package** contains the built CLI and runtime assets. **Markdown guides** (architecture, skills, shell, troubleshooting) are maintained in the repository:
354
126
 
355
- - **Standalone command:**
356
- ```bash
357
- pithosai shell "ls -la"
358
- pithosai shell "git status" --cwd ./my-project
359
- pithosai shell "npm test" --timeout 60
360
- pithosai shell --raw "echo hello"
361
- ```
362
- - **Interactive mode:**
363
- ```
364
- You: /shell ls -la
365
- ```
366
- Use `/shell` prefix in interactive sessions to run shell commands.
127
+ | Doc | Link |
128
+ |-----|------|
129
+ | Changelog | [CHANGELOG.md](CHANGELOG.md) (included in package) |
130
+ | Architecture | [docs/ARCHITECTURE.md](https://gitee.com/sihuic/pithosai/blob/master/docs/ARCHITECTURE.md) |
131
+ | Configuration | [docs/Configuration.md](https://gitee.com/sihuic/pithosai/blob/master/docs/Configuration.md) |
132
+ | Troubleshooting | [docs/TROUBLESHOOTING.md](https://gitee.com/sihuic/pithosai/blob/master/docs/TROUBLESHOOTING.md) |
133
+ | Skills CLI | [docs/SKILLS-CLI.md](https://gitee.com/sihuic/pithosai/blob/master/docs/SKILLS-CLI.md) |
134
+ | Shell CLI | [docs/SHELL-CLI.md](https://gitee.com/sihuic/pithosai/blob/master/docs/SHELL-CLI.md) |
367
135
 
368
- See [Shell CLI Documentation](docs/SHELL-CLI.md) for complete usage.
136
+ **Repository:** [gitee.com/sihuic/pithosai](https://gitee.com/sihuic/pithosai)
369
137
 
370
138
  ---
371
139
 
372
- ## Commands and options
373
-
374
- | Command / option | Description |
375
- |------------------|-------------|
376
- | `pithosai [request]` | Run the agent for `request`. Omit to show help (or use `-i` for interactive mode). |
377
- | `pithosai init [dir]` | Create project: scaffold by type/role, `.pithosai/sessions/`, and settings. Prompts loaded from SQLite at runtime. |
378
- | `pithosai add-role <role>` | Add role: create `.pithosai/<role>/` if missing and update `supportedRoles`. |
379
- | `pithosai skills` | Manage skills from Clawhub AI (install, list, remove). |
380
- | `pithosai skill-convert` | Convert successful skills to permanent tools (monitor usage, analyze patterns, generate tools). |
381
- | `pithosai shell <command>` | Execute shell commands with timeout and formatting. |
382
- | `pithosai task` | Watch a task markdown file and process tasks sequentially (`processing` first, then `pending`). |
383
- | `pithosai heartbeat` | Poll inbox for task emails (`task:...` / `任务:...`), enqueue and run one per tick. State in `~/.pithosai/heartbeat-state.json`. |
384
- | `pithosai heartbeat --once` | Run one tick (fetch emails, process one task if any) then exit. |
385
- | `pithosai heartbeat --interval <seconds>` | Poll interval in seconds (default: 60). |
386
- | `pithosai show-prompt` | Display the system prompt that would be used for a run. Options: `--mode <agent|dialog|plan>`, `--raw` (show before truncation), `--truncated` (show truncated version). |
387
- | `-i, --interactive` | Start in interactive mode without a request; load latest session and prompt. |
388
- | `--no-interactive` | After running a request, do not prompt for more (one-shot). |
389
- | `-C, --cwd <dir>` | Project directory (default: current directory). |
390
- | `-l, --lang <lang>` | Language for prompts and init (e.g. `en`, `zh`). |
391
- | `-r, --role <role>` | Role/template set (e.g. `RD`, `CO`). |
392
- | `--timeout <seconds>` | Max agent run time (default: 1800). |
393
- | `--cursor [model]` | Use Cursor CLI model (no API key; auth via `cursor-agent login`). Optional model: `auto`, `sonnet-4.6`, `opus-4.6`, `gpt-5.2`. If model is omitted, use `pithosai "<request>" --cursor` (or `--cursor -- "<request>"`) to avoid argument ambiguity. |
394
- | `--reasoner` | Use DeepSeek Reasoner (thinking) model. |
395
- | `--chat` | Use DeepSeek Chat model (general chat). |
396
- | `--no-markdown` | Disable terminal markdown rendering and print plain text only. |
397
- | `--skills-dir <dir>` | Directory for `read_skill` (default: `./.pithosai/skills` or `PITHOSAI_SKILLS_DIR`). |
398
- | `--log-path <file>` | Log file path (default: `<project>/logs/pithosai.log`). |
399
-
400
- ---
401
-
402
- ## Environment variables
403
-
404
- | Variable | Description |
405
- |----------|-------------|
406
- | `CURSOR_MODEL` | Cursor CLI model id (e.g. `auto`, `sonnet-4.6`, `opus-4.6`, `gpt-5.2`). No API key needed — uses `cursor-agent login` auth. |
407
- | `CURSOR_AGENT_BIN` | Path to `cursor-agent` binary (default: `cursor-agent` on `PATH`). |
408
- | `DEEPSEEK_API_KEY` | API key for DeepSeek (Coder / Chat / Reasoner). |
409
- | `OPENROUTER_API_KEY` | API key when using OpenRouter. |
410
- | `SCRAPERAPI_API_KEY` | API key for ScraperAPI (used by skills command and proxy downloader). |
411
- | `PITHOSAI_TIMEOUT_MS` | Max run time in milliseconds (overrides `--timeout` when set). |
412
- | `PITHOSAI_SKILLS_DIR` | Default skills directory for `read_skill`. |
413
- | `PITHOSAI_RESULT_BROWSER` | Result viewer selection. Default: **pi-tui** full-screen markdown viewer. Set to `chrome` to use Playwright browser preview. |
414
- | `PITHOSAI_PLAYWRIGHT_CHANNEL` | Playwright browser channel for Chrome preview mode (e.g. `chrome`, `msedge`, `chrome-beta`, `bundled`). |
415
- | `PITHOSAI_SKIP_RESULT_BROWSER` | Set to `1` to skip result preview and print markdown in terminal instead. |
416
- | `PITHOSAI_DEBUG_STREAM` | Set to `1` to log stream completion (for troubleshooting hangs). |
417
- | `PITHOSAI_DEBUG_HOOKS` | Set to `1` to enable debug hook handlers (logging, performance, stats). |
418
- | `PITHOSAI_SECURITY_HOOKS` | Set to `1` to enable security hook handlers (tool blocking, sensitive-info detection). |
419
- | `PITHOSAI_BLOCKED_TOOLS` | Comma-separated list of tool names to block (requires `PITHOSAI_SECURITY_HOOKS=1`). |
420
- | `PITHOSAI_DB_PATH` | Override SQLite database path (default: `~/.pithosai/pithosai.db`). |
421
- | `SUPPORT_EMAIL` | When a heartbeat task fails, the failure reply is sent to this address instead of the customer. Default: `support@pithosai.com`. |
422
- | `PITHOSAI_MAX_MESSAGE_TOKENS` | Max tokens for conversation messages before compression (defaults to model context minus reserved system tokens). |
423
- | `PITHOSAI_MAX_HISTORY_MESSAGES` | Max number of recent messages kept before earlier history is dropped (default: 40). |
424
- | `PITHOSAI_MIN_HISTORY_MESSAGES` | Minimum number of recent messages to keep when aggressively compacting history (default: 10). |
425
- | `PITHOSAI_MAX_TOOL_RESULT_CHARS` | Max characters per tool result string before truncation (default: 8000). |
426
- | `PITHOSAI_MIN_TOOL_RESULT_CHARS` | Minimum characters per tool result when aggressively truncating tool outputs (default: 2000). |
427
-
428
- ---
429
-
430
- ## Testing
431
-
432
- Unit tests use [Vitest](https://vitest.dev/). Run all tests:
433
-
434
- ```bash
435
- npm test
436
- ```
140
+ ## Docker
437
141
 
438
- Tests cover prompts (loader, validator), agent event handlers (message-utils, chat, reasoner), skills (loader, read-skill tool), init (scaffold, templates, init/add-role), models (DeepSeek config, Cursor config, resolution), utils (paths, path-utils, sleep, logger), settings (read/write and merge), heartbeat, and agent tools (common, web, list-files, playwright-markdown-preview, playwright-view-tool, email).
142
+ To build an image from source, clone the repo and run `docker build -t pithosai .`. Do not mount the same directory you use for a normal (non-Docker) install.
439
143
 
440
144
  ---
441
145
 
442
- ## Docs
146
+ ## Contributing
443
147
 
444
- - [Changelog](CHANGELOG.md) - Release history ([Keep a Changelog](https://keepachangelog.com/) style).
445
- - [Architecture](docs/ARCHITECTURE.md) - Layout, data flow, public API.
446
- - [Configuration](docs/Configuration.md) - Global and project config files (`~/.pithosai/heartbeat-state.json`, `.pithosai/sessions`, `.pithosai/<role>` prompts). In **agent** mode, `.pithosai/<role>/TOOLS.md` (or `TOOLS-zh.md`) can list allowed tools under `# pi-agent-tools` and `# pithosai tools`; if those sections are missing or empty, the full toolset is used. **Dialog** / **plan** modes do not apply this filter.
447
- - [Troubleshooting](docs/TROUBLESHOOTING.md) - Agent hangs, timeouts, stream debug.
448
- - [Tools loop](docs/TOOLS-LOOP.md) - How the agent uses tools.
148
+ Clone the repo, run `npm install`, then `npm test`. Development uses the same `package.json`; publishing runs `npm run build` via `prepublishOnly`.
449
149
 
450
150
  ---
451
151
 
package/dist/935.cjs CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- "use strict";exports.ids=["935"],exports.modules={117(t,e,i){i.d(e,{showMarkdownInPiTui:()=>a});var s=i(895),l=i(950),r=i(168);let h=!1;class n{constructor(t){const{terminal:e,tui:i,markdown:s,hintText:l,documentTitle:r,onClose:h}=t;this.terminal=e,this.tui=i,this._markdown=s,this.hintText=l,this.documentTitle=r?.trim()||"",this.onClose=h,this.scrollTop=0,this._fullLines=null,this._cachedWidth=null,this._ggAwaitingSecondG=!1,this._ggTimer=null}clearGgPrefixState(){null!=this._ggTimer&&(clearTimeout(this._ggTimer),this._ggTimer=null),this._ggAwaitingSecondG=!1}invalidate(){this._markdown.invalidate(),this._fullLines=null,this._cachedWidth=null}handleInput(t){let e=this.terminal.columns,i=Math.max(1,this.terminal.rows-!!this.documentTitle-1),s=Math.max(0,this._getFullLines(e).length-i);if((0,r.matchesKey)(t,"escape")||(0,r.matchesKey)(t,"esc")||(0,r.matchesKey)(t,"q")||(0,r.matchesKey)(t,"shift+q")||(0,r.matchesKey)(t,"ctrl+c")){this.clearGgPrefixState(),this.onClose();return}if((0,r.matchesKey)(t,"shift+g")){this.clearGgPrefixState(),this.scrollTop=s;return}if((0,r.matchesKey)(t,"g")){if(this._ggAwaitingSecondG){this.clearGgPrefixState(),this.scrollTop=0;return}this._ggAwaitingSecondG=!0,null!=this._ggTimer&&clearTimeout(this._ggTimer),this._ggTimer=setTimeout(()=>{this._ggTimer=null,this._ggAwaitingSecondG=!1},500);return}if(this.clearGgPrefixState(),(0,r.matchesKey)(t,"up")||(0,r.matchesKey)(t,"k")){this.scrollTop=Math.max(0,this.scrollTop-1);return}if((0,r.matchesKey)(t,"down")||(0,r.matchesKey)(t,"j")){this.scrollTop=Math.min(s,this.scrollTop+1);return}if((0,r.matchesKey)(t,"pageUp")||(0,r.matchesKey)(t,"ctrl+u")){this.scrollTop=Math.max(0,this.scrollTop-i);return}if((0,r.matchesKey)(t,"pageDown")||(0,r.matchesKey)(t,"ctrl+d")){this.scrollTop=Math.min(s,this.scrollTop+i);return}if((0,r.matchesKey)(t,"home")){this.scrollTop=0;return}if((0,r.matchesKey)(t,"end")){this.scrollTop=s;return}}_getFullLines(t){return this._fullLines&&this._cachedWidth===t||(this._cachedWidth=t,this._fullLines=this._markdown.render(t)),this._fullLines}render(t){let e=this.terminal.rows,i=this.documentTitle?[s.bold.cyan((0,r.truncateToWidth)(this.documentTitle,t))]:[],l=Math.max(1,e-i.length-1);null!=this._cachedWidth&&this._cachedWidth!==t&&this.invalidate();let h=this._getFullLines(t),n=Math.max(0,h.length-l);this.scrollTop=Math.min(this.scrollTop,n);let a=h.slice(this.scrollTop,this.scrollTop+l);for(;a.length<l;)a.push("");return[...i,...a,s.dim((0,r.truncateToWidth)(this.hintText,t))]}}async function a(t){let{markdown:e,t:i,documentTitle:s,tuiSession:a=null}=t;if(!e||"string"!=typeof e||!e.trim())return;if(!(process.stdout.isTTY&&process.stdin.isTTY))return void process.stdout.write(`${e}
3
- `);let o=a&&"function"==typeof a.suspendForReadline&&"function"==typeof a.resumeFromReadline;o&&a.suspendForReadline();try{h||((0,l.CK)("dark"),h=!0);let t=(0,l.pd)(),a=new r.Markdown(e,1,1,t),o=i("cli.resultPreviewTerminalHint"),c=new r.ProcessTerminal,u=new r.TUI(c);u.setClearOnShrink(!0),await new Promise(t=>{let e,i=new n({terminal:c,tui:u,markdown:a,hintText:o,documentTitle:s,onClose:()=>{e?.clearGgPrefixState(),u.stop(),t()}});e=i;let l=new r.Container;l.addChild(i),u.addChild(l),u.setFocus(i),u.start(),u.requestRender(!0)})}finally{o&&a.resumeFromReadline()}}}};
2
+ "use strict";exports.ids=["935"],exports.modules={117(t,e,i){i.d(e,{showMarkdownInPiTui:()=>a});var s=i(691),l=i(950),r=i(168);let h=!1;class n{constructor(t){const{terminal:e,tui:i,markdown:s,hintText:l,documentTitle:r,onClose:h}=t;this.terminal=e,this.tui=i,this._markdown=s,this.hintText=l,this.documentTitle=r?.trim()||"",this.onClose=h,this.scrollTop=0,this._fullLines=null,this._cachedWidth=null,this._ggAwaitingSecondG=!1,this._ggTimer=null}clearGgPrefixState(){null!=this._ggTimer&&(clearTimeout(this._ggTimer),this._ggTimer=null),this._ggAwaitingSecondG=!1}invalidate(){this._markdown.invalidate(),this._fullLines=null,this._cachedWidth=null}handleInput(t){let e=this.terminal.columns,i=Math.max(1,this.terminal.rows-!!this.documentTitle-1),s=Math.max(0,this._getFullLines(e).length-i);if((0,r.matchesKey)(t,"escape")||(0,r.matchesKey)(t,"esc")||(0,r.matchesKey)(t,"q")||(0,r.matchesKey)(t,"shift+q")||(0,r.matchesKey)(t,"ctrl+c")){this.clearGgPrefixState(),this.onClose();return}if((0,r.matchesKey)(t,"shift+g")){this.clearGgPrefixState(),this.scrollTop=s;return}if((0,r.matchesKey)(t,"g")){if(this._ggAwaitingSecondG){this.clearGgPrefixState(),this.scrollTop=0;return}this._ggAwaitingSecondG=!0,null!=this._ggTimer&&clearTimeout(this._ggTimer),this._ggTimer=setTimeout(()=>{this._ggTimer=null,this._ggAwaitingSecondG=!1},500);return}if(this.clearGgPrefixState(),(0,r.matchesKey)(t,"up")||(0,r.matchesKey)(t,"k")){this.scrollTop=Math.max(0,this.scrollTop-1);return}if((0,r.matchesKey)(t,"down")||(0,r.matchesKey)(t,"j")){this.scrollTop=Math.min(s,this.scrollTop+1);return}if((0,r.matchesKey)(t,"pageUp")||(0,r.matchesKey)(t,"ctrl+u")){this.scrollTop=Math.max(0,this.scrollTop-i);return}if((0,r.matchesKey)(t,"pageDown")||(0,r.matchesKey)(t,"ctrl+d")){this.scrollTop=Math.min(s,this.scrollTop+i);return}if((0,r.matchesKey)(t,"home")){this.scrollTop=0;return}if((0,r.matchesKey)(t,"end")){this.scrollTop=s;return}}_getFullLines(t){return this._fullLines&&this._cachedWidth===t||(this._cachedWidth=t,this._fullLines=this._markdown.render(t)),this._fullLines}render(t){let e=this.terminal.rows,i=this.documentTitle?[s.m.bold.cyan((0,r.truncateToWidth)(this.documentTitle,t))]:[],l=Math.max(1,e-i.length-1);null!=this._cachedWidth&&this._cachedWidth!==t&&this.invalidate();let h=this._getFullLines(t),n=Math.max(0,h.length-l);this.scrollTop=Math.min(this.scrollTop,n);let a=h.slice(this.scrollTop,this.scrollTop+l);for(;a.length<l;)a.push("");return[...i,...a,s.m.dim((0,r.truncateToWidth)(this.hintText,t))]}}async function a(t){let{markdown:e,t:i,documentTitle:s,tuiSession:a=null}=t;if(!e||"string"!=typeof e||!e.trim())return;if(!(process.stdout.isTTY&&process.stdin.isTTY))return void process.stdout.write(`${e}
3
+ `);let o=a&&"function"==typeof a.suspendForReadline&&"function"==typeof a.resumeFromReadline;o&&a.suspendForReadline();try{h||((0,l.CK)("dark"),h=!0);let t=(0,l.pd)(),a=new r.Markdown(e,1,1,t),o=i("cli.resultPreviewTerminalHint"),c=new r.ProcessTerminal,m=new r.TUI(c);m.setClearOnShrink(!0),await new Promise(t=>{let e,i=new n({terminal:c,tui:m,markdown:a,hintText:o,documentTitle:s,onClose:()=>{e?.clearGgPrefixState(),m.stop(),t()}});e=i;let l=new r.Container;l.addChild(i),m.addChild(l),m.setFocus(i),m.start(),m.requestRender(!0)})}finally{o&&a.resumeFromReadline()}}}};