cofluxd 0.14.0 → 1.0.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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: coflux
3
- description: When you run inside a coflux terminal, this skill documents the local cofluxd commands that open terminals the user can watch and take over from the coflux web/mobile app, report progress, call the user and hand out preview URLs, plus the center MCP for reaching other workspaces and devices. Your coordinates (device / project / workspace / terminal) arrive in a <coflux-session> block at session start, or via the COFLUX_* environment variables. Inside your own workspace always use the zero-credential local cofluxd commands (open, read, wait, send, report progress, call the user, get preview URLs); use the center's coflux MCP only to leave this workspace (child workspaces, other workspaces or devices). Use when the user should be able to watch, step into or stop a command (interactive steps, dev servers, a job they are waiting on), when the user has to decide something, when you want to hand the user a clickable preview URL, or when you need an isolated child workspace for parallel work.
3
+ description: Use coflux to open visible terminals, read, wait, type, report progress, notify the user and obtain preview URLs. Prefer zero-credential local commands in the current workspace; use the account CLI across workspaces and devices. Coordinates arrive through coflux-session or COFLUX_* variables.
4
4
  ---
5
5
 
6
6
  # Working inside coflux
@@ -10,13 +10,12 @@ machines from a browser or a phone and take over at any time. This skill gives y
10
10
  user can see and take over, a progress line and a call button on the workspace card, preview URLs,
11
11
  and a way to operate the other workspaces and devices under the account when you need to.
12
12
 
13
- Two tracks, one rule: **whatever closes locally uses local commands; only leaving this
14
- workspace goes through MCP.**
13
+ **Use local commands in this workspace and account CLI commands across workspaces and devices.**
15
14
 
16
15
  | Track | Credentials | Reach | Use for |
17
16
  |---|---|---|---|
18
- | Local commands `cofluxd terminal/progress/notify/ports` | none (the daemon identifies you by process tree) | **the workspace you are in** | open, read, wait, send, report progress, call the user, preview URLs: the default, fastest, no network dependency |
19
- | Center MCP `coflux` | one OAuth authorization by the user in the host | **the whole account**: every device, project, workspace and terminal | child workspaces (git worktrees), cross-workspace / cross-device access, joining from outside coflux |
17
+ | Local commands `coflux terminal/progress/notify/ports` | none (the daemon identifies you by process tree) | **the workspace your cwd is in** | open, read, wait, send, report progress, call the user, preview URLs: the default, fastest, no network dependency |
18
+ | Account CLI | app login or `coflux login` | all devices and workspaces in the account | child workspaces and remote terminals; JSON output |
20
19
 
21
20
  Of the local commands, `send`/`read`/`wait`/`notify`/`progress` complete entirely inside the
22
21
  local daemon and never touch the center; `new`/`list`/`ports` are relayed to the center by the
@@ -36,22 +35,86 @@ env | grep '^COFLUX_'
36
35
 
37
36
  - **`COFLUX_WORKSPACE_ID` is non-empty** (or the `<coflux-session>` block is present) → you are in
38
37
  a coflux terminal with an up-to-date daemon. The variables below are your coordinates; pass
39
- these ids to MCP tools directly instead of guessing from `list_*`:
38
+ these ids to account CLI commands directly instead of guessing from `list_*`:
40
39
 
41
40
  | Variable | Meaning |
42
41
  |---|---|
43
42
  | `COFLUX_DEVICE_ID` | id of the device you run on (the id in `list_devices`) |
44
43
  | `COFLUX_PROJECT_ID` | owning project id; empty string for a directory workspace without a repository |
45
- | `COFLUX_WORKSPACE_ID` | owning workspace id (the id in `list_workspaces`) |
44
+ | `COFLUX_WORKSPACE_ID` | the workspace this terminal was **opened** in (the id in `list_workspaces`). The variable is frozen when the terminal starts; the workspace the terminal *belongs to* can still change — see below. `coflux workspace` is the authority |
46
45
  | `COFLUX_TASK_ID` | id of this terminal (the taskId / terminalId used by local commands and `read_terminal`) |
