@tikoci/quickchr 0.5.0 → 0.5.2
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/.bun-version +1 -0
- package/DESIGN.md +60 -8
- package/MANUAL.md +150 -43
- package/README.md +26 -11
- package/package.json +3 -2
- package/src/cli/flags.ts +7 -2
- package/src/cli/index.ts +63 -33
- package/src/cli/wizard.ts +54 -58
- package/src/lib/cache.ts +220 -38
- 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 +2 -1
- package/src/lib/packages.ts +66 -40
- package/src/lib/platform.ts +13 -1
- package/src/lib/quickchr.ts +87 -62
- package/src/lib/rename.ts +41 -0
- package/src/lib/settings.ts +20 -9
- package/src/lib/state.ts +26 -1
- package/src/lib/storage-lease.ts +169 -0
- package/src/lib/storage.ts +223 -66
- package/src/lib/types.ts +13 -3
package/.bun-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.4.4
|
package/DESIGN.md
CHANGED
|
@@ -144,7 +144,8 @@ Current consumers are all first-party tikoci projects (centrs, donny, restraml),
|
|
|
144
144
|
├── machines/
|
|
145
145
|
│ └── 7.22.1-arm64-1/
|
|
146
146
|
│ ├── machine.json # Config + state
|
|
147
|
-
│ ├── disk.img
|
|
147
|
+
│ ├── boot.qcow2 # Boot disk, qcow2 — or disk.img when raw (see below)
|
|
148
|
+
│ ├── disk<N>.qcow2 # Extra disks
|
|
148
149
|
│ ├── efi-vars.qcow2 # UEFI vars (arm64; qcow2 so savevm works — #31)
|
|
149
150
|
│ ├── monitor.sock # QEMU monitor
|
|
150
151
|
│ ├── serial.sock # Serial console
|
|
@@ -156,12 +157,60 @@ Current consumers are all first-party tikoci projects (centrs, donny, restraml),
|
|
|
156
157
|
└── boot-failure-<machine>-<iso8601>.json
|
|
157
158
|
```
|
|
158
159
|
|
|
160
|
+
**One boot disk per machine.** A raw machine boots `disk.img`, a copy of the cached
|
|
161
|
+
image. A qcow2 machine boots `boot.qcow2`, converted straight from the cached image
|
|
162
|
+
into a `.tmp` file, checked to be a standalone qcow2 (no backing file), then renamed
|
|
163
|
+
into place. Machines created before 0.5.1 also kept the raw `disk.img` the qcow2 came
|
|
164
|
+
from: a full-size copy (128 MiB x86) that nothing reads. Restart no longer requires it
|
|
165
|
+
(#200). `clean` removes it, and nothing else deletes it implicitly (#199). The shared
|
|
166
|
+
cache image stays: `clean` and a failed first boot's rollback rebuild from it.
|
|
167
|
+
|
|
168
|
+
A missing disk is rebuilt only while the machine has never booted. A booted machine's
|
|
169
|
+
disks hold guest state, so a missing `boot.qcow2`, `disk.img` or extra disk is
|
|
170
|
+
`MACHINE_NOT_FOUND`, never a silent rebuild from factory. The way out is to restore the
|
|
171
|
+
file or run `quickchr clean`.
|
|
172
|
+
|
|
173
|
+
**Storage admission (#199).** An operation that writes new data (creating a machine,
|
|
174
|
+
an image or package download) is admitted when **each filesystem it writes to** has
|
|
175
|
+
`estimate + storage-reserve` free there. It replaced a flat 10 GiB floor that refused
|
|
176
|
+
small hosts which had room. The operation's writes are parts with paths (boot disk →
|
|
177
|
+
`machines/`, downloads → the cache it writes to), grouped by `stat().dev`. The estimate
|
|
178
|
+
is a per-stage constant (`STORAGE_ESTIMATES` in `storage.ts`), rounded up from one
|
|
179
|
+
host's measurements and written down there. The reserve (default 2 GiB) absorbs the
|
|
180
|
+
estimate's error and keeps the host usable. Restart is never gated. Virtual disk
|
|
181
|
+
capacity is not charged: a sparse disk's growth is the guest's, after admission.
|
|
182
|
+
|
|
183
|
+
Under pressure, eligible cache entries are evicted, but only from a cache on the short
|
|
184
|
+
filesystem, and only when everything eligible could cover the gap. Free space is then
|
|
185
|
+
**measured again**, in passes, until the measurement admits or nothing more can be
|
|
186
|
+
evicted. Logical sizes are not proof of room (sparse files, APFS clones).
|
|
187
|
+
|
|
188
|
+
**Coordination** (`storage-lease.ts`, after Codex's review of #203 reproduced both
|
|
189
|
+
races). One data-dir lock, held for milliseconds: a check-and-record, or an eviction
|
|
190
|
+
pass. Under it, an operation records a **lease** naming the cache entries it is about
|
|
191
|
+
to read (pins) and the bytes it is about to write, per filesystem. Admission subtracts
|
|
192
|
+
other live leases' bytes from measured free space, so two creators cannot spend the
|
|
193
|
+
same bytes. Eviction skips pinned entries. A pin is recorded before the reader checks
|
|
194
|
+
the entry exists, so an eviction either sees it or has already finished, and then the
|
|
195
|
+
reader fetches the entry again. A create's lease lasts until its `machine.json` is
|
|
196
|
+
saved, which protects the image from then on. A download's lease lasts the download.
|
|
197
|
+
A dead pid's lease is ignored and deleted. A create's own downloads are checked up
|
|
198
|
+
front, so it refuses early, but are reserved only by the download itself, so they are
|
|
199
|
+
not counted twice. Automatic eviction also skips anything used in the last 30
|
|
200
|
+
minutes (a cache hit bumps its mtime). That rule is not what protects a reader; pins
|
|
201
|
+
are. It spares what a finished `cache add` fetched for a later process.
|
|
202
|
+
|
|
203
|
+
The cache cap (`cache-max-size`) is retention, separate from admission. It counts
|
|
204
|
+
images, package archives with their extractions (one entry: the extraction is only a
|
|
205
|
+
hit while its archive exists) and interrupted downloads. Files quickchr did not write
|
|
206
|
+
are reported and never deleted. A failed delete is reported as failed, not freed.
|
|
207
|
+
|
|
159
208
|
**Global settings** live separately, under the XDG **config** tier (not the data tree
|
|
160
209
|
above): `~/.config/quickchr/quickchr.env`, dotenv-style (`QUICKCHR_KEY=value` lines).
|
|
161
210
|
Managed via `quickchr settings get|set|print|reset`. Precedence per key: CLI flag >
|
|
162
|
-
`QUICKCHR_<KEY>` env var > `quickchr.env` > built-in default. The
|
|
163
|
-
`default-channel`, `default-arch`, `accel`, `cache-max-size`, `
|
|
164
|
-
`secure-login`.
|
|
211
|
+
`QUICKCHR_<KEY>` env var > `quickchr.env` > built-in default. The 7 managed keys:
|
|
212
|
+
`default-channel`, `default-arch`, `accel`, `cache-max-size`, `storage-reserve`,
|
|
213
|
+
`timeout-extra`, `secure-login`.
|
|
165
214
|
See MANUAL.md's CLI reference and environment-variables sections for the full surface.
|
|
166
215
|
|
|
167
216
|
## Platform Support
|
|
@@ -196,7 +245,9 @@ CI, integration and release all install, enforced by `scripts/check-bun-pin.ts`
|
|
|
196
245
|
runtime could change between two identical commits — and did: a six-week gap with no `ci.yml`
|
|
197
246
|
runs spanned the Bun 1.4.0 release, and the next PR inherited a 1.3.14 → 1.4.2 jump as if it
|
|
198
247
|
were its own regression. Anything that can turn the build red is a dependency and belongs in
|
|
199
|
-
a reviewable diff; "whatever is newest at run time" is not a version.
|
|
248
|
+
a reviewable diff; "whatever is newest at run time" is not a version. The same
|
|
249
|
+
`.bun-version` file ships in the npm package so `doctor` can name the tested
|
|
250
|
+
runtime and warn when the running Bun is older without duplicating the pin.
|
|
200
251
|
|
|
201
252
|
**The 2026-07 refactor (#29)** replaced the organically-grown scheme (integration on every
|
|
202
253
|
PR push, three parallel copies of the runner logic, `continue-on-error` green-washing)
|
|
@@ -229,9 +280,10 @@ with a layered design:
|
|
|
229
280
|
- **`release.yml`** — one-click publish from committed release state: freshness gate
|
|
230
281
|
(no suite re-run — main is kept continuously release-able) + `package.json` version
|
|
231
282
|
with a matching non-empty CHANGELOG section → tag + GitHub Release + `npm publish
|
|
232
|
-
--provenance`
|
|
233
|
-
|
|
234
|
-
|
|
283
|
+
--provenance` under the dispatch-time `npm-tag` (default `next`; promoted to `latest`
|
|
284
|
+
after QA — not derived from the version number; a `latest` release is also tagged
|
|
285
|
+
`next`, since there is no separately maintained pre-release line and `next` must not
|
|
286
|
+
point at something older than `latest`). CI never bumps versions or pushes
|
|
235
287
|
to protected `main`.
|
|
236
288
|
- **`ros-versions.yml`** — daily: new RouterOS versions (per channel) with no linux-x86
|
|
237
289
|
record in `ci-data/tested-versions.json` ride the `routeros-targets` matrix of a
|
package/MANUAL.md
CHANGED
|
@@ -64,7 +64,7 @@ by the user (or their AI agent) using `quickchr` as a building block.
|
|
|
64
64
|
| Bun ≥ 1.1 | runtime | macOS/Linux: `curl -fsSL https://bun.sh/install \| bash` · Windows: `powershell -c "irm bun.sh/install.ps1 \| iex"` (or `winget install Oven-sh.Bun`) |
|
|
65
65
|
| `qemu-system-x86_64` | x86 CHR | brew/apt/dnf/pacman · Windows: `winget install SoftwareFreedomConservancy.QEMU` |
|
|
66
66
|
| `qemu-system-aarch64` | arm64 CHR | brew/apt/dnf/pacman · Windows: bundled in the SFC QEMU package above |
|
|
67
|
-
| `qemu-img` | `--boot-size`, `--add-disk`, snapshots | included in all standard QEMU packages (brew, apt, dnf, SFC installer) |
|
|
67
|
+
| `qemu-img` | Default qcow2 creation, setup wizard, `--boot-size`, `--add-disk`, snapshots | included in all standard QEMU packages (brew, apt, dnf, SFC installer) |
|
|
68
68
|
| UEFI firmware (edk2) | arm64 CHR | `qemu-efi-aarch64` (apt), `edk2-aarch64` (dnf), bundled with `qemu` (brew) |
|
|
69
69
|
| `socket_vmnet` (optional) | rootless `shared`/`bridged` networking on macOS | `brew install socket_vmnet` |
|
|
70
70
|
| `socat` (optional) | piping serial console externally | brew/apt |
|
|
@@ -72,31 +72,40 @@ by the user (or their AI agent) using `quickchr` as a building block.
|
|
|
72
72
|
|
|
73
73
|
### Install quickchr
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
odd/even policy. Not yet on npm.
|
|
75
|
+
Install the stable npm channel:
|
|
77
76
|
|
|
78
77
|
```bash
|
|
79
|
-
|
|
80
|
-
bun add
|
|
78
|
+
bun install -g @tikoci/quickchr
|
|
79
|
+
bun add @tikoci/quickchr
|
|
80
|
+
```
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
For prerelease QA, use `@next` for the current candidate or, after publication,
|
|
83
|
+
`@0.5.1` to pin this candidate. A release is published to `next` first and promoted
|
|
84
|
+
to `latest` once QA passes; `next` is never older than `latest`. The quickchr package
|
|
85
|
+
channel is independent of `--channel`, which selects a RouterOS firmware channel.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
bun install -g @tikoci/quickchr@0.5.1
|
|
89
|
+
bun add @tikoci/quickchr@0.5.1
|
|
90
|
+
quickchr --version
|
|
87
91
|
```
|
|
88
92
|
|
|
89
|
-
|
|
93
|
+
To run an unpublished checkout:
|
|
90
94
|
|
|
91
95
|
```bash
|
|
92
|
-
|
|
96
|
+
git clone https://github.com/tikoci/quickchr
|
|
97
|
+
cd quickchr
|
|
98
|
+
bun install
|
|
99
|
+
bun run dev -- doctor
|
|
93
100
|
```
|
|
94
101
|
|
|
95
102
|
### `quickchr doctor`
|
|
96
103
|
|
|
97
104
|
Reports prerequisite status, accelerator availability, image cache
|
|
98
105
|
size, machine count, free disk space, and shell-completion install
|
|
99
|
-
state.
|
|
106
|
+
state. The disk check measures the data dir's filesystem and warns when free
|
|
107
|
+
space is under `storage-reserve` + 2 GiB. Exit code is `0` when no checks return
|
|
108
|
+
`error` (warnings are OK).
|
|
100
109
|
|
|
101
110
|
```bash
|
|
102
111
|
quickchr doctor # human-readable
|
|
@@ -107,7 +116,9 @@ The `--json` form emits `{ ok, checks, staleImages }`, where `checks` is an
|
|
|
107
116
|
array of `{ label, status, detail }` and `staleImages` lists cached images older
|
|
108
117
|
than the current long-term release. The exit code still reflects `ok`.
|
|
109
118
|
|
|
110
|
-
|
|
119
|
+
`doctor` reports the tested Bun pin and warns when the running runtime is older.
|
|
120
|
+
|
|
121
|
+

|
|
111
122
|
|
|
112
123
|
Use this whenever a `start` fails — the diagnostic almost always points
|
|
113
124
|
at a missing dependency, missing firmware, or insufficient disk.
|
|
@@ -116,7 +127,7 @@ at a missing dependency, missing firmware, or insufficient disk.
|
|
|
116
127
|
|
|
117
128
|
## 3. CLI command reference
|
|
118
129
|
|
|
119
|
-
The dispatcher lives in `src/cli/index.ts
|
|
130
|
+
The dispatcher lives in `src/cli/index.ts`. Help text is
|
|
120
131
|
available for every command via `quickchr help <command>`.
|
|
121
132
|
|
|
122
133
|
### Lifecycle
|
|
@@ -129,14 +140,14 @@ directory, downloads the RouterOS image (cached), and writes
|
|
|
129
140
|
|
|
130
141
|
| Flag | Default | Notes |
|
|
131
142
|
|---|---|---|
|
|
132
|
-
| `--name <s>` | auto | `
|
|
143
|
+
| `--name <s>` | auto | `version-arch-N` if omitted |
|
|
133
144
|
| `--version <ver>` | latest in channel | e.g., `7.22.1` |
|
|
134
145
|
| `--channel <ch>` | `stable` | `stable`, `long-term`, `testing`, `development` |
|
|
135
146
|
| `--arch <a>` | host native | `arm64`, `x86`, or `auto` |
|
|
136
147
|
| `--cpu <n>` | `1` | vCPU count |
|
|
137
148
|
| `--mem <mb>` | `512` | RAM (cross-arch TCG bumps to `1024`) |
|
|
138
149
|
| `--boot-disk-format <f>` | `qcow2` | `qcow2` or `raw` |
|
|
139
|
-
| `--boot-size <size>` | — | Resize boot disk; needs `qemu-img`;
|
|
150
|
+
| `--boot-size <size>` | — | Resize qcow2 boot disk; needs `qemu-img`; explicit raw is refused |
|
|
140
151
|
| `--add-disk <size>` | — | Extra blank qcow2 disk; repeatable |
|
|
141
152
|
| `--forward <spec>` | — | Extra hostfwd port or built-in service host-port pin; repeatable. See §Custom port forwards. |
|
|
142
153
|
| `--add-package <pkg>` | — | Provisioning, repeatable, ≥ 7.20.8 |
|
|
@@ -150,6 +161,7 @@ directory, downloads the RouterOS image (cached), and writes
|
|
|
150
161
|
| `--device-mode <m>` | — | `rose`, `advanced`, `basic`, `home`, `auto`, `skip`, ≥ 7.20.8 |
|
|
151
162
|
| `--device-mode-enable <f,...>` | — | Repeatable, comma-separated |
|
|
152
163
|
| `--device-mode-disable <f,...>` | — | Repeatable, comma-separated |
|
|
164
|
+
| `--no-device-mode` | — | Skip device-mode provisioning entirely |
|
|
153
165
|
| `--add-network <spec>` | `user` | See §7. Repeatable. |
|
|
154
166
|
| `--no-network` | false | Headless, no NICs |
|
|
155
167
|
| `--no-winbox` | false | Exclude WinBox port |
|
|
@@ -168,15 +180,19 @@ stdio to your terminal (`--fg`). Accepts the same provisioning flags as `add`.
|
|
|
168
180
|
QEMU runs detached in its own session either way, so it survives a signal to the
|
|
169
181
|
shell that started it.
|
|
170
182
|
|
|
183
|
+
When `<name>` matches no machine (a typo, or one removed earlier), `start` creates a
|
|
184
|
+
factory CHR under that name and says so: `<name> created and started`, or
|
|
185
|
+
`created — not waiting for RouterOS` with `--no-wait`. A machine that already
|
|
186
|
+
existed, including one made by `add`, prints `started`.
|
|
187
|
+
|
|
171
188
|
Additional flags:
|
|
172
189
|
|
|
173
190
|
| Flag | Notes |
|
|
174
191
|
|---|---|
|
|
175
|
-
| `--all` | Start every stopped machine in background; accepts readiness, acceleration, timeout and secure-login options only. Other options are refused rather than ignored |
|
|
192
|
+
| `--all` | Start every stopped machine in background; accepts readiness, acceleration, timeout and secure-login options only. Other options are refused rather than ignored. `--secure-login` is resolved per machine: one that has never booted creates the managed login; one that already booted accepts it as a no-op only if it already has one, and is refused otherwise. With `--no-wait`, a never-booted machine refuses it (provisioning needs the wait). Machines start one at a time, so a refusal stops the batch after the earlier machines have started |
|
|
176
193
|
| `--no-wait` | Return as soon as QEMU is running (past the 1.5 s early-exit check), with state and ports persisted; do not wait for RouterOS. Refused with any provisioning flag, including first-boot options `add` recorded, and with `--fg` |
|
|
177
194
|
| `--fg` / `--foreground` (alias `--no-bg`, `--no-background`) | Serial console on stdio |
|
|
178
195
|
| `--bg` / `--background` | **Deprecated, does nothing.** Background is the default, and the flag never made `start` return early — it only ever chose where the serial console went. Prints a warning; use `--no-wait` |
|
|
179
|
-
| `--install-deps` | Auto-install missing host deps (calls package manager) |
|
|
180
196
|
| `--timeout-extra <s>` / `-T <s>` | Add extra seconds to computed boot timeout |
|
|
181
197
|
| `--dry-run` | Print resolved options and QEMU command, exit |
|
|
182
198
|
|
|
@@ -394,7 +410,8 @@ the Library API reference.
|
|
|
394
410
|
#### `exec <name> <command> [--via=auto|rest|qga|console|ssh] [--user u] [--password p] [--timeout=ms]`
|
|
395
411
|
|
|
396
412
|
Run a RouterOS CLI command. See §12 for transport details and JSON
|
|
397
|
-
output trick.
|
|
413
|
+
output trick. Exit 0 means the command was delivered, not that RouterOS
|
|
414
|
+
accepted it — see §12 "Exit status" for the pass/fail route.
|
|
398
415
|
|
|
399
416
|
#### `console <name>`
|
|
400
417
|
|
|
@@ -471,7 +488,7 @@ Interactive wizard (`@clack/prompts`) that walks through all machine creation
|
|
|
471
488
|
options and starts the CHR. Triggered by `quickchr setup` or automatically
|
|
472
489
|
when `quickchr` is run with no subcommand on a TTY.
|
|
473
490
|
|
|
474
|
-

|
|
491
|
+

|
|
475
492
|
|
|
476
493
|
**First-run detection**: if no machines exist yet, the wizard opens with a
|
|
477
494
|
welcome message before the first prompt.
|
|
@@ -498,7 +515,10 @@ another machine, view status, or quit.
|
|
|
498
515
|
| 12 | Run mode: background / foreground | background | (default) / `--fg` |
|
|
499
516
|
| 13 | Final confirmation | — | — |
|
|
500
517
|
|
|
501
|
-
|
|
518
|
+
The wizard requires `qemu-img` and refuses before any prompts or image downloads
|
|
519
|
+
when it is absent, showing the install remedy. For a raw x86 boot without `qemu-img`,
|
|
520
|
+
use `quickchr add --arch x86 --boot-disk-format raw` to create a stopped machine,
|
|
521
|
+
then `quickchr start <name>` with the returned name to boot it. Step 10
|
|
502
522
|
only appears when the platform supports networks beyond user-mode (macOS or
|
|
503
523
|
Linux). The provisioning gate (step 11) only appears for RouterOS ≥ 7.20.8;
|
|
504
524
|
older versions show an upgrade prompt.
|
|
@@ -567,6 +587,64 @@ appended directly to `$GITHUB_OUTPUT`.
|
|
|
567
587
|
`--json` intentionally emits one JSON object for programmatic parsing; use the
|
|
568
588
|
default output form when writing step outputs directly.
|
|
569
589
|
|
|
590
|
+
`cache list [--json]` shows each cache entry with its version, arch, size, age
|
|
591
|
+
(time since it was cached or last used) and whether it is in use. Entries are:
|
|
592
|
+
|
|
593
|
+
- **images** (`chr-<ver>[-arm64].img`, and a `.img.zip` not yet extracted). An
|
|
594
|
+
image is **in use** while any machine, running or stopped, was created from
|
|
595
|
+
that version and arch: `clean` and a failed first boot rebuild from it.
|
|
596
|
+
- **package archives** (`packages-<arch>-<ver>`): the `all_packages` ZIP and its
|
|
597
|
+
extraction, sized and deleted together, since the extraction is only a cache
|
|
598
|
+
hit while its ZIP is there. In use while a machine that asks for packages has
|
|
599
|
+
not finished its first boot.
|
|
600
|
+
- **partial** entries: an interrupted download (`*.<pid>-<id>.part`) or
|
|
601
|
+
extraction (`.quickchr-image-*`, `.quickchr-packages-*`). In use while the
|
|
602
|
+
process that wrote it is alive (an extraction: for 30 minutes after its last
|
|
603
|
+
write). `prune` removes stale ones before anything else.
|
|
604
|
+
|
|
605
|
+
`cache list --json` prints an array of entry objects, including `kind` (`image`, `image-zip`,
|
|
606
|
+
`packages` or `partial`) and `paths` (every file deleting the entry removes).
|
|
607
|
+
Files in the cache that quickchr did not write are reported as "Other files"
|
|
608
|
+
and never deleted. `prune` and `clear` never delete an in-use entry.
|
|
609
|
+
|
|
610
|
+
```bash
|
|
611
|
+
quickchr cache list
|
|
612
|
+
quickchr cache prune --older-than 7.22 --dry-run # versions below 7.22
|
|
613
|
+
quickchr cache prune --max-age 30d # not used for more than 30 days
|
|
614
|
+
quickchr cache prune --max-size 2G # oldest versions first, until <= 2 GiB
|
|
615
|
+
quickchr cache clear --all # every entry not in use
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
`prune` needs at least one of `--older-than <ver>`, `--max-age <dur>` or
|
|
619
|
+
`--max-size <size>`, and applies them in that order when combined. `--max-size`
|
|
620
|
+
evicts the oldest RouterOS version first (oldest cache time breaks ties) until
|
|
621
|
+
the total, in-use entries included, fits. Durations are `<N>(s|m|h|d|w)`; sizes
|
|
622
|
+
are `<N>(K|M|G|T)` with an optional `i`/`B`, read as IEC binary. `--dry-run`
|
|
623
|
+
lists what `prune` or `clear` would delete without deleting it. `clear` refuses
|
|
624
|
+
without `--all`. A delete that fails is listed on stderr, is not counted as
|
|
625
|
+
freed, and makes the command exit 1. A cache hit counts as a use, so `--max-age`
|
|
626
|
+
measures time since an entry was last used.
|
|
627
|
+
|
|
628
|
+
Separately, a successful `start` prunes to the `cache-max-size` setting (default
|
|
629
|
+
`2G`; see `settings` below). That automatic prune, and the one below, skip any
|
|
630
|
+
entry used in the last 30 minutes, which another create may be reading.
|
|
631
|
+
|
|
632
|
+
**Disk space.** Creating a machine (`add`, or `start` with a new name) and
|
|
633
|
+
filling the cache (an image or package download) are admitted when each
|
|
634
|
+
filesystem the operation writes to has room for what it writes there plus the
|
|
635
|
+
`storage-reserve` setting (default `2G`), less what other quickchr operations
|
|
636
|
+
in progress have already claimed. The estimate is the boot disk
|
|
637
|
+
(192 MiB), plus an image download (256 MiB) and a package download (192 MiB)
|
|
638
|
+
when those are not cached yet, so a cold create needs about 2.6 GiB free and a
|
|
639
|
+
warm one about 2.2 GiB. When there is not enough, quickchr first evicts what the
|
|
640
|
+
cache can spare on that filesystem (oldest version first; never entries a
|
|
641
|
+
machine or an operation in progress needs, nor recently used ones), measures
|
|
642
|
+
again until there is room or nothing more can go, and only then refuses with `INSUFFICIENT_DISK_SPACE`,
|
|
643
|
+
naming the free space, what it needed, what it evicted and what it kept.
|
|
644
|
+
Restarting an existing machine, `stop`, `remove` and read-only commands are
|
|
645
|
+
never gated. The estimate covers creation, not a guest that later fills its
|
|
646
|
+
disk: extra disks and `--boot-size` are sparse and grow as the guest writes.
|
|
647
|
+
|
|
570
648
|
#### `settings [print|get|set|reset] [key] [value] [--json]`
|
|
571
649
|
|
|
572
650
|
Manage quickchr's own global preferences — repeated flags/defaults that
|
|
@@ -583,6 +661,7 @@ Precedence per key (highest wins): CLI flag > `QUICKCHR_<KEY>` env var >
|
|
|
583
661
|
| `default-arch` | `add`/`start`'s `--arch`, wizard's arch prompt | `arm64`\|`x86`\|`auto` | `auto` (host native) |
|
|
584
662
|
| `accel` | `add`/`start`'s `--accel`; every `detectAccel()` call in the run | `auto`\|`tcg`\|`hvf`\|`kvm` | `auto` (detect) |
|
|
585
663
|
| `cache-max-size` | Auto-prune cap applied after each successful `start` | size string (e.g. `2G`, `512M`) | `2G` |
|
|
664
|
+
| `storage-reserve` | Free space creating a machine or filling the cache must leave, beyond what it writes | size string | `2G` |
|
|
586
665
|
| `timeout-extra` | `start`'s `--timeout-extra`/`-T` when omitted | non-negative integer seconds | `0` |
|
|
587
666
|
| `secure-login` | `add`/`start`'s `--secure-login` when neither `--secure-login` nor `--no-secure-login` is passed | boolean | `unset` (reported as `(unset)` — see note) |
|
|
588
667
|
|
|
@@ -601,7 +680,7 @@ the wizard's own recommended "managed login" highlighted). Giving it a real
|
|
|
601
680
|
the setting resolves to exactly `true`.
|
|
602
681
|
|
|
603
682
|
```bash
|
|
604
|
-
quickchr settings print # all
|
|
683
|
+
quickchr settings print # all 7 keys, resolved value + source
|
|
605
684
|
quickchr settings set default-channel testing # write one key to quickchr.env
|
|
606
685
|
quickchr settings get default-arch # print one key's resolved value
|
|
607
686
|
quickchr settings reset default-channel # delete one managed line
|
|
@@ -609,14 +688,14 @@ quickchr settings reset # clear all managed lines
|
|
|
609
688
|
```
|
|
610
689
|
|
|
611
690
|
Credentials (`--add-user`, `MIKROTIK_WEB_ACCOUNT`/`MIKROTIK_WEB_PASSWORD`) are
|
|
612
|
-
never stored here — `settings` only manages the
|
|
691
|
+
never stored here — `settings` only manages the 7 keys above, and does not
|
|
613
692
|
mutate any machine's `machine.json`.
|
|
614
693
|
|
|
615
694
|
### Global behavior
|
|
616
695
|
|
|
617
696
|
| Env var | Effect |
|
|
618
697
|
|---|---|
|
|
619
|
-
| `QUICKCHR_DATA_DIR` | Override the data root (defaults to
|
|
698
|
+
| `QUICKCHR_DATA_DIR` | Override the data root (defaults to `~/.local/share/quickchr` on POSIX or the Windows path — see §8) |
|
|
620
699
|
| `QUICKCHR_NO_PROMPT` | Force non-interactive mode (skips all wizards) |
|
|
621
700
|
| `QUICKCHR_DEBUG` | Emit `[debug]` lines from the progress logger |
|
|
622
701
|
| `QUICKCHR_INTEGRATION` | Required to run `test/integration/` |
|
|
@@ -824,14 +903,14 @@ redact before logging or attaching to bug reports.
|
|
|
824
903
|
| Field | Type | Default | Notes |
|
|
825
904
|
|---|---|---|---|
|
|
826
905
|
| `name` | string | auto | Must not start with `-` |
|
|
827
|
-
| `version` | string | — |
|
|
906
|
+
| `version` | string | — | Wins over `channel`: passing both warns and uses `version` |
|
|
828
907
|
| `channel` | Channel | `"stable"` | |
|
|
829
908
|
| `arch` | `"arm64" \| "x86"` | host | |
|
|
830
909
|
| `cpu` | number | `1` | |
|
|
831
910
|
| `mem` | number | `512` (1024 cross-arch TCG) | MiB |
|
|
832
911
|
| `background` | boolean | `true` | Where the serial console goes — not whether `start()` waits |
|
|
833
912
|
| `wait` | boolean | `true` | `false` resolves once QEMU is running and leaves readiness to the caller (`instance.waitForBoot()`); refused with provisioning or `background: false` (`INVALID_ARGUMENT`) |
|
|
834
|
-
| `bootDiskFormat` | `"raw" \| "qcow2"` | `"raw"` (auto-`qcow2` if `bootSize`) | |
|
|
913
|
+
| `bootDiskFormat` | `"raw" \| "qcow2"` | `"raw"` (auto-`qcow2` if `bootSize`) | The CLI always passes a format, defaulting to `qcow2`; the `"raw"` default applies to library callers only |
|
|
835
914
|
| `bootSize` | string | — | e.g., `"512M"`, `"2G"`. Needs `qemu-img` |
|
|
836
915
|
| `extraDisks` | string[] | `[]` | Each entry is a size string |
|
|
837
916
|
| `networks` | NetworkSpecifier[] | `["user"]` | See §7 |
|
|
@@ -845,7 +924,7 @@ redact before logging or attaching to bug reports.
|
|
|
845
924
|
| `secureLogin` | boolean | `false` | **`true` is the explicit trigger** for managed-account creation |
|
|
846
925
|
| `license` | `LicenseInput` | — | `"p1"` / `"p10"` / `"unlimited"` or `LicenseOptions` |
|
|
847
926
|
| `deviceMode` | `DeviceModeOptions` | — | `{mode?, enable?[], disable?[]}` |
|
|
848
|
-
| `installDeps` | boolean | — |
|
|
927
|
+
| `installDeps` | boolean | — | **Deprecated, ignored.** Never installed anything; run `quickchr doctor` for install hints |
|
|
849
928
|
| `dryRun` | boolean | `false` | Print QEMU command and exit |
|
|
850
929
|
| `timeoutExtra` | number | `0` | Extra **milliseconds** added to boot timeout |
|
|
851
930
|
| `onProgress` | `(msg) => void` | `console.log` | `[debug]` lines only when `QUICKCHR_DEBUG=1` |
|
|
@@ -1183,10 +1262,10 @@ restrictions, half-open SLiRP under TCG), see `docs/networking.md`.
|
|
|
1183
1262
|
|
|
1184
1263
|
## 8. Storage layout
|
|
1185
1264
|
|
|
1186
|
-
### macOS / Linux
|
|
1265
|
+
### macOS / Linux
|
|
1187
1266
|
|
|
1188
1267
|
```text
|
|
1189
|
-
|
|
1268
|
+
~/.local/share/quickchr/
|
|
1190
1269
|
├── .allocate.lock/ held while a new machine picks its ports/MACs
|
|
1191
1270
|
├── cache/ Downloaded RouterOS images
|
|
1192
1271
|
│ ├── chr-7.22.1.img.zip
|
|
@@ -1195,8 +1274,8 @@ $XDG_DATA_HOME/quickchr/ (defaults to ~/.local/share/quickchr/)
|
|
|
1195
1274
|
├── machines/
|
|
1196
1275
|
│ └── <name>/
|
|
1197
1276
|
│ ├── machine.json Persisted MachineState
|
|
1198
|
-
│ ├──
|
|
1199
|
-
│ ├──
|
|
1277
|
+
│ ├── boot.qcow2 | disk.img boot disk: qcow2 (CLI default) or raw — one, not both
|
|
1278
|
+
│ ├── disk<N>.qcow2 extra disks
|
|
1200
1279
|
│ ├── efi-vars.fd arm64 only (UEFI vars)
|
|
1201
1280
|
│ ├── monitor.sock QEMU monitor
|
|
1202
1281
|
│ ├── serial.sock serial console
|
|
@@ -1209,8 +1288,8 @@ $XDG_DATA_HOME/quickchr/ (defaults to ~/.local/share/quickchr/)
|
|
|
1209
1288
|
└── <name>.json
|
|
1210
1289
|
```
|
|
1211
1290
|
|
|
1212
|
-
|
|
1213
|
-
whole tree with `QUICKCHR_DATA_DIR=/some/path`.
|
|
1291
|
+
The data root is `~/.local/share/quickchr/`; `XDG_DATA_HOME` does not
|
|
1292
|
+
change it. Override the whole tree with `QUICKCHR_DATA_DIR=/some/path`.
|
|
1214
1293
|
|
|
1215
1294
|
**Global settings** live separately, under the XDG **config** tier, not this
|
|
1216
1295
|
data tree: `~/.config/quickchr/quickchr.env` (dotenv-style). See §3's
|
|
@@ -1224,7 +1303,7 @@ var list.
|
|
|
1224
1303
|
├── cache\
|
|
1225
1304
|
├── machines\<name>\
|
|
1226
1305
|
│ ├── machine.json
|
|
1227
|
-
│ ├── disk.img
|
|
1306
|
+
│ ├── boot.qcow2 | disk.img
|
|
1228
1307
|
│ ├── monitor (named pipe handle, no on-disk file)
|
|
1229
1308
|
│ └── …
|
|
1230
1309
|
└── …
|
|
@@ -1370,7 +1449,7 @@ managed via `quickchr settings get|set|print|reset` (§3, Meta). Atomic writes
|
|
|
1370
1449
|
preserve every other line (comments, blank lines, foreign vars) byte-for-byte.
|
|
1371
1450
|
`reset <key>` deletes the line entirely rather than blanking it, since a blank
|
|
1372
1451
|
`KEY=` line is still "set" to a bash-sourced file. Never stores credentials —
|
|
1373
|
-
the
|
|
1452
|
+
the 7 managed keys are all structural preferences, not secrets.
|
|
1374
1453
|
|
|
1375
1454
|
### Environment variables consumed
|
|
1376
1455
|
|
|
@@ -1387,6 +1466,7 @@ the 6 managed keys are all structural preferences, not secrets.
|
|
|
1387
1466
|
| `QUICKCHR_DEFAULT_ARCH` | `settings.ts` — env tier for the `default-arch` setting |
|
|
1388
1467
|
| `QUICKCHR_ACCEL` | `settings.ts` / `platform.ts` — env tier for the `accel` setting; forces `-accel` and bypasses detection |
|
|
1389
1468
|
| `QUICKCHR_CACHE_MAX_SIZE` | `settings.ts` — env tier for the `cache-max-size` setting |
|
|
1469
|
+
| `QUICKCHR_STORAGE_RESERVE` | `settings.ts` — env tier for the `storage-reserve` setting |
|
|
1390
1470
|
| `QUICKCHR_SHUTDOWN_TIMEOUT` | CLI `shutdown` grace budget in positive integer seconds; default 10, overridden by `--timeout` |
|
|
1391
1471
|
| `QUICKCHR_TIMEOUT_EXTRA` | `settings.ts` — env tier for the `timeout-extra` setting |
|
|
1392
1472
|
| `QUICKCHR_SECURE_LOGIN` | `settings.ts` — env tier for the `secure-login` setting |
|
|
@@ -1436,6 +1516,29 @@ funnel through the same transport selector.
|
|
|
1436
1516
|
> (see [`docs/centrs-interface.md`](./docs/centrs-interface.md)) — it never reads
|
|
1437
1517
|
> `machine.json`, and neither should you.
|
|
1438
1518
|
|
|
1519
|
+
### Exit status
|
|
1520
|
+
|
|
1521
|
+
`quickchr exec` exits 0 when the command was **delivered**, not when RouterOS
|
|
1522
|
+
accepted it. `/rest/execute` returns HTTP 200 with the rejection text in the same
|
|
1523
|
+
envelope as a success, so a refused command looks like this:
|
|
1524
|
+
|
|
1525
|
+
```console
|
|
1526
|
+
$ quickchr exec my-chr "/user/add name=-2 group=read password=x"; echo "rc=$?"
|
|
1527
|
+
failure: invalid user name (/user/add; line 1)
|
|
1528
|
+
rc=0
|
|
1529
|
+
```
|
|
1530
|
+
|
|
1531
|
+
The library is the same: `chr.exec()` resolves, and `ExecResult` has no failure
|
|
1532
|
+
field. quickchr does not pattern-match RouterOS error text, whose wording changes
|
|
1533
|
+
between versions (#142). When a script needs a pass/fail exit code, run the
|
|
1534
|
+
command through centrs, which validates it first and exits non-zero on a rejection.
|
|
1535
|
+
A write command needs `--yes` outside a TTY; without it centrs refuses with
|
|
1536
|
+
`usage/confirmation-required` (also exit 1) and sends nothing:
|
|
1537
|
+
|
|
1538
|
+
```bash
|
|
1539
|
+
centrs execute --quickchr my-chr --yes "/user/add name=-2 group=read password=x"
|
|
1540
|
+
```
|
|
1541
|
+
|
|
1439
1542
|
### Transports
|
|
1440
1543
|
|
|
1441
1544
|
| `--via` | Source | Notes |
|
|
@@ -1483,12 +1586,16 @@ ceiling.
|
|
|
1483
1586
|
|
|
1484
1587
|
### Boot disk
|
|
1485
1588
|
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1589
|
+
The CLI and wizard default to **qcow2**, converted from the raw MikroTik
|
|
1590
|
+
image before first boot. Creating qcow2 requires `qemu-img` even without resize.
|
|
1591
|
+
`--boot-size` resizes qcow2 to the requested size; explicitly selecting raw
|
|
1592
|
+
with a boot size is refused. Without `--boot-size`, qcow2 keeps the original
|
|
1593
|
+
image size and enables snapshots.
|
|
1489
1594
|
|
|
1490
|
-
|
|
1491
|
-
|
|
1595
|
+
Library callers default to **raw** unless `bootSize` implies qcow2. CLI users
|
|
1596
|
+
can select raw explicitly with `--boot-disk-format raw`. On x86, this permits
|
|
1597
|
+
creation without `qemu-img` when no resize or extra disks are requested. ARM64
|
|
1598
|
+
also needs `qemu-img` for its writable UEFI firmware disk.
|
|
1492
1599
|
|
|
1493
1600
|
### Extra disks
|
|
1494
1601
|
|
|
@@ -1605,7 +1712,7 @@ present, then exits `1`.
|
|
|
1605
1712
|
| `DOWNLOAD_FAILED` | image fetch failed | retry; check connectivity to MikroTik download server |
|
|
1606
1713
|
| `INVALID_VERSION` / `INVALID_ARCH` / `INVALID_NAME` / `INVALID_DISK_SIZE` | argument parse | fix the value |
|
|
1607
1714
|
| `MACHINE_EXISTS` | name already in `machines/` | choose another name or `QuickCHR.get(name)` |
|
|
1608
|
-
| `MACHINE_NOT_FOUND` | name not in `machines
|
|
1715
|
+
| `MACHINE_NOT_FOUND` | name not in `machines/`, or a booted machine's disk file is missing | `quickchr list`; for a missing disk, restore it or `quickchr clean <name>` |
|
|
1609
1716
|
| `MACHINE_RUNNING` / `MACHINE_STOPPED` | wrong lifecycle state | `start` or `stop` first |
|
|
1610
1717
|
| `MACHINE_LOCKED` | another operation holds the machine (the message names it, its pid and age) | wait for it; a `foreground` holder must be quit from its console |
|
|
1611
1718
|
| `EXEC_FAILED` | RouterOS rejected the command (auth, syntax) | check creds, command syntax |
|
|
@@ -1618,7 +1725,7 @@ present, then exits `1`.
|
|
|
1618
1725
|
| `PROVISIONING_VERSION_UNSUPPORTED` | provisioning option on RouterOS < 7.20.8 (including any 6.x) | use `--channel long-term` or pin a `7.20.8+` version |
|
|
1619
1726
|
| `REST_UNAVAILABLE` | REST operation (`exec`, `get`, `rest()`) on a RouterOS 6 machine | use the native API — `centrs … --via native-api --no-validate` |
|
|
1620
1727
|
| `INVALID_ARGUMENT` | a flag combination quickchr will not honour — e.g. `--no-wait` with provisioning | drop one of the two |
|
|
1621
|
-
| `INSUFFICIENT_DISK_SPACE` |
|
|
1728
|
+
| `INSUFFICIENT_DISK_SPACE` | data dir's filesystem has less than the operation's estimate plus `storage-reserve`, even after evicting what the cache could spare | free space, remove machines, lower `storage-reserve`, or move via `QUICKCHR_DATA_DIR` |
|
|
1622
1729
|
| `STATE_ERROR` | snapshot on raw boot disk | recreate with `--boot-disk-format=qcow2` |
|
|
1623
1730
|
| `INVALID_SIZE_STRING` | invalid cache/settings size string | use size syntax like `512M`, `2G`, or `1.5G` |
|
|
1624
1731
|
| `INVALID_SETTING_KEY` | `settings get`/`set`/`reset` received an unrecognized key | `quickchr settings print` to see the managed keys |
|
package/README.md
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
# quickchr
|
|
2
2
|
|
|
3
|
-
> **Experimental** — quickchr is under active development. Most testing has been on
|
|
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, 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
|
-
|
|
9
3
|
CLI and library to download, launch, and manage MikroTik CHR virtual machines via QEMU.
|
|
10
4
|
|
|
11
5
|
## Quick Start
|
|
@@ -14,7 +8,7 @@ CLI and library to download, launch, and manage MikroTik CHR virtual machines vi
|
|
|
14
8
|
|
|
15
9
|
- [Bun](https://bun.sh) runtime
|
|
16
10
|
- [QEMU](https://www.qemu.org) with `qemu-system-x86_64` and/or `qemu-system-aarch64`
|
|
17
|
-
- `qemu-img` for
|
|
11
|
+
- `qemu-img` for default qcow2 creation, the setup wizard, disk resize, extra disks, and snapshots
|
|
18
12
|
- UEFI firmware (edk2) for arm64 CHR
|
|
19
13
|
|
|
20
14
|
Install QEMU:
|
|
@@ -57,10 +51,28 @@ Library:
|
|
|
57
51
|
bun add @tikoci/quickchr
|
|
58
52
|
```
|
|
59
53
|
|
|
54
|
+
### Prerelease QA (0.5.1)
|
|
55
|
+
|
|
56
|
+
0.5.1 is published to npm `next` first; the unqualified install above uses `latest`,
|
|
57
|
+
and 0.5.1 is promoted there once QA passes. Pin this published candidate for
|
|
58
|
+
reproducible CLI or library QA:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
bun install -g @tikoci/quickchr@0.5.1
|
|
62
|
+
bun add @tikoci/quickchr@0.5.1
|
|
63
|
+
quickchr --version
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Use `@next` instead of `@0.5.1` to follow later candidates. See the
|
|
67
|
+
[0.5.1 changelog](./CHANGELOG.md#051--2026-10-22) for the changes since 0.5.0,
|
|
68
|
+
including storage admission, cache accounting, and disk preservation fixes.
|
|
69
|
+
The [0.5.0 notes](./CHANGELOG.md#050--2026-10-22) cover migration from 0.4.x.
|
|
70
|
+
|
|
60
71
|
### CLI Usage
|
|
61
72
|
|
|
62
73
|
The easiest way to start is the interactive wizard — it walks through
|
|
63
|
-
every option and starts the CHR for you
|
|
74
|
+
every option and starts the CHR for you. It requires `qemu-img` and reports
|
|
75
|
+
a missing tool before prompting or downloading:
|
|
64
76
|
|
|
65
77
|
```bash
|
|
66
78
|
quickchr setup
|
|
@@ -184,6 +196,7 @@ reports a forced power cut if the guest does not stop within the grace budget.
|
|
|
184
196
|
| `--install-all-packages` | Install all packages from `all_packages.zip` | |
|
|
185
197
|
| `--add-user <user:pass>` | Create a user after boot | |
|
|
186
198
|
| `--disable-admin` | Disable the default admin account | |
|
|
199
|
+
| `--secure-login` | Create a managed login; use `--disable-admin` to disable admin | |
|
|
187
200
|
| `--no-secure-login` | Keep admin with no password (skip managed account creation) | |
|
|
188
201
|
| `--add-network <spec>` | Add a network NIC (repeatable). Specs: `user`, `shared`, `bridged:<iface>`, `socket::<name>`, `tap:<iface>`. Default: single user NIC. | |
|
|
189
202
|
| `--no-network` | Start with no NICs (headless) | |
|
|
@@ -195,6 +208,7 @@ reports a forced power cut if the guest does not stop within the grace budget.
|
|
|
195
208
|
| `--device-mode <m>` | Configure device-mode: rose\|advanced\|basic\|home\|auto\|skip | |
|
|
196
209
|
| `--device-mode-enable <f>` | Set one or more device-mode flags to yes | |
|
|
197
210
|
| `--device-mode-disable <f>` | Set one or more device-mode flags to no | |
|
|
211
|
+
| `--no-device-mode` | Skip device-mode provisioning entirely | |
|
|
198
212
|
| `--port-base <port>` | Starting port number | Auto (9100+) |
|
|
199
213
|
| `--timeout-extra <s>` | Add extra seconds to the auto-computed boot timeout | |
|
|
200
214
|
| `--dry-run` | Print what would run without executing | |
|
|
@@ -238,11 +252,12 @@ In **foreground** mode, your terminal becomes the CHR serial console. Use these
|
|
|
238
252
|
| `Ctrl-A C` | Toggle QEMU monitor (`quit` to force-stop) |
|
|
239
253
|
| `Ctrl-A H` | List all key shortcuts |
|
|
240
254
|
|
|
241
|
-
> **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.
|
|
255
|
+
> **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.
|
|
242
256
|
|
|
243
257
|
### Disk Support
|
|
244
258
|
|
|
245
|
-
-
|
|
259
|
+
- CLI and wizard boot disks default to qcow2, converted from the raw MikroTik image using `qemu-img`. Library callers default to raw unless `bootSize` implies qcow2.
|
|
260
|
+
- `--boot-size` resizes qcow2 before first boot; explicitly combining raw with a boot size is refused.
|
|
246
261
|
- Extra disks from `--add-disk` are always created as blank qcow2 images.
|
|
247
262
|
- `quickchr clean <name>` removes any resized boot disk and extra disks, then recreates them from the saved machine config.
|
|
248
263
|
- `quickchr disk <name>` shows the stored disk layout. If `qemu-img` is installed, it also shows virtual and actual sizes.
|
|
@@ -437,7 +452,7 @@ afterAll(async () => {
|
|
|
437
452
|
|----------|-------------|
|
|
438
453
|
| `MIKROTIK_WEB_ACCOUNT` | MikroTik.com account email (for license renewal) |
|
|
439
454
|
| `MIKROTIK_WEB_PASSWORD` | MikroTik.com password (for license renewal) |
|
|
440
|
-
| `QUICKCHR_DEFAULT_CHANNEL`, `QUICKCHR_DEFAULT_ARCH`, `QUICKCHR_CACHE_MAX_SIZE`, `QUICKCHR_TIMEOUT_EXTRA`, `QUICKCHR_SECURE_LOGIN` | Env-tier overrides for the
|
|
455
|
+
| `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) |
|
|
441
456
|
| `QUICKCHR_INTEGRATION` | Set to `1` to run integration tests |
|
|
442
457
|
| `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 |
|
|
443
458
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tikoci/quickchr",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
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",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
|
+
".bun-version",
|
|
18
19
|
"src",
|
|
19
20
|
"README.md",
|
|
20
21
|
"DESIGN.md",
|
|
@@ -25,7 +26,7 @@
|
|
|
25
26
|
"lint": "biome check . && tsc --noEmit",
|
|
26
27
|
"lint:biome": "biome check .",
|
|
27
28
|
"lint:typecheck": "tsc --noEmit",
|
|
28
|
-
"lint:markdown": "
|
|
29
|
+
"lint:markdown": "markdownlint-cli2 '**/*.md'",
|
|
29
30
|
"lint:cspell": "cspell lint . --no-progress",
|
|
30
31
|
"lint:examples": "bun run scripts/validate-examples.ts",
|
|
31
32
|
"lint:specifiers": "bun run scripts/validate-network-specifiers.ts",
|