@ia-ccun/code-agent-cli 0.0.52-beta.2 → 0.0.52-beta.4
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/config/agent/extensions/aicode-advisor.ts +13 -0
- package/config/agent/extensions/aicode-btw.ts +66 -14
- package/config/agent/extensions/aicode-cd.ts +834 -0
- package/config/agent/extensions/aicode-grillMe.ts +198 -0
- package/config/agent/extensions/aicode-pets.ts +362 -0
- package/config/agent/extensions/aicode-safety-guard.ts +550 -0
- package/config/agent/extensions/aicode-tips.ts +19 -10
- package/config/agent/extensions/aicode-todo-progress.ts +488 -0
- package/config/agent/extensions/custom.ts +0 -32
- package/config/agent/extensions/error-monitor.ts +1 -18
- package/config/agent/extensions/ponytail.ts +441 -0
- package/config/agent/extensions/tps.ts +87 -0
- package/config/agent/extensions/working-msg.ts +160 -66
- package/config/agent/settings.json +2 -1
- package/config/agent/skills/ponytail/SKILL.md +100 -0
- package/config/agent/skills/ponytail-audit/SKILL.md +40 -0
- package/config/agent/skills/ponytail-debt/SKILL.md +44 -0
- package/config/agent/skills/ponytail-help/SKILL.md +68 -0
- package/config/agent/skills/ponytail-review/SKILL.md +56 -0
- package/config/agent/skills/zread/README.md +115 -0
- package/config/agent/skills/zread/SKILL.md +103 -0
- package/config/agent/skills/zread/references/stdio-protocol.md +312 -0
- package/package.json +4 -2
- package/scripts/postinstall.js +0 -1
- package/config/agent/dangerous-patterns.json +0 -106
- package/config/agent/extensions/bash-check.ts +0 -227
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Zread Skill
|
|
2
|
+
|
|
3
|
+
This repository contains a skill for `zread`, a CLI that generates wiki-style
|
|
4
|
+
documentation for code repositories.
|
|
5
|
+
|
|
6
|
+
The skill is meant for one job: help an agent understand an unfamiliar codebase
|
|
7
|
+
through `zread` output instead of re-reading the entire repository file by file.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
### 1. Install the zread CLI
|
|
12
|
+
|
|
13
|
+
Install `zread` first. There are two supported installation methods:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g zread_cli
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
or
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
brew tap ZreadAI/homebrew-tap
|
|
23
|
+
brew install zread
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Then verify the installation:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
zread version
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Install this skill
|
|
33
|
+
|
|
34
|
+
Ask your AI agent to install the skill from GitHub:
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
install this skill https://github.com/ZreadAI/zread-skill
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If you prefer to install it manually, copy this directory into your local
|
|
41
|
+
skills directory:
|
|
42
|
+
|
|
43
|
+
| Agent | Skills directory |
|
|
44
|
+
| ----------- | ----------------------- |
|
|
45
|
+
| Claude Code | `~/.claude/skills/` |
|
|
46
|
+
| OpenClaw | `~/.openclaw/skills/` |
|
|
47
|
+
| Codex | `~/.agents/skills/` |
|
|
48
|
+
|
|
49
|
+
Example:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
cp -R zread ~/.claude/skills/zread
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Your final layout should look like this:
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
<skills-dir>/zread/
|
|
59
|
+
SKILL.md
|
|
60
|
+
README.md
|
|
61
|
+
references/
|
|
62
|
+
stdio-protocol.md
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Once the folder is in place, an agent that supports `SKILL.md`-based skills can
|
|
66
|
+
load and use it.
|
|
67
|
+
|
|
68
|
+
## Features
|
|
69
|
+
|
|
70
|
+
- Read existing `./.zread/wiki/` output instead of crawling source files again
|
|
71
|
+
- Guide an agent to run `zread generate` safely when documentation does not
|
|
72
|
+
exist yet
|
|
73
|
+
- Use `--stdio` as the default mode for agent automation, instead of parsing
|
|
74
|
+
the interactive TUI
|
|
75
|
+
- Explain the role of `current`, `versions`, and `drafts` in zread output
|
|
76
|
+
- Include a reference for the `zread --stdio` JSON-line protocol
|
|
77
|
+
|
|
78
|
+
## When To Use
|
|
79
|
+
|
|
80
|
+
Use this skill when you want to:
|
|
81
|
+
|
|
82
|
+
- understand an unfamiliar repository quickly
|
|
83
|
+
- read an existing zread-generated wiki
|
|
84
|
+
- generate a repository overview or project wiki
|
|
85
|
+
- serve docs locally with `zread browse`
|
|
86
|
+
- drive `zread` programmatically from a script or agent
|
|
87
|
+
|
|
88
|
+
## How It Works
|
|
89
|
+
|
|
90
|
+
The skill follows a simple workflow:
|
|
91
|
+
|
|
92
|
+
1. If `./.zread/wiki/current` exists, read the generated wiki files directly.
|
|
93
|
+
2. If no wiki exists, run `zread generate` only when the user wants docs to be
|
|
94
|
+
generated.
|
|
95
|
+
3. Before generation, confirm with the user because generation consumes LLM
|
|
96
|
+
tokens and writes under `./.zread/`.
|
|
97
|
+
4. In automated workflows, use `--stdio`.
|
|
98
|
+
|
|
99
|
+
## Repository Layout
|
|
100
|
+
|
|
101
|
+
- `SKILL.md`: the skill definition, trigger conditions, and operating rules
|
|
102
|
+
- `references/stdio-protocol.md`: the `zread --stdio` machine protocol
|
|
103
|
+
- `appmap.log`: local artifact, not part of the skill itself
|
|
104
|
+
|
|
105
|
+
## zread Output
|
|
106
|
+
|
|
107
|
+
After a successful generation, zread typically writes:
|
|
108
|
+
|
|
109
|
+
- `./.zread/wiki/current`: the active wiki version id
|
|
110
|
+
- `./.zread/wiki/versions/<id>/wiki.json`: the generated page index
|
|
111
|
+
- `./.zread/wiki/versions/<id>/<file>`: the actual markdown pages
|
|
112
|
+
- `./.zread/wiki/drafts/`: unfinished generation state
|
|
113
|
+
|
|
114
|
+
If you need to integrate with `zread` programmatically, see
|
|
115
|
+
[references/stdio-protocol.md](./references/stdio-protocol.md).
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zread
|
|
3
|
+
description: Produce and consume a wiki-style knowledge base for a code repository via the `zread` CLI and its on-disk output under `./.zread/wiki/`. Use this skill whenever the user wants to understand, onboard onto, explore, summarize, map, or get an overview of an unfamiliar codebase; asks for architecture docs, a project wiki, a repo walkthrough, module/package explanations, or "what does this repo do"; wants to generate, regenerate, resume, browse, or serve code documentation locally; or mentions zread / zread.ai directly. Also use it proactively before diving into a large unknown repo — if `./.zread/wiki/current` exists, read the generated pages instead of crawling source file-by-file; if it doesn't, consider offering to run `zread generate`. The trigger is the intent (understand a codebase through generated docs), not the literal word "zread".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# zread skill
|
|
7
|
+
|
|
8
|
+
`zread` is a CLI that generates wiki documentation from code in the current
|
|
9
|
+
workspace using an LLM. Output lives under `./.zread/wiki/` in the workspace;
|
|
10
|
+
public repos can also be viewed at https://zread.ai.
|
|
11
|
+
|
|
12
|
+
This skill is intended for agent use. Read generated files directly from disk,
|
|
13
|
+
and use `--stdio` as the default mode for any zread command instead of trying
|
|
14
|
+
to parse the human TUI.
|
|
15
|
+
|
|
16
|
+
## On-disk layout (read these directly)
|
|
17
|
+
|
|
18
|
+
Always run `zread` from the workspace root. After a successful generation:
|
|
19
|
+
|
|
20
|
+
- `./.zread/wiki/current` — text file containing the active version id
|
|
21
|
+
(e.g. `2026-03-12-010203`).
|
|
22
|
+
- `./.zread/wiki/versions/<id>/wiki.json` — TOC: `{id, generated_at, language,
|
|
23
|
+
pages: [{slug, title, file, section, group, level}]}`.
|
|
24
|
+
- `./.zread/wiki/versions/<id>/<file>` — page markdown referenced by `pages[*].file`.
|
|
25
|
+
- `./.zread/wiki/drafts/` — in-progress generation; presence means a previous
|
|
26
|
+
run did not finish. `drafts/wiki.json` exists once the catalog phase
|
|
27
|
+
completed.
|
|
28
|
+
- `~/.zread/config.yaml` — global config (LLM provider, language, concurrency).
|
|
29
|
+
- `~/.zread/login.json` — presence indicates the user has logged in.
|
|
30
|
+
|
|
31
|
+
To answer questions about a codebase that already has zread output, read these
|
|
32
|
+
files directly with the file tools — do not invoke `zread browse`.
|
|
33
|
+
|
|
34
|
+
## Commands
|
|
35
|
+
|
|
36
|
+
| Command | Purpose | Key flags |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `zread generate` | Generate wiki for cwd | `-y/--yes`, `--draft resume\|clear\|cancel`, `--skip-failed`, `--stdio` |
|
|
39
|
+
| `zread browse` | Serve docs at http://localhost:9681+ and open browser | `--generate`, `--version <id>`, `--host`, `--port`, `--stdio` |
|
|
40
|
+
| `zread login` | OAuth into BigModel/Z.AI to obtain an API key | `--custom`, `--model`, `--stdio` |
|
|
41
|
+
| `zread config` | Edit `~/.zread/config.yaml` | `--stdio` |
|
|
42
|
+
| `zread update` | Self-update CLI | `--stdio` |
|
|
43
|
+
| `zread version` | Print version | `--stdio` |
|
|
44
|
+
|
|
45
|
+
`--stdio` is supported on every command and turns the process into a JSON-line
|
|
46
|
+
machine protocol on stdin/stdout. See
|
|
47
|
+
[references/stdio-protocol.md](./references/stdio-protocol.md) for the wire
|
|
48
|
+
format (events, `waiting_for`, `done`, `quit`). Load it whenever zread is
|
|
49
|
+
invoked from another program/agent.
|
|
50
|
+
|
|
51
|
+
## Decision tree for an AI agent
|
|
52
|
+
|
|
53
|
+
1. **User wants to read existing wiki content?**
|
|
54
|
+
- Check `./.zread/wiki/current`. If present, read `wiki.json` and the page
|
|
55
|
+
markdown directly. No CLI invocation needed.
|
|
56
|
+
- For known *public* GitHub repos, prefer the `mcp__zread__*` tools
|
|
57
|
+
(`get_repo_structure`, `read_file`, `search_doc`) over running the CLI.
|
|
58
|
+
|
|
59
|
+
2. **User wants to (re)generate docs?**
|
|
60
|
+
- Confirm with the user first — `generate` is long-running, calls an LLM,
|
|
61
|
+
and writes files. Get explicit consent in unfamiliar directories.
|
|
62
|
+
- Verify `~/.zread/login.json` exists or `~/.zread/config.yaml` has an
|
|
63
|
+
`llm.api_key`. If neither, run `zread login` first.
|
|
64
|
+
- If `./.zread/wiki/drafts/` exists, decide:
|
|
65
|
+
- resume previous run → `zread generate --draft resume -y`
|
|
66
|
+
- throw away and start fresh → `zread generate --draft clear -y`
|
|
67
|
+
- Otherwise: `zread generate -y`.
|
|
68
|
+
- To not block on a few failing pages: add `--skip-failed`.
|
|
69
|
+
|
|
70
|
+
3. **User wants to view docs in a browser?**
|
|
71
|
+
- `zread browse` (add `--generate` to bootstrap if no wiki exists yet).
|
|
72
|
+
|
|
73
|
+
4. **User wants to script zread / consume output programmatically?**
|
|
74
|
+
- Use `--stdio` and follow stdio-protocol.md. Do not screen-scrape the TUI.
|
|
75
|
+
|
|
76
|
+
## Non-interactive invocation rules
|
|
77
|
+
|
|
78
|
+
- Always pass `-y` to `generate` when running unattended; otherwise it stops
|
|
79
|
+
at a catalog confirmation gate.
|
|
80
|
+
- Always set `--draft` explicitly when a draft may exist, so the command does
|
|
81
|
+
not prompt.
|
|
82
|
+
- For any command run from another agent/script, use `--stdio` so output is
|
|
83
|
+
parseable JSON instead of ANSI TUI frames.
|
|
84
|
+
- `zread` writes logs to `~/.zread/log/zread.log` — read this if a run fails
|
|
85
|
+
silently.
|
|
86
|
+
|
|
87
|
+
## Safety / blast radius
|
|
88
|
+
|
|
89
|
+
- `generate` consumes LLM tokens (real cost) and can run for many minutes on
|
|
90
|
+
large repos. Confirm before launching.
|
|
91
|
+
- `generate` writes only under `./.zread/` and does not commit anything to
|
|
92
|
+
git. It is safe to delete `./.zread/wiki/drafts/` to recover from a stuck
|
|
93
|
+
state.
|
|
94
|
+
- `update` replaces the zread binary in place and is hard to reverse — only
|
|
95
|
+
run it when the user explicitly asks.
|
|
96
|
+
- `login` opens a browser for OAuth; do not run it in a non-interactive
|
|
97
|
+
context unless the user has asked for it.
|
|
98
|
+
|
|
99
|
+
## Reference files
|
|
100
|
+
|
|
101
|
+
- [references/stdio-protocol.md](./references/stdio-protocol.md) — JSON-line
|
|
102
|
+
wire protocol shared by every command's `--stdio` mode. Load when
|
|
103
|
+
programmatically driving zread.
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# zread `--stdio` protocol
|
|
2
|
+
|
|
3
|
+
Every zread command accepts `--stdio`, switching the process from an interactive
|
|
4
|
+
TUI into a JSON-line machine protocol on stdin/stdout. This is the contract used
|
|
5
|
+
by GUI / programmatic clients to drive zread.
|
|
6
|
+
|
|
7
|
+
## Architecture
|
|
8
|
+
|
|
9
|
+
zread internally uses a Driver / Client split:
|
|
10
|
+
|
|
11
|
+
- **Driver** holds all business logic (loading config, calling LLMs, running the
|
|
12
|
+
doc server, managing drafts). It is framework-agnostic and only talks to a
|
|
13
|
+
`Transport`.
|
|
14
|
+
- **Client** is either a Bubbletea TUI or `StdioClient`. With `--stdio`, the
|
|
15
|
+
cobra command instantiates `transport.NewLocalTransport()` (a channel pair),
|
|
16
|
+
spawns the driver in a goroutine, then runs `StdioClient.Run(ctx)`.
|
|
17
|
+
- `StdioClient` reads JSON lines from `os.Stdin` and forwards them as commands
|
|
18
|
+
to the driver, while encoding `Event`s from the driver to `os.Stdout` (one
|
|
19
|
+
JSON object per line). It returns when an event with `"done": true` is
|
|
20
|
+
received.
|
|
21
|
+
|
|
22
|
+
Result: stdin = command stream, stdout = event stream, both newline-delimited
|
|
23
|
+
JSON. stderr is reserved for logs/errors and should not be parsed.
|
|
24
|
+
|
|
25
|
+
## Event format (driver → client, stdout)
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"vm": { ... },
|
|
30
|
+
"waiting_for": ["..."],
|
|
31
|
+
"done": false,
|
|
32
|
+
"error": ""
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- `vm`: full ViewModel snapshot for the current state (shape varies per command — see below).
|
|
37
|
+
- `waiting_for`: command `type` values the client may legally send right now. `quit` is always accepted regardless.
|
|
38
|
+
- `done`: `true` on the final event; the process will exit on its own.
|
|
39
|
+
- `error`: non-empty when the previous command was rejected; `vm`/`waiting_for` remain unchanged.
|
|
40
|
+
|
|
41
|
+
Rules:
|
|
42
|
+
- An event is emitted after every state transition. Treat `vm` as the full current state (no diffs).
|
|
43
|
+
- `waiting_for: []` with `done: false` means the driver is awaiting an internal async result — do not send any command; just keep reading.
|
|
44
|
+
- The very last event always has `done: true` and an empty `waiting_for`.
|
|
45
|
+
|
|
46
|
+
## Command format (client → driver, stdin)
|
|
47
|
+
|
|
48
|
+
One JSON object per line:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{"type": "<command_type>", "params": { ... }}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- `type` is required. `params` may be omitted (treated as `{}`).
|
|
55
|
+
- Universal command: `{"type":"quit","params":{}}` — every driver handles it and shuts down cleanly.
|
|
56
|
+
- Command types prefixed with `_` are driver-internal. They never appear in `waiting_for`; clients must not send them.
|
|
57
|
+
- Sending a command not in `waiting_for` returns an event with `error` set while `vm`/`waiting_for` remain unchanged.
|
|
58
|
+
- Error message format: `"command \"xxx\" not allowed in state yyy"` / `"invalid params: ..."` / `"invalid JSON: ..."`.
|
|
59
|
+
|
|
60
|
+
## Driving a session
|
|
61
|
+
|
|
62
|
+
1. Spawn `zread <command> --stdio` with piped stdin/stdout.
|
|
63
|
+
2. Read the first event — it carries the initial ViewModel and `waiting_for`.
|
|
64
|
+
3. Render or inspect `vm`; pick a legal command from `waiting_for` and write it as a single JSON line followed by `\n`.
|
|
65
|
+
4. Loop: read next event, react, write next command.
|
|
66
|
+
5. Stop when `done: true` arrives. The process will exit on its own. Sending `quit` at any time triggers the same shutdown.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## `zread browse --stdio`
|
|
71
|
+
|
|
72
|
+
### ViewModel fields
|
|
73
|
+
|
|
74
|
+
| Field | Type | Notes |
|
|
75
|
+
|---|---|---|
|
|
76
|
+
| `state` | string | `"loading"` `"serving"` `"select_version"` `"no_wiki"` `"error"` |
|
|
77
|
+
| `url` | string | Local server URL; present when `state="serving"` |
|
|
78
|
+
| `browser_opened` | bool | Whether the browser was auto-launched |
|
|
79
|
+
| `has_current` | bool | Whether a "current" wiki version exists |
|
|
80
|
+
| `versions` | array | Present when `state="select_version"` |
|
|
81
|
+
| `versions[].id` | string | Wiki version ID |
|
|
82
|
+
| `versions[].timestamp` | string | Version timestamp |
|
|
83
|
+
| `versions[].is_current` | bool | Whether this is the current version |
|
|
84
|
+
| `error` | string | Present when `state="error"` |
|
|
85
|
+
|
|
86
|
+
### Commands
|
|
87
|
+
|
|
88
|
+
| State | `waiting_for` | Command | Params |
|
|
89
|
+
|---|---|---|---|
|
|
90
|
+
| `select_version` | `["select_version","quit"]` | `select_version` | `{"wiki_id":"<id>"}` or `{"current":true}` |
|
|
91
|
+
| `serving` | `["quit"]` | — | — |
|
|
92
|
+
| `no_wiki` | `["quit"]` | — | — |
|
|
93
|
+
| `loading` | `[]` | *(wait for internal event)* | — |
|
|
94
|
+
| `error` | `[]` | — | — |
|
|
95
|
+
|
|
96
|
+
### State machine
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
loading ──(server ok)──────────────────► serving
|
|
100
|
+
loading ──(error)──────────────────────► error (terminal)
|
|
101
|
+
select_version ──(select_version cmd)──► loading ──► serving
|
|
102
|
+
no_wiki ───────────────────────────────► (terminal, done=true)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## `zread generate --stdio`
|
|
108
|
+
|
|
109
|
+
### ViewModel fields
|
|
110
|
+
|
|
111
|
+
| Field | Type | Notes |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| `state` | string | `"select_action"` `"running"` `"done"` `"error"` |
|
|
114
|
+
| `max_retries` | int | Configured max retries per page |
|
|
115
|
+
| `select_action.scenario` | string | `"has_wiki"` `"has_draft"` `"empty"` |
|
|
116
|
+
| `select_action.wiki_date` | string | Date of existing wiki (when `scenario="has_wiki"`) |
|
|
117
|
+
| `select_action.draft_done` | int | Pages already done in draft |
|
|
118
|
+
| `select_action.draft_total` | int | Total pages in draft |
|
|
119
|
+
| `select_action.next_action` | string | Pre-suggested action: `"generate"` `"browse"` `""` |
|
|
120
|
+
| `catalog.status` | string | `"idle"` `"running"` `"done"` `"resumed"` `"error"` |
|
|
121
|
+
| `catalog.tool_name` | string | Currently-running LLM tool (if any) |
|
|
122
|
+
| `catalog.error` | string | Catalog error message |
|
|
123
|
+
| `catalog.auto_retry` | int | Auto-retry count so far |
|
|
124
|
+
| `pages.tasks` | array | Per-page task list |
|
|
125
|
+
| `pages.tasks[].id` | int | Task ID (used for `retry` command) |
|
|
126
|
+
| `pages.tasks[].title` | string | Page title |
|
|
127
|
+
| `pages.tasks[].slug` | string | Page slug |
|
|
128
|
+
| `pages.tasks[].state` | string | `"pending"` `"running"` `"retry_pending"` `"done"` `"failed"` `"resumed"` |
|
|
129
|
+
| `pages.tasks[].retry_count` | int | Retries attempted so far |
|
|
130
|
+
| `pages.tasks[].max_retries` | int | Retry limit for this task |
|
|
131
|
+
| `pages.tasks[].error` | string | Error message if failed |
|
|
132
|
+
| `pages.done` | int | Completed page count |
|
|
133
|
+
| `pages.total` | int | Total page count |
|
|
134
|
+
| `pages.waiting_retry` | bool | `true` when driver is paused waiting for retry/skip decision |
|
|
135
|
+
| `done_total` | int | Total pages done (in `state="done"`) |
|
|
136
|
+
| `error` | string | Fatal error message |
|
|
137
|
+
|
|
138
|
+
### Commands
|
|
139
|
+
|
|
140
|
+
| State / condition | `waiting_for` | Command | Params |
|
|
141
|
+
|---|---|---|---|
|
|
142
|
+
| `select_action` | `["select_action","cancel","quit"]` | `select_action` | `{"action":"generate"}` or `"browse"` or `"resume"` or `"clear"` or `"cancel"` |
|
|
143
|
+
| `running` (normal) | `["quit"]` | — | — |
|
|
144
|
+
| `running` (catalog error) | `["quit","retry_catalog"]` | `retry_catalog` | `{}` |
|
|
145
|
+
| `running` (pages waiting retry) | `["quit","retry","skip_all"]` | `retry` | `{"task_id":<int>}` |
|
|
146
|
+
| `running` (pages waiting retry) | `["quit","retry","skip_all"]` | `skip_all` | `{}` |
|
|
147
|
+
| `running` | `["quit","cancel"]` | `cancel` | `{}` |
|
|
148
|
+
|
|
149
|
+
### CLI flags that affect stdio flow
|
|
150
|
+
|
|
151
|
+
- `--yes` / `-y`: skips the `select_action` gate; generation starts immediately.
|
|
152
|
+
- `--draft-action <resume|clear|cancel>`: pre-answers the draft prompt.
|
|
153
|
+
- `--skip-failed`: equivalent to auto-sending `skip_all` when pages fail.
|
|
154
|
+
|
|
155
|
+
### State machine
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
select_action ──(generate/resume)──► running ──(all done, no failures)──► done
|
|
159
|
+
select_action ──(cancel/browse)────► done (immediate)
|
|
160
|
+
running ──(pages failed)───────────► waiting_retry=true, accepts retry/skip_all
|
|
161
|
+
running ──(cancel)─────────────────► done
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## `zread config --stdio`
|
|
167
|
+
|
|
168
|
+
### ViewModel fields
|
|
169
|
+
|
|
170
|
+
| Field | Type | Notes |
|
|
171
|
+
|---|---|---|
|
|
172
|
+
| `fields` | array (9 items) | Ordered config fields |
|
|
173
|
+
| `fields[].title_key` | string | Display label key |
|
|
174
|
+
| `fields[].json_key` | string | Key to use in `update_fields`; empty = read-only |
|
|
175
|
+
| `fields[].initial` | string | Value at load time |
|
|
176
|
+
| `fields[].value` | string | Current (possibly edited) value |
|
|
177
|
+
| `dirty` | bool | `true` if any field differs from `initial` |
|
|
178
|
+
| `saved` | bool | `true` after successful save |
|
|
179
|
+
| `error` | string | Validation error |
|
|
180
|
+
|
|
181
|
+
Field index → `json_key` mapping:
|
|
182
|
+
|
|
183
|
+
| Index | `json_key` | Notes |
|
|
184
|
+
|---|---|---|
|
|
185
|
+
| 0 | `language` | generation language |
|
|
186
|
+
| 1 | `doc_language` | doc language |
|
|
187
|
+
| 2 | *(empty)* | read-only LLM provider display |
|
|
188
|
+
| 3 | `max_concurrent` | int |
|
|
189
|
+
| 4 | `max_retries` | int |
|
|
190
|
+
| 5 | `llm_provider` | editable in stdio mode |
|
|
191
|
+
| 6 | `llm_base_url` | editable in stdio mode |
|
|
192
|
+
| 7 | `llm_model` | editable in stdio mode |
|
|
193
|
+
| 8 | `llm_api_key` | editable in stdio mode |
|
|
194
|
+
|
|
195
|
+
### Commands
|
|
196
|
+
|
|
197
|
+
No state machine. Fixed `waiting_for`: `["update_fields","save","reload_llm","quit"]`.
|
|
198
|
+
|
|
199
|
+
| Command | Params | Effect |
|
|
200
|
+
|---|---|---|
|
|
201
|
+
| `update_fields` | `{"fields":{"<json_key>": "<value>", ...}}` | Partial update; only listed keys change |
|
|
202
|
+
| `save` | `{}` | Persists config and terminates (`done=true`) |
|
|
203
|
+
| `reload_llm` | `{}` | Re-validates LLM provider settings |
|
|
204
|
+
| `quit` | `{}` | Exits without saving |
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## `zread login --stdio`
|
|
209
|
+
|
|
210
|
+
### ViewModel fields
|
|
211
|
+
|
|
212
|
+
| Field | Type | Notes |
|
|
213
|
+
|---|---|---|
|
|
214
|
+
| `state` | string | See states below |
|
|
215
|
+
| `authorize_url` | string | OAuth URL to open; present in `open_browser` state |
|
|
216
|
+
| `auth_timeout` | int | Nanoseconds until auth expires; present in `waiting` state |
|
|
217
|
+
| `browser_warn` | string | Warning if browser launch failed |
|
|
218
|
+
| `username` | string | Logged-in username; present in `done` state |
|
|
219
|
+
| `avail_models` | array of string | Models to choose from; present in `select_model` state |
|
|
220
|
+
| `selected_model` | string | Currently selected model |
|
|
221
|
+
| `error` | string | Error message in `error` state |
|
|
222
|
+
| `wants_llm_provider_editor` | bool | `true` (with `done=true`) when `--custom` flag was used |
|
|
223
|
+
|
|
224
|
+
States: `"select_region"` → `"init_flow"` → `"open_browser"` → `"waiting"` → `"select_model"` → `"saving"` → `"done"` / `"error"`
|
|
225
|
+
|
|
226
|
+
### Commands
|
|
227
|
+
|
|
228
|
+
| State | `waiting_for` | Command | Params |
|
|
229
|
+
|---|---|---|---|
|
|
230
|
+
| `select_region` | `["select_region","quit"]` | `select_region` | `{"region":"<provider_key>"}` or `{"region":"__use_own_key__"}` |
|
|
231
|
+
| `select_model` | `["select_model","quit"]` | `select_model` | `{"model":"<model_id>"}` |
|
|
232
|
+
| all others | `[]` | *(wait for internal auth events)* | — |
|
|
233
|
+
|
|
234
|
+
### Special cases
|
|
235
|
+
|
|
236
|
+
- `--custom` flag: driver immediately emits `done: true` with `wants_llm_provider_editor: true`. Client should then launch `zread config --stdio` to configure a custom LLM provider.
|
|
237
|
+
|
|
238
|
+
### State machine
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
select_region ──(cmd)──► init_flow ──► open_browser ──► waiting ──► select_model
|
|
242
|
+
select_model ──(cmd)───► saving ──► done
|
|
243
|
+
any ────────────────────────────────────────────────────────────────► error
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## `zread update --stdio`
|
|
249
|
+
|
|
250
|
+
### ViewModel fields
|
|
251
|
+
|
|
252
|
+
| Field | Type | Notes |
|
|
253
|
+
|---|---|---|
|
|
254
|
+
| `state` | string | See states below |
|
|
255
|
+
| `current_version` | string | Installed version |
|
|
256
|
+
| `latest_version` | string | Available version; present in `has_update`+ |
|
|
257
|
+
| `download_url` | string | Asset URL for the update binary |
|
|
258
|
+
| `package_manager` | string | e.g. `"brew"`; present in `package_manager` state |
|
|
259
|
+
| `downloaded_bytes` | int | Bytes downloaded so far |
|
|
260
|
+
| `total_bytes` | int | Total download size |
|
|
261
|
+
| `download_percent` | float | 0–100 |
|
|
262
|
+
| `error` | string | Error message in `error` state |
|
|
263
|
+
|
|
264
|
+
States: `"checking"` → `"up_to_date"` / `"package_manager"` / `"has_update"` → `"downloading"` → `"confirm_restart"` / `"error"`
|
|
265
|
+
|
|
266
|
+
Terminal states (emit `done=true`): `up_to_date`, `package_manager`, `error`, and after restart/skip.
|
|
267
|
+
|
|
268
|
+
### Commands
|
|
269
|
+
|
|
270
|
+
| State | `waiting_for` | Command | Params |
|
|
271
|
+
|---|---|---|---|
|
|
272
|
+
| `has_update` | `["download","quit"]` | `download` | `{}` |
|
|
273
|
+
| `confirm_restart` | `["restart","skip_restart","quit"]` | `restart` | `{}` |
|
|
274
|
+
| `confirm_restart` | `["restart","skip_restart","quit"]` | `skip_restart` | `{}` |
|
|
275
|
+
| all others | `[]` | *(wait for internal events)* | — |
|
|
276
|
+
|
|
277
|
+
### State machine
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
checking ──► up_to_date (terminal)
|
|
281
|
+
──► package_manager (terminal)
|
|
282
|
+
──► has_update ──(download)──► downloading ──► confirm_restart
|
|
283
|
+
──(restart/skip)──► done
|
|
284
|
+
checking / downloading ──(error)──► error (terminal)
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## `zread version --stdio`
|
|
290
|
+
|
|
291
|
+
Emits a single event with `done: true` immediately. No commands are accepted.
|
|
292
|
+
|
|
293
|
+
### ViewModel fields
|
|
294
|
+
|
|
295
|
+
| Field | Type | Notes |
|
|
296
|
+
|---|---|---|
|
|
297
|
+
| `version` | string | e.g. `"1.2.3"` |
|
|
298
|
+
| `channel` | string | Release channel (if set) |
|
|
299
|
+
| `go_version` | string | Go runtime version |
|
|
300
|
+
| `os` | string | OS name |
|
|
301
|
+
| `arch` | string | CPU architecture |
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Practical tips
|
|
306
|
+
|
|
307
|
+
- Always flush stdin after writing a command (the driver reads line-by-line).
|
|
308
|
+
- Treat any line on stdout that fails to parse as JSON as a bug — log it but do not crash; zread should not print non-JSON to stdout in `--stdio` mode.
|
|
309
|
+
- When `waiting_for` is `[]` and `done` is `false`, keep reading — the driver is awaiting an internal async result and will emit the next event on its own.
|
|
310
|
+
- For long-running commands (`generate`), keep reading events continuously; there is no heartbeat, but progress events arrive whenever state changes.
|
|
311
|
+
- To cancel cleanly, send `{"type":"quit","params":{}}` and then drain events until `done` rather than killing the process.
|
|
312
|
+
- `done: true` events are always terminal. Do not send further commands.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ia-ccun/code-agent-cli",
|
|
3
|
-
"version": "0.0.52-beta.
|
|
3
|
+
"version": "0.0.52-beta.4",
|
|
4
4
|
"description": "AI Coding Agent CLI - 基于OpenClaw🦞底层Agent原理封装的编码智能体(供学习使用)。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"@earendil-works/pi-agent-core": "^0.77.0",
|
|
39
39
|
"@earendil-works/pi-ai": "^0.77.0",
|
|
40
40
|
"@earendil-works/pi-coding-agent": "^0.77.0",
|
|
41
|
-
"@earendil-works/pi-tui": "^0.77.0"
|
|
41
|
+
"@earendil-works/pi-tui": "^0.77.0",
|
|
42
|
+
"@firstpick/pi-utils": "^0.2.2"
|
|
42
43
|
},
|
|
43
44
|
"overrides": {
|
|
44
45
|
"glob": "^11.0.0",
|
|
@@ -60,6 +61,7 @@
|
|
|
60
61
|
"@typescript-eslint/parser": "^8.57.0",
|
|
61
62
|
"eslint": "^10.0.3",
|
|
62
63
|
"husky": "^9.1.7",
|
|
64
|
+
"pi-lean-ctx": "^3.8.11",
|
|
63
65
|
"playwright": "^1.60.0",
|
|
64
66
|
"shx": "^0.4.0",
|
|
65
67
|
"typescript": "^5.7.2",
|
package/scripts/postinstall.js
CHANGED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"_comment": "危险命令模式配置 - 放置位置: config/agent/dangerous-patterns.json",
|
|
3
|
-
"_comment2": "安装后会复制到 ~/.aicode-cli/agent/",
|
|
4
|
-
"_comment3": "commandPrefix: 命令必须以该前缀开头才触发拦截(防止误拦截路径中的字符串)",
|
|
5
|
-
"patterns": [
|
|
6
|
-
{
|
|
7
|
-
"pattern": "rm\\s+-rf",
|
|
8
|
-
"commandPrefix": "rm",
|
|
9
|
-
"name": "rm -rf",
|
|
10
|
-
"risk": "🔴 高危",
|
|
11
|
-
"description": "递归强制删除文件和目录",
|
|
12
|
-
"impact": "删除后数据不可恢复",
|
|
13
|
-
"explanation": "rm -rf 是 Linux/Unix 中最危险的命令之一。-r 表示递归遍历所有子目录,-f 表示强制执行不提示确认。这意味着将无提示地删除指定路径下的所有文件和目录,且无法通过回收站或普通方式恢复。"
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"pattern": "git\\s+reset\\s+--hard",
|
|
17
|
-
"commandPrefix": "git",
|
|
18
|
-
"name": "git reset --hard",
|
|
19
|
-
"risk": "🔴 高危",
|
|
20
|
-
"description": "强制重置到指定提交",
|
|
21
|
-
"impact": "丢失未提交的更改",
|
|
22
|
-
"explanation": "git reset --hard 会将 HEAD 指针移动到指定提交,并丢弃所有未提交的更改。这包括工作区和暂存区的修改,执行后这些更改将永久丢失,无法通过 git 恢复。"
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"pattern": "git\\s+push\\s+(--force|-f)",
|
|
26
|
-
"commandPrefix": "git",
|
|
27
|
-
"name": "git push --force",
|
|
28
|
-
"risk": "🔴 高危",
|
|
29
|
-
"description": "强制推送到远程",
|
|
30
|
-
"impact": "覆盖远程历史,可能丢失他人提交",
|
|
31
|
-
"explanation": "git push --force 会强制用本地分支覆盖远程分支,忽略远程的更新历史。在多人协作项目中,这可能覆盖他人的提交,导致协作者的提交丢失或造成分支冲突。"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
"pattern": "git\\s+push\\s+--delete",
|
|
35
|
-
"commandPrefix": "git",
|
|
36
|
-
"name": "git push --delete",
|
|
37
|
-
"risk": "🔴 高危",
|
|
38
|
-
"description": "删除远程分支",
|
|
39
|
-
"impact": "分支删除后不可恢复",
|
|
40
|
-
"explanation": "git push --delete 会从远程仓库删除指定的分支。分支一旦删除,如果没有本地备份或其他人有该分支的副本,所有提交历史都将永久丢失。"
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"pattern": "git\\s+branch\\s+-D",
|
|
44
|
-
"commandPrefix": "git",
|
|
45
|
-
"name": "git branch -D",
|
|
46
|
-
"risk": "🔴 高危",
|
|
47
|
-
"description": "强制删除本地分支",
|
|
48
|
-
"impact": "分支删除后不可恢复",
|
|
49
|
-
"explanation": "git branch -D 会强制删除本地分支(不检查是否已合并)。所有在该分支上的提交历史都将丢失,除非有其他分支包含这些提交。"
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
"pattern": "git\\s+rebase\\s+-i",
|
|
53
|
-
"commandPrefix": "git",
|
|
54
|
-
"name": "git rebase -i",
|
|
55
|
-
"risk": "🔴 高危",
|
|
56
|
-
"description": "交互式变基",
|
|
57
|
-
"impact": "改变提交历史,多人协作时易冲突",
|
|
58
|
-
"explanation": "git rebase -i 允许你交互式地修改、合并、删除或重排提交。这会改变提交的历史哈希值,在已推送的分支上使用会导致后续 push 需要 --force,可能影响协作者。"
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
"pattern": "git\\s+clean\\s+-f(d)?",
|
|
62
|
-
"commandPrefix": "git",
|
|
63
|
-
"name": "git clean",
|
|
64
|
-
"risk": "🔴 高危",
|
|
65
|
-
"description": "删除未跟踪文件",
|
|
66
|
-
"impact": "删除的文件不可恢复",
|
|
67
|
-
"explanation": "git clean 会删除工作区中未被 git 跟踪的文件(新建的文件)。这些文件不在版本控制中,删除后无法通过 git 恢复。"
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
"pattern": "shutdown|halt|init\\s+0",
|
|
71
|
-
"commandPrefix": "shutdown",
|
|
72
|
-
"name": "系统关机",
|
|
73
|
-
"risk": "🔴 高危",
|
|
74
|
-
"description": "关闭或停止系统",
|
|
75
|
-
"impact": "系统将关机或停止服务",
|
|
76
|
-
"explanation": "这些命令会立即关闭或停止系统。如果在服务器上执行,可能导致正在运行的服务中断,数据丢失或损坏。在 SSH 会话中执行可能导致无法重新连接的严重后果。"
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
"pattern": "kill\\s+(-9)?\\s*\\$?(1|init|sshd|systemd)",
|
|
80
|
-
"commandPrefix": "kill",
|
|
81
|
-
"name": "杀系统进程",
|
|
82
|
-
"risk": "🔴 高危",
|
|
83
|
-
"description": "终止系统关键进程",
|
|
84
|
-
"impact": "可能导致系统不稳定或崩溃",
|
|
85
|
-
"explanation": "kill 命令用于终止进程。杀死 PID 1 (init/systemd)、sshd 等系统关键进程可能导致系统服务崩溃、SSH 连接中断或系统完全无法响应。"
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
"pattern": "chmod\\s+0[0-7]{3}\\s+\\/",
|
|
89
|
-
"commandPrefix": "chmod",
|
|
90
|
-
"name": "修改根目录权限",
|
|
91
|
-
"risk": "🔴 高危",
|
|
92
|
-
"description": "修改系统关键路径权限",
|
|
93
|
-
"impact": "可能导致系统无法正常启动",
|
|
94
|
-
"explanation": "chmod 修改文件或目录权限。将根目录 / 的权限改为 0xxx 会影响所有系统文件和程序,导致系统服务无法正常运行,甚至无法重启恢复。"
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
"pattern": "dd\\s+if=.*of=\\/(dev|sd)",
|
|
98
|
-
"commandPrefix": "dd",
|
|
99
|
-
"name": "dd 磁盘操作",
|
|
100
|
-
"risk": "🔴 高危",
|
|
101
|
-
"description": "直接写入磁盘设备",
|
|
102
|
-
"impact": "可能导致数据永久丢失",
|
|
103
|
-
"explanation": "dd 直接读取和写入磁盘设备,绕过文件系统。如果目标指向 /dev/sda 等磁盘设备,会直接覆盖磁盘数据,导致分区表、文件系统、所有数据永久丢失,无法恢复。"
|
|
104
|
-
}
|
|
105
|
-
]
|
|
106
|
-
}
|