laracrew 0.2.1 → 0.3.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/CHANGELOG.md CHANGED
@@ -1,188 +1,236 @@
1
- # Changelog
2
-
3
- All notable changes to this project are documented here.
4
-
5
- The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
6
- adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). While the version is
7
- below `1.0.0`, minor versions may contain breaking config changes; those are always listed
8
- under **Changed** with a migration note.
9
-
10
- ## [Unreleased]
11
-
12
- Planned, in order — see `.claude/PLAN.md`:
13
-
14
- - `laracrew scan` to discover Laravel projects and scaffold a stack
15
- - Live queue depth and Redis stream consumer lag in the process tree
16
- - File watching with graceful `queue:restart`
17
- - `laracrew run <task>` for one-shot cross-project sequences
18
- - Background daemon: `up --detach`, `attach`, `status`, `logs -f`
19
-
20
- ## [0.2.1] — 2026-09-20
21
-
22
- ### Added
23
-
24
- - **A stack builder**, [`docs/stack-builder.html`](docs/stack-builder.html) — a single self-contained
25
- page that writes a `stack.yaml` from projects and process commands as you fill them in. It
26
- encodes the rules the config resolver enforces, so it catches the mistakes before laracrew does:
27
- a service with no command, `stop.artisan` on a service with no project, a `needs:` pointing at
28
- nothing, an auto-started service depending on one you have to start by hand, a dependency cycle.
29
- It also shows the boot order the `needs:` graph produces, level by level.
30
-
31
- Open it from disk or serve `docs/` with GitHub Pages. It is not part of the npm package — no
32
- runtime dependencies, no build step, nothing to install.
33
-
34
- ## [0.2.0] — 2026-09-20
35
-
36
- Graceful shutdown for any process, not only Laravel queue workers, and a `doctor` that only
37
- applies its Laravel checks to Laravel.
38
-
39
- laracrew has always been able to *run* anything — the supervisor takes a command and knows
40
- nothing about the language behind it. But the two things that made it more than a process
41
- runner, the graceful stop and the pre-flight checks, both assumed PHP. This release closes that
42
- gap. Existing stack files keep working unchanged.
43
-
44
- ### Added
45
-
46
- - **`stop.exec`** — any command as the first step of the stop ladder. It runs in the service's
47
- `cwd`, with the service's environment, and laracrew waits `graceMs` for the process to exit by
48
- itself before escalating to the signal and the tree kill. A Celery worker, a BullMQ consumer or
49
- a Compose project now shuts down as carefully as a queue worker:
50
-
51
- ```yaml
52
- stop: { exec: ["celery", "-A", "app", "control", "shutdown"], graceMs: 25000 }
53
- stop: { exec: "npm run drain", graceMs: 10000 }
54
- stop: { exec: ["docker", "compose", "stop"], graceMs: 30000 }
55
- ```
56
-
57
- - **`doctor` checks external dependencies.** Every `external: true` service is probed through the
58
- `tcp` or `http` gate it already declares, so a stack's Postgres, RabbitMQ or HTTP dependency is
59
- verified before boot — whatever the stack is written in.
60
- - `doctor` reads `REDIS_URL` when a project sets it instead of `REDIS_HOST` / `REDIS_PORT`.
61
-
62
- ### Changed
63
-
64
- - **`stop.artisan` is now shorthand for `stop.exec`.** It resolves to `<project php> artisan
65
- <command>`, run from the project root even when the service sets its own `cwd`. Behaviour for
66
- existing Laravel stacks is unchanged; a service may declare one or the other, not both. A
67
- service that declares its own graceful step now replaces an inherited one in either direction,
68
- so a stack can default to `artisan: queue:restart` and still give one service its own `exec`.
69
- - **`doctor` applies each check only where it means something.** It works out which projects run
70
- PHP (from their commands and from `stop.artisan`) and which talk to Redis (from their `.env`
71
- and their commands). A stack with no PHP in it gets no PHP findings; a stack with no Redis gets
72
- no Redis findings. Laravel stacks see exactly what they saw before.
73
- - A Redis address already covered by an `external: true` service's gate is no longer probed a
74
- second time from the project's `.env`.
75
- - `laracrew --help` and the generated `projects.yaml` no longer describe projects as Laravel-only.
76
- `php:` is documented as what it is: the binary the `stop.artisan` shorthand runs.
77
-
78
- ### Fixed
79
-
80
- - **`laracrew --version` reported `0.1.0` on every release.** The version was a hardcoded
81
- constant that nobody bumped, so `0.1.1` and `0.1.2` both identified themselves as `0.1.0`. It is
82
- now baked in from `package.json` at build time, with a test that fails if the two ever disagree.
83
- - **`stop.artisan` on a service with no project was silently ignored** — the graceful step was
84
- skipped and nothing said so. It is now a config error that names `stop.exec` as the way out.
85
- - **`doctor` failed on a machine without PHP** for a stack that contains no PHP: `php --version`
86
- ran for every declared project and a missing binary was a blocking `✖` with exit code 1.
87
- - **False Redis collision between projects that never touch Redis.** Two projects with no `.env`
88
- both resolved to the same synthesized default namespace and were reported as sharing it.
89
- - The "no `artisan` file" and "`.env` is missing or empty" warnings no longer fire for projects
90
- that are not PHP projects.
91
-
92
- ### Notes
93
-
94
- - 244 tests. The graceful stop step had no coverage before this release; it now has unit tests
95
- for both outcomes (the process exits by itself, and the ladder escalating when it does not),
96
- plus tests for every new config error.
97
- - The npm description and `laracrew --help` now say "your projects" rather than "your Laravel
98
- projects". The README still leads with the Laravel story, which is what the tool was built for.
99
-
100
- ## [0.1.2] — 2026-09-20
101
-
102
- ### Added
103
-
104
- - `repository`, `homepage` and `bugs` metadata, so the npm page links back to the source.
105
-
106
- ## [0.1.1] — 2026-09-20
107
-
108
- First release published to npm. No code changes from `0.1.0`.
109
-
110
- ## [0.1.0] — 2026-09-19
111
-
112
- First release. Boots and supervises the long-running processes of several Laravel projects at
113
- once, from one command.
114
-
115
- ### Added
116
-
117
- **Supervision**
118
-
119
- - Dependency-ordered boot (`needs:`), with independent services started in parallel.
120
- - Readiness gates before a dependent service starts: `tcp`, `http`, `logMatch`, `delayMs`.
121
- - Restart policies (`never`, `on-failure`, `always`) with exponential backoff, a restart
122
- ceiling, and an attempt counter that resets after a service has been stable.
123
- - A Laravel-aware stop ladder: `php artisan queue:restart` (or `horizon:terminate`) first, wait
124
- for the worker to finish the job it is holding, then terminate — and always as a process
125
- tree, so `artisan serve`'s child PHP server and `npm run dev`'s Vite are never orphaned.
126
- - Rollback on a failed boot: a readiness gate that never opens stops everything that had
127
- already started, instead of leaving a half-booted stack behind.
128
- - `external: true` for services laracrew health-checks but never starts, such as Redis.
129
- - `autostart: false` for services defined but not launched, started later on demand.
130
-
131
- **Interface**
132
-
133
- - A full-screen process tree as the default view, which renders no log output at all; logs are
134
- opened one process at a time. Built on plain ANSI — no TUI framework.
135
- - Per-process log inspection, a merged log across all services, restart/stop/start, and help.
136
- - `external: true` dependencies are listed above the tree under their own heading rather than
137
- numbered among the managed processes, so a digit key always selects something startable.
138
- - `--plain` prefixed interleaved logs, selected automatically when stdout is not a TTY.
139
- - `--json` newline-delimited events for scripting.
140
- - A broken pipe (`laracrew up --json | head`) shuts the stack down cleanly instead of crashing.
141
-
142
- **Logs**
143
-
144
- - Every line is written to `~/.laracrew/logs/<stack>/<service>.log`, on by default, rotated by
145
- size. Plain text with a sortable local timestamp and no colour codes, so `grep` works.
146
- - `laracrew logs [service]` reads them back after the fact, with `-n`, `-f`, `--since 10m`,
147
- `--all` to merge every service in time order, and `--list`.
148
- - Writes go through a held file descriptor rather than a stream, so a line reaches disk before
149
- a crashing process can lose it, and rotation can close the handle deterministically — a
150
- rename with an open handle fails outright on Windows.
151
-
152
- **Configuration**
153
-
154
- - `~/.laracrew/` home: `config.yaml`, `projects.yaml`, one folder per stack, tasks, fragments.
155
- - YAML stacks validated against a schema, with errors that name the file, the field, and a
156
- spelling suggestion.
157
- - Interpolation: `${env:VAR}`, `${env:VAR:fallback}`, `${project.path}`, `${project.env:VAR}`,
158
- `${stack.dir}`, `${port:N}`.
159
- - Groups, profiles, `--only` / `--except` filtering, and `services/*.yaml` fragments.
160
-
161
- **Commands**
162
-
163
- - `laracrew init [--examples]`, `ls`, `up`, `doctor`, `link`, `unlink`.
164
- - `laracrew link <stack>` installs a global command that boots one stack, so a project set is
165
- one word to launch. Generated shims are marked, and laracrew refuses to overwrite files it
166
- did not write or to shadow names like `npm` and `git`.
167
-
168
- **Checks (`laracrew doctor`)**
169
-
170
- - Two projects sharing a Redis database *and* a queue or stream name, computing the effective
171
- prefix the way Laravel does (`REDIS_PREFIX`, else a slug of `APP_NAME`) so it does not report
172
- a collision that isn't one.
173
- - `QUEUE_CONNECTION=sync` in a project that runs a queue worker.
174
- - Port clashes, missing project paths, an unreachable Redis, and a PHP binary that will not run.
175
-
176
- ### Notes
177
-
178
- - Requires Node 20 or newer. Windows, macOS and Linux.
179
- - Runtime dependencies: `commander`, `yaml`, `zod`.
180
- - Accepted by the schema but not yet acted on: `watch`, `metrics` (read by `doctor` only), and
181
- `hooks`. Stack files written today stay valid.
182
-
183
- [Unreleased]: https://github.com/vidux/laracrew/compare/v0.2.1...HEAD
184
- [0.2.1]: https://github.com/vidux/laracrew/compare/v0.2.0...v0.2.1
185
- [0.2.0]: https://github.com/vidux/laracrew/compare/v0.1.2...v0.2.0
186
- [0.1.2]: https://github.com/vidux/laracrew/compare/v0.1.1...v0.1.2
187
- [0.1.1]: https://github.com/vidux/laracrew/releases/tag/v0.1.1
188
- [0.1.0]: https://github.com/vidux/laracrew/releases/tag/v0.1.0
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
6
+ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). While the version is
7
+ below `1.0.0`, minor versions may contain breaking config changes; those are always listed
8
+ under **Changed** with a migration note.
9
+
10
+ ## [Unreleased]
11
+
12
+ Planned, in order — see `.claude/PLAN.md`:
13
+
14
+ - `laracrew scan` to discover Laravel projects and scaffold a stack
15
+ - Live queue depth and Redis stream consumer lag in the process tree
16
+ - File watching with graceful `queue:restart`
17
+ - `laracrew run <task>` for one-shot cross-project sequences
18
+ - Background daemon: `up --detach`, `attach`, `status`, `logs -f`
19
+
20
+ ## [0.3.0] — 2026-09-30
21
+
22
+ ### Added
23
+
24
+ - **`laracrew draft`: build a stack without writing YAML.** `laracrew draft dual` starts
25
+ `dual.laracrew.yaml` in the current folder. `laracrew draft add --project api --path D:/work/api
26
+ --command "php artisan queue:work"` appends a service; the project's path is remembered after
27
+ its first mention and defaults to the current folder. `--default-state stopped` defines a
28
+ service that stays idle until you press `s`. `laracrew draft` shows the draft (so does `laracrew draft <name>` once it exists), and
29
+ `laracrew draft publish` validates it with the real schema and installs it under
30
+ `~/.laracrew/stacks/`, with `--link` to also install the global command. Service names are
31
+ derived from the project and the command (`api:queue:work`); `--name` overrides. The draft
32
+ is a plain stack file that can be edited by hand and committed next to the code.
33
+
34
+ ### Changed
35
+
36
+ - **The console got a polish.** Every command now shares one vocabulary of marks — `✔` done,
37
+ `✖` failed, `▲` worth a look, `▸` a next step — with ASCII stand-ins under `LARACREW_ASCII=1`
38
+ or `TERM=dumb`. `ls` counts and aligns its sections, `doctor` names the stack it checked and
39
+ ends with a one-line verdict, `init` and `link` report what they did as a checklist, config
40
+ errors separate the file, the message and the hints, and `--help` is coloured. `up --plain`
41
+ tells a clean exit (`▲ exited (code 0)`) from a crash (`✖ exited (code 1)`).
42
+ - Colour comes from `chalk` 5 (44 KB, no dependencies) instead of the hand-rolled painter. The
43
+ decision stays laracrew's own: `NO_COLOR`, `FORCE_COLOR` and the TTY check behave as before,
44
+ and `FORCE_COLOR=0` now means off, as it does everywhere else.
45
+ - `commander` 12 → 14 for the help styling hooks. One visible side effect: an extra positional
46
+ argument (`laracrew up dual extra`) is now an error instead of being ignored.
47
+
48
+ ## [0.2.2] — 2026-09-30
49
+
50
+ ### Added
51
+
52
+ - **`R` restarts every running process** with one keypress, in dependency order, so a
53
+ dependency is back and ready before the services that need it are bounced. Only what is
54
+ `running` is touched: a service you stopped, one defined with `autostart: false`, one that
55
+ exited on its own and one that gave up all stay exactly as they are. Plain and JSON runs see
56
+ the usual stop and start events plus a notice naming the services.
57
+
58
+ ### Notes
59
+
60
+ - Releases are now built and published by GitHub Actions. `test.yml` runs the suite and the
61
+ packed-tarball smoke test on Windows and Ubuntu for every push and pull request; `publish.yml`
62
+ is a manual release through npm trusted publishing, with a dry-run rehearsal as the default.
63
+ - Three tests left a log file handle open, which made the suite's teardown fail on Windows with
64
+ Node 20. Fixed; 248 tests.
65
+
66
+ ## [0.2.1] — 2026-09-20
67
+
68
+ ### Added
69
+
70
+ - **A stack builder**, [`docs/stack-builder.html`](docs/stack-builder.html) — a single self-contained
71
+ page that writes a `stack.yaml` from projects and process commands as you fill them in. It
72
+ encodes the rules the config resolver enforces, so it catches the mistakes before laracrew does:
73
+ a service with no command, `stop.artisan` on a service with no project, a `needs:` pointing at
74
+ nothing, an auto-started service depending on one you have to start by hand, a dependency cycle.
75
+ It also shows the boot order the `needs:` graph produces, level by level.
76
+
77
+ Open it from disk or serve `docs/` with GitHub Pages. It is not part of the npm package — no
78
+ runtime dependencies, no build step, nothing to install.
79
+
80
+ ## [0.2.0] — 2026-09-20
81
+
82
+ Graceful shutdown for any process, not only Laravel queue workers, and a `doctor` that only
83
+ applies its Laravel checks to Laravel.
84
+
85
+ laracrew has always been able to *run* anything — the supervisor takes a command and knows
86
+ nothing about the language behind it. But the two things that made it more than a process
87
+ runner, the graceful stop and the pre-flight checks, both assumed PHP. This release closes that
88
+ gap. Existing stack files keep working unchanged.
89
+
90
+ ### Added
91
+
92
+ - **`stop.exec`** — any command as the first step of the stop ladder. It runs in the service's
93
+ `cwd`, with the service's environment, and laracrew waits `graceMs` for the process to exit by
94
+ itself before escalating to the signal and the tree kill. A Celery worker, a BullMQ consumer or
95
+ a Compose project now shuts down as carefully as a queue worker:
96
+
97
+ ```yaml
98
+ stop: { exec: ["celery", "-A", "app", "control", "shutdown"], graceMs: 25000 }
99
+ stop: { exec: "npm run drain", graceMs: 10000 }
100
+ stop: { exec: ["docker", "compose", "stop"], graceMs: 30000 }
101
+ ```
102
+
103
+ - **`doctor` checks external dependencies.** Every `external: true` service is probed through the
104
+ `tcp` or `http` gate it already declares, so a stack's Postgres, RabbitMQ or HTTP dependency is
105
+ verified before boot — whatever the stack is written in.
106
+ - `doctor` reads `REDIS_URL` when a project sets it instead of `REDIS_HOST` / `REDIS_PORT`.
107
+
108
+ ### Changed
109
+
110
+ - **`stop.artisan` is now shorthand for `stop.exec`.** It resolves to `<project php> artisan
111
+ <command>`, run from the project root even when the service sets its own `cwd`. Behaviour for
112
+ existing Laravel stacks is unchanged; a service may declare one or the other, not both. A
113
+ service that declares its own graceful step now replaces an inherited one in either direction,
114
+ so a stack can default to `artisan: queue:restart` and still give one service its own `exec`.
115
+ - **`doctor` applies each check only where it means something.** It works out which projects run
116
+ PHP (from their commands and from `stop.artisan`) and which talk to Redis (from their `.env`
117
+ and their commands). A stack with no PHP in it gets no PHP findings; a stack with no Redis gets
118
+ no Redis findings. Laravel stacks see exactly what they saw before.
119
+ - A Redis address already covered by an `external: true` service's gate is no longer probed a
120
+ second time from the project's `.env`.
121
+ - `laracrew --help` and the generated `projects.yaml` no longer describe projects as Laravel-only.
122
+ `php:` is documented as what it is: the binary the `stop.artisan` shorthand runs.
123
+
124
+ ### Fixed
125
+
126
+ - **`laracrew --version` reported `0.1.0` on every release.** The version was a hardcoded
127
+ constant that nobody bumped, so `0.1.1` and `0.1.2` both identified themselves as `0.1.0`. It is
128
+ now baked in from `package.json` at build time, with a test that fails if the two ever disagree.
129
+ - **`stop.artisan` on a service with no project was silently ignored** — the graceful step was
130
+ skipped and nothing said so. It is now a config error that names `stop.exec` as the way out.
131
+ - **`doctor` failed on a machine without PHP** for a stack that contains no PHP: `php --version`
132
+ ran for every declared project and a missing binary was a blocking `✖` with exit code 1.
133
+ - **False Redis collision between projects that never touch Redis.** Two projects with no `.env`
134
+ both resolved to the same synthesized default namespace and were reported as sharing it.
135
+ - The "no `artisan` file" and "`.env` is missing or empty" warnings no longer fire for projects
136
+ that are not PHP projects.
137
+
138
+ ### Notes
139
+
140
+ - 244 tests. The graceful stop step had no coverage before this release; it now has unit tests
141
+ for both outcomes (the process exits by itself, and the ladder escalating when it does not),
142
+ plus tests for every new config error.
143
+ - The npm description and `laracrew --help` now say "your projects" rather than "your Laravel
144
+ projects". The README still leads with the Laravel story, which is what the tool was built for.
145
+
146
+ ## [0.1.2] — 2026-09-20
147
+
148
+ ### Added
149
+
150
+ - `repository`, `homepage` and `bugs` metadata, so the npm page links back to the source.
151
+
152
+ ## [0.1.1] — 2026-09-20
153
+
154
+ First release published to npm. No code changes from `0.1.0`.
155
+
156
+ ## [0.1.0] — 2026-09-19
157
+
158
+ First release. Boots and supervises the long-running processes of several Laravel projects at
159
+ once, from one command.
160
+
161
+ ### Added
162
+
163
+ **Supervision**
164
+
165
+ - Dependency-ordered boot (`needs:`), with independent services started in parallel.
166
+ - Readiness gates before a dependent service starts: `tcp`, `http`, `logMatch`, `delayMs`.
167
+ - Restart policies (`never`, `on-failure`, `always`) with exponential backoff, a restart
168
+ ceiling, and an attempt counter that resets after a service has been stable.
169
+ - A Laravel-aware stop ladder: `php artisan queue:restart` (or `horizon:terminate`) first, wait
170
+ for the worker to finish the job it is holding, then terminate — and always as a process
171
+ tree, so `artisan serve`'s child PHP server and `npm run dev`'s Vite are never orphaned.
172
+ - Rollback on a failed boot: a readiness gate that never opens stops everything that had
173
+ already started, instead of leaving a half-booted stack behind.
174
+ - `external: true` for services laracrew health-checks but never starts, such as Redis.
175
+ - `autostart: false` for services defined but not launched, started later on demand.
176
+
177
+ **Interface**
178
+
179
+ - A full-screen process tree as the default view, which renders no log output at all; logs are
180
+ opened one process at a time. Built on plain ANSI — no TUI framework.
181
+ - Per-process log inspection, a merged log across all services, restart/stop/start, and help.
182
+ - `external: true` dependencies are listed above the tree under their own heading rather than
183
+ numbered among the managed processes, so a digit key always selects something startable.
184
+ - `--plain` prefixed interleaved logs, selected automatically when stdout is not a TTY.
185
+ - `--json` newline-delimited events for scripting.
186
+ - A broken pipe (`laracrew up --json | head`) shuts the stack down cleanly instead of crashing.
187
+
188
+ **Logs**
189
+
190
+ - Every line is written to `~/.laracrew/logs/<stack>/<service>.log`, on by default, rotated by
191
+ size. Plain text with a sortable local timestamp and no colour codes, so `grep` works.
192
+ - `laracrew logs [service]` reads them back after the fact, with `-n`, `-f`, `--since 10m`,
193
+ `--all` to merge every service in time order, and `--list`.
194
+ - Writes go through a held file descriptor rather than a stream, so a line reaches disk before
195
+ a crashing process can lose it, and rotation can close the handle deterministically — a
196
+ rename with an open handle fails outright on Windows.
197
+
198
+ **Configuration**
199
+
200
+ - `~/.laracrew/` home: `config.yaml`, `projects.yaml`, one folder per stack, tasks, fragments.
201
+ - YAML stacks validated against a schema, with errors that name the file, the field, and a
202
+ spelling suggestion.
203
+ - Interpolation: `${env:VAR}`, `${env:VAR:fallback}`, `${project.path}`, `${project.env:VAR}`,
204
+ `${stack.dir}`, `${port:N}`.
205
+ - Groups, profiles, `--only` / `--except` filtering, and `services/*.yaml` fragments.
206
+
207
+ **Commands**
208
+
209
+ - `laracrew init [--examples]`, `ls`, `up`, `doctor`, `link`, `unlink`.
210
+ - `laracrew link <stack>` installs a global command that boots one stack, so a project set is
211
+ one word to launch. Generated shims are marked, and laracrew refuses to overwrite files it
212
+ did not write or to shadow names like `npm` and `git`.
213
+
214
+ **Checks (`laracrew doctor`)**
215
+
216
+ - Two projects sharing a Redis database *and* a queue or stream name, computing the effective
217
+ prefix the way Laravel does (`REDIS_PREFIX`, else a slug of `APP_NAME`) so it does not report
218
+ a collision that isn't one.
219
+ - `QUEUE_CONNECTION=sync` in a project that runs a queue worker.
220
+ - Port clashes, missing project paths, an unreachable Redis, and a PHP binary that will not run.
221
+
222
+ ### Notes
223
+
224
+ - Requires Node 20 or newer. Windows, macOS and Linux.
225
+ - Runtime dependencies: `commander`, `yaml`, `zod`.
226
+ - Accepted by the schema but not yet acted on: `watch`, `metrics` (read by `doctor` only), and
227
+ `hooks`. Stack files written today stay valid.
228
+
229
+ [Unreleased]: https://github.com/vidux/laracrew/compare/v0.3.0...HEAD
230
+ [0.3.0]: https://github.com/vidux/laracrew/compare/v0.2.2...v0.3.0
231
+ [0.2.2]: https://github.com/vidux/laracrew/compare/v0.2.1...v0.2.2
232
+ [0.2.1]: https://github.com/vidux/laracrew/compare/v0.2.0...v0.2.1
233
+ [0.2.0]: https://github.com/vidux/laracrew/compare/v0.1.2...v0.2.0
234
+ [0.1.2]: https://github.com/vidux/laracrew/compare/v0.1.1...v0.1.2
235
+ [0.1.1]: https://github.com/vidux/laracrew/releases/tag/v0.1.1
236
+ [0.1.0]: https://github.com/vidux/laracrew/releases/tag/v0.1.0
package/README.md CHANGED
@@ -160,6 +160,23 @@ a browser. Add your projects and the commands that run under them, and it writes
160
160
  as you go — checking the same rules laracrew does, so a stack that looks right there boots. No
161
161
  install, no build step; it is one file.
162
162
 
163
+ **Or build it from the command line**, one service at a time, from inside the project:
164
+
165
+ ```bash
166
+ cd D:/work/api
167
+ laracrew draft dual # starts ./dual.laracrew.yaml
168
+ laracrew draft add --project api --command "php artisan queue:work" # --path defaults to this folder
169
+ laracrew draft add --project api --command "php artisan schedule:work" # the path is remembered
170
+ laracrew draft add --project portal --path D:/work/portal --command "php artisan queue:work"
171
+ laracrew draft add --project portal --command "npm run dev" --default-state stopped # idle until you press s
172
+ laracrew draft publish # validates it, installs ~/.laracrew/stacks/dual
173
+ ```
174
+
175
+ `laracrew draft` on its own shows what the draft holds. Service names come from the project and
176
+ the command (`api:queue:work`, `portal:dev`); `--name` overrides. The draft is a plain
177
+ `stack.yaml`: edit it by hand, keep it next to the code, commit it. `publish` checks it with the
178
+ same rules as any other stack, and `--link` also installs the global command (`dual`).
179
+
163
180
  ---
164
181
 
165
182
  ## One command per project set
@@ -172,7 +189,7 @@ laracrew link dual
172
189
  ```
173
190
 
174
191
  ```
175
- created dual -> laracrew up dual
192
+ ✔ created dual → laracrew up dual
176
193
 
177
194
  in C:\Users\you\AppData\Roaming\npm
178
195
 
@@ -310,6 +327,7 @@ the stack with a message naming both services rather than hanging.
310
327
  | `esc` | Back to the tree |
311
328
  | `a` | Merged log across every service - the firehose, on demand |
312
329
  | `r` | Restart the selected process (graceful: `queue:restart` first) |
330
+ | `R` | Restart every running process, in dependency order. Stopped, idle and failed ones stay as they are |
313
331
  | `s` | Stop it, or start it again if stopped |
314
332
  | `f` / `g` / `G` | Follow-pause tailing; jump to top or bottom |
315
333
  | `?` | Help |
@@ -466,6 +484,9 @@ profiles:
466
484
 
467
485
  ```bash
468
486
  laracrew init [--examples] # create ~/.laracrew; --examples adds a demo stack + template
487
+ laracrew draft [name] # start a stack draft in this folder, or show it
488
+ laracrew draft add --command "…" [--project key] [--path dir] [--name svc] [--default-state stopped]
489
+ laracrew draft publish [--force] [--link] # validate the draft and install it under ~/.laracrew
469
490
  laracrew ls [--json] # list stacks, projects and tasks
470
491
  laracrew doctor [stack] # check a stack before booting it
471
492
  laracrew up [stack] [options] # boot the fleet and supervise it
@@ -498,6 +519,8 @@ laracrew up dual --json | jq 'select(.type=="service:exit")'
498
519
  ### What `doctor` checks
499
520
 
500
521
  ```
522
+ doctor · dual
523
+
501
524
  ✔ stack "dual" is valid — 8 services
502
525
  ✔ php: PHP 8.3.11 (cli)
503
526
  ✖ api and portal share Redis 127.0.0.1:6379/0# AND queue(s): default
@@ -506,6 +529,8 @@ laracrew up dual --json | jq 'select(.type=="service:exit")'
506
529
  jobs run inline on dispatch, so the worker will sit idle forever — set it to redis or database
507
530
  ✖ port 8000 is already in use
508
531
  ▲ redis not reachable at 127.0.0.1:6380
532
+
533
+ ✖ 3 problems, 1 warning
509
534
  ```
510
535
 
511
536
  Exit code is 1 when anything is at `✖`, so it drops straight into a pre-flight script.
@@ -518,11 +543,15 @@ commands say it talks to Redis. Run `doctor` on a Django or Node stack and you g
518
543
  that apply to it, not a wall of PHP complaints:
519
544
 
520
545
  ```
546
+ doctor · django-celery
547
+
521
548
  ✔ stack "django-celery" is valid — 8 services
522
549
  ✔ port 8000 is free
523
550
  ✔ postgres is reachable — tcp 127.0.0.1:5432
524
551
  ▲ redis is not reachable — tcp 127.0.0.1:6379 (ECONNREFUSED)
525
552
  laracrew never starts an external service; anything that needs it will wait at its gate
553
+
554
+ ✔ no blocking problems, 1 warning
526
555
  ```
527
556
 
528
557
  Services marked `external: true` are checked through the gate they already declare, so whatever
@@ -580,13 +609,13 @@ project, `LARACREW_PROJECT=<key>`.
580
609
 
581
610
  ## Status
582
611
 
583
- **v0.2.1 — supervisor and full-screen view are built and tested.**
612
+ **v0.3.0 — supervisor, full-screen view and `laracrew draft` are built and tested.**
584
613
 
585
614
  Working now: config pipeline, dependency-ordered boot with readiness gates, restart policies with
586
615
  exponential backoff, the graceful stop ladder — `stop.exec` for any process, `stop.artisan` as the
587
- Laravel shorthand — the full-screen process tree with per-process log inspection, logs persisted to
588
- disk with `laracrew logs` to read them back, plain and JSON renderers, per-stack global commands
589
- (`link` / `unlink`), `doctor`, `init`, `ls`.
616
+ Laravel shorthand — the full-screen process tree with per-process log inspection and a one-key
617
+ restart of everything running, logs persisted to disk with `laracrew logs` to read them back,
618
+ plain and JSON renderers, per-stack global commands (`link` / `unlink`), `doctor`, `init`, `ls`.
590
619
 
591
620
  See [CHANGELOG.md](CHANGELOG.md) for what changed in each release.
592
621
 
@@ -620,15 +649,15 @@ The full plan lives in [.claude/PLAN.md](.claude/PLAN.md), with the design in
620
649
  npm install
621
650
  npm run dev -- up example # tsx, no build step
622
651
  npm run build # tsup -> dist/index.js
623
- npm test # vitest, 244 tests
652
+ npm test # vitest, 281 tests
624
653
  npm run typecheck
625
654
  npm link # put `laracrew` on PATH while hacking on it
626
655
  ```
627
656
 
628
- Runtime dependencies, in total: `commander`, `yaml`, `zod`. Process spawning, tree-killing and
629
- colour are hand-rolled — see [ARCHITECTURE.md §9](.claude/ARCHITECTURE.md) for why `execa`,
630
- `tree-kill` and `picocolors` were dropped. Startup time is a feature for a tool you run twenty
631
- times a day.
657
+ Runtime dependencies, in total: `commander`, `yaml`, `zod` and `chalk`. Process spawning and
658
+ tree-killing are hand-rolled — see [ARCHITECTURE.md §9](.claude/ARCHITECTURE.md) for why `execa`
659
+ and `tree-kill` were dropped, and what `chalk` costs. Startup time is a feature for a tool you run
660
+ twenty times a day.
632
661
 
633
662
  The test suite spawns real child processes, binds real ports and asserts that no pid survives a
634
663
  shutdown — including a deliberately spawned grandchild and a process that ignores `SIGTERM`. Every
@@ -638,6 +667,51 @@ Architectural rule worth knowing before you contribute: **nothing in `src/core/`
638
667
  `src/cli/`**. Core emits typed events; the plain renderer, the JSON renderer and the coming TUI are
639
668
  all just subscribers. That's what keeps `--plain`, `--detach` and the tests honest.
640
669
 
670
+ ### Try it without installing from npm
671
+
672
+ Five steps from a fresh clone to a running stack, without touching your real `~/.laracrew`:
673
+
674
+ 1. **Clone and install.**
675
+
676
+ ```bash
677
+ git clone https://github.com/vidux/laracrew.git && cd laracrew && npm install
678
+ ```
679
+
680
+ 2. **Point it at a throwaway home.** Everything below reads and writes there, not your real config.
681
+
682
+ ```bash
683
+ export LARACREW_HOME=/tmp/laracrew-try # PowerShell: $env:LARACREW_HOME = "$env:TEMP\laracrew-try"
684
+ ```
685
+
686
+ 3. **Run from source.** `npm run dev` runs `src/index.ts` through `tsx` — no build step, every edit is live.
687
+
688
+ ```bash
689
+ npm run dev -- init --examples
690
+ npm run dev -- doctor example
691
+ npm run dev -- up example # the full-screen view; q quits
692
+ npm run dev -- up example --plain # what a pipe or CI sees
693
+ ```
694
+
695
+ 4. **Run the real binary.** `laracrew link` needs the build, and this is what users get.
696
+
697
+ ```bash
698
+ npm run build && npm link # `laracrew` on your PATH -> this checkout's dist/
699
+ laracrew up example
700
+ npm unlink -g laracrew # when you are done
701
+ ```
702
+
703
+ Rebuild after each change: the link runs `dist/index.js`, not the TypeScript.
704
+
705
+ 5. **Test the exact tarball npm would publish.** The smoke test packs it, installs it into an empty
706
+ directory, runs the installed binary and checks that no child process survived:
707
+
708
+ ```bash
709
+ bash .claude/skills/prepare-for-publish/smoke-test.sh
710
+ ```
711
+
712
+ By hand: `npm pack`, then in an empty directory `npm install ../laracrew/laracrew-<version>.tgz`
713
+ and `npx laracrew --version`.
714
+
641
715
  ## License
642
716
 
643
717
  MIT