genaicode 2.18.4 → 2.20.0

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/docs/CHANGELOG.md CHANGED
@@ -20,6 +20,8 @@
20
20
  (e.g. `!npm run dev` after `genaicode embed`), its output in the transcript; `/stop`, Esc
21
21
  or the Stop button end it and what it started, `!!` sends a leading `!` to the agent.
22
22
  `<AgentChat canStop>` offers Stop while the agent is idle.
23
+ - `Markdown` renders GFM tables (alignment, `\|` escapes, horizontal scroll when wide),
24
+ `~~strikethrough~~` and task lists (`- [x]`). A table may follow a paragraph line directly.
23
25
 
24
26
  ### Changed
25
27
 
package/docs/agents.md CHANGED
@@ -7,6 +7,57 @@
7
7
  behind one interface. It is the agent-side counterpart of `ModelProvider`. A driver
8
8
  translates at the edge and does not own application policy.
9
9
 
10
+ ## Quick look
11
+
12
+ `genaicode/agents` turns the coding-agent CLIs installed on a machine into one API. Give
13
+ any of them a task (a prompt and a working directory) and get back the same event stream
14
+ and result, whichever agent does the work. It is how you script, compare, or chain coding
15
+ agents from a job, a bot, or a CI step without writing a parser per vendor.
16
+
17
+ ```ts
18
+ import { claude, codex, copilot, cursor, detectAgents } from 'genaicode/agents';
19
+
20
+ const [found] = detectAgents([claude(), codex(), copilot(), cursor()]).filter(({ path }) => path);
21
+ if (!found) throw new Error('No coding agent installed.');
22
+
23
+ const run = found.agent.run({ prompt: 'Add a unit test for parseDate', cwd: '/path/to/repo', timeoutMs: 20 * 60_000 });
24
+ for await (const event of run) {
25
+ if (event.type === 'tool-start') console.log('⚙', event.name);
26
+ if (event.type === 'file-change') console.log('edited', event.paths.join(', '));
27
+ }
28
+ const result = await run.result; // { status, ok, text, sessionId, usage, error, ... }
29
+ ```
30
+
31
+ | Agent | Driver | Extras |
32
+ | ---------------- | ----------------------------- | ----------------------------------------------- |
33
+ | Claude Code | `claude()` | MCP servers, approvals, max turns, effort, cost |
34
+ | Codex | `codex()`, `codexLive()` | MCP servers; live: `steer()`, approvals |
35
+ | GitHub Copilot | `copilot()` | MCP servers, allow/deny tool patterns |
36
+ | Cursor | `cursor()` | streamed text deltas |
37
+ | Gemini CLI | `gemini()` | approval mode |
38
+ | opencode | `opencode()` | `provider/model` ids, variants |
39
+ | Mistral Vibe | `vibe()` | agent profile, max turns, max price |
40
+ | Antigravity CLI | `antigravity()` | sandbox, effort, usage |
41
+ | Muse | `muse()`, `museLive()` | max turns; live: `steer()`, approvals |
42
+ | Your own CLI/API | `cliAgent()`, `hostedAgent()` | plug in any JSON-lines CLI or hosted agent |
43
+
44
+ On top of the drivers:
45
+
46
+ - **Steer a running task** with `run.steer(text)` (live drivers), and answer permission
47
+ prompts with `onApproval` (Claude, live Codex and Muse).
48
+ - **Pick approval and sandbox policy** with `permissions: { approval, sandbox }` (or
49
+ `'yolo'`); each driver maps it to the agent's own flags and refuses what it cannot honor.
50
+ - **Attach MCP servers per task** with `mcpServers`. Header secrets stay out of argv.
51
+ - **Verify and repair**: `runWithVerify` runs your check (tests, lint) after the agent and
52
+ sends failures back for another attempt.
53
+ - **Keep credentials apart**: `withoutProviderCredentials()` strips your app's LLM API keys
54
+ from the agent's environment, so it bills its own login.
55
+
56
+ Importing `genaicode` never spawns anything; only `genaicode/agents` does. The agent uses
57
+ its own credentials and billing, and its own permission settings unless `permissions` sets
58
+ them; any sandbox is the agent's own. GenAIcode does not choose a model or retry it. See the sections below for events, options per
59
+ driver, and writing your own driver.
60
+
10
61
  ## Scope
11
62
 
12
63
  In scope:
