@cabane/cli 0.1.11 → 0.2.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/README.md +41 -41
- package/dist/cli.js +34 -29
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# cabane CLI
|
|
1
|
+
# cabane-server CLI
|
|
2
2
|
|
|
3
3
|
Run a self-hosted [Cabane](https://cabane.ai) on your own machine. `@cabane/cli`
|
|
4
4
|
installs the Cabane server, runs the whole stack — server plus embedded Postgres —
|
|
@@ -13,12 +13,12 @@ itself and needs no model key of its own.
|
|
|
13
13
|
The short version:
|
|
14
14
|
|
|
15
15
|
```sh
|
|
16
|
-
npm i -g @cabane/cli
|
|
17
|
-
cabane init # first-run wizard (data location, port, URL)
|
|
18
|
-
cabane install --token cabdist_… # fetch + verify + unpack the server
|
|
19
|
-
cabane up --daemon # run the stack
|
|
16
|
+
npm i -g @cabane/cli # install the CLI (bin: `cabane-server`)
|
|
17
|
+
cabane-server init # first-run wizard (data location, port, URL)
|
|
18
|
+
cabane-server install --token cabdist_… # fetch + verify + unpack the server
|
|
19
|
+
cabane-server up --daemon # run the stack
|
|
20
20
|
# open http://localhost:3000, sign up
|
|
21
|
-
cabane setup-agent # confirm your account + how to pair a companion
|
|
21
|
+
cabane-server setup-agent # confirm your account + how to pair a companion
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
Each step, in order, below.
|
|
@@ -33,26 +33,26 @@ Each step, in order, below.
|
|
|
33
33
|
|
|
34
34
|
## Getting started
|
|
35
35
|
|
|
36
|
-
1. **Install the CLI.** `npm i -g @cabane/cli` — installs the `cabane` binary.
|
|
36
|
+
1. **Install the CLI.** `npm i -g @cabane/cli` — installs the `cabane-server` binary.
|
|
37
37
|
|
|
38
|
-
2. **Run `cabane init`** — the interactive first-run wizard. It asks where your
|
|
38
|
+
2. **Run `cabane-server init`** — the interactive first-run wizard. It asks where your
|
|
39
39
|
data lives (and shows the resolved paths — `data/storage` for uploads,
|
|
40
40
|
`data/pg` for the database), the port, and an optional public URL. Everything
|
|
41
|
-
persists to config, so a later `cabane up` needs no flags. Re-run it any time to
|
|
41
|
+
persists to config, so a later `cabane-server up` needs no flags. Re-run it any time to
|
|
42
42
|
reconfigure, or skip it and pass flags directly if you prefer.
|
|
43
43
|
|
|
44
|
-
3. **Run `cabane install --token cabdist_…`** — fetches the server artifact with
|
|
44
|
+
3. **Run `cabane-server install --token cabdist_…`** — fetches the server artifact with
|
|
45
45
|
your distribution token, verifies its sha256, and unpacks it. (Have a local
|
|
46
|
-
tarball instead? `cabane install --from <artifact.tgz>` works offline.)
|
|
46
|
+
tarball instead? `cabane-server install --from <artifact.tgz>` works offline.)
|
|
47
47
|
|
|
48
|
-
4. **Run `cabane up --daemon`** — starts and supervises the stack: embedded
|
|
48
|
+
4. **Run `cabane-server up --daemon`** — starts and supervises the stack: embedded
|
|
49
49
|
Postgres and the server. Leave off `--daemon` to run it in the foreground.
|
|
50
50
|
|
|
51
51
|
5. **Sign up.** Open <http://localhost:3000> and create your account and first
|
|
52
52
|
workspace.
|
|
53
53
|
|
|
54
54
|
6. **Pair a companion.** Your workspace seeds an agent, but it has nowhere to run
|
|
55
|
-
until you pair a device. `cabane setup-agent` (mint an access token in
|
|
55
|
+
until you pair a device. `cabane-server setup-agent` (mint an access token in
|
|
56
56
|
**Settings → Developer**, paste it at the prompt) confirms your account and
|
|
57
57
|
prints the steps: install the Companion (desktop app, or the headless
|
|
58
58
|
`@cabane/companion`), sign in against this instance, pair it, then assign the
|
|
@@ -64,7 +64,7 @@ see the [Cabane docs](https://app.cabane.ai/docs).
|
|
|
64
64
|
|
|
65
65
|
## What it supervises
|
|
66
66
|
|
|
67
|
-
`cabane up` runs two children in order, with a clean SIGTERM teardown:
|
|
67
|
+
`cabane-server up` runs two children in order, with a clean SIGTERM teardown:
|
|
68
68
|
|
|
69
69
|
1. **Embedded Postgres** — the `embedded-postgres` binaries (pinned pg 16.14) run
|
|
70
70
|
as a child on a local off-5432 port; data in `<CABANE_HOME>/data/pg`. No system
|
|
@@ -72,7 +72,7 @@ see the [Cabane docs](https://app.cabane.ai/docs).
|
|
|
72
72
|
2. **The server** — the artifact's single-process API+SPA (`server.js`, filesystem
|
|
73
73
|
storage, the bundled SPA served via `WEB_DIST`), env composed automatically
|
|
74
74
|
(`NODE_ENV=production`, `http://localhost:<port>`, generated-once vision
|
|
75
|
-
secret, any persisted `cabane set-env` creds). Migrations apply on boot.
|
|
75
|
+
secret, any persisted `cabane-server set-env` creds). Migrations apply on boot.
|
|
76
76
|
|
|
77
77
|
Agents don't run here — they run on a companion you pair (a separate process on a
|
|
78
78
|
device you control), the same as hosted Cabane.
|
|
@@ -93,35 +93,35 @@ which a standalone `@cabane/companion` user companion already keys off, so a
|
|
|
93
93
|
self-host install can never clobber a companion's device pairing on a shared box.
|
|
94
94
|
Override the whole root with the **`CABANE_HOME`** env var (the multi-instance
|
|
95
95
|
lever); a pre-existing self-host install still living at `~/.cabane` is adopted in
|
|
96
|
-
place, so no data moves. A `cabane install` / `set-env` pointed (via `CABANE_HOME`)
|
|
96
|
+
place, so no data moves. A `cabane-server install` / `set-env` pointed (via `CABANE_HOME`)
|
|
97
97
|
at a directory that holds a companion config refuses rather than overwrite it.
|
|
98
98
|
|
|
99
|
-
**Relocating just the data.** `cabane init` can point the **data** leg (pg +
|
|
99
|
+
**Relocating just the data.** `cabane-server init` can point the **data** leg (pg +
|
|
100
100
|
storage) at any path you choose while `config.json` + `app/` stay under the root —
|
|
101
101
|
handy for putting bulky uploads on a bigger disk. The default is still
|
|
102
102
|
`<root>/data`; the chosen location persists in config, so `up` finds it with no
|
|
103
103
|
env var or flag.
|
|
104
104
|
|
|
105
105
|
**Your data is safe across upgrades.** `data/` (pg + storage) sits apart from the
|
|
106
|
-
versioned `app/<version>/` tree, so `cabane install`, `cabane update`, and a
|
|
106
|
+
versioned `app/<version>/` tree, so `cabane-server install`, `cabane-server update`, and a
|
|
107
107
|
same-version reinstall only ever touch the app tree — your account, files, and
|
|
108
|
-
conversations persist untouched. `cabane status` prints the `home` + `data`
|
|
108
|
+
conversations persist untouched. `cabane-server status` prints the `home` + `data`
|
|
109
109
|
paths so you can see it.
|
|
110
110
|
|
|
111
111
|
## Commands
|
|
112
112
|
|
|
113
|
-
| Command
|
|
114
|
-
|
|
|
115
|
-
| `cabane init` | interactive first-run wizard: data location, port, public URL |
|
|
116
|
-
| `cabane install` | fetch (token → gated artifact) or `--from` a local tarball; unpack + `npm install --omit=dev` |
|
|
117
|
-
| `cabane up` | start + supervise the stack (`--daemon` for background) |
|
|
118
|
-
| `cabane setup-agent` | after signup: confirm your account + print companion-pairing guidance |
|
|
119
|
-
| `cabane update` | install a newer published artifact (keeps N-1 for rollback) |
|
|
120
|
-
| `cabane set-env` | persist generic `KEY=VALUE` server env forwarded to the server (`--list` / `--unset`) |
|
|
121
|
-
| `cabane down` | stop a running stack |
|
|
122
|
-
| `cabane status` | what's installed + running |
|
|
123
|
-
| `cabane logs` | tail the server log |
|
|
124
|
-
| `cabane doctor` | preflight: diagnose common self-host failure classes (runs with the stack down) |
|
|
113
|
+
| Command | What it does |
|
|
114
|
+
| --------------------------- | --------------------------------------------------------------------------------------------- |
|
|
115
|
+
| `cabane-server init` | interactive first-run wizard: data location, port, public URL |
|
|
116
|
+
| `cabane-server install` | fetch (token → gated artifact) or `--from` a local tarball; unpack + `npm install --omit=dev` |
|
|
117
|
+
| `cabane-server up` | start + supervise the stack (`--daemon` for background) |
|
|
118
|
+
| `cabane-server setup-agent` | after signup: confirm your account + print companion-pairing guidance |
|
|
119
|
+
| `cabane-server update` | install a newer published artifact (keeps N-1 for rollback) |
|
|
120
|
+
| `cabane-server set-env` | persist generic `KEY=VALUE` server env forwarded to the server (`--list` / `--unset`) |
|
|
121
|
+
| `cabane-server down` | stop a running stack |
|
|
122
|
+
| `cabane-server status` | what's installed + running |
|
|
123
|
+
| `cabane-server logs` | tail the server log |
|
|
124
|
+
| `cabane-server doctor` | preflight: diagnose common self-host failure classes (runs with the stack down) |
|
|
125
125
|
|
|
126
126
|
## Running agents
|
|
127
127
|
|
|
@@ -134,9 +134,9 @@ against the login or key already there; the server never sees the credential. Fo
|
|
|
134
134
|
single-box setup, the companion can run on the same machine as the server (point it
|
|
135
135
|
at `http://localhost:3000`).
|
|
136
136
|
|
|
137
|
-
## Troubleshooting — `cabane doctor`
|
|
137
|
+
## Troubleshooting — `cabane-server doctor`
|
|
138
138
|
|
|
139
|
-
When something won't start, run `cabane doctor` **first**. It's a standalone
|
|
139
|
+
When something won't start, run `cabane-server doctor` **first**. It's a standalone
|
|
140
140
|
preflight (no server needed — it's what you reach for precisely when things are
|
|
141
141
|
broken) that checks the common self-host failure classes and prints a legible
|
|
142
142
|
pass/fail/warn report, each with a one-line fix, then exits non-zero if any hard
|
|
@@ -149,29 +149,29 @@ check fails. It's strictly local — nothing phones home. Checks:
|
|
|
149
149
|
- **Disk space** for the data dir.
|
|
150
150
|
- **macOS Gatekeeper** — quarantine on the Postgres binaries (macOS only).
|
|
151
151
|
|
|
152
|
-
## Server env — `cabane set-env`
|
|
152
|
+
## Server env — `cabane-server set-env`
|
|
153
153
|
|
|
154
|
-
The self-hosted server needs no model credential of its own. `cabane set-env` stays
|
|
154
|
+
The self-hosted server needs no model credential of its own. `cabane-server set-env` stays
|
|
155
155
|
for any generic server env you _do_ want to persist:
|
|
156
156
|
|
|
157
157
|
```sh
|
|
158
158
|
# persisted — save once; every future `up` (fresh shell, reboot) picks it up.
|
|
159
159
|
# A bare KEY prompts for the value (hidden); `KEY=VALUE` still works for scripting.
|
|
160
|
-
cabane set-env SOME_KEY
|
|
161
|
-
cabane down && cabane up --daemon
|
|
160
|
+
cabane-server set-env SOME_KEY
|
|
161
|
+
cabane-server down && cabane-server up --daemon
|
|
162
162
|
```
|
|
163
163
|
|
|
164
164
|
It stores generic `KEY=VALUE` pairs in `<CABANE_HOME>/config.json` and layers them
|
|
165
165
|
into the server's env on every `up` — beneath the composed infra vars, so an
|
|
166
166
|
operator key reaches the server but can never clobber `DATABASE_URL` / `NODE_ENV` /
|
|
167
|
-
`STORAGE_*`. A bare `cabane set-env KEY` (no `=value`) prompts for the value without
|
|
167
|
+
`STORAGE_*`. A bare `cabane-server set-env KEY` (no `=value`) prompts for the value without
|
|
168
168
|
echoing, so a secret never lands on the command line. Inspect with
|
|
169
|
-
`cabane set-env --list` (values masked), remove with `cabane set-env --unset KEY`.
|
|
169
|
+
`cabane-server set-env --list` (values masked), remove with `cabane-server set-env --unset KEY`.
|
|
170
170
|
A live shell export takes precedence over a persisted value. Apply a change to an
|
|
171
|
-
already-running stack with `cabane down && cabane up`.
|
|
171
|
+
already-running stack with `cabane-server down && cabane-server up`.
|
|
172
172
|
|
|
173
173
|
## Notes
|
|
174
174
|
|
|
175
175
|
- **macOS Gatekeeper** may quarantine the unsigned Postgres binaries. If pg
|
|
176
176
|
fails to exec on first run, clear the quarantine xattr and retry —
|
|
177
|
-
`cabane doctor` detects this and prints the fix.
|
|
177
|
+
`cabane-server doctor` detects this and prints the fix.
|
package/dist/cli.js
CHANGED
|
@@ -224,7 +224,7 @@ async function checkPort(ctx) {
|
|
|
224
224
|
"port",
|
|
225
225
|
"Port",
|
|
226
226
|
`:${port} is occupied by another process`,
|
|
227
|
-
`Free port ${port}, or install on another with \`cabane install --port <n>\`, then retry.`
|
|
227
|
+
`Free port ${port}, or install on another with \`cabane-server install --port <n>\`, then retry.`
|
|
228
228
|
);
|
|
229
229
|
}
|
|
230
230
|
function ownSupervisorPid(paths) {
|
|
@@ -275,7 +275,7 @@ function checkStorage(ctx) {
|
|
|
275
275
|
`Make ${target} writable, or point Cabane elsewhere with \`CABANE_HOME=<dir>\`.`
|
|
276
276
|
);
|
|
277
277
|
}
|
|
278
|
-
const note = existsSync2(root) ? "" : " (will be created on first `cabane up`)";
|
|
278
|
+
const note = existsSync2(root) ? "" : " (will be created on first `cabane-server up`)";
|
|
279
279
|
return pass("storage", "Storage root", `${root} \u2014 writable${note}`);
|
|
280
280
|
}
|
|
281
281
|
async function resolvePgBinaries(platform, arch) {
|
|
@@ -328,7 +328,7 @@ async function checkPostgres(ctx) {
|
|
|
328
328
|
return pass(
|
|
329
329
|
"postgres",
|
|
330
330
|
"Embedded Postgres",
|
|
331
|
-
`binaries present; data dir uninitialised \u2014 first \`cabane up\` will init it (${dataDir})`
|
|
331
|
+
`binaries present; data dir uninitialised \u2014 first \`cabane-server up\` will init it (${dataDir})`
|
|
332
332
|
);
|
|
333
333
|
}
|
|
334
334
|
const stale = stalePostmaster(dataDir);
|
|
@@ -337,7 +337,7 @@ async function checkPostgres(ctx) {
|
|
|
337
337
|
"postgres",
|
|
338
338
|
"Embedded Postgres",
|
|
339
339
|
`data dir initialised but holds a stale postmaster.pid (pid ${stale}, not running) \u2014 ${dataDir}`,
|
|
340
|
-
"Harmless \u2014 Postgres clears it on the next `cabane up`; remove data/pg/postmaster.pid if start still refuses."
|
|
340
|
+
"Harmless \u2014 Postgres clears it on the next `cabane-server up`; remove data/pg/postmaster.pid if start still refuses."
|
|
341
341
|
);
|
|
342
342
|
}
|
|
343
343
|
return pass("postgres", "Embedded Postgres", `binaries present; data dir healthy \u2014 ${dataDir}`);
|
|
@@ -428,7 +428,7 @@ var STATUS_GLYPH = {
|
|
|
428
428
|
};
|
|
429
429
|
var NAME_WIDTH = 22;
|
|
430
430
|
function reportLines(summary) {
|
|
431
|
-
const lines = ["cabane doctor", ""];
|
|
431
|
+
const lines = ["cabane-server doctor", ""];
|
|
432
432
|
for (const r of summary.results) {
|
|
433
433
|
lines.push(`${STATUS_GLYPH[r.status]} ${r.name.padEnd(NAME_WIDTH)} ${r.detail}`);
|
|
434
434
|
if (r.fix) lines.push(` ${" ".repeat(NAME_WIDTH)} \u21B3 fix: ${r.fix}`);
|
|
@@ -565,7 +565,7 @@ async function down() {
|
|
|
565
565
|
rmSync2(paths.supervisorPidFile, { force: true });
|
|
566
566
|
rmSync2(paths.stateFile, { force: true });
|
|
567
567
|
if (free) ok("stopped");
|
|
568
|
-
else warn2(`stopped, but port ${port} still looks busy \u2014 check \`cabane status\`.`);
|
|
568
|
+
else warn2(`stopped, but port ${port} still looks busy \u2014 check \`cabane-server status\`.`);
|
|
569
569
|
}
|
|
570
570
|
async function killPid(pid) {
|
|
571
571
|
try {
|
|
@@ -666,7 +666,7 @@ async function promptSecret(question) {
|
|
|
666
666
|
async function init() {
|
|
667
667
|
if (!isInteractive()) {
|
|
668
668
|
throw new Error(
|
|
669
|
-
"`cabane init` is an interactive wizard \u2014 run it in a terminal, or configure non-interactively with `cabane install --port \u2026` + `cabane set-env KEY=VALUE`."
|
|
669
|
+
"`cabane-server init` is an interactive wizard \u2014 run it in a terminal, or configure non-interactively with `cabane-server install --port \u2026` + `cabane-server set-env KEY=VALUE`."
|
|
670
670
|
);
|
|
671
671
|
}
|
|
672
672
|
assertNotForeignCompanion();
|
|
@@ -716,9 +716,13 @@ async function init() {
|
|
|
716
716
|
info("");
|
|
717
717
|
const installed = config.currentVersion && isInstalled(appDirFor(paths, config.currentVersion));
|
|
718
718
|
if (installed) {
|
|
719
|
-
info(
|
|
719
|
+
info(
|
|
720
|
+
"next: `cabane-server up` (no flags needed), then sign up and `cabane-server setup-agent`."
|
|
721
|
+
);
|
|
720
722
|
} else {
|
|
721
|
-
info(
|
|
723
|
+
info(
|
|
724
|
+
"next: `cabane-server install` to fetch the server, then `cabane-server up` (no flags needed)."
|
|
725
|
+
);
|
|
722
726
|
}
|
|
723
727
|
}
|
|
724
728
|
function expandPath(input, root) {
|
|
@@ -736,7 +740,7 @@ async function promptPort(current) {
|
|
|
736
740
|
if (Number.isInteger(n) && n > 0 && n <= 65535) return n;
|
|
737
741
|
warn2(`invalid port: ${answer} \u2014 enter a number between 1 and 65535.`);
|
|
738
742
|
}
|
|
739
|
-
throw new Error("no valid port after several tries \u2014 re-run `cabane init`.");
|
|
743
|
+
throw new Error("no valid port after several tries \u2014 re-run `cabane-server init`.");
|
|
740
744
|
}
|
|
741
745
|
|
|
742
746
|
// src/commands/install.ts
|
|
@@ -759,7 +763,7 @@ async function fetchManifest(distBase, token, version) {
|
|
|
759
763
|
if (res.status === 404) return null;
|
|
760
764
|
if (res.status === 401) {
|
|
761
765
|
throw new Error(
|
|
762
|
-
"distribution token rejected (401) \u2014 check the token passed to `cabane install`"
|
|
766
|
+
"distribution token rejected (401) \u2014 check the token passed to `cabane-server install`"
|
|
763
767
|
);
|
|
764
768
|
}
|
|
765
769
|
if (!res.ok) {
|
|
@@ -846,7 +850,7 @@ async function install(opts) {
|
|
|
846
850
|
} else {
|
|
847
851
|
info(`data will live at ${paths.dataDir} (pg + storage) \u2014 preserved across upgrades`);
|
|
848
852
|
}
|
|
849
|
-
info("next: cabane up");
|
|
853
|
+
info("next: cabane-server up");
|
|
850
854
|
} finally {
|
|
851
855
|
cleanup?.();
|
|
852
856
|
}
|
|
@@ -878,7 +882,7 @@ async function logs(opts) {
|
|
|
878
882
|
const paths = resolvePaths();
|
|
879
883
|
const n = String(opts.lines ?? 80);
|
|
880
884
|
if (!existsSync6(paths.serverLog)) {
|
|
881
|
-
info("no logs yet \u2014 start the stack with `cabane up`.");
|
|
885
|
+
info("no logs yet \u2014 start the stack with `cabane-server up`.");
|
|
882
886
|
return;
|
|
883
887
|
}
|
|
884
888
|
const args = opts.follow ? ["-n", n, "-F", paths.serverLog] : ["-n", n, paths.serverLog];
|
|
@@ -895,7 +899,7 @@ function printList() {
|
|
|
895
899
|
const env = loadConfig().companionEnv ?? {};
|
|
896
900
|
const keys = Object.keys(env);
|
|
897
901
|
if (keys.length === 0) {
|
|
898
|
-
info("no persisted server env. Add one: `cabane set-env KEY=VALUE`");
|
|
902
|
+
info("no persisted server env. Add one: `cabane-server set-env KEY=VALUE`");
|
|
899
903
|
return;
|
|
900
904
|
}
|
|
901
905
|
step("persisted server env:");
|
|
@@ -941,7 +945,7 @@ async function setEnv(pairs, opts) {
|
|
|
941
945
|
config.companionEnv = { ...config.companionEnv ?? {}, ...parsed };
|
|
942
946
|
});
|
|
943
947
|
for (const key of Object.keys(parsed)) ok(`set ${key}=${mask(parsed[key])}`);
|
|
944
|
-
info("restart to apply: `cabane down && cabane up --daemon`");
|
|
948
|
+
info("restart to apply: `cabane-server down && cabane-server up --daemon`");
|
|
945
949
|
}
|
|
946
950
|
}
|
|
947
951
|
|
|
@@ -1025,7 +1029,7 @@ async function setupAgent(opts) {
|
|
|
1025
1029
|
const base = localBaseUrl(config.port);
|
|
1026
1030
|
const instanceUrl = config.publicUrl ?? base;
|
|
1027
1031
|
if (!await healthy(config.port)) {
|
|
1028
|
-
throw new Error(`server is not up on ${base} \u2014 run \`cabane up\` and sign up first.`);
|
|
1032
|
+
throw new Error(`server is not up on ${base} \u2014 run \`cabane-server up\` and sign up first.`);
|
|
1029
1033
|
}
|
|
1030
1034
|
const token = await resolvePat(opts, base);
|
|
1031
1035
|
const client = makeClient(base, token);
|
|
@@ -1099,7 +1103,7 @@ async function status() {
|
|
|
1099
1103
|
process.stdout.write(` ${label.padEnd(12)}${value}
|
|
1100
1104
|
`);
|
|
1101
1105
|
};
|
|
1102
|
-
process.stdout.write("cabane\n");
|
|
1106
|
+
process.stdout.write("cabane-server\n");
|
|
1103
1107
|
line("version", config.currentVersion ?? "(not installed)");
|
|
1104
1108
|
if (config.previousVersion) line("previous", config.previousVersion);
|
|
1105
1109
|
line("port", String(config.port));
|
|
@@ -1107,7 +1111,7 @@ async function status() {
|
|
|
1107
1111
|
line("data", `${paths.dataDir} (pg + storage \xB7 kept across upgrades)`);
|
|
1108
1112
|
line("supervisor", supervisorUp ? `up (pid ${supervisorPid})` : "down");
|
|
1109
1113
|
line("server", serverUp ? `up \xB7 http://localhost:${config.port}` : "down");
|
|
1110
|
-
if (!supervisorUp) info("start it: cabane up");
|
|
1114
|
+
if (!supervisorUp) info("start it: cabane-server up");
|
|
1111
1115
|
}
|
|
1112
1116
|
function readState2(file) {
|
|
1113
1117
|
try {
|
|
@@ -1281,7 +1285,7 @@ async function up(opts) {
|
|
|
1281
1285
|
const paths = pathsFor(config);
|
|
1282
1286
|
if (opts.port) config.port = opts.port;
|
|
1283
1287
|
if (!config.currentVersion) {
|
|
1284
|
-
throw new Error("nothing installed yet \u2014 run `cabane install` first.");
|
|
1288
|
+
throw new Error("nothing installed yet \u2014 run `cabane-server install` first.");
|
|
1285
1289
|
}
|
|
1286
1290
|
const appDir = appDirFor(paths, config.currentVersion);
|
|
1287
1291
|
if (!isInstalled(appDir)) {
|
|
@@ -1296,7 +1300,7 @@ async function up(opts) {
|
|
|
1296
1300
|
}
|
|
1297
1301
|
if (await portInUse(config.port)) {
|
|
1298
1302
|
throw new Error(
|
|
1299
|
-
`port ${config.port} is already in use. If cabane is running, use \`cabane down\`; otherwise a stale process is holding it \u2014 free it and retry.`
|
|
1303
|
+
`port ${config.port} is already in use. If cabane is running, use \`cabane-server down\`; otherwise a stale process is holding it \u2014 free it and retry.`
|
|
1300
1304
|
);
|
|
1301
1305
|
}
|
|
1302
1306
|
if (opts.daemon) {
|
|
@@ -1309,7 +1313,7 @@ async function launchDaemon(paths, config) {
|
|
|
1309
1313
|
if (existsSync8(paths.supervisorPidFile)) {
|
|
1310
1314
|
const pid = Number(readFileSync6(paths.supervisorPidFile, "utf8").trim());
|
|
1311
1315
|
if (pid && pidAlive(pid)) {
|
|
1312
|
-
warn2(`already running (supervisor pid ${pid}). Use \`cabane down\` to stop it.`);
|
|
1316
|
+
warn2(`already running (supervisor pid ${pid}). Use \`cabane-server down\` to stop it.`);
|
|
1313
1317
|
return;
|
|
1314
1318
|
}
|
|
1315
1319
|
}
|
|
@@ -1342,8 +1346,8 @@ async function launchDaemon(paths, config) {
|
|
|
1342
1346
|
}
|
|
1343
1347
|
function daemonFooter() {
|
|
1344
1348
|
return [
|
|
1345
|
-
"next: open the URL, sign up, then pair a companion so your agents can answer \u2014 `cabane setup-agent` explains how",
|
|
1346
|
-
"logs: cabane logs \xB7 stop: cabane down"
|
|
1349
|
+
"next: open the URL, sign up, then pair a companion so your agents can answer \u2014 `cabane-server setup-agent` explains how",
|
|
1350
|
+
"logs: cabane-server logs \xB7 stop: cabane-server down"
|
|
1347
1351
|
];
|
|
1348
1352
|
}
|
|
1349
1353
|
var Supervisor = class {
|
|
@@ -1369,7 +1373,7 @@ var Supervisor = class {
|
|
|
1369
1373
|
visionSecret: config.visionSecret,
|
|
1370
1374
|
...config.credentialKey ? { credentialKey: config.credentialKey } : {},
|
|
1371
1375
|
...config.publicUrl ? { publicBaseUrl: config.publicUrl } : {},
|
|
1372
|
-
// Persisted `cabane set-env` creds (generic server env) are layered beneath
|
|
1376
|
+
// Persisted `cabane-server set-env` creds (generic server env) are layered beneath
|
|
1373
1377
|
// the composed infra vars.
|
|
1374
1378
|
...config.companionEnv ? { persistedEnv: config.companionEnv } : {},
|
|
1375
1379
|
// The artifact's build version → the server reports it on the companion
|
|
@@ -1473,8 +1477,9 @@ async function update(opts) {
|
|
|
1473
1477
|
const distBase = (opts.distBase ?? config.distBase).replace(/\/$/, "");
|
|
1474
1478
|
const token = opts.token ?? config.distToken;
|
|
1475
1479
|
if (!token)
|
|
1476
|
-
throw new Error("no distribution token stored \u2014 run `cabane install --token \u2026` first.");
|
|
1477
|
-
if (!config.currentVersion)
|
|
1480
|
+
throw new Error("no distribution token stored \u2014 run `cabane-server install --token \u2026` first.");
|
|
1481
|
+
if (!config.currentVersion)
|
|
1482
|
+
throw new Error("nothing installed \u2014 run `cabane-server install` first.");
|
|
1478
1483
|
step(`checking ${distBase} for updates\u2026`);
|
|
1479
1484
|
const manifest = await fetchManifest(distBase, token, opts.version);
|
|
1480
1485
|
if (!manifest) throw new Error("no artifact available from the distribution endpoint.");
|
|
@@ -1490,12 +1495,12 @@ async function update(opts) {
|
|
|
1490
1495
|
}
|
|
1491
1496
|
await install({ token, distBase, version: target });
|
|
1492
1497
|
ok(`installed ${target} (previous kept for rollback)`);
|
|
1493
|
-
info("restart to run it: cabane down && cabane up");
|
|
1498
|
+
info("restart to run it: cabane-server down && cabane-server up");
|
|
1494
1499
|
}
|
|
1495
1500
|
|
|
1496
1501
|
// src/cli.ts
|
|
1497
1502
|
var program = new Command();
|
|
1498
|
-
program.name("cabane").description("Run a self-hosted Cabane on your own machine \u2014 no docker, no repo.").version("0.
|
|
1503
|
+
program.name("cabane-server").description("Run a self-hosted Cabane on your own machine \u2014 no docker, no repo.").version("0.2.0");
|
|
1499
1504
|
var parsePort = (raw) => {
|
|
1500
1505
|
const n = Number(raw);
|
|
1501
1506
|
if (!Number.isInteger(n) || n <= 0 || n > 65535) throw new Error(`invalid port: ${raw}`);
|
|
@@ -1503,7 +1508,7 @@ var parsePort = (raw) => {
|
|
|
1503
1508
|
};
|
|
1504
1509
|
program.command("init").description("interactive first-run wizard: data location, port, and public URL").action(init);
|
|
1505
1510
|
program.command("install").description("install the server artifact (token \u2192 gated download, or --from a local tarball)").option("--token <token>", "distribution token (cabdist_\u2026) \u2014 prompted if omitted").option("--from <tarball>", "install from a local artifact tarball instead of downloading").option("--dist-base <url>", "distribution origin to fetch from (default https://dist.cabane.ai)").option("--version <version>", "install a specific published version (default: latest)").option("--port <port>", "local port the server will listen on (default 3000)", parsePort).option("--force", "reinstall even if this version is already present").action(install);
|
|
1506
|
-
program.command("up").description("start + supervise the stack (Postgres + server)").option("--daemon", "run in the background (terminal returns; stop with `cabane down`)").option("--port <port>", "override the configured port", parsePort).action(up);
|
|
1511
|
+
program.command("up").description("start + supervise the stack (Postgres + server)").option("--daemon", "run in the background (terminal returns; stop with `cabane-server down`)").option("--port <port>", "override the configured port", parsePort).action(up);
|
|
1507
1512
|
program.command("setup-agent").description("after browser signup: confirm your account and print companion-pairing guidance").option("--token <token>", "a Cabane access token (cab_\u2026) \u2014 prompted if omitted").action(setupAgent);
|
|
1508
1513
|
program.command("update").description("install a newer published artifact (keeps the previous for rollback)").option("--token <token>", "distribution token (cabdist_\u2026) \u2014 defaults to the stored one").option("--dist-base <url>", "distribution origin to fetch from").option("--version <version>", "install a specific version instead of latest").action(update);
|
|
1509
1514
|
program.command("set-env [pairs...]").description(
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cabane/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "The cabane CLI — install, run, and update a self-hosted Cabane on your own machine (server + embedded Postgres; agents run on a companion you pair).",
|
|
5
|
+
"description": "The cabane-server CLI — install, run, and update a self-hosted Cabane on your own machine (server + embedded Postgres; agents run on a companion you pair).",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"homepage": "https://cabane.ai",
|
|
8
8
|
"repository": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"cli"
|
|
17
17
|
],
|
|
18
18
|
"bin": {
|
|
19
|
-
"cabane": "dist/cli.js"
|
|
19
|
+
"cabane-server": "dist/cli.js"
|
|
20
20
|
},
|
|
21
21
|
"main": "./dist/cli.js",
|
|
22
22
|
"files": [
|