@bachbntdev/devcmd 0.0.0-stage → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +849 -2
  3. package/dev +33 -0
  4. package/package.json +47 -4
  5. package/src/cli.js +217 -0
  6. package/src/commands/completion.js +97 -0
  7. package/src/commands/devices.js +26 -0
  8. package/src/commands/docker.js +35 -0
  9. package/src/commands/env.js +52 -0
  10. package/src/commands/frameworks.js +36 -0
  11. package/src/commands/history.js +59 -0
  12. package/src/commands/inspect.js +48 -0
  13. package/src/commands/lifecycle.js +70 -0
  14. package/src/config/index.js +35 -0
  15. package/src/config/user.js +101 -0
  16. package/src/constants.js +23 -0
  17. package/src/devices/android.js +89 -0
  18. package/src/devices/index.js +14 -0
  19. package/src/devices/ios.js +47 -0
  20. package/src/generators/clean-project.js +52 -0
  21. package/src/generators/python-project.js +175 -0
  22. package/src/generators/reset-project.js +16 -0
  23. package/src/handlers/clone.js +73 -0
  24. package/src/handlers/devices.js +78 -0
  25. package/src/handlers/history.js +75 -0
  26. package/src/handlers/json.js +68 -0
  27. package/src/handlers/lifecycle.js +119 -0
  28. package/src/handlers/mcp.js +10 -0
  29. package/src/handlers/scaffold.js +166 -0
  30. package/src/handlers/system.js +135 -0
  31. package/src/handlers/tools.js +66 -0
  32. package/src/handlers/workflow.js +121 -0
  33. package/src/mcp/processes.js +164 -0
  34. package/src/mcp/server.js +32 -0
  35. package/src/mcp/tools.js +389 -0
  36. package/src/openers/built-ins.json +80 -0
  37. package/src/openers/engine.js +51 -0
  38. package/src/openers/index.js +26 -0
  39. package/src/openers/loader.js +89 -0
  40. package/src/openers/schema.js +81 -0
  41. package/src/projects/adapters/android.js +24 -0
  42. package/src/projects/adapters/common.js +24 -0
  43. package/src/projects/adapters/flutter.js +29 -0
  44. package/src/projects/adapters/index.js +30 -0
  45. package/src/projects/adapters/ios.js +35 -0
  46. package/src/projects/adapters/node.js +112 -0
  47. package/src/projects/adapters/python.js +90 -0
  48. package/src/projects/adapters/recipe.js +13 -0
  49. package/src/projects/detect.js +187 -0
  50. package/src/projects/profile.js +175 -0
  51. package/src/projects/recent.js +50 -0
  52. package/src/projects/workspaces.js +96 -0
  53. package/src/recipes/action-runner.js +24 -0
  54. package/src/recipes/built-ins.json +417 -0
  55. package/src/recipes/engine.js +159 -0
  56. package/src/recipes/index.js +34 -0
  57. package/src/recipes/loader.js +82 -0
  58. package/src/recipes/schema.js +225 -0
  59. package/src/runner/captured.js +125 -0
  60. package/src/runner/check.js +93 -0
  61. package/src/runner/command.js +43 -0
  62. package/src/runner/parallel.js +110 -0
  63. package/src/runner/process.js +80 -0
  64. package/src/runtime/execute.js +99 -0
  65. package/src/utils/args.js +219 -0
  66. package/src/utils/interpolate.js +10 -0
package/README.md CHANGED
@@ -1,3 +1,850 @@
1
- # Temporary Holding Version
1
+ # DevCmd
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ DevCmd is an interactive development CLI for scaffolding projects, detecting existing projects, running common lifecycle tasks, and managing Android emulators and iOS simulators.
4
+
5
+ [Download the latest DevCmd release](https://github.com/bachbnt/dev-cmd/releases/latest) | [View all releases](https://github.com/bachbnt/dev-cmd/releases)
6
+
7
+ ## Features
8
+
9
+ - Scaffold JavaScript, mobile, and Python web projects with framework-appropriate defaults.
10
+ - Pass project or device targets directly, or use interactive prompts.
11
+ - Preview commands with `--dry-run`.
12
+ - Select TypeScript/JavaScript, package manager, Git, and ESLint where supported.
13
+ - Inspect device runtime and boot status.
14
+ - Cold boot Android emulators and shut down all iOS simulators.
15
+ - View command history, repeat any recent command, and filter by project.
16
+ - Detect Node.js, Python, Flutter, Android, and iOS projects from any child directory.
17
+ - Use consistent `install`, `run`, `test`, `build`, `clean`, `reset`, and `open` commands.
18
+ - Inspect detected projects and their resolved lifecycle commands before execution.
19
+ - Run framework-aware quality checks with one `dev check` command.
20
+ - Add trusted user-defined framework recipes without changing DevCmd source.
21
+ - Check the local toolchain with `dev doctor`.
22
+ - Store defaults and recently used projects under `~/.devcmd`.
23
+ - Target one package in a monorepo with `--filter`.
24
+ - Lint, format, audit, and upgrade dependencies with the same lifecycle commands.
25
+ - Define project-specific commands and tasks in a trusted `.devcmd.json`.
26
+ - Run an action in several projects at once with `dev parallel`.
27
+ - Manage `.env` files and Docker Compose from the same CLI.
28
+ - Print machine-readable output with `--json`.
29
+ - Let AI agents scaffold, inspect, run, and monitor projects through the built-in MCP server.
30
+
31
+ ## Screenshots
32
+
33
+ | Interactive framework picker (`dev init`) | Interactive options (`dev next`) |
34
+ |:-:|:-:|
35
+ | <img src="docs/screenshots/init.png" alt="dev init: select a framework" width="100%"> | <img src="docs/screenshots/next.png" alt="dev next: project name, TypeScript, package manager, Git and ESLint prompts" width="100%"> |
36
+
37
+ | Preview with `--dry-run` | Toolchain check (`dev doctor`) |
38
+ |:-:|:-:|
39
+ | <img src="docs/screenshots/dry-run.png" alt="dev --dry-run previews for react, next, flutter and angular" width="100%"> | <img src="docs/screenshots/doctor.png" alt="dev doctor: installed development tools" width="100%"> |
40
+
41
+ | Android and iOS devices (`dev devices`) | Framework recipes (`dev recipes`) |
42
+ |:-:|:-:|
43
+ | <img src="docs/screenshots/devices.png" alt="dev devices: Android emulators and iOS simulators" width="100%"> | <img src="docs/screenshots/recipes.png" alt="dev recipes: built-in framework recipes" width="100%"> |
44
+
45
+ <details>
46
+ <summary>All commands (<code>dev help</code>)</summary>
47
+
48
+ <img src="docs/screenshots/help.png" alt="dev help: every command and option" width="60%">
49
+
50
+ </details>
51
+
52
+ ## Requirements
53
+
54
+ - Node.js 20.12 or newer, including npm. CI covers Node.js 20, 22, and 24.
55
+ - Android Studio is only required for Android emulator features.
56
+ - Xcode is only required for iOS simulator features.
57
+ - Framework SDKs are only required for the frameworks you use, such as Flutter or Python.
58
+
59
+ ## Installation
60
+
61
+ ### Install from npm
62
+
63
+ DevCmd is published as the scoped package `@bachbntdev/devcmd`. The unscoped registry package named `devcmd` belongs to a different project, so always include the scope:
64
+
65
+ ```bash
66
+ npm install --global @bachbntdev/devcmd
67
+ dev help
68
+ dev doctor
69
+ ```
70
+
71
+ Run it without installing:
72
+
73
+ ```bash
74
+ npx @bachbntdev/devcmd doctor
75
+ ```
76
+
77
+ Update with `dev update` (it runs `npm install --global @bachbntdev/devcmd@latest`). Remove it with:
78
+
79
+ ```bash
80
+ npm uninstall --global @bachbntdev/devcmd
81
+ ```
82
+
83
+ If you installed an older release from a GitHub archive, it was registered as `devcmd`. Remove it first with `npm uninstall --global devcmd`.
84
+
85
+ ### Download from GitHub
86
+
87
+ Open the latest GitHub Release to view release notes and downloadable source archives:
88
+
89
+ [Download the latest release](https://github.com/bachbnt/dev-cmd/releases/latest)
90
+
91
+ Downloading an archive does not install the CLI automatically. To install straight from GitHub instead of the npm registry, use npm with a GitHub URL below. No repository clone is required.
92
+
93
+ ### Install the current source
94
+
95
+ Install the newest committed source from the `main` branch. This is the installation that matches the current README:
96
+
97
+ ```bash
98
+ npm install --global https://github.com/bachbnt/dev-cmd/archive/refs/heads/main.tar.gz
99
+ ```
100
+
101
+ The installation provides both `dev` and `devcmd`. Verify the CLI and inspect the tools available on your machine:
102
+
103
+ ```bash
104
+ dev help
105
+ dev doctor
106
+ ```
107
+
108
+ You can use the full command name if `dev` conflicts with another executable:
109
+
110
+ ```bash
111
+ devcmd help
112
+ ```
113
+
114
+ No repository checkout, `chmod`, `npm link`, or shell `source` command is needed.
115
+
116
+ When this repository is already available on macOS, double-click `commands/install-remote.command` in Finder to load the newest available source, then verify it with `dev help` and `dev doctor`. If the checkout has local or unpushed changes, the launcher links that source; otherwise it installs GitHub `main`.
117
+
118
+ ### Install a tagged release
119
+
120
+ <!-- devcmd-release-version:start -->
121
+ For a reproducible released snapshot, install a specific GitHub tag. The tag matching the current package version is `v2.7.1`:
122
+
123
+ ```bash
124
+ npm install --global https://github.com/bachbnt/dev-cmd/archive/refs/tags/v2.7.1.tar.gz
125
+ ```
126
+ <!-- devcmd-release-version:end -->
127
+
128
+ Tagged releases can predate features documented on `main`. Check [GitHub Releases](https://github.com/bachbnt/dev-cmd/releases) for newer tags and release notes. These archive URLs do not require Git.
129
+
130
+ ### Update or uninstall
131
+
132
+ Run `dev update`, install a newer release tag, or run the `main` installation command again to update DevCmd. To remove a copy installed from a GitHub archive:
133
+
134
+ ```bash
135
+ npm uninstall --global @bachbntdev/devcmd
136
+ ```
137
+
138
+ Repository contributors can also double-click `commands/install-remote.command` instead of entering setup or update commands manually.
139
+
140
+ When using NVM, global npm packages belong to the active Node.js version. Install DevCmd once for each Node.js version where it should be available. If the command is not found immediately after installation, open a new terminal and check the active npm prefix with `npm config get prefix`.
141
+
142
+ ### Alternative GitHub syntax
143
+
144
+ If Git is installed, npm also accepts this shorter syntax for the latest source on `main`:
145
+
146
+ ```bash
147
+ npm install --global github:bachbnt/dev-cmd
148
+ ```
149
+
150
+ ### Local development only
151
+
152
+ Cloning is only needed when contributing to DevCmd itself. Clone the repository, then run the reusable setup script:
153
+
154
+ ```bash
155
+ git clone https://github.com/bachbnt/dev-cmd.git
156
+ cd dev-cmd
157
+ ./scripts/install-local.sh
158
+ # or
159
+ npm run install-local
160
+ ```
161
+
162
+ The setup installs dependencies and creates an npm symlink from the active Node.js installation to the local repository. Run it once; later source changes are used automatically the next time `dev` runs, without `source ~/.zshrc` or relinking.
163
+
164
+ ## Usage
165
+
166
+ ```bash
167
+ dev <command> [target] [options]
168
+ # or
169
+ devcmd <command> [target] [options]
170
+ ```
171
+
172
+ Interactive project creation with framework selection:
173
+
174
+ ```bash
175
+ dev init
176
+ ```
177
+
178
+ Interactive project creation for a specific framework:
179
+
180
+ ```bash
181
+ dev next
182
+ ```
183
+
184
+ Direct, non-interactive project creation:
185
+
186
+ ```bash
187
+ dev react my-app --typescript --pnpm --git
188
+ dev next my-app --typescript --npm --eslint
189
+ dev angular my-app --pnpm --git
190
+ dev vue my-app --javascript --yarn --no-eslint
191
+ dev django my-app
192
+ dev fastapi my-api
193
+ dev flask my-app
194
+ ```
195
+
196
+ Preview without executing:
197
+
198
+ ```bash
199
+ dev flutter demo --dry-run
200
+ ```
201
+
202
+ Check installed development tools and see how to install the missing ones:
203
+
204
+ ```bash
205
+ dev doctor
206
+ ```
207
+
208
+ Inspect the current project without executing anything:
209
+
210
+ ```bash
211
+ dev inspect
212
+ dev inspect ../my-project
213
+ ```
214
+
215
+ ## Framework Commands
216
+
217
+ | Command | Scaffolder |
218
+ | --- | --- |
219
+ | `flutter` | `flutter create` |
220
+ | `react` | Vite React template for apps built from scratch |
221
+ | `react_native` | Expo via `create-expo-app` (recommended) |
222
+ | `react_native_cli` | React Native Community CLI without a framework |
223
+ | `next` | `create-next-app` |
224
+ | `vue` | Official `create-vue` |
225
+ | `angular` | Angular CLI (`ng new`) |
226
+ | `express` | Official `express-generator` |
227
+ | `nest` | Nest CLI |
228
+ | `django` | Official Django `startproject` inside a local virtual environment |
229
+ | `fastapi` | Minimal FastAPI package with tests and `pyproject.toml` |
230
+ | `flask` | Flask application factory with tests and `pyproject.toml` |
231
+
232
+ Direct targets use recommended defaults: TypeScript, npm, Git, and ESLint where the selected scaffolder supports them. Run a framework command without a target to configure supported presets interactively.
233
+
234
+ React recommends using a framework for new production applications. Use `dev next` for a full-stack React framework, or `dev react` when a client-side Vite application is the right fit. React Native recommends a framework, so `dev react_native` uses Expo; use `dev react_native_cli` only when framework constraints do not fit the project.
235
+
236
+ Angular CLI scaffolds a full TypeScript workspace via `ng new`. DevCmd forwards the package manager and Git flags directly; TypeScript is Angular's default and is not a separate option.
237
+
238
+ Python projects create a local `.venv`, install their declared dependencies, and include development instructions in the generated README. Django uses the official project generator; FastAPI and Flask use small DevCmd templates based on their official recommended layouts.
239
+
240
+ ```bash
241
+ dev django my-app
242
+ dev fastapi my-api --no-git
243
+ dev flask my-app
244
+ ```
245
+
246
+ ```bash
247
+ dev react web-app --typescript --pnpm
248
+ dev react_native mobile-app --typescript --pnpm
249
+ dev react_native_cli NativeApp --yarn
250
+ ```
251
+
252
+ Skip dependency installation where supported:
253
+
254
+ ```bash
255
+ dev next web-app --no-install
256
+ dev fastapi my-api --no-install
257
+ dev django my-app --python python3.13
258
+ ```
259
+
260
+ ## Project Lifecycle
261
+
262
+ Run these commands from a project root or any child directory:
263
+
264
+ ```bash
265
+ dev install
266
+ dev run
267
+ dev test
268
+ dev build
269
+ dev check
270
+ dev lint
271
+ dev format
272
+ dev outdated
273
+ dev upgrade
274
+ dev audit
275
+ dev clean
276
+ dev reset
277
+ dev open
278
+ ```
279
+
280
+ | Action | Node.js | Python | Flutter |
281
+ | --- | --- | --- | --- |
282
+ | `lint` | `lint` script (`lint:fix` with `--fix`) | `ruff check` (`--fix`) | `flutter analyze` |
283
+ | `format` | `format` script | `ruff format` | `dart format .` |
284
+ | `outdated` | `<pm> outdated` | `pip list --outdated` | `flutter pub outdated` |
285
+ | `upgrade` | `<pm> update` (`yarn upgrade`) | `pip install --upgrade -e .[dev]` | `flutter pub upgrade` |
286
+ | `audit` | `<pm> audit` (`yarn npm audit` on Yarn Berry) | `pip_audit` | not supported |
287
+
288
+ `dev outdated` exits with code 1 under npm when outdated packages exist; that is npm behavior, not a DevCmd failure.
289
+
290
+ `dev reset` removes the dependency directory (`node_modules` or `.venv`) and reinstalls from scratch. Flutter runs `flutter clean` then `flutter pub get`. iOS runs `xcodebuild clean` then resolves package dependencies.
291
+
292
+ You can also pass a project path:
293
+
294
+ ```bash
295
+ dev test ../my-api
296
+ dev build ~/Projects/my-app
297
+ dev open cursor ~/Projects/my-app
298
+ ```
299
+
300
+ DevCmd detects projects using files such as `package.json`, `pyproject.toml`, `manage.py`, `pubspec.yaml`, `gradlew`, `.xcworkspace`, and `.xcodeproj`. Node package managers are selected from lockfiles. Node lifecycle commands use the project's `package.json` scripts; Python commands prefer the project's `.venv`.
301
+
302
+ `dev inspect` reports the detected type, root, package manager, and the exact command resolved for every lifecycle action. Unsupported actions are shown with a reason instead of failing the whole inspection.
303
+
304
+ `dev check` runs the quality sequence supported by the detected project:
305
+
306
+ - Node.js: available `lint`, `typecheck`, `test`, then `build` scripts
307
+ - Python: Ruff when configured, then pytest and package build
308
+ - Flutter: analyze then test
309
+ - Android: Gradle lint and test
310
+ - iOS: Xcode analyze and build
311
+
312
+ Current native defaults:
313
+
314
+ - Flutter build: `flutter build apk`
315
+ - Android run/install: `./gradlew installDebug`
316
+ - Android build: `./gradlew assembleDebug`
317
+ - iOS build/test/clean: `xcodebuild` with the detected workspace or project
318
+ - iOS automatic run is intentionally not provided because it requires an explicit scheme and destination
319
+
320
+ ### Monorepos and Workspaces
321
+
322
+ DevCmd detects npm, Yarn, and pnpm workspaces (`workspaces` in `package.json` or `pnpm-workspace.yaml`). `dev inspect` lists them. Target one workspace with `--filter`, using its package name, directory, or directory name:
323
+
324
+ ```bash
325
+ dev test --filter @acme/web
326
+ dev run --filter web
327
+ dev lint --filter apps/api --fix
328
+ dev check --filter web
329
+ ```
330
+
331
+ `--filter` works with `run`, `test`, `build`, `check`, `lint`, `format`, and `task`. It resolves to `npm run <script> --workspace <name>`, `pnpm --filter <name> run <script>`, or `yarn workspace <name> run <script>`, and checks the selected workspace's scripts. Without `--filter`, the commands run in the repository root.
332
+
333
+ ### Tasks
334
+
335
+ `dev task` lists the tasks DevCmd can run: tasks from `.devcmd.json` first, then `package.json` scripts. Run one by name:
336
+
337
+ ```bash
338
+ dev task
339
+ dev task seed
340
+ dev task seed ../my-api
341
+ dev task migrate --filter api
342
+ ```
343
+
344
+ ### Project Profile (`.devcmd.json`)
345
+
346
+ A `.devcmd.json` file at the project root overrides lifecycle actions and defines tasks. It also lets DevCmd drive projects it cannot detect, such as a Go or Make based repository (the project type is `custom`). Commands use the same structured `run` actions as recipes: separate `executable` and `args`, no shell, and the placeholders `{root}`, `{packageManager}`, and `{python}`.
347
+
348
+ ```json
349
+ {
350
+ "name": "my-service",
351
+ "lifecycle": {
352
+ "run": [{ "type": "run", "executable": "go", "args": ["run", "./cmd/server"], "cwd": "{root}" }],
353
+ "test": [{ "type": "run", "executable": "go", "args": ["test", "./..."], "cwd": "{root}" }]
354
+ },
355
+ "tasks": {
356
+ "seed": {
357
+ "description": "Load sample data",
358
+ "commands": [{ "type": "run", "executable": "go", "args": ["run", "./cmd/seed"], "cwd": "{root}" }]
359
+ }
360
+ }
361
+ }
362
+ ```
363
+
364
+ Actions that the profile does not define fall back to the detected project type. A profile executes commands, so DevCmd never runs it until you approve it:
365
+
366
+ ```bash
367
+ dev trust # shows every command, then asks for confirmation
368
+ dev trust --yes # approve without the prompt
369
+ ```
370
+
371
+ Approval is stored in `~/.devcmd/trusted.json` together with a hash of the file. Changing the file requires approval again. Shell executables such as `bash` or `cmd` are rejected, as in recipes. `dev inspect` shows whether the profile is trusted.
372
+
373
+ ### Parallel Execution
374
+
375
+ Run one lifecycle action in several projects at once. Output lines are prefixed with the project name and Ctrl+C stops every child process:
376
+
377
+ ```bash
378
+ dev parallel run ./api ./web
379
+ dev parallel test ./api ./web ./worker
380
+ dev parallel build ./api ./web --dry-run
381
+ ```
382
+
383
+ ### Environment Files
384
+
385
+ ```bash
386
+ dev env # create .env from .env.example, .env.sample, or .env.template (never overwrites)
387
+ dev env check # report variables missing from .env; exits 1 when any are missing
388
+ dev env check ../my-api
389
+ ```
390
+
391
+ Variable values are never printed.
392
+
393
+ ### Docker Compose
394
+
395
+ ```bash
396
+ dev docker up # docker compose up -d
397
+ dev docker logs
398
+ dev docker down
399
+ dev docker build ./services/api
400
+ ```
401
+
402
+ Supported actions are `up`, `down`, `build`, `ps`, `logs`, and `restart`. DevCmd looks for `compose.yaml`, `compose.yml`, `docker-compose.yaml`, or `docker-compose.yml`.
403
+
404
+ ### JSON Output
405
+
406
+ Add `--json` to print machine-readable JSON on stdout for `inspect`, `doctor`, `projects`, `history`, `recipes`, `openers`, `devices`, and `config`. Errors are written to stderr as `{"error": "..."}` and the exit code is 1. `dev doctor --json` exits 1 when a required tool is missing.
407
+
408
+ ```bash
409
+ dev inspect --json | jq '.actions[] | select(.available) | .command'
410
+ dev doctor --json
411
+ ```
412
+
413
+ ### Continuous Integration
414
+
415
+ The repository provides a composite GitHub Action that runs a DevCmd command in your workflow:
416
+
417
+ ```yaml
418
+ - uses: actions/checkout@v4
419
+ - uses: actions/setup-node@v4
420
+ with:
421
+ node-version: 22
422
+ - uses: bachbnt/dev-cmd@main
423
+ with:
424
+ command: check
425
+ path: .
426
+ ```
427
+
428
+ `dev check` returns the failing command's exit code, so the step fails when linting, type checking, tests, or the build fail.
429
+
430
+ ### Project Openers
431
+
432
+ `dev open` uses Visual Studio Code by default. Select another built-in opener with a short positional name:
433
+
434
+ ```bash
435
+ dev open
436
+ dev open cursor
437
+ dev open pycharm ~/Projects/my-api
438
+ dev open webstorm ./frontend
439
+ ```
440
+
441
+ Built-in openers:
442
+
443
+ | Name | Description | Aliases |
444
+ | --- | --- | --- |
445
+ | `vscode` | Visual Studio Code | |
446
+ | `antigravity` | Google Antigravity IDE | |
447
+ | `cursor` | Cursor | |
448
+ | `intellij` | IntelliJ IDEA | |
449
+ | `pycharm` | PyCharm | |
450
+ | `webstorm` | WebStorm | |
451
+ | `android_studio` | Android Studio native project | `android` |
452
+ | `xcode` | Xcode workspace or project | `ios` |
453
+
454
+ Android Studio automatically prefers the detected project's `android/` directory. Xcode opens a detected `.xcworkspace` before `.xcodeproj` and is available only on macOS.
455
+
456
+ ```bash
457
+ dev open android
458
+ dev open ios
459
+ dev open --list
460
+ ```
461
+
462
+ Use `--with` when a path could be confused with an opener name, or use the legacy executable override when an unregistered editor is already available in `PATH`:
463
+
464
+ ```bash
465
+ dev open ./cursor --with vscode
466
+ dev open ./project --editor my-editor
467
+ ```
468
+
469
+ Custom openers are loaded from `~/.devcmd/openers/*.json`. Validate and install one without modifying DevCmd source:
470
+
471
+ ```bash
472
+ dev openers validate ./fleet.json
473
+ mkdir -p ~/.devcmd/openers
474
+ cp ./fleet.json ~/.devcmd/openers/
475
+ dev open fleet ./my-project
476
+ ```
477
+
478
+ Example `fleet.json`:
479
+
480
+ ```json
481
+ {
482
+ "name": "fleet",
483
+ "description": "JetBrains Fleet",
484
+ "target": "project",
485
+ "platforms": {
486
+ "darwin": {
487
+ "executable": "open",
488
+ "args": ["-a", "Fleet", "{target}"]
489
+ },
490
+ "linux": {
491
+ "executable": "fleet",
492
+ "args": ["{target}"]
493
+ }
494
+ }
495
+ }
496
+ ```
497
+
498
+ Supported platforms are `darwin`, `linux`, and `win32`. Supported targets are `project`, `android`, and `xcode`; placeholders are `{target}`, `{root}`, and `{platform}`. Commands always use separate executable and argument arrays. Shell executables and executable placeholders are rejected. A custom opener with the same canonical name overrides its built-in definition.
499
+
500
+ ## Device Commands
501
+
502
+ ```bash
503
+ dev devices
504
+ dev android Pixel_9_Pro_Fold
505
+ dev android Pixel_9_Pro_Fold --cold-boot
506
+ dev ios "iPhone 17 Pro"
507
+ dev ios --shutdown-all
508
+ ```
509
+
510
+ `dev devices` shows device name, runtime, and `Booted`/`Shutdown` status.
511
+
512
+ The standalone `dev android` and `dev ios` commands manage devices. They do not create native source projects.
513
+
514
+ ## Configuration
515
+
516
+ DevCmd stores user defaults in `~/.devcmd/config.json`:
517
+
518
+ ```bash
519
+ dev config
520
+ dev config set packageManager pnpm
521
+ dev config set initializeGit false
522
+ dev config set python python3.13
523
+ dev config set opener cursor
524
+ dev config set notify 10
525
+ ```
526
+
527
+ `notify` sets the notification threshold in seconds. DevCmd sends a system notification when a command runs longer than the threshold. Set to `0` to disable (default).
528
+
529
+ Default configuration:
530
+
531
+ ```json
532
+ {
533
+ "packageManager": "npm",
534
+ "initializeGit": true,
535
+ "python": "python3",
536
+ "opener": "vscode",
537
+ "notify": 0
538
+ }
539
+ ```
540
+
541
+ ## Recent Projects
542
+
543
+ Successful scaffold and lifecycle commands register projects in `~/.devcmd/projects.json`:
544
+
545
+ ```bash
546
+ dev projects
547
+ dev open recent
548
+ ```
549
+
550
+ ## Clone and Update
551
+
552
+ Clone a repository and automatically install its dependencies:
553
+
554
+ ```bash
555
+ dev clone owner/repo
556
+ dev clone owner/repo my-dir
557
+ dev clone https://github.com/owner/repo
558
+ dev clone git@github.com:owner/repo.git
559
+ ```
560
+
561
+ `owner/repo` is treated as a GitHub shorthand. DevCmd detects the project type after cloning and runs `dev install` automatically.
562
+
563
+ Update DevCmd to the latest version from npm:
564
+
565
+ ```bash
566
+ dev update
567
+ ```
568
+
569
+ ## Shell Completion
570
+
571
+ Generate completion for the current shell:
572
+
573
+ ```bash
574
+ dev completion zsh > ~/.zfunc/_dev
575
+ dev completion bash > ~/.devcmd-completion.bash
576
+ ```
577
+
578
+ For Zsh, ensure `~/.zfunc` is included in `fpath`. For Bash, source the generated file from `.bashrc`. Completion generation itself prints a pure shell script, so it can also be evaluated or managed by a dotfiles tool.
579
+
580
+ The generated completion registers both executable names: `dev` and `devcmd`.
581
+
582
+ ## History
583
+
584
+ ```bash
585
+ dev history
586
+ dev history --clear
587
+ dev history --project ~/Projects/my-app
588
+ dev history --search next
589
+ dev again
590
+ dev again 3
591
+ dev again --dry-run
592
+ ```
593
+
594
+ The latest 50 successful commands are stored in `~/.devcmd/history.json`.
595
+
596
+ `dev again <n>` repeats the nth entry shown by `dev history`. `dev history --clear` deletes the history file. `dev history --project <path>` filters entries by project path and `dev history --search <text>` filters by text in the command, project name, or type. Filters can be combined.
597
+
598
+ History entries store executables and argument arrays instead of shell command strings. Compatible older entries are rebuilt from their saved metadata before `dev again` runs them.
599
+
600
+ ## Options
601
+
602
+ ```text
603
+ --dry-run
604
+ --typescript, --ts
605
+ --javascript, --js
606
+ --package-manager <npm|pnpm|yarn>, --pm <npm|pnpm|yarn>
607
+ --npm, --pnpm, --yarn
608
+ --git, --no-git
609
+ --eslint, --no-eslint
610
+ --install, --no-install
611
+ --python <executable>
612
+ --editor <executable>
613
+ --with <opener>
614
+ --list
615
+ --filter <workspace> (run, test, build, check, lint, format, task)
616
+ --fix (lint only) Apply automatic fixes
617
+ --json (inspect, doctor, projects, history, recipes, openers, devices, config)
618
+ --yes, -y (trust only) Approve without the prompt
619
+ --set <name=value>
620
+ --cold-boot
621
+ --shutdown-all
622
+ --clear (history only) Delete the history file
623
+ --project <path> (history only) Filter history by project path
624
+ --search <text> (history only) Filter history by text
625
+ ```
626
+
627
+ ## Development
628
+
629
+ DevCmd does not execute generated commands through a shell. Every executable and argument is passed separately to Node.js `spawn`, and multi-step operations such as scaffolding followed by `git init` run as separate processes.
630
+
631
+ ```text
632
+ dev CLI entry point
633
+ commands/ macOS double-click launchers
634
+ install-local.command Link local source via npm
635
+ install-remote.command Install latest source from GitHub
636
+ release.command Create a GitHub release interactively
637
+ scripts/ Shell and Node.js automation scripts
638
+ src/cli.js Prompt and command orchestration
639
+ src/constants.js Shared command name lists
640
+ src/commands/ Framework, device, and history commands
641
+ src/config/ Branding, version, user paths, and defaults
642
+ src/devices/ Android and iOS discovery
643
+ src/generators/ Node.js scripts invoked as child processes
644
+ src/handlers/ CLI command handlers
645
+ src/openers/ Built-in and custom project opener engine
646
+ src/projects/ Detection, workspaces, .devcmd.json profiles, lifecycle adapters, recent projects
647
+ src/recipes/ Built-in and custom framework recipe engine
648
+ src/mcp/ MCP server, tools, and background process manager
649
+ .github/workflows/ CI (Node 20/22/24) and npm publish workflows
650
+ action.yml Composite GitHub Action for dev check
651
+ src/runtime/ Shared command execution flow
652
+ src/runner/ Command formatting and process execution
653
+ src/utils/ Argument parsing and validation
654
+ test/ Node.js unit tests
655
+ ```
656
+
657
+ Run the test suite with:
658
+
659
+ ```bash
660
+ npm test
661
+ ```
662
+
663
+ ### Release
664
+
665
+ Create a release interactively and choose `patch`, `minor`, `major`, the current version, or a custom semantic version:
666
+
667
+ ```bash
668
+ npm run release
669
+ ```
670
+
671
+ On macOS, double-click `commands/release.command` in Finder to open Terminal and choose either a real release or a dry-run preview. The launcher runs the release through a Zsh login shell so Node.js, NVM, and GitHub CLI remain available without loading Zsh configuration inside Bash. It keeps the window open after an error so the message can be reviewed.
672
+
673
+ The release script validates Git and GitHub CLI state, checks that local `main` is not behind `origin/main`, runs tests and package validation, updates `package.json`, `package-lock.json`, and the tagged-install version in this README, commits all current changes, creates an annotated tag, pushes the branch and tag, and creates a GitHub Release with generated notes.
674
+
675
+ Use a specific increment or version for automation:
676
+
677
+ ```bash
678
+ npm run release -- patch
679
+ npm run release -- minor
680
+ npm run release -- 3.0.0
681
+ ```
682
+
683
+ Preview all checks and the release plan without changing the repository or publishing anything:
684
+
685
+ ```bash
686
+ npm run release -- patch --dry-run
687
+ ```
688
+
689
+ Pass `--yes` for a non-interactive release or `--draft` to create a draft GitHub Release.
690
+
691
+ Publishing a GitHub Release triggers `.github/workflows/publish.yml`, which checks that the tag matches `package.json`, runs the tests, and runs `npm publish --provenance --access public`. Add an npm automation token as the repository secret `NPM_TOKEN` before the first release; without it the workflow skips publishing with a warning and can be re-run after the secret is added. Draft releases do not publish. The `gh` CLI must be installed and authenticated with `gh auth login`.
692
+
693
+ `SIGINT` and `SIGTERM` are forwarded to the active child process. DevCmd preserves child exit codes, uses `127` for missing executables, and uses conventional signal exit codes such as `130` for `SIGINT`.
694
+
695
+ Lifecycle behavior is implemented through project adapters under `src/projects/adapters/`. Detection, inspection, and execution all use the same adapters, preventing displayed commands from drifting away from commands that actually run.
696
+
697
+ ## Custom Framework Recipes
698
+
699
+ All default framework commands are built-in recipes stored in `src/recipes/built-ins.json`. User recipes use the same validation, placeholder resolver, structured process execution, detection, and lifecycle pipeline. DevCmd does not load project-local recipes automatically; only recipes placed in the trusted user directory are discovered:
700
+
701
+ ```text
702
+ ~/.devcmd/recipes/*.json
703
+ ```
704
+
705
+ List active recipes and their source:
706
+
707
+ ```bash
708
+ dev recipes
709
+ ```
710
+
711
+ Validate a recipe before installing it:
712
+
713
+ ```bash
714
+ dev recipes validate ./my-backend.json
715
+ mkdir -p ~/.devcmd/recipes
716
+ cp ./my-backend.json ~/.devcmd/recipes/
717
+ ```
718
+
719
+ A minimal multi-step recipe can define inputs, safe file actions, executable requirements, detection rules, and lifecycle commands:
720
+
721
+ ```json
722
+ {
723
+ "name": "my_backend",
724
+ "description": "Example custom backend",
725
+ "capabilities": { "git": true },
726
+ "inputs": {
727
+ "module": {
728
+ "description": "Module identifier",
729
+ "required": true
730
+ }
731
+ },
732
+ "requirements": [
733
+ "node",
734
+ "tool-cli",
735
+ { "value": "git", "when": { "option": "git", "equals": true } }
736
+ ],
737
+ "actions": [
738
+ { "type": "mkdir", "path": "." },
739
+ { "type": "write", "path": ".devcmd-recipe", "content": "my_backend\n" },
740
+ {
741
+ "type": "run",
742
+ "executable": "tool-cli",
743
+ "args": ["init", "--module", "{module}"],
744
+ "cwd": "{target}"
745
+ }
746
+ ],
747
+ "detect": {
748
+ "priority": 10,
749
+ "rules": [{ "files": [".devcmd-recipe"] }]
750
+ },
751
+ "lifecycle": {
752
+ "run": [{ "type": "run", "executable": "tool-cli", "args": ["run"], "cwd": "{root}" }],
753
+ "test": [{ "type": "run", "executable": "tool-cli", "args": ["test"], "cwd": "{root}" }],
754
+ "build": [{ "type": "run", "executable": "tool-cli", "args": ["build"], "cwd": "{root}" }]
755
+ }
756
+ }
757
+ ```
758
+
759
+ Run it like a built-in framework:
760
+
761
+ ```bash
762
+ dev my_backend my-api --set module=example.com/my-api --dry-run
763
+ dev my_backend my-api --set module=example.com/my-api
764
+ ```
765
+
766
+ Supported scaffold and lifecycle action types are `run`, `mkdir`, `write`, and `copy`. File destinations are restricted to the target project, `copy` sources must remain inside the recipe directory, and existing files are not overwritten. Recipe commands never use `shell: true` or shell command strings. A user recipe with the same name overrides its built-in recipe.
767
+
768
+ ## MCP Server
769
+
770
+ DevCmd exposes an [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server so AI agents such as Claude Code and Codex can call DevCmd tools directly without spawning shell commands.
771
+
772
+ ### Setup
773
+
774
+ Inside this repository the server is discovered automatically through `.mcp.json`. For any other project, register it with an agent. With DevCmd installed globally:
775
+
776
+ ```json
777
+ {
778
+ "mcpServers": {
779
+ "devcmd": { "command": "dev", "args": ["mcp"] }
780
+ }
781
+ }
782
+ ```
783
+
784
+ Without a global installation, let `npx` fetch it on demand:
785
+
786
+ ```json
787
+ {
788
+ "mcpServers": {
789
+ "devcmd": { "command": "npx", "args": ["-y", "@bachbntdev/devcmd", "mcp"] }
790
+ }
791
+ }
792
+ ```
793
+
794
+ Claude Code can add it with `claude mcp add devcmd -- npx -y @bachbntdev/devcmd mcp`. Agents spawn `dev mcp` on demand and shut it down when the session ends; background processes are stopped with it.
795
+
796
+ ### Tools
797
+
798
+ | Tool | Description |
799
+ | --- | --- |
800
+ | `inspect_project` | Project type, package manager, workspaces, tasks, profile trust state, and the exact command for every lifecycle action. |
801
+ | `run_lifecycle` | Run `install`, `run`, `test`, `build`, `check`, `lint`, `format`, `outdated`, `upgrade`, `audit`, `clean`, `reset`, or `open`. Supports `filter`, `fix`, `dryRun`, `timeoutMs`, and `maxOutputBytes`. Returns JSON with `ok`, `exitCode`, `output`, and `timedOut`. |
802
+ | `run_task` | Run a `.devcmd.json` task or `package.json` script. |
803
+ | `start_process` | Start a lifecycle action, such as a dev server, in the background and return a process id. |
804
+ | `get_process_logs` | Status and the latest output lines of a background process. |
805
+ | `stop_process` | Stop a background process. |
806
+ | `list_processes` | List background processes. |
807
+ | `scaffold_project` | Create a project from a recipe. `dryRun` defaults to `true`; review the command, then call again with `dryRun: false`. |
808
+ | `list_frameworks` | Recipes with their supported options. |
809
+ | `doctor` | Installed tools and install hints. |
810
+ | `list_devices` | Android emulators and iOS simulators. |
811
+ | `boot_device` | Boot an Android emulator (background process) or an iOS simulator. |
812
+ | `get_history` | Recent successful commands, filterable by `project` and `search`. |
813
+
814
+ Failed commands are returned with `isError: true` so agents can react to them. Profile commands from `.devcmd.json` are refused until you run `dev trust` yourself; the MCP server has no tool for approving a profile.
815
+
816
+ ### Running manually
817
+
818
+ `dev mcp` starts the server on stdio and blocks waiting for JSON-RPC input. This is only useful for debugging; in normal use the agent manages the process lifecycle.
819
+
820
+ ```bash
821
+ dev mcp
822
+ ```
823
+
824
+ ## AI Agent Skills
825
+
826
+ DevCmd keeps reusable AI instructions in a vendor-neutral directory:
827
+
828
+ ```text
829
+ .ai/skills/ Canonical skill source
830
+ .claude/skills Claude Code discovery link
831
+ .agents/skills Codex discovery link
832
+ AGENTS.md Independent Codex instructions
833
+ CLAUDE.md Independent Claude Code instructions
834
+ ```
835
+
836
+ `AGENTS.md` and `CLAUDE.md` do not import or reference each other. Each agent has independent project instructions, while both discovery directories point to `.ai/skills` so Claude Code and Codex use the same canonical skill content.
837
+
838
+ Each skill uses a portable `SKILL.md` as its required entrypoint. Vendor-specific UI metadata is intentionally omitted so the same skill directories remain neutral between Claude Code and Codex.
839
+
840
+ These AI instruction files are contributor tooling stored in the GitHub repository. They are not included in the globally installed CLI package produced by `npm pack`.
841
+
842
+ | Skill | Purpose |
843
+ | --- | --- |
844
+ | `devcmd-add-framework` | Add framework scaffolding end to end using current official practices. |
845
+ | `devcmd-add-lifecycle-adapter` | Add project detection and lifecycle command resolution. |
846
+ | `devcmd-review-command-safety` | Audit input validation, child processes, history, and cleanup safety. |
847
+ | `devcmd-add-device-provider` | Extend device discovery and control without requiring real devices in tests. |
848
+ | `devcmd-debug-cli` | Reproduce, classify, fix, and regression-test CLI failures. |
849
+ | `devcmd-release-check` | Validate versioning, packaging, tags, installation, and GitHub releases. |
850
+ | `devcmd-update-docs` | Keep README, help, completion, examples, and installation guidance aligned. |