@@ -0,0 +1,71 @@
1
+ # Agent inside your app (`genaicode/app-agent`)
2
+
3
+ [← README](../README.md)
4
+
5
+ `genaicode/app-agent` puts an agent in a local app you run on your machine (an admin
6
+ console, an internal tool, a game editor). The user chats with an agent CLI they already
7
+ have; the agent works the app through tools the app serves over MCP, changes wait for the
8
+ user's approval, and in `dev` mode the agent also edits the app's code and proposes a commit.
9
+
10
+ ```ts
11
+ import { createServer } from 'node:http';
12
+ import { createAppAgent, createAppAgentHandler } from 'genaicode/app-agent';
13
+
14
+ const agent = createAppAgent({
15
+ name: 'the shop admin',
16
+ mcpUrl: 'http://127.0.0.1:3000/api/agent/mcp',
17
+ tools: [
18
+ { name: 'orders', description: 'List open orders.', run: () => JSON.stringify(listOrders()) },
19
+ {
20
+ name: 'refund',
21
+ description: 'Refund an order.',
22
+ write: true, // a card with Approve and Reject; runs only after Approve
23
+ inputSchema: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] },
24
+ run: ({ id }) => refund(String(id)),
25
+ },
26
+ ],
27
+ pages: () => ['/orders', '/customers'], // page context, link chips, "take me there"
28
+ dev: { cwd: process.cwd(), commands: ['npm test'] }, // optional: the agent edits the app
29
+ });
30
+ const handle = createAppAgentHandler(agent, { authorize: (req) => isSignedIn(req) });
31
+
32
+ createServer(async (req, res) => {
33
+ if (await handle(req, res)) return;
34
+ // ...the rest of the app
35
+ }).listen(3000, '127.0.0.1');
36
+ ```
37
+
38
+ On the page, `AppAgentChat` from `genaicode/react` is the whole drawer: the chat, the agent's
39
+ page chips under its replies, Approve and Reject cards (with the diff of a proposed commit),
40
+ and the agent and mode pickers. It reports `currentPath` to the agent and calls `onNavigate`
41
+ when a chip is clicked or the agent is asked to go somewhere.
42
+
43
+ ```tsx
44
+ import { AppAgentChat } from 'genaicode/react';
45
+ import 'genaicode/react/styles.css';
46
+
47
+ <AppAgentChat currentPath={location.pathname} onNavigate={(path) => router.push(path)} />;
48
+ ```
49
+
50
+ <p align="center">
51
+ <img alt="A shop admin with the agent drawer: the agent proposed a refund, waiting for Approve." src="media/screenshots/app-agent.png" width="80%">
52
+ </p>
53
+
54
+ Under it, `/api/agent` serves `GET /events` (a stream of `AppAgentState`: the session, earlier
55
+ turns, pending actions, link chips, navigation requests) and `POST /send`, `/stop`, `/reset`,
56
+ `/config`, `/view`, `/actions/:id` and `/approvals/:id` (the agent CLI's own permission
57
+ prompts); `useAppAgent` wraps them for a page of your own. Switching agent or mode keeps the
58
+ conversation: the next agent gets a short transcript. `trace` receives every prompt, MCP call,
59
+ decision and finished turn, for a log. Default agents are Claude Code, Codex and
60
+ Copilot CLI, locked down per mode: in `use` mode they get only the app's tools (no shell, no
61
+ file edits); in `dev` mode they edit files and run the listed commands, never commit or push (Claude and
62
+ Copilot enforce the command list; Codex has no per-command allowlist, so it runs in its
63
+ `workspace-write` sandbox: writes only inside `cwd`, no network).
64
+ `propose_commit` snapshots the worktree, the user reviews that diff, and Approve commits
65
+ exactly that tree on the reviewed HEAD, or refuses if the files or HEAD changed since, a hook
66
+ changed the files, or a merge or rebase is in progress. The repository's commit hooks run.
67
+ The agent sees no MCP server but the app's: Claude runs with `--strict-mcp-config`, and Codex
68
+ and Copilot get the user's own configured servers switched off. The MCP endpoint takes a per-run
69
+ bearer and refuses browser requests; every other route asks `authorize` and refuses
70
+ cross-site requests. Without `authorize` only a loopback `Host` is accepted (add names with
71
+ `allowedHosts`), so a DNS-rebinding page cannot reach the agent.
package/docs/cli.md ADDED
@@ -0,0 +1,105 @@
1
+ # Command line: run, chat, ui, embed
2
+
3
+ [← README](../README.md)
4
+
5
+ ## From the command line
6
+
7
+ The `genaicode` bin runs the same headless drivers without writing any code:
8
+
9
+ ```bash
10
+ npx genaicode agents # which agent CLIs are installed
11
+ npx genaicode run "Add a unit test for parseDate" # first installed agent, current dir
12
+ npx genaicode run -a codex -C ../api --verify "npm test" "Fix the failing date tests"
13
+ git diff | npx genaicode run --json -a claude - # prompt from stdin, JSON-lines events
14
+ ```
15
+
16
+ Assistant text goes to stdout and tool calls, edits, and the result line go to stderr.
17
+ `--verify` runs a shell command after the agent finishes and sends its output back for up
18
+ to `--max-repairs` more attempts (`runWithVerify`). The exit code is 0 on success, 1 when
19
+ the agent or the check fails, 2 on a usage error, and 130 when interrupted.
20
+ `npx genaicode --help` lists every option.
21
+
22
+ ## Chat with an agent: terminal and browser
23
+
24
+ ```bash
25
+ npx genaicode # chat in this terminal (same as "genaicode chat")
26
+ npx genaicode chat -a claude -C ../api
27
+ npx genaicode ui # the same chat in your browser, served on 127.0.0.1
28
+ npx genaicode chat --web # both: the terminal and the browser on one session
29
+ ```
30
+
31
+ The terminal and the browser can show one session. `/web` in the terminal chat opens it in
32
+ the browser (`/web off` stops the server), and Enter in the terminal that runs
33
+ `genaicode ui` brings it into that terminal. A prompt, an approval or a stop from either
34
+ side shows up in both.
35
+
36
+ Each prompt after the first continues the agent's own session (`AgentTask.resume`), so you
37
+ can say "now add a test for that". Prompts sent while the agent works wait in a queue and
38
+ run next; Esc stops the agent. When the agent asks for permission, `y` approves, `n`
39
+ denies and `a` approves everything from then on (`/auto`, or the Auto-approve chip in the
40
+ browser; `-y` starts that way). `!` on an empty prompt switches to shell mode, as in Claude
41
+ Code: `!npm run dev` runs in the project with its output in the transcript, and `/stop` (or
42
+ Esc) ends it. `/agent`, `/model` and `/new` switch agent,
43
+ model and session; `/help` lists the rest.
44
+
45
+ <p align="center">
46
+ <picture>
47
+ <source media="(prefers-reduced-motion: reduce)" srcset="media/screenshots/chat-terminal.png">
48
+ <img alt="genaicode chat in a terminal: the agent fixes a failing test, then takes queued follow-ups." src="media/screenshots/chat-terminal.gif" width="49%">
49
+ </picture>
50
+ <picture>
51
+ <source media="(prefers-reduced-motion: reduce) and (prefers-color-scheme: dark)" srcset="media/screenshots/wolf-dark.png">
52
+ <source media="(prefers-reduced-motion: reduce)" srcset="media/screenshots/wolf-light.png">
53
+ <source media="(prefers-color-scheme: dark)" srcset="media/screenshots/chat-browser-dark.gif">
54
+ <source media="(prefers-color-scheme: light)" srcset="media/screenshots/chat-browser-light.gif">
55
+ <img alt="genaicode ui in a browser: the same fix and a follow-up." src="media/screenshots/chat-browser-light.gif" width="49%">
56
+ </picture>
57
+ </p>
58
+
59
+ The wolf from genaicode 1.0 is back. When the agent asks for approval or finishes, the
60
+ browser UI barks if its tab is in the background and counts those events in the tab title.
61
+ The terminal UI rings the terminal bell instead. `/bark off` (or the Bark button) quiets it.
62
+
63
+ <p align="center">
64
+ <picture>
65
+ <source media="(prefers-color-scheme: dark)" srcset="media/screenshots/wolf-dark.png">
66
+ <source media="(prefers-color-scheme: light)" srcset="media/screenshots/wolf-light.png">
67
+ <img alt="The browser UI with the wolf behind a finished turn." src="media/screenshots/wolf-light.png" width="80%">
68
+ </picture>
69
+ </p>
70
+
71
+ `genaicode ui` listens on the loopback address and prints a link with a random access
72
+ token. The page, the event stream and every command need that token; only the bundled
73
+ script and the four mascot files (`/app.js`, `/assets/…`) are served without it, since they
74
+ hold nothing about your session. Both front ends are bundled into the package and load
75
+ only for these commands; importing `genaicode` or `genaicode/agents` pulls in no UI code.
76
+ In code, the same conversation is `createAgentSession` from `genaicode/agents` (see
77
+ [agents.md](agents.md#chat-sessions)); with a live driver (`codexLive`,
78
+ `museLive`) it also steers the running agent and asks you about permission requests.
79
+
80
+ ## Let your agent embed it
81
+
82
+ ```bash
83
+ npx genaicode embed # in your project: your agent wires genaicode in
84
+ npx genaicode embed -a codex "only the dev panel"
85
+ npx genaicode embed --print | pbcopy # just the instructions, for any other agent
86
+ ```
87
+
88
+ `genaicode embed` does not inspect your project itself. It starts your agent with
89
+ instructions on how to embed genaicode, and the agent reads the project and picks the way
90
+ in: the [Vite overlay](vite.md) for an app on Vite; for any other Node dev server (webpack,
91
+ Next.js, Express...) the same overlay through `createDevOverlay` from `genaicode/ui`; for
92
+ pages with no dev server at all, a small dev-only server of its own with that overlay; the in-app agent (`genaicode/app-agent` with
93
+ `<AppAgentChat>`) when the agent should act on the app itself; and `npx genaicode ui` next
94
+ to the dev server when there is no Node process to host it. Words after `embed` go to the
95
+ agent as your request. You watch and answer in the same chat as `genaicode chat` (`--ui`
96
+ for the browser); without a terminal it runs headless like `run`. The agent installs the
97
+ package, edits the config, runs your checks and reports; it does not commit.
98
+
99
+ The instructions are also a Claude Code skill. Copy
100
+ [`skills/genaicode-embed`](skills/genaicode-embed/SKILL.md) into `.claude/skills/` (or
101
+ `~/.claude/skills/`) and ask Claude to "embed genaicode":
102
+
103
+ ```bash
104
+ mkdir -p .claude/skills && cp -r node_modules/genaicode/docs/skills/genaicode-embed .claude/skills/
105
+ ```