@cabane/companion 0.6.184 → 0.6.186
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -52
- package/dist/cli.js +833 -3274
- package/dist/launch.js +11 -60
- package/dist/pairing-config.js +51 -62
- package/dist/runtime.js +750 -5284
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -14,19 +14,18 @@ Three things, one relation each.
|
|
|
14
14
|
- **A harness** is a coding tool on the device with a login behind it. The Companion detects each one and reports its state: connected, needs sign-in, limited, problem, off or gone. A device offers exactly the harnesses it has.
|
|
15
15
|
- **An agent** is assigned to one device and runs through one of that device's harnesses, with a model from it. Assign in as many workspaces as you like: one Companion serves them all.
|
|
16
16
|
|
|
17
|
-
**Cabane decides what an agent is; the device decides what it can touch.** Everything about the agent lives on its page in Cabane and is delivered with each turn, so an edit there lands on the next reply with no restart: its charter, its harness and model, its MCP servers, its host access and its starting folder. The device holds only what can't travel from a server: the device token, your secrets,
|
|
17
|
+
**Cabane decides what an agent is; the device decides what it can touch.** Everything about the agent lives on its page in Cabane and is delivered with each turn, so an edit there lands on the next reply with no restart: its charter, its harness and model, its MCP servers, its host access and its starting folder. The device holds only what can't travel from a server: the device token, your secrets, and local overrides for this device.
|
|
18
18
|
|
|
19
19
|
How a turn runs, top to bottom:
|
|
20
20
|
|
|
21
|
-
| Layer | Holds
|
|
22
|
-
| ------------- |
|
|
23
|
-
| **Cabane** | The agent's reach: **host access** off (workspace only, the default) or on (shell and files on the device, starting in a folder). Only the agent's owner changes it. A conversation can't widen it.
|
|
24
|
-
| **Companion** | The listener on the device. Holds the pairing and the harness logins
|
|
25
|
-
| **Runner** | A child process per turn with a one-turn credential
|
|
26
|
-
| **
|
|
27
|
-
| **Harness** | Claude Code, Codex or OpenCode with its normal tools. Nothing is removed by name; the sandbox is enforced by the operating system around the process, never by a list of tool names. Nothing asks for permission mid-task. |
|
|
21
|
+
| Layer | Holds |
|
|
22
|
+
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
23
|
+
| **Cabane** | The agent's reach: **host access** off (workspace only, the default) or on (shell and files on the device, starting in a folder). Only the agent's owner changes it. A conversation can't widen it. |
|
|
24
|
+
| **Companion** | The listener on the device. Holds the pairing and the harness logins, and runs as you. |
|
|
25
|
+
| **Runner** | A child process per turn with a one-turn credential. |
|
|
26
|
+
| **Harness** | Claude Code, Codex or OpenCode with its normal tools and your own settings. Nothing asks for permission mid-task. |
|
|
28
27
|
|
|
29
|
-
> **An agent with host access acts on the device as the user account the Companion runs under, with no approval prompts.** Turn it on for an agent whose work needs the device, on a device where that reach is acceptable,
|
|
28
|
+
> **An agent with host access acts on the device as the user account the Companion runs under, with no approval prompts.** Turn it on for an agent whose work needs the device, on a device where that reach is acceptable. To isolate an agent, isolate the Companion (see Isolation). An agent that reads untrusted input (public web, inbound mail, outside members) runs on a Companion that is isolated, whatever the device.
|
|
30
29
|
|
|
31
30
|
**No account password or full-account token ever touches the device.** The setup code delivers a device token (`cabdev_…`) good only for pulling this device's assignments and reporting liveness. Each assigned agent gets its own workspace-bound credential, delivered once. Renaming, deactivating, removing a device and rotating its token happen in Cabane.
|
|
32
31
|
|
|
@@ -71,17 +70,17 @@ If `cabane` isn't found afterwards, open a new terminal, or run the `source` lin
|
|
|
71
70
|
|
|
72
71
|
## Commands
|
|
73
72
|
|
|
74
|
-
| Command | What it does
|
|
75
|
-
| ------------------------------------ |
|
|
76
|
-
| `setup [CODE]` | With a code: pair or join, detect harnesses, start. Without: a re-runnable checklist that reports harnesses and starts what isn't running.
|
|
77
|
-
| `start [--foreground]` | Run in the background. Never asks. Unpaired, it names `setup`. `--foreground` stays attached, for a supervisor of your own.
|
|
78
|
-
| `stop` | Stop a running Companion cleanly. Ends any turn in progress.
|
|
79
|
-
| `status` | Version and install, the paired device by its Cabane name, its state in Cabane's words and when it last checked in, each harness's state,
|
|
80
|
-
| `update [--auto on\|off]` | Install the version Cabane names now; with `--auto`, set whether the Companion keeps itself up to date.
|
|
81
|
-
| `service install\|uninstall\|status` | Run as a systemd user service or a LaunchAgent that starts at boot and restarts if it stops; remove it; show its state.
|
|
82
|
-
| `logs [-n N] [-f]` | Recent log lines, or follow.
|
|
83
|
-
| `transcript [file] [--last] [-f]` | Read back a full agent turn, tool calls and results included.
|
|
84
|
-
| `logout [--purge]` | Remove the device token and cached agent credentials. Doesn't remove the device from Cabane.
|
|
73
|
+
| Command | What it does |
|
|
74
|
+
| ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
75
|
+
| `setup [CODE]` | With a code: pair or join, detect harnesses, start. Without: a re-runnable checklist that reports harnesses and starts what isn't running. |
|
|
76
|
+
| `start [--foreground]` | Run in the background. Never asks. Unpaired, it names `setup`. `--foreground` stays attached, for a supervisor of your own. |
|
|
77
|
+
| `stop` | Stop a running Companion cleanly. Ends any turn in progress. |
|
|
78
|
+
| `status` | Version and install, the paired device by its Cabane name, its state in Cabane's words and when it last checked in, each harness's state, where agents work, declared secret names, and local overrides. |
|
|
79
|
+
| `update [--auto on\|off]` | Install the version Cabane names now; with `--auto`, set whether the Companion keeps itself up to date. |
|
|
80
|
+
| `service install\|uninstall\|status` | Run as a systemd user service or a LaunchAgent that starts at boot and restarts if it stops; remove it; show its state. |
|
|
81
|
+
| `logs [-n N] [-f]` | Recent log lines, or follow. |
|
|
82
|
+
| `transcript [file] [--last] [-f]` | Read back a full agent turn, tool calls and results included. |
|
|
83
|
+
| `logout [--purge]` | Remove the device token and cached agent credentials. Doesn't remove the device from Cabane. |
|
|
85
84
|
|
|
86
85
|
Anything else about a device is done in Cabane, on the device's page.
|
|
87
86
|
|
|
@@ -99,7 +98,8 @@ All of it in `~/.cabane/`, mode 600, no database. Cabane is the source of truth
|
|
|
99
98
|
|
|
100
99
|
```
|
|
101
100
|
~/.cabane/
|
|
102
|
-
├── config.json # pairing, local overrides
|
|
101
|
+
├── config.json # pairing, local overrides
|
|
102
|
+
├── work/ # a directory per agent and conversation, for agents with no folder of their own
|
|
103
103
|
├── credentials.json # per-agent workspace-bound credentials, delivered once
|
|
104
104
|
├── secrets.json # { NAME: "value" } for ${NAME} placeholders
|
|
105
105
|
├── transcripts/ # one JSONL per turn, newest ~200 kept, local only
|
|
@@ -116,41 +116,16 @@ An MCP server configured in Cabane names its credential as `${NAME}`; the value
|
|
|
116
116
|
`config.json` can carry, per agent (keyed by id, `@username` or `workspace-slug/username`) or for the whole device:
|
|
117
117
|
|
|
118
118
|
- `cwd`: wins over the agent's **Starts in** folder set in Cabane.
|
|
119
|
-
- `prepareHook`: a command that resolves the working directory before each turn; wins over both. A device-level hook applies to every agent that doesn't name its own.
|
|
119
|
+
- `prepareHook`: a command that resolves the working directory before each turn; wins over both. A device-level hook applies to every agent that doesn't name its own. The hook gets `CABANE_DEFAULT_CWD`, the directory below, for a hook that only adds to it.
|
|
120
|
+
- `root`: where agents work when nothing else says. Every agent gets a directory per conversation under it, `<root>/<workspace>/<agent>/<conversation>/`, made on the first turn and never removed by the Companion. Default `~/.cabane/work`; absolute, or `~/…`. An agent with no folder in Cabane, no `cwd` and no hook stands there; a folder or `cwd` that isn't an existing directory is passed over with a line in the log.
|
|
120
121
|
- `harnesses`: an allowlist such as `["claude-code"]`; absent means all three.
|
|
121
122
|
- `claudeCode.autoMemory`: Claude Code's local memory directory is off by default on every Companion, because notes belong in the workspace where others can read them. `true` hands it back.
|
|
122
123
|
|
|
123
|
-
A malformed block fails `cabane start` with the field named.
|
|
124
|
-
|
|
125
|
-
### Sandbox
|
|
126
|
-
|
|
127
|
-
```jsonc
|
|
128
|
-
{
|
|
129
|
-
"runners": {
|
|
130
|
-
"enabled": true,
|
|
131
|
-
"sandbox": "os", // or "provider": "docker", where the container is the sandbox
|
|
132
|
-
"policy": {
|
|
133
|
-
"hosts": { "allow": ["gitlab.example.com"], "deny": [], "defaults": true },
|
|
134
|
-
"filesystem": { "mode": "blocklist", "denyRead": [], "allowRead": [], "allowWrite": [] },
|
|
135
|
-
"credentials": {
|
|
136
|
-
"env": { "GH_TOKEN": { "secret": "${GITHUB_TOKEN}", "hosts": ["api.github.com"] } },
|
|
137
|
-
"git": [{ "host": "github.com", "secret": "${GITHUB_TOKEN}" }],
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
}
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
Every key under `policy` is optional. The defaults:
|
|
145
|
-
|
|
146
|
-
- **Network**: Cabane and the turn's model provider always; GitHub, npm, PyPI and crates.io by default; `allow` adds hosts, `deny` removes them and wins. Nothing else is reachable.
|
|
147
|
-
- **Reads**: everything except known credential locations (`~/.ssh`, `~/.aws`, `~/.gnupg`, `~/.config/gh`, `~/.netrc`, `~/.npmrc`, `~/.kube`, cloud CLI configs, every Companion's own `~/.cabane` and the harness logins beside it) plus your `denyRead` globs. `.env` files are readable unless you deny them. `"mode": "strict"` hides the whole home except the working directory, the harness state and your `allowRead` list; name your toolchains there.
|
|
148
|
-
- **Writes**: the working directory, the temp dir, the harness's own state, plus `allowWrite`.
|
|
149
|
-
- **Credentials**: an entry sets the variable to a placeholder inside the sandbox and the proxy swaps the real value in only on requests to the hosts named. The harness never holds the token. A `git` entry does the same for HTTPS remotes (`~/.ssh` is unreadable, so use HTTPS).
|
|
124
|
+
A malformed block fails `cabane start` with the field named. A `runners` block or a row's `sandbox` from an older Companion is ignored, with one line in the log naming it.
|
|
150
125
|
|
|
151
|
-
|
|
126
|
+
### Isolation
|
|
152
127
|
|
|
153
|
-
|
|
128
|
+
The companion does no sandboxing. An agent with host access runs as you, with your tools, your settings and your files. On Claude Code your own `~/.claude/settings.json` applies, permission rules and hooks included; on Codex your `config.toml` applies except the sandbox, which Cabane turns off for a host-access turn; OpenCode is your own server. To isolate an agent, run the companion itself somewhere isolated: a container, a VM, or a machine that exists for agents. Recipes for that follow. Cabane shows on the device page who the Companion runs as and whether it is in a container.
|
|
154
129
|
|
|
155
130
|
## Debugging a turn
|
|
156
131
|
|
|
@@ -167,4 +142,4 @@ cabane logs -f # follow the log
|
|
|
167
142
|
|
|
168
143
|
## Not yet
|
|
169
144
|
|
|
170
|
-
Windows has no service install and no self-update. There is no per-tool permissioning for an agent with host access:
|
|
145
|
+
Windows has no service install and no self-update. There is no per-tool permissioning for an agent with host access in Cabane: it's all or nothing per agent, and the harness's own settings are the harness's.
|