agentp 1.14.0 → 2.0.1

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/CONTRIBUTING.md CHANGED
@@ -2,9 +2,20 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
- agentp is a collection of three zero-dependency Node.js CLI tools that extend [OpenCode](https://opencode.ai) with per-project tmux server management (`ocmux`), a stdin-to-session pipe (`agentp`), and a Telegram bot bridge (`tgagentp`).
5
+ agentp is a collection of three **zero-dependency** Node.js CLI tools that
6
+ extend [OpenCode](https://opencode.ai) v2:
6
7
 
7
- The project aims to stay **zero npm dependencies** — all tools use only the Node.js 18+ stdlib (`http`, `https`, `readline`, `url`, `child_process`, `fs`, `path`, `crypto`, `os`). PRs introducing new dependencies will not be accepted unless there is an exceptional justification.
8
+ - **`agentp`** — pipes prompt text into a running OpenCode session and streams the answer back to stdout.
9
+ - **`ocmux`** — manages per-project TUI windows in tmux (session picker, project switcher, create/rename/delete/annotate sessions) on top of a single **user-managed** OpenCode server.
10
+ - **`tgagentp`** — bridges a Telegram bot chat with OpenCode (multi-chat, multi-server, file sharing). *Experimental.*
11
+
12
+ The project aims to stay **zero npm dependencies** — everything uses only the
13
+ Node.js 18+ stdlib (`http`, `https`, `readline`, `url`, `child_process`, `fs`,
14
+ `path`, `crypto`, `os`). PRs introducing new dependencies will not be accepted
15
+ unless there is an exceptional justification.
16
+
17
+ **OpenCode v2 only.** OpenCode v1 support was removed in 2.0.0; there are no
18
+ legacy code paths. The HTTP client lives in `lib/opencode.js`.
8
19
 
9
20
  ## Development Setup
10
21
 
@@ -12,7 +23,8 @@ The project aims to stay **zero npm dependencies** — all tools use only the No
12
23
 
13
24
  - Node.js >= 18
14
25
  - npm (ships with Node.js)
15
- - tmux (optional, only needed for `ocmux` and `tgagentp` features)
26
+ - tmux (only needed for `ocmux` and `tgagentp`)
27
+ - an OpenCode v2 server for manual testing (`opencode serve`)
16
28
 
17
29
  ### Local Install
18
30
 
@@ -21,119 +33,104 @@ git clone <your-fork>
21
33
  cd agentp
22
34
  npm link # registers bin/agentp, bin/ocmux, bin/tgagentp globally
23
35
  # or
24
- npm install -g . # alternative
36
+ npm install -g .
25
37
  ```
26
38
 
27
- After linking, all three binaries are available globally. Run `tgagentp --help` or refer to `README.md`.
28
-
29
- ### Code Map
39
+ ## Code Map
30
40
 
31
41
  ```
32
42
  agentp/
33
43
  ├── bin/
34
- │ ├── agentp — Stdin-to-OpenCode pipe
35
- │ ├── ocmux — Tmux server manager
36
- │ └── tgagentp — Telegram bot bridge
44
+ │ ├── agentp — stdin-to-session pipe
45
+ │ ├── ocmux — project/TUI window manager + interactive pickers
46
+ │ └── tgagentp — Telegram bot bridge
37
47
  ├── lib/
38
- │ ├── opencode.js — HTTP session API client (shared by agentp + tgagentp)
39
- │ └── ocmux.js — Tmux management (shared by ocmux + tgagentp)
40
- ├── tests/
41
- │ ├── opencode.test.js — Unit tests for lib/opencode.js
42
- │ └── ocmux.test.js — Unit tests for lib/ocmux.js
48
+ │ ├── opencode.js — OpenCode v2 HTTP/SSE client (shared by all three)
49
+ │ ├── ocmux.js — tmux helpers (shared by ocmux + tgagentp)
50
+ │ ├── project-state.js — `.ocmux.json` v2 schema + per-session reminders
51
+ │ ├── tui-cmd.js — tmux send-keys passthrough (tgagentp)
52
+ │ ├── file-share.js — telegram-shared directory + upload/download
53
+ │ └── telegram-*.js — Telegram API + formatting helpers
54
+ ├── tests/ — node:test suites (one per module)
43
55
  ├── docs/
44
- │ └── specification.md — Technical architecture reference
45
- ├── AGENTS.md — Development notes and TODO
46
- ├── CONTRIBUTING.md — This file
56
+ │ ├── specification.md — short pointer (superseded)
57
+ │ └── specification_v2.md — current architecture reference
58
+ ├── AGENTS.md — agent/dev notes
59
+ ├── CONTRIBUTING.md — this file
47
60
  └── package.json
48
61
  ```
49
62
 
50
63
  ## Coding Standards
51
64
 
52
- ### Style
53
-
54
- - **CommonJS** (`require` / `module.exports`) — no ES modules
55
- - **No semicolons** — the project uses ASI (automatic semicolon insertion)
56
- - **No comments** in production code — let the code speak; use descriptive variable/function names
57
- - **2-space indentation**
58
- - Single quotes for strings
59
- - `const` over `let`; avoid `var`
60
- - Arrow functions for callbacks and closures
65
+ - **CommonJS** (`require` / `module.exports`) — no ES modules.
66
+ - **2-space indentation**, single quotes, `const` over `let` (avoid `var`),
67
+ `async/await` over `.then()`.
68
+ - **Semicolons are used** in `bin/` and `lib/` — except `lib/tui-cmd.js`, which
69
+ is deliberately no-semicolons. Match the file you are editing.
70
+ - Comments are welcome and present throughout; keep them meaningful.
61
71
 
62
72
  ### Conventions
63
73
 
64
- - Async functions: use `async/await`, avoid raw `.then()`
65
- - Error handling: use try-catch at call sites; log errors via `log.error()`
66
- - Logging: use the `log` helper (`log.info`, `log.error`, `log.debug`) — never `console.log`
67
- - HTTP: use `lib/opencode.js` request helpers instead of raw `http.request`
68
- - Tmux: use `lib/ocmux.js` helpers instead of raw `spawnSync`
74
+ - **HTTP:** use `lib/opencode.js` helpers — never raw `http.request`.
75
+ - **tmux:** use `lib/ocmux.js` helpers (`_tmux` / exported wrappers) — never raw
76
+ `spawnSync`.
77
+ - **State:** `.ocmux.json` I/O goes through `lib/project-state.js`
78
+ (`readProjectState`, `writeProjectState`, `readAnnotations`, `writeAnnotation`,
79
+ atomic writes). Never hand-roll reads/writes.
80
+ - **Logging:** `tgagentp` uses `log.info`/`log.error`/`log.debug` (never bare
81
+ `console.log`). `agentp`/`ocmux` use `console.log` for CLI stdout (answers,
82
+ lists, `--version`) and `console.error` for diagnostics.
69
83
 
70
84
  ### Architecture Rules
71
85
 
72
- 1. **Zero npm dependencies.** The `package.json` `"dependencies"` field must remain empty.
73
- 2. **`bin/`** files are entry points — keep them thin. Business logic goes in `lib/`.
74
- 3. **`bin/tgagentp`** is the largest file (~2000 lines). When adding new features, extract reusable logic into `lib/` when possible.
75
- 4. **Shared state** (e.g., `chatStates`, `serverOwners`) is held in module-level variables in `bin/tgagentp` and `lib/ocmux.js`. Be mindful of mutation.
76
- 5. **All external calls must be mockable.** `lib/opencode.js` tests mock `http.request`; `lib/ocmux.js` tests mock `child_process.spawnSync` and `fs.*`.
86
+ 1. **Zero npm dependencies.** `package.json` `"dependencies"` must remain empty.
87
+ 2. **`bin/` entry points stay thin**; business logic goes in `lib/`.
88
+ 3. **`bin/tgagentp` is the largest file (~3000 lines).** Extract reusable logic
89
+ into `lib/` when adding features.
90
+ 4. **Mockable externals.** All network/subprocess/filesystem access must be
91
+ interceptable (the existing test suites mock `http.request`,
92
+ `child_process.spawnSync`, and `fs.*`).
93
+ 5. **Sessions created via the API have no model** and will not execute prompts
94
+ until one is set — always create them with `createSessionWithModel`.
77
95
 
78
96
  ## Running Tests
79
97
 
80
- Tests use Node.js built-in test runner (`node:test`) — zero additional dependencies.
98
+ Tests use the built-in `node:test` runner (no extra dependencies). Every
99
+ external interface is mocked, so the suite runs fully in-process and is safe to
100
+ run alongside a live OpenCode instance.
81
101
 
82
102
  ```bash
83
- # Run all tests
84
- npm test
85
-
86
- # Run a specific test file
87
- node --test tests/opencode.test.js
103
+ npm test # all suites
104
+ node --test tests/opencode.test.js # one file
88
105
  node --test tests/ocmux.test.js
89
-
90
- # Run with verbose output
91
- node --test tests/opencode.test.js | bunyan # or just grep for results
106
+ node --test tests/project-state.test.js
92
107
  ```
93
108
 
94
- All external interfaces are mocked — tests run entirely in-process without touching the network, tmux, or the filesystem. They are safe to run alongside a live OpenCode instance.
95
-
96
- ### Test Architecture
97
-
98
- Tests are structured in phases (see `AGENTS.md` for the full plan):
99
-
100
- | Phase | Module | Boundary Mocked |
101
- |-------|--------|----------------|
102
- | 1a | `lib/opencode.js` | `http.request` |
103
- | 1b | `lib/ocmux.js` | `child_process.spawnSync`, `child_process.execSync`, `fs.*` |
104
-
105
- Each test file uses `node:test`'s `mock` API in `before()`/`after()` hooks to install and tear down mocks. Tests within a describe block run serially (`concurrency: false`) when they share mocked state.
109
+ Mock boundaries are installed in `before()`/`after()` (opencode) or
110
+ `beforeEach()`/`afterEach()` (ocmux) hooks. Tests that share mocked state run
111
+ serially (`concurrency: false`).
106
112
 
107
113
  ### Adding Tests
108
114
 
109
- 1. Place new tests in `tests/<module>.test.js`
110
- 2. Use `describe`, `it`, `before`, `after` from `node:test`
111
- 3. Use `node:assert` for assertions
112
- 4. Mock all external boundaries (network, filesystem, subprocesses)
113
- 5. Run the full suite before submitting a PR
115
+ 1. Add them to the matching `tests/<module>.test.js`.
116
+ 2. Use `describe`/`it`/`before`/`after` from `node:test` and `node:assert`.
117
+ 3. Mock every external boundary.
118
+ 4. Run the full suite before opening a PR.
114
119
 
115
120
  ## Pull Request Process
116
121
 
117
- 1. **Fork the repo** and create a feature branch from `main`.
118
- 2. **Make your changes** following the coding standards above.
119
- 3. **Run `npm test`** and ensure all tests pass.
120
- 4. **Update documentation** if your change affects user-facing behavior:
121
- - Help text in `bin/tgagentp` (the `cmdHelp` function)
122
- - `docs/specification.md` for architecture changes
123
- - Command table in `devto-article.md` (if adding/changing a slash command)
124
- - `AGENTS.md` Done section (move items in/out as appropriate)
125
- 5. **Commit with a descriptive message** following the existing style (e.g., `fix: ...`, `feat: ...`, `refactor: ...`, `docs: ...`).
126
- 6. **Open a pull request** against `main`. Include a summary of the change and any testing instructions.
127
-
128
- ### Review Process
129
-
130
- - Maintainers review within a few business days
131
- - Focus areas: mock correctness, zero-dependency rule, architectural consistency
132
- - Large changes may be asked to split into smaller PRs
133
- - All PRs must pass the test suite before merging
122
+ 1. Fork the repo and branch from `main`.
123
+ 2. Follow the coding standards above.
124
+ 3. Run `npm test` — all suites must pass.
125
+ 4. Update documentation when user-facing behavior changes:
126
+ - `README.md` (usage/behavior),
127
+ - `docs/specification_v2.md` (architecture),
128
+ - `AGENTS.md` (test counts / non-obvious facts),
129
+ - `CHANGELOG.md` (with every release).
130
+ 5. Commit with a descriptive message (`fix:`, `feat:`, `refactor:`, `docs:` …).
131
+ 6. Open a PR against `main` with a summary and testing instructions.
134
132
 
135
133
  ## Getting Help
136
134
 
137
- - Open an issue on GitHub for bugs or feature requests
138
- - Tag questions with `question` label for general help
139
- - For OpenCode-specific questions, refer to [opencode.ai](https://opencode.ai)
135
+ - Open a GitHub issue for bugs or feature requests.
136
+ - For OpenCode-specific questions, refer to [opencode.ai](https://opencode.ai).
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
  This package provides three CLI tools:
9
9
 
10
10
  - **`agentp`** — pipes prompt text into a running OpenCode server and streams the assistant final answer back to stdout
11
- - **`ocmux`** — manages OpenCode server + TUI sessions in tmux (create, switch, kill, list)
11
+ - **`ocmux`** — manages project TUI windows in tmux on top of a single user-managed OpenCode server (session picker, project switcher, create/rename/delete/annotate sessions)
12
12
  - **`tgagentp`** — bridges a Telegram bot chat with all running OpenCode servers (receives messages from Telegram, routes them to the active server, sends answers back). Supports slash commands for multi-server management, session switching, agent/model listing, including file sharing from the chat.
13
13
 
14
14
  It is designed for prompt-driven workflows where you want to do things like:
@@ -41,14 +41,41 @@ npm link
41
41
  ## Requirements
42
42
 
43
43
  - Node.js 18+
44
- - An OpenCode server session listening locally (default port: `4096`)
44
+ - **OpenCode v2** (`opencode serve`) — the server is user-managed; these tools only check it is reachable and complain otherwise.
45
+ - [tmux](https://github.com/tmux/tmux) when using `ocmux` (project TUI windows).
45
46
 
46
- Notes:
47
+ ## Servers
48
+
49
+ The OpenCode server is **user-managed**: start it yourself (e.g. `opencode serve`).
50
+ `agentp` and `ocmux` only *check* that it is reachable and complain otherwise.
51
+
52
+ - Each project records the server it uses in `.ocmux.json` (`"server"`). If that
53
+ server is not reachable:
54
+ - `agentp` exits with `Error connecting to server: …`;
55
+ - `ocmux` exits with `OpenCode server not reachable at <url>.`
56
+ - **Point somewhere else for one command** (without touching any file):
57
+
58
+ ```bash
59
+ cat prompt.txt | agentp --server http://127.0.0.1:4097
60
+ # or the positional form:
61
+ cat prompt.txt | agentp http://127.0.0.1:4097
62
+ ```
47
63
 
48
- - `agentp` connects to the OpenCode event endpoint over HTTP.
49
- - In practice this means running `opencode serve` (or equivalent serve mode) so the port is open.
50
- - `opencode attach` (older OpenCode) / `opencode --server <url>` (OpenCode v2) is optional but useful to monitor the full conversation in another terminal/tmux pane. `ocmux` picks the right form automatically.
51
- - If the OpenCode server is password-protected (`OPENCODE_SERVER_PASSWORD`), both `agentp` and `ocmux` automatically send the required HTTP Basic Auth credentials.
64
+ - **Repoint an existing project** (e.g. the server moved to a new port/host) and
65
+ relaunch its TUI on the stored session:
66
+
67
+ ```bash
68
+ ocmux serve --server http://127.0.0.1:4097 --force
69
+ ```
70
+
71
+ Without `--force`, `ocmux serve` refuses when `.ocmux.json` already exists.
72
+
73
+ - **Remote or containerized servers** work too: pass any host reachable over
74
+ HTTP, e.g. a published Docker port (`--server http://192.168.1.50:4096`) or an
75
+ SSH tunnel. Auth uses `OPENCODE_SERVER_PASSWORD`/`OPENCODE_SERVER_USERNAME`.
76
+ The client speaks **HTTP only** (no `https://`). Note that `ocmux` launches the
77
+ *local* `opencode --server <url>` for the TUI, so use a local OpenCode version
78
+ compatible with the remote server.
52
79
 
53
80
  ## Usage
54
81
 
@@ -67,6 +94,7 @@ Options:
67
94
  - `--getLast <n>`: retrieve last n assistant answers from session history
68
95
  - `--session <name>`: target a specific session by name (exact or partial match)
69
96
  - `--new`: create a new session with the given title (requires `--session`)
97
+ - `--server <url>`: use this OpenCode server instead of the one in `.ocmux.json` (e.g. `http://host:4096`)
70
98
  - `--version`: show version
71
99
  - `--help`: show help message
72
100
 
@@ -82,8 +110,8 @@ With `--tg`, errors if tgagentp is unavailable.
82
110
 
83
111
  Arguments:
84
112
 
85
- - `url`: OpenCode TUI server URL or port number (defaults to `4096`). Examples: `4096`, `http://localhost:4096`, `http://192.168.1.50:4096`
86
- - Tip: `$(ocmux)` expands to the URL of the current project's server, so you can run `agentp $(ocmux)` from any shell.
113
+ - `url`: OpenCode server URL or port number (defaults to `4096`). Examples: `4096`, `http://localhost:4096`, `http://192.168.1.50:4096`
114
+ - Omit it and agentp resolves the project itself: the nearest `.ocmux.json` (upward from the working directory) supplies the server URL, the project directory, and the target session id. `agentp $(ocmux)` still works as an override, but is no longer needed.
87
115
 
88
116
  ## Examples
89
117
 
@@ -186,9 +214,11 @@ The ticket is `agentp_ticket` followed by a JSON object with these fields:
186
214
  - `ctime` — creation timestamp (ISO 8601). Only used to compute `elapsed`.
187
215
  - `path` — path to the temp file holding the result.
188
216
  - `server` — OpenCode server URL used by the deferred job.
189
- - `sessionId` — OpenCode session ID used by the deferred job.
217
+ - `sessionId` — OpenCode session ID used by a normal deferred job.
218
+ - `sessionIds` — array of OpenCode session IDs used by a **broadcast** deferred job (replaces `sessionId`).
190
219
  - `elapsed` — seconds since `ctime`, included only when the ticket is re-printed (not on first print).
191
220
  - `defer` — the timeout requested at submission, included only when it was > 0.
221
+ - `cancelled` — always present (defaults to `false`). Set it to `true` and pipe the ticket back to cancel the running job (see below).
192
222
 
193
223
  Tickets are printed as pretty-printed (multi-line) JSON for easier reading and
194
224
  editing; pass `--onlineTicket` to print them on a single line instead:
@@ -200,6 +230,13 @@ printf "Refactor the auth module" | agentp --defer --onlineTicket
200
230
 
201
231
  Both formats are accepted when piping a ticket back to `agentp --defer`.
202
232
 
233
+ When `ocmux` has a broadcast selection, `agentp --defer` creates a ticket with
234
+ `sessionIds` and sends the prompt to every selected session. On retrieval,
235
+ `--qa` includes the original prompt plus one `💬 <name> [<id>]` answer section
236
+ per session. Individual failures/incomplete sessions are listed with an error
237
+ and timestamp. Broadcast tickets do **not** support queued follow-up text (a
238
+ follow-up is inherently ambiguous across multiple sessions).
239
+
203
240
  You can also append follow-up text after a not-yet-ready ticket to queue more
204
241
  input into the original running task, similar to typing into the OpenCode TUI
205
242
  while the agent is busy:
@@ -233,6 +270,27 @@ the ticket's own `defer` value as the timeout (default `0`):
233
270
  - If the answer is ready, it is returned and the temp file is removed.
234
271
  - If not, the ticket is re-printed with the elapsed time updated.
235
272
 
273
+ Cancel a running deferred job by flipping `cancelled` to `true` and piping the
274
+ ticket back (the equivalent of pressing `ESC` in the TUI window):
275
+
276
+ ```bash
277
+ cat <<'EOF' | agentp --defer
278
+ agentp_ticket {
279
+ "ctime": "2026-08-03T14:30:00.000Z",
280
+ "path": "/tmp/agentp_deferred_...tmp",
281
+ "server": "http://localhost:4096",
282
+ "sessionId": "ses_abc123",
283
+ "cancelled": true
284
+ }
285
+ EOF
286
+ # 🚫 Prompt cancelled.
287
+ ```
288
+
289
+ `agentp` interrupts the session's execution (`POST /api/session/:id/interrupt`),
290
+ discards the ticket and its queued follow-ups, and prints
291
+ `🚫 Prompt cancelled` (with `(or already finished)` when there was nothing left
292
+ to interrupt).
293
+
236
294
  Works as a Vim/Neovim filter with deferred execution:
237
295
 
238
296
  ```vim
@@ -265,68 +323,109 @@ Useful to grab recent answers without sending a new prompt.
265
323
 
266
324
  ## ocmux
267
325
 
268
- Manage OpenCode server + TUI in tmux for project directories.
326
+ Manage **project TUI windows** in tmux on top of a single user-managed OpenCode
327
+ server. A project is a directory holding a `.ocmux.json` state file recording
328
+ the target session; an `Opencode` tmux session holds one window per project
329
+ (TUI only, pane 0).
269
330
 
270
331
  ```bash
271
332
  ocmux [-l] [<subcommand>] [<directory>]
272
333
  ```
273
334
 
274
- Without arguments, searches upward from `<directory>` (default: `$PWD`) for `.ocmux.json` and switches to that server's tmux window.
335
+ Without arguments (and with a TTY), opens an **interactive session picker** for
336
+ the project found upward from `<directory>` (default: `$PWD`):
337
+
338
+ - sessions are listed most-recently-viewed first
339
+ - `/` starts an **incremental search** of the list (matches title/id,
340
+ case-insensitive, space-separated tokens are ANDed). While the search line is
341
+ active it shows `Enter: confirm · Esc: cancel` on the right: `Enter` keeps the
342
+ filter and returns to normal navigation, `ESC` clears it, `/` resumes editing
343
+ it, and `Backspace` on an already-empty search also exits it. The same `/`
344
+ search works in the model/agent pickers and the project switcher.
345
+ - `Enter` switches (menu stays open). `Space` over a different session enters
346
+ **broadcast mode**: Space selects/deselects sessions; `Enter` keeps the list
347
+ and switches normally; `ESC`/`q` cancels back to the session list and returns
348
+ the TUI to the stored session; deselecting down to a single session selects
349
+ that remaining session. New selections open in the TUI for inspection.
350
+ Broadcast mode also has `h` help, `d` delete, and `m` to change the model for
351
+ every selected session.
352
+ - `n` create (name input) · `r` rename (edit in place) · `R` set a reminder ·
353
+ `d` delete (confirm) · `a` switch agent · `m` switch model · `p` project
354
+ switcher · `h` help · `q` quit
355
+ - **`q` only quits the session picker.** In every other menu (model/agent
356
+ pickers, project switcher, help/input prompts) `q`/`ESC` just closes that menu
357
+ and returns to the previous one. **`Ctrl+C` fully exits** `ocmux` from any menu.
358
+ - switching updates `.ocmux.json` and relaunches the TUI on the chosen session
359
+ (`opencode --server <url> --session <id>`); silent on success
360
+ - new sessions inherit the model of the previously selected session (v2
361
+ sessions created via the API have no model and won't run a prompt until set)
362
+
363
+ Reminders (`R`) are stored in the `.ocmux.json` `annotations` map; `agentp`
364
+ prepends a session's reminder to every prompt sent to it.
365
+
366
+ Broadcast selections are stored in `.ocmux.json` as `broadcast`. `agentp`
367
+ sends a prompt to all selected sessions (waiting for busy sessions to go idle),
368
+ and prints a labeled answer section for each. Errors/incomplete targets are
369
+ reported individually with session name, id, error, and timestamp.
275
370
 
276
371
  Subcommands:
277
372
 
278
- - **`serve [--git|--GIT] [--print-logs] [dir]`** — Create a server in `dir` (default: `$PWD`) and attach a TUI pane. Aliased as `new` for backwards compatibility (to be removed in 1.0). Errors if one already exists there. Warns if a parent directory already has a server.
279
- - `--git` resolves `dir` to the nearest parent with a `.git` entry (file or dir); errors if none is found.
280
- - `--GIT` resolves `dir` to the nearest parent with a `.git` directory only; errors if none is found.
281
- - `--print-logs` passes `--print-logs` to `opencode serve`, which prints server logs to stderr in the server tmux pane.
282
- - **`kill [dir]`** — Kill the server found upward from `dir`. Removes its tmux window and state file.
283
- - **`resurrect [--print-logs] [dir]`** — Recover a dead/crashed server: reads `.ocmux.json`, kills old tmux window, removes state file, then creates a fresh server + TUI in the same directory. Works even if no tmux window exists (stale state file).
284
- - **`model [ref]`** — Switch the model of the newest session on the current project's server. With no `ref`, shows an interactive model picker (TTY required). With `ref`, switches directly and prints the server URL on stdout so `agentp $(ocmux model <ref>)` composes: the switch (a side effect) takes effect before agentp sends the next prompt. `ref` supports partial matches when unique (`ocmux model deepseek`, `opencode-go/deepseek`, `...#high`); multiple matches open the picker (or error when not a TTY).
285
- - **`switch`** — Interactive session picker: an interactive menu of all running servers (columns: dirname, status, url, full path). Arrow keys or `j`/`k` move the selection; `Enter`/`Space` switches to the selected server's tmux window (the menu stays open, so you can hop between servers); `q` or `Ctrl+C` exits. The currently active server (queried live from tmux on every redraw) is highlighted across the full line width. Prints the URL of the last selected server on exit. Requires a TTY.
286
- - **`list`** — List all running servers with their directories, URLs, and status.
287
-
288
- Options:
289
-
290
- - `-l`: long output for default/serve commands (append `→ <dir>` after the URL)
291
- - `--version`: show version
292
- - `-h`: show help message
293
- - `--`: treat the next argument as a directory even if it matches a subcommand name
373
+ - **`serve [--server <url>] [--git|--GIT] [dir]`** — create a project TUI window
374
+ (checks the server is reachable first). Aliased as `new` for backwards
375
+ compatibility. `--git`/`--GIT` resolve `dir` to the nearest parent with a
376
+ `.git` entry / directory.
377
+ - **`session <id|title> [dir]`** — non-interactive session switch.
378
+ - **`list [-l]`** — list project windows (with `-l`, their server URL).
379
+ - **`model [ref]`** — switch the model of the selected session.
380
+ - **`kill [dir]`** — close the project's TUI window. **Keeps `.ocmux.json`**
381
+ (session memory; marks it `stopped`).
382
+ - **`resurrect [dir]`** — recreate the project window from its state file.
383
+ - **`migrate`** — rewrite legacy (v1-style) `.ocmux.json` files to the v2 schema.
384
+
385
+ The old `switch` subcommand is gone: press **`p`** inside the session picker to
386
+ open the (read-only) project switcher instead. `ocmux` never starts or stops the
387
+ OpenCode server — run `opencode serve` yourself (see [Versioning](#versioning)
388
+ for the pairing policy).
389
+
390
+ Options: `-l` · `--version` · `-h` · `--` (treat the next argument as a directory).
294
391
 
295
392
  Notes:
296
393
 
297
- - If `<directory>` is not a valid path, `ocmux` tries to match it against the basenames of existing sessions (exact unique match).
298
- - When using `--git`/`--GIT`, `ocmux` refuses to create a new server above an existing `.ocmux.json` found while searching for the git root.
299
- - In default mode, if no server is found, the primary error line is printed to stdout. This intentionally makes `agentp $(ocmux)` fail instead of silently falling back to `agentp`'s default `localhost:4096` server.
300
-
301
- ### Requirements
302
-
303
- - Node.js 18+
304
- - [tmux](https://github.com/tmux/tmux) — session multiplexer
305
- - `opencode` binary in PATH (the OpenCode CLI)
394
+ - If `<directory>` is not a valid path, `ocmux` matches it against the basenames
395
+ of existing project windows (exact unique match).
396
+ - If the server is password-protected (`OPENCODE_SERVER_PASSWORD`), both
397
+ `agentp` and `ocmux` send the required HTTP Basic Auth credentials.
306
398
 
307
399
  ### State file
308
400
 
309
- `ocmux` stores per-project state in `.ocmux.json` (contains URL, log path, window index). It searches upward from the target directory, similar to git.
401
+ `.ocmux.json` (in the project directory) stores `version`, `directory`,
402
+ `session`, and `server`. It is found by searching upward, like git. It is
403
+ gitignored — never commit it.
310
404
 
311
405
  ## How agentp Works
312
406
 
313
407
  1. Reads all stdin into a single prompt string.
314
- 2. Finds the most recently updated session, or creates one named `agentp`.
315
- 3. Sends the prompt via the session API (`POST /session/:id/message`).
316
- 4. Prints the assistant answer to stdout.
317
- 5. With `--tg` (or by default when `--qa` is given), forwards the answer to Telegram
318
- via the agentp gateway. The answer appears in your Telegram chat as if tgagentp
319
- itself had processed the request.
320
- 6. If tgagentp's [/record](#tgagentp) feature was active, the gateway response includes
321
- the recorded conversation buffer. In `--qa` mode, agentp prepends this buffer (with
322
- rulers) to its stdout so OpenCode receives the full Telegram context. Use `--flush`
323
- to clear the buffer without prepending.
324
-
325
- The session API ensures the request is processed even when no TUI is attached, and returns the full answer in a single HTTP response.
408
+ 2. Resolves the target from the nearest `.ocmux.json`: server URL, project
409
+ directory, and the stored session id (falls back to the most recently viewed
410
+ session in that directory, or creates one pinned to the directory).
411
+ 3. Focuses the project's TUI window, prepends the session annotation (if any),
412
+ and sends the prompt via the v2 session API (`POST /api/session/:id/prompt`,
413
+ delivering to that session regardless of what the TUI shows).
414
+ 4. Attaches to the SSE stream first so no events are missed, and streams text
415
+ until the session is quiescent after its terminal signal.
416
+ 5. Prints the assistant answer to stdout (with `--qa`, a header with the project
417
+ path and session id/title before the prompt/answer rulers).
418
+ 6. With `--tg` (or by default when `--qa` is given), forwards the answer to
419
+ Telegram via the agentp gateway. If tgagentp's [/record](#tgagentp) feature
420
+ was active, the gateway response includes the recorded conversation buffer,
421
+ which `--qa` prepends to stdout (use `--flush` to clear it).
326
422
 
327
423
  Operational hint:
328
424
 
329
- - You can keep a separate TUI view open to see the full run context while `agentp` is used from shell scripts or editor buffers: `opencode --server '<url>' --continue` on OpenCode v2, or `opencode attach --continue '<url>'` on older versions (`ocmux` uses the right one automatically).
425
+ - You can keep a separate TUI view open to see the full run context while
426
+ `agentp` is used from shell scripts or editor buffers:
427
+ `opencode --server '<url>' --session '<id>'` (or `--continue` for the last
428
+ session). `ocmux` manages these windows per project.
330
429
 
331
430
  ## tgagentp
332
431
 
@@ -447,6 +546,21 @@ Chat-to-server directory mappings are saved to `/tmp/tgagentp-connections.json`
447
546
  | `TGAGENTP_DEBOUNCE_MS` | Optional. Debounce interval for queued-message notifications (default: `5000`). |
448
547
  | `TGAGENTP_ROOT` | Optional. Root directory for `/serve` and `/new` commands (must be writable). |
449
548
 
549
+ ## Versioning
550
+
551
+ The 1.x line was born with some internal inconsistency: early releases bumped
552
+ middle digits for small fixes, and `agentp`/`ocmux` were versioned independently
553
+ of the OpenCode they talked to. `2.0.0` marks a cleanup of that history — and a
554
+ single policy from now on:
555
+
556
+ > **agentp/ocmux/tgagentp share one version, and its major number is paired with
557
+ > the OpenCode major version they target.** OpenCode 2.x ⇒ this project lands in
558
+ > 2.x; if OpenCode ever ships a 3.0, a 3.x here targets it (the minor tracks
559
+ > features, the patch tracks fixes).
560
+
561
+ OpenCode v1 support was dropped in 2.0.0; the HTTP client (`lib/opencode.js`)
562
+ is v2-only and the tools assume `opencode serve` is user-managed.
563
+
450
564
  ## License
451
565
 
452
566
  MIT