47
46
  | `COFLUX_SESSION_ID` | id of this PTY session |
48
- | `COFLUX_MCP_URL` | the center's MCP URL; the user configures MCP with it |
49
47
 
50
- - **Variables empty or absent** → treat yourself as outside coflux: forget this skill and use your
51
- own tools as usual (if the user configured the coflux MCP in the host, the MCP tools still work;
52
- you just have no "where am I" coordinates). If the user insists you are inside a coflux terminal,
53
- this machine's daemon has not been upgraded: tell the user to run `cofluxd update && cofluxd restart`;
54
- after reopening the terminal the variables and the local commands are there.
48
+ - **Variables empty or absent**: there is no local terminal context. Use `coflux whoami` to check
49
+ account access and the account CLI to discover workspaces. Ask the user to log in when needed;
50
+ never fabricate COFLUX_* coordinates.
51
+
52
+ ### Two workspaces to keep apart: owning and effective
53
+
54
+ - **Owning workspace** = the workspace this terminal **belongs to**: what the user's sidebar shows it
55
+ under, what its turn state, branch and diff stats are attributed to. It starts out as
56
+ `COFLUX_WORKSPACE_ID` and moves with you when you enter or leave a git worktree (below).
57
+ - **Effective workspace** = the workspace **your current working directory is inside**. This is what
58
+ every local command acts on.
59
+
60
+ They are the same until your cwd wanders off. A plain `cd <path>` moves a *live* session — same
61
+ conversation, no restart — and a coflux child workspace is a normal registered git worktree, so a
62
+ session whose terminal belongs to workspace A can end up working inside workspace B. From that
63
+ moment, in B:
64
+
65
+ - `coflux terminal new` opens the terminal **in B**, under B in the user's sidebar, running in B's
66
+ directory, counting against B's terminal cap;
67
+ - `coflux terminal list` lists B's terminals, and A's terminals answer `read` / `wait` / `send`
68
+ with "not in this workspace or does not exist" (`cd` back to A to reach them again);
69
+ - Account CLI calls need **B's** id as `workspaceId`;
70
+ - the terminal itself stays under A, and `progress`, `notify` and `ports` still belong to it,
71
+ whatever your cwd is; `COFLUX_TASK_ID` and `COFLUX_SESSION_ID` never change.
72
+
73
+ If your cwd is outside every coflux workspace (say `/tmp`), local commands fall back to the owning
74
+ workspace.
75
+
76
+ A terminal opened before the daemon was upgraded is the one case with no owning workspace at all:
77
+ its local commands are refused with "predates the daemon upgrade" whatever your cwd is, because the
78
+ daemon never guesses ownership from a directory. Open a new terminal.
79
+
80
+ ### coflux follows you into a git worktree
81
+
82
+ `EnterWorktree` switches this live session into a git worktree (its own, or an existing one you point
83
+ it at), `ExitWorktree` switches back, and resuming a session that had entered one puts you straight
84
+ back in it. **coflux comes along**: the terminal's *owning* workspace moves to the workspace that
85
+ worktree is, and if coflux has never seen that worktree it registers it as a child workspace of this
86
+ project first — a new card appears in the user's sidebar, with its branch and diff stats. Nothing is
87
+ interrupted: same terminal, same PTY, same conversation, and the user keeps watching it where it now
88
+ lives. When Claude Code cleans up its own worktree on exit, that workspace's terminals move back to
89
+ the project's main workspace and the record disappears by itself.
90
+
91
+ So, after entering or leaving a worktree, owning **and** effective are both the new workspace: pass
92
+ its id to account CLI commands and everything local already acts on it. The plugin drops the new id next to the
93
+ tool result, and `coflux workspace` always tells you. Two things stay behind on purpose:
94
+
95
+ - `COFLUX_WORKSPACE_ID` (and the id in the `<coflux-session>` block from earlier in this session)
96
+ still names where the terminal was *opened*; it is frozen when the PTY starts and cannot be
97
+ rewritten. Never reuse it after a move.
98
+ - The shell inside this terminal keeps its own directory. That is only about the shell; it does not
99
+ affect where your work is attributed.
100
+
101
+ Nothing happens when coflux cannot follow, and nothing is blocked either: another repository, a
102
+ directory that is not a git repository, a terminal opened in a directory workspace (no project), or
103
+ a daemon that is down or too old — the session just carries on with the ownership it had.
104
+
105
+ ### Ask where you are
106
+
107
+ ```sh
108
+ coflux workspace
109
+ {"workspaceId":"ws-b","path":"/Users/me/.coflux/worktrees/ws-b","owningWorkspaceId":"ws-a","moved":true}
110
+ ```
111
+
112
+ One line of JSON: `workspaceId` (+ `path`) is the **effective** workspace, `owningWorkspaceId` is the
113
+ workspace this terminal belongs to right now, and `moved` says whether they differ. With the plugin
114
+ installed you also get a `<coflux-session-moved>` block at the start of every prompt while the two
115
+ differ — but that block only arrives with the **next** user prompt. **About to call an account command right
116
+ after a `cd`? Run `coflux workspace` first** and use the `workspaceId` it prints; do not reuse
117
+ `COFLUX_WORKSPACE_ID`.
55
118
 
56
119
  ## When to open a terminal
57
120
 
@@ -76,12 +139,13 @@ own tools are faster, and a pile of one-second terminals is just noise to the us
76
139
  There are two kinds, told apart by one single thing: **whether you pass a command**.
77
140
 
78
141
  ```sh
79
- cofluxd terminal new --title="Run unit tests" --cmd="pnpm -C tests test" # job terminal
80
- cofluxd terminal new --title="Debug shell" # session terminal
142
+ coflux terminal new --title="Run unit tests" --cmd="pnpm -C tests test" # job terminal
143
+ coflux terminal new --title="Debug shell" # session terminal
81
144
  ```
82
145
 
83
146
  `--title` is the name the user sees in the sidebar; **name it properly**: "Run unit tests",
84
- "Start dev server", never "terminal 1". Either kind runs in the current workspace directory.
147
+ "Start dev server", never "terminal 1". Either kind runs in the directory of the workspace your cwd
148
+ is in (which is not always the one this terminal was opened in — see "owning and effective").
85
149
 
86
150
  Always write `--cmd=<value>` and `--title=<value>` with the `=`, never separated by a space: a
87
151
  value that starts with `-` is otherwise taken for another option and the call fails outright.
@@ -105,14 +169,14 @@ from what is on screen, and `wait` is only meaningful after you have sent `exit`
105
169
 
106
170
  Driving a session terminal:
107
171
 
108
- 1. `cofluxd terminal new --title="Debug shell"` → prints a taskId.
109
- 2. `cofluxd terminal read <taskId>` until you see the shell prompt. The shell needs a moment to
172
+ 1. `coflux terminal new --title="Debug shell"` → prints a taskId.
173
+ 2. `coflux terminal read <taskId>` until you see the shell prompt. The shell needs a moment to
110
174
  start and the first read can come back empty — **never `send` before you have seen a prompt**.
111
- 3. `cofluxd terminal send <taskId> --text="pnpm build" --enter`, then `read` again to see what
175
+ 3. `coflux terminal send <taskId> --text="pnpm build" --enter`, then `read` again to see what
112
176
  happened. One send per command; nothing signals you when a command finished, so read until the
113
177
  prompt is back. To make that unambiguous, end the command with a marker of your own
114
178
  (`pnpm build; echo DONE-$?`) and read until the marker shows up.
115
- 4. `cofluxd terminal send <taskId> --text="exit" --enter` when you are done; the terminal then
179
+ 4. `coflux terminal send <taskId> --text="exit" --enter` when you are done; the terminal then
116
180
  becomes `exited` with the shell's exit code.
117
181
 
118
182
  The new terminal has the same `COFLUX_*` variables (pointing at its own task/session ids, same
@@ -121,9 +185,9 @@ workspace as you).
121
185
  ### See how far it got
122
186
 
123
187
  ```sh
124
- cofluxd terminal list # every terminal in this workspace: id, state, exit code, title
125
- cofluxd terminal read <taskId> # a terminal's content (plain text, last 200 lines by default)
126
- cofluxd terminal read <taskId> --lines 50
188
+ coflux terminal list # every terminal in the workspace your cwd is in: id, state, exit code, title
189
+ coflux terminal read <taskId> # a terminal's content (plain text, last 200 lines by default)
190
+ coflux terminal read <taskId> --lines 50
127
191
  ```
128
192
 
129
193
  `list` states are `running` / `exited` / `idle`; `exited` carries `exit=<code>`.
@@ -135,8 +199,8 @@ history, and empty for the first moments after opening. Both are immediate.
135
199
  ### Wait for a command to finish
136
200
 
137
201
  ```sh
138
- cofluxd terminal wait <taskId> # block until that terminal exits and print the exit code (default cap 30 minutes)
139
- cofluxd terminal wait <taskId> --timeout 300 # custom timeout in seconds; a timeout fails loudly with a non-zero exit
202
+ coflux terminal wait <taskId> # block until that terminal exits and print the exit code (default cap 30 minutes)
203
+ coflux terminal wait <taskId> --timeout 300 # custom timeout in seconds; a timeout fails loudly with a non-zero exit
140
204
  ```
141
205
 
142
206
  To wait for a command use `wait`; **do not write your own polling loop**. One command blocks
@@ -155,10 +219,10 @@ not any command's: check what a command did by reading the screen.
155
219
  **Keep working, and be woken up when it finishes.** `wait` blocks, so run it as a backgrounded Bash
156
220
  call of your own:
157
221
 
158
- 1. `cofluxd terminal new --title="Run the test suite" --cmd="pnpm -C tests test"` → prints a taskId.
159
- 2. Run `cofluxd terminal wait <taskId>` as a backgrounded Bash call, then go do something else.
222
+ 1. `coflux terminal new --title="Run the test suite" --cmd="pnpm -C tests test"` → prints a taskId.
223
+ 2. Run `coflux terminal wait <taskId>` as a backgrounded Bash call, then go do something else.
160
224
  3. The host wakes you when that call exits. Check its output for `# exited exit=<code>`, then
161
- `cofluxd terminal read <taskId>` to see what actually happened.
225
+ `coflux terminal read <taskId>` to see what actually happened.
162
226
 
163
227
  That gets you both halves at once: the user watches (and can take over) a real terminal, and you are
164
228
  still told the moment it is over, instead of blocking or polling for it.
@@ -166,8 +230,8 @@ still told the moment it is over, instead of blocking or polling for it.
166
230
  ### Type into a terminal
167
231
 
168
232
  ```sh
169
- cofluxd terminal send <taskId> --text "y" --enter # type a line and press Enter
170
- cofluxd terminal send <taskId> --enter # just press Enter
233
+ coflux terminal send <taskId> --text "y" --enter # type a line and press Enter
234
+ coflux terminal send <taskId> --enter # just press Enter
171
235
  ```
172
236
 
173
237
  For interactive confirmations (y/N, menus), or to add a command in the same shell after the
@@ -184,7 +248,7 @@ previous one finished. Discipline:
184
248
  ### Report progress
185
249
 
186
250
  ```sh
187
- cofluxd progress "Reproduced; narrowing down the relay reconnect timing"
251
+ coflux progress "Reproduced; narrowing down the relay reconnect timing"
188
252
  ```
189
253
 
190
254
  One sentence telling the user how far you are, shown on the workspace card and replaced by the
@@ -199,7 +263,7 @@ If unsure: when the user does not have to do anything, use `progress`.
199
263
  ### Call the user
200
264
 
201
265
  ```sh
202
- cofluxd notify "Both approaches work; I need you to pick one"
266
+ coflux notify "Both approaches work; I need you to pick one"
203
267
  ```
204
268
 
205
269
  The user's sidebar switches this workspace to "waiting for interaction" and shows this sentence;
@@ -213,7 +277,7 @@ extra notify. This is for "what you have to say cannot be guessed from the statu
213
277
  ### Hand the user a clickable preview
214
278
 
215
279
  ```sh
216
- cofluxd ports
280
+ coflux ports
217
281
  ```
218
282
 
219
283
  Lists every listening port in this workspace with its public preview URL. After starting a dev
@@ -223,72 +287,56 @@ server, use it to get the URL and tell the user directly; they click it and nobo
223
287
 
224
288
  Errors are one readable sentence; do what they say: "not inside a coflux terminal" = you are not
225
289
  in a coflux session; "terminal is not in this workspace or does not exist" = check the id with
226
- `list`; "predates the daemon upgrade" = that terminal was opened before the daemon upgrade, open a
227
- new one; a `new` without `--cmd` refused for a missing command = this machine's daemon is older
290
+ `list`, and if you moved into another workspace that is exactly what a terminal of the other one
291
+ looks like (`coflux workspace` to confirm, `cd` back to reach it); "predates the daemon upgrade" =
292
+ that terminal was opened before the daemon upgrade, open a new one; a `new` without `--cmd` refused for a missing command = this machine's daemon is older
228
293
  than session terminals, tell the user to run `cofluxd update && cofluxd restart` (or pass a command
229
294
  and use a job terminal); "daemon is not connected to the center" only appears on
230
295
  `new`/`list`/`ports`, retry once it reconnects.
231
296
 
232
- ## Center MCP: leaving this workspace
233
-
234
- Local commands only see the workspace you are in. Use the MCP server named `coflux` in the host
235
- **only** for these:
236
-
237
- - **Open an isolated child workspace to work in parallel**: `create_workspace` (project id from
238
- `$COFLUX_PROJECT_ID`) really runs `git worktree add` on the device; then `create_terminal` runs
239
- commands there. The same two kinds apply: `create_terminal` with a `command` opens a
240
- job terminal, without one it opens a session terminal.
241
- - **Look at or operate terminals in other workspaces or on other devices**: `list_*` →
242
- `read_terminal` / `send_terminal_input`.
243
- - **Join everything under the account when you are not inside a coflux terminal** (for example
244
- Claude Code the user started on their own machine).
245
- - **Never run `git worktree add` yourself**: inside a coflux project the plugin blocks
246
- `git worktree add|remove|move` and points you to `create_workspace` / `remove_workspace`; a
247
- worktree you create is invisible to the user and cannot host a terminal.
297
+ ## Account CLI: across workspaces and devices
248
298
 
249
- Do not detour through MCP for work inside this workspace: that is an extra round trip to the
250
- center, while a local command does it in one step.
251
-
252
- ### When MCP is not configured
253
-
254
- Run `claude mcp list` (Codex: `codex mcp list`) to see whether `coflux` is there. If not, give
255
- the user the one-line setup, with the URL from `$COFLUX_MCP_URL` (it is the center's public URL
256
- + `/mcp`):
299
+ The bundled CLI can use the desktop app's login without receiving its token. For a standalone CLI,
300
+ use `coflux login --username <account> --password-stdin`; the user supplies the password safely,
301
+ never as a command argument. Account commands return JSON. A workspace ID identifies its device.
257
302
 
258
303
  ```sh
259
- claude mcp add --transport http coflux "$COFLUX_MCP_URL" # Claude Code
260
- codex mcp add coflux --url "$COFLUX_MCP_URL" # Codex
304
+ coflux device list
305
+ coflux project list --device <deviceId>
306
+ coflux workspace list --device <deviceId>
307
+ coflux workspace new --project <projectId> --branch <branch>
308
+ coflux terminal new --workspace <workspaceId> --title <title> [--cmd <command>]
309
+ coflux terminal list --workspace <workspaceId>
310
+ coflux terminal read <terminalId> --remote
311
+ coflux terminal send <terminalId> --remote --text <text> [--enter]
312
+ coflux terminal wait <terminalId> --remote --timeout 30
313
+ coflux terminal stop <terminalId> --remote
314
+ coflux terminal remove <terminalId> --remote
315
+ coflux workspace rename <workspaceId> --name <name>
316
+ coflux workspace remove <workspaceId>
317
+ coflux ports --remote --device <deviceId>
261
318
  ```
262
319
 
263
- The host then guides the user through a one-time OAuth authorization in the browser (`/mcp` in
264
- Claude Code). Authorization is the user's job; you only hand over the URL and the command. Until
265
- it is set up, keep doing the work inside this workspace with local commands.
266
-
267
- ### Using the tools
268
-
269
- The tool list and each tool's contract (parameters, limits, what an error means) come from the
270
- MCP server itself: read the tool descriptions in the host, they are the source of truth and this
271
- file does not repeat them. Take ids from the `COFLUX_*` variables first; for anything outside this
272
- workspace, find ids with the `list_*` tools.
273
-
274
- The local-command disciplines apply to MCP just the same: `read_terminal` before
275
- `send_terminal_input`, stop when refused because the user is taking over (communicate with
276
- `cofluxd notify` instead of retrying), `wait_terminal` instead of a polling loop around
277
- `read_terminal`, and stop on "needs upgrade" (tell the user to run
278
- `cofluxd update && cofluxd restart` on that device; do not retry or work around it).
320
+ `--remote` selects account access, including other workspaces on this machine. Read before sending;
321
+ stop immediately when the user takes over. If a write times out, inspect the result before retrying.
322
+ Exiting the CLI does not stop its terminals. Delete workspaces through `coflux workspace remove`
323
+ so the filesystem and workspace records stay consistent.
279
324
 
280
325
  ## Boundaries
281
326
 
282
327
  - You can open, read, wait and type, but **typing is a restricted write with humans first**: you
283
328
  cannot write into a terminal the user is taking over (you are refused explicitly), and the user
284
329
  taking over at any time displaces you. Do not fight a human for a terminal.
285
- - Local commands only see **the workspace you are in**; other workspaces and other machines go
286
- through MCP and are limited to the same account.
330
+ - Local commands only see **the workspace your cwd is in** (`coflux workspace` says which one);
331
+ use the account CLI for other workspaces and machines in the same account.
287
332
  - A workspace has a cap on concurrently live terminals (default 8, including the user's own).
288
333
  On hitting the cap, `list` first: usually some finished terminals were never collected. If the
289
334
  user really filled it up, `notify` them instead of forcing it.
290
- - `new`/`list`/`ports` and every MCP tool need the daemon connected to the center; "letting the
335
+ - `new`/`list`/`ports` and account commands need the daemon connected to the center; "letting the
291
336
  user see" is their whole point. `send`/`read`/`wait`/`notify`/`progress` do not depend on the
292
337
  center. When disconnected they fail loudly rather than degrade silently.
293
338
  - `COFLUX_*` variables exist only in PTYs opened by coflux; exporting or changing them yourself
294
- has no effect, the center only trusts the ids it issued.
339
+ has no effect, the center only trusts the ids it issued. `COFLUX_WORKSPACE_ID` always means the
340
+ workspace this terminal was **opened** in and goes stale the moment coflux follows you into a
341
+ worktree; both "where does this terminal belong now" and "where am I acting" come from
342
+ `coflux workspace`.