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 +236 -188
- package/README.md +84 -10
- package/dist/index.js +1017 -542
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
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.
|
|
21
|
-
|
|
22
|
-
### Added
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
-
|
|
120
|
-
|
|
121
|
-
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
- `
|
|
130
|
-
|
|
131
|
-
**
|
|
132
|
-
|
|
133
|
-
-
|
|
134
|
-
|
|
135
|
-
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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
|
|
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.
|
|
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
|
|
588
|
-
disk with `laracrew logs` to read them back,
|
|
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,
|
|
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
|
|
629
|
-
|
|
630
|
-
`tree-kill` and `
|
|
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
|