@tikoci/quickchr 0.4.8 → 0.5.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/DESIGN.md +219 -14
- package/MANUAL.md +396 -71
- package/README.md +33 -8
- package/package.json +2 -2
- package/src/cli/flags.ts +22 -3
- package/src/cli/index.ts +461 -104
- package/src/cli/wizard.ts +10 -2
- package/src/index.ts +2 -0
- package/src/lib/api-login.ts +138 -0
- package/src/lib/cache.ts +220 -38
- package/src/lib/completions.ts +20 -11
- package/src/lib/device-mode.ts +149 -10
- package/src/lib/diagnostics.ts +13 -6
- package/src/lib/disk.ts +90 -33
- package/src/lib/download.ts +3 -2
- package/src/lib/images.ts +34 -15
- package/src/lib/lock.ts +498 -0
- package/src/lib/names.ts +24 -0
- package/src/lib/network.ts +16 -16
- package/src/lib/packages.ts +66 -40
- package/src/lib/provision.ts +3 -2
- package/src/lib/provisioning-window.ts +356 -0
- package/src/lib/qemu.ts +54 -2
- package/src/lib/quickchr.ts +950 -359
- package/src/lib/rename.ts +41 -0
- package/src/lib/settings.ts +20 -9
- package/src/lib/shutdown.ts +49 -0
- package/src/lib/socket-registry.ts +2 -2
- package/src/lib/state.ts +89 -2
- package/src/lib/storage-lease.ts +169 -0
- package/src/lib/storage.ts +223 -66
- package/src/lib/types.ts +109 -23
- package/src/lib/versions.ts +54 -0
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
> **Experimental** — quickchr is under active development. Most testing has been on
|
|
4
4
|
> macOS (Apple Silicon + Intel), with CI on Linux (x86_64 + aarch64). Windows support
|
|
5
|
-
> is early-stage: unit tests pass on `windows-latest` CI,
|
|
6
|
-
>
|
|
7
|
-
>
|
|
5
|
+
> is early-stage: unit tests pass on `windows-latest` CI, and a weekly sweep boots a real
|
|
6
|
+
> CHR on Windows (TCG, anchor smoke subset only). Expect rough edges on Windows — bug
|
|
7
|
+
> reports welcome.
|
|
8
8
|
|
|
9
9
|
CLI and library to download, launch, and manage MikroTik CHR virtual machines via QEMU.
|
|
10
10
|
|
|
@@ -57,6 +57,23 @@ Library:
|
|
|
57
57
|
bun add @tikoci/quickchr
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
+
### Prerelease QA (0.5.1)
|
|
61
|
+
|
|
62
|
+
0.5.1 is published to npm `next` first; the unqualified install above uses `latest`,
|
|
63
|
+
and 0.5.1 is promoted there once QA passes. After 0.5.1 is published, pin it for
|
|
64
|
+
reproducible CLI or library QA:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
bun install -g @tikoci/quickchr@0.5.1
|
|
68
|
+
bun add @tikoci/quickchr@0.5.1
|
|
69
|
+
quickchr --version
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Use `@next` instead of `@0.5.1` to follow later candidates. See the
|
|
73
|
+
[0.5.1 changelog](./CHANGELOG.md#051--2026-10-22) for the changes since 0.5.0,
|
|
74
|
+
including storage admission, cache accounting, and disk preservation fixes.
|
|
75
|
+
The [0.5.0 notes](./CHANGELOG.md#050--2026-10-22) cover migration from 0.4.x.
|
|
76
|
+
|
|
60
77
|
### CLI Usage
|
|
61
78
|
|
|
62
79
|
The easiest way to start is the interactive wizard — it walks through
|
|
@@ -158,6 +175,11 @@ quickchr remove my-chr
|
|
|
158
175
|
quickchr doctor
|
|
159
176
|
```
|
|
160
177
|
|
|
178
|
+
`quickchr stop <name>` terminates QEMU (a power cut). For an explicit guest
|
|
179
|
+
shutdown request, use `quickchr shutdown <name> [--timeout <seconds>]` (default
|
|
180
|
+
10 seconds, or `QUICKCHR_SHUTDOWN_TIMEOUT`). It waits for QEMU to exit and clearly
|
|
181
|
+
reports a forced power cut if the guest does not stop within the grace budget.
|
|
182
|
+
|
|
161
183
|
### Create / Start Options
|
|
162
184
|
|
|
163
185
|
| Flag | Description | Default |
|
|
@@ -172,8 +194,9 @@ quickchr doctor
|
|
|
172
194
|
| `--boot-size <size>` | Resize boot disk (e.g., 512M, 2G). Requires `qemu-img`. | |
|
|
173
195
|
| `--add-disk <size>` | Attach an extra blank qcow2 disk. Repeatable. Requires `qemu-img`. | |
|
|
174
196
|
| `--forward <spec>` | Add or pin a QEMU SLiRP hostfwd mapping. Repeatable. | |
|
|
175
|
-
| `--
|
|
197
|
+
| `--no-wait` | Return once QEMU is running; readiness is up to the caller. Not with provisioning flags or `--fg` | |
|
|
176
198
|
| `--fg` / `--foreground` | Run in foreground — serial console on stdio | |
|
|
199
|
+
| `--bg` / `--background` | **Deprecated, does nothing** — background is already the default. Warns; use `--no-wait` to return early | |
|
|
177
200
|
| `--add-package <pkg>` | Extra package to install (repeatable) | |
|
|
178
201
|
| `--install-all-packages` | Install all packages from `all_packages.zip` | |
|
|
179
202
|
| `--add-user <user:pass>` | Create a user after boot | |
|
|
@@ -189,6 +212,7 @@ quickchr doctor
|
|
|
189
212
|
| `--device-mode <m>` | Configure device-mode: rose\|advanced\|basic\|home\|auto\|skip | |
|
|
190
213
|
| `--device-mode-enable <f>` | Set one or more device-mode flags to yes | |
|
|
191
214
|
| `--device-mode-disable <f>` | Set one or more device-mode flags to no | |
|
|
215
|
+
| `--no-device-mode` | Skip device-mode provisioning entirely | |
|
|
192
216
|
| `--port-base <port>` | Starting port number | Auto (9100+) |
|
|
193
217
|
| `--timeout-extra <s>` | Add extra seconds to the auto-computed boot timeout | |
|
|
194
218
|
| `--dry-run` | Print what would run without executing | |
|
|
@@ -204,7 +228,7 @@ quickchr separates **boot-only** machine management from **post-boot provisionin
|
|
|
204
228
|
|
|
205
229
|
| Feature | Minimum RouterOS | Notes |
|
|
206
230
|
|---------|------------------|-------|
|
|
207
|
-
| Boot / start / stop | Any RouterOS 7.x | Boot-only path; no post-boot RouterOS mutations |
|
|
231
|
+
| Boot / start / stop | Any RouterOS 7.x; RouterOS 6 on x86 (best-effort) | Boot-only path; no post-boot RouterOS mutations. 6.x has no REST: readiness is a native-API login, and provisioning is refused — see MANUAL "RouterOS 6 (boot-only)" |
|
|
208
232
|
| Disk resize / extra disks / disk inspection | Any RouterOS 7.x | Requires host `qemu-img`; QEMU-local only |
|
|
209
233
|
| Network attachment / port mappings | Any RouterOS 7.x | QEMU networking setup; not provisioning |
|
|
210
234
|
| Managed login / custom user / disable-admin | 7.20.8+ | Post-boot provisioning |
|
|
@@ -232,7 +256,7 @@ In **foreground** mode, your terminal becomes the CHR serial console. Use these
|
|
|
232
256
|
| `Ctrl-A C` | Toggle QEMU monitor (`quit` to force-stop) |
|
|
233
257
|
| `Ctrl-A H` | List all key shortcuts |
|
|
234
258
|
|
|
235
|
-
> **Note:** Background QEMU processes are true OS-level orphans — `quickchr` does not use shell job control (`&`). After the command returns you can close the terminal and QEMU keeps running.
|
|
259
|
+
> **Note:** Background QEMU processes are true OS-level orphans — `quickchr` does not use shell job control (`&`). After the command returns you can close the terminal and QEMU keeps running. `quickchr stop <name>` ends it with a power cut; `quickchr shutdown <name>` asks the guest to shut down first, and still falls back to a power cut if it does not exit in time.
|
|
236
260
|
|
|
237
261
|
### Disk Support
|
|
238
262
|
|
|
@@ -359,7 +383,8 @@ const result = await chr.exec("/system/resource/print");
|
|
|
359
383
|
console.log(result);
|
|
360
384
|
|
|
361
385
|
// Stop (or remove)
|
|
362
|
-
await chr.stop();
|
|
386
|
+
await chr.stop(); // power cut for normal teardown
|
|
387
|
+
// Alternatively, replace stop() above with: await chr.shutdown({ timeoutMs: 10_000 });
|
|
363
388
|
await chr.remove();
|
|
364
389
|
|
|
365
390
|
console.log(chr.state.bootDiskFormat); // "qcow2"
|
|
@@ -430,7 +455,7 @@ afterAll(async () => {
|
|
|
430
455
|
|----------|-------------|
|
|
431
456
|
| `MIKROTIK_WEB_ACCOUNT` | MikroTik.com account email (for license renewal) |
|
|
432
457
|
| `MIKROTIK_WEB_PASSWORD` | MikroTik.com password (for license renewal) |
|
|
433
|
-
| `QUICKCHR_DEFAULT_CHANNEL`, `QUICKCHR_DEFAULT_ARCH`, `QUICKCHR_CACHE_MAX_SIZE`, `QUICKCHR_TIMEOUT_EXTRA`, `QUICKCHR_SECURE_LOGIN` | Env-tier overrides for the
|
|
458
|
+
| `QUICKCHR_DEFAULT_CHANNEL`, `QUICKCHR_DEFAULT_ARCH`, `QUICKCHR_ACCEL`, `QUICKCHR_CACHE_MAX_SIZE`, `QUICKCHR_STORAGE_RESERVE`, `QUICKCHR_TIMEOUT_EXTRA`, `QUICKCHR_SECURE_LOGIN` | Env-tier overrides for the 7 `quickchr settings` keys — see [MANUAL.md §3 `settings`](./MANUAL.md#3-cli-command-reference) |
|
|
434
459
|
| `QUICKCHR_INTEGRATION` | Set to `1` to run integration tests |
|
|
435
460
|
| `QUICKCHR_TEST_TARGET` | Integration tests only: RouterOS channel (`stable`/`long-term`/`testing`/`development`) or pinned version (e.g. `7.22.1`) to boot. Empty = `stable`. The Integration workflow resolves each `routeros-target` once, then sets this to that exact pin across platforms |
|
|
436
461
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tikoci/quickchr",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "CLI and library to download, launch, and manage MikroTik CHR virtual machines via QEMU",
|
|
5
5
|
"module": "src/index.ts",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"lint": "biome check . && tsc --noEmit",
|
|
26
26
|
"lint:biome": "biome check .",
|
|
27
27
|
"lint:typecheck": "tsc --noEmit",
|
|
28
|
-
"lint:markdown": "
|
|
28
|
+
"lint:markdown": "markdownlint-cli2 '**/*.md'",
|
|
29
29
|
"lint:cspell": "cspell lint . --no-progress",
|
|
30
30
|
"lint:examples": "bun run scripts/validate-examples.ts",
|
|
31
31
|
"lint:specifiers": "bun run scripts/validate-network-specifiers.ts",
|
package/src/cli/flags.ts
CHANGED
|
@@ -24,13 +24,27 @@ const CREATE_FLAGS = [
|
|
|
24
24
|
|
|
25
25
|
/** `start` also boots, so it owns the run-time flags on top of the create set. */
|
|
26
26
|
const START_ONLY_FLAGS = [
|
|
27
|
-
"all", "dry-run", "background", "bg", "fg", "foreground",
|
|
28
|
-
"
|
|
27
|
+
"all", "dry-run", "wait", "background", "bg", "fg", "foreground",
|
|
28
|
+
"timeout-extra",
|
|
29
29
|
"license-level", "license-account", "license-password",
|
|
30
30
|
] as const;
|
|
31
31
|
|
|
32
|
+
/** `set` applies a change to a machine that has already booted, so it takes the
|
|
33
|
+
* post-boot subset of the provisioning flags plus `--license`'s credential flags.
|
|
34
|
+
*
|
|
35
|
+
* It is listed here for the **valueless** check, not for strictness: `set` still
|
|
36
|
+
* tolerates an unknown flag like every other non-creating command. The check that
|
|
37
|
+
* matters is arity — `quickchr set lab --device-mode` with no value parses as a
|
|
38
|
+
* boolean and would otherwise reach "Nothing to set", which blames the user for the
|
|
39
|
+
* wrong thing. */
|
|
40
|
+
const SET_ONLY_FLAGS = [
|
|
41
|
+
"name", "license", "level", "account", "password",
|
|
42
|
+
"device-mode", "device-mode-enable", "device-mode-disable",
|
|
43
|
+
] as const;
|
|
44
|
+
|
|
32
45
|
export const ADD_FLAGS: readonly string[] = CREATE_FLAGS;
|
|
33
46
|
export const START_FLAGS: readonly string[] = [...CREATE_FLAGS, ...START_ONLY_FLAGS];
|
|
47
|
+
export const SET_FLAGS: readonly string[] = SET_ONLY_FLAGS;
|
|
34
48
|
|
|
35
49
|
/** Every flag that takes a value, across every command — `parseFlags`'s arity table.
|
|
36
50
|
*
|
|
@@ -82,10 +96,15 @@ export const VALUE_FLAGS: ReadonlySet<string> = new Set([
|
|
|
82
96
|
* that `--add-network` already expresses in general (#164). Removing them silently would
|
|
83
97
|
* repeat the defect they were removed for: a flag that is accepted and does nothing. A
|
|
84
98
|
* removed name stays known for as long as anyone might still type it, and says what
|
|
85
|
-
* replaced it.
|
|
99
|
+
* replaced it.
|
|
100
|
+
*
|
|
101
|
+
* `--install-deps` is the same defect from the other side: `start` accepted it from
|
|
102
|
+
* the beginning and nothing ever read it (#193). It never installed anything, so the
|
|
103
|
+
* replacement is the command that names what to install. */
|
|
86
104
|
export const REMOVED_FLAGS: ReadonlyMap<string, string> = new Map([
|
|
87
105
|
["vmnet-shared", "--add-network shared"],
|
|
88
106
|
["vmnet-bridge", "--add-network bridged:<iface>"],
|
|
107
|
+
["install-deps", "quickchr doctor (it never installed anything; doctor lists missing host dependencies and how to install them)"],
|
|
89
108
|
]);
|
|
90
109
|
|
|
91
110
|
/** Value-taking flags with a documented `--no-` spelling, where `false` is a real
|