dev-cockpit 0.2.6 → 0.2.8
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/README.md +32 -32
- package/bin/dev-cockpit.mjs +1 -1
- package/dist/buildCli.d.ts.map +1 -1
- package/dist/{chunk-A446TCT5.js → chunk-YTMK7EXK.js} +1 -1
- package/dist/chunk-YTMK7EXK.js.map +7 -0
- package/dist/cockpit/Footer.d.ts.map +1 -1
- package/dist/cockpit/hooks/useGlobalKeys.d.ts.map +1 -1
- package/dist/cockpit/panes/FilterModal.d.ts.map +1 -1
- package/dist/cockpit/panes/Output.d.ts.map +1 -1
- package/dist/cockpit/panes/Repos.d.ts.map +1 -1
- package/dist/cockpit/panes/SearchModal.d.ts.map +1 -1
- package/dist/cockpit/state/store.d.ts.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/init-config-wizard.d.ts.map +1 -1
- package/dist/commands/init-config.d.ts.map +1 -1
- package/dist/commands/link.d.ts.map +1 -1
- package/dist/commands/migrate-config.d.ts.map +1 -1
- package/dist/commands/mount.d.ts +1 -3
- package/dist/commands/mount.d.ts.map +1 -1
- package/dist/core/config-discovery.d.ts.map +1 -1
- package/dist/core/config.d.ts +27 -6
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/manifest.d.ts.map +1 -1
- package/dist/core/migrations.d.ts.map +1 -1
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/subprocess.d.ts.map +1 -1
- package/dist/core/types.d.ts +16 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/docker/highlights.d.ts.map +1 -1
- package/dist/health/builtin.d.ts.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +274 -170
- package/dist/index.js.map +3 -3
- package/dist/ink.d.ts +1 -1
- package/dist/ink.d.ts.map +1 -1
- package/dist/{link-VWT2VQH6.js → link-Y7OFHOUP.js} +4 -6
- package/dist/link-Y7OFHOUP.js.map +7 -0
- package/dist/mount/compose.d.ts.map +1 -1
- package/dist/mount/symlinks.d.ts +4 -4
- package/dist/mount/symlinks.d.ts.map +1 -1
- package/dist/mount/types.d.ts +15 -2
- package/dist/mount/types.d.ts.map +1 -1
- package/docs/commands.md +8 -8
- package/docs/config-reference.md +45 -41
- package/docs/health.md +32 -22
- package/docs/init-config.md +16 -16
- package/docs/mount.md +14 -9
- package/docs/notifications.md +3 -3
- package/docs/panes.md +5 -5
- package/docs/processes.md +7 -5
- package/examples/cockpit.schema.json +230 -59
- package/examples/cockpit.yaml +8 -6
- package/package.json +99 -93
- package/prettier-config.json +7 -0
- package/dist/chunk-A446TCT5.js.map +0 -7
- package/dist/link-VWT2VQH6.js.map +0 -7
package/dist/ink.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { Box, Text, render, useApp, useInput, useFocus, useFocusManager, useStdout, useStderr, useStdin, Static, Newline, Spacer, Transform } from 'ink';
|
|
1
|
+
export { Box, Text, render, useApp, useInput, useFocus, useFocusManager, useStdout, useStderr, useStdin, Static, Newline, Spacer, Transform, } from 'ink';
|
|
2
2
|
export type { BoxProps, TextProps, RenderOptions, Instance, AppProps } from 'ink';
|
|
3
3
|
//# sourceMappingURL=ink.d.ts.map
|
package/dist/ink.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ink.d.ts","sourceRoot":"","sources":["../src/ink.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ink.d.ts","sourceRoot":"","sources":["../src/ink.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EACH,IAAI,EACJ,MAAM,EACN,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,SAAS,EACT,SAAS,EACT,QAAQ,EACR,MAAM,EACN,OAAO,EACP,MAAM,EACN,SAAS,GACV,MAAM,KAAK,CAAC;AACb,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC"}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
manifestPath,
|
|
8
8
|
removeMapping,
|
|
9
9
|
setMapping
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-YTMK7EXK.js";
|
|
11
11
|
import "./chunk-6XGHLLYT.js";
|
|
12
12
|
|
|
13
13
|
// src/commands/link.ts
|
|
@@ -24,10 +24,8 @@ function linkAddCommand(opts) {
|
|
|
24
24
|
process.exit(1);
|
|
25
25
|
}
|
|
26
26
|
setMapping(cwd, absConfig);
|
|
27
|
-
process.stdout.write(
|
|
28
|
-
|
|
29
|
-
`
|
|
30
|
-
);
|
|
27
|
+
process.stdout.write(`dev-cockpit link: ${canonical(cwd)} \u2192 ${canonical(absConfig)}
|
|
28
|
+
`);
|
|
31
29
|
}
|
|
32
30
|
function linkListCommand() {
|
|
33
31
|
const entries = listMappings();
|
|
@@ -62,4 +60,4 @@ export {
|
|
|
62
60
|
linkListCommand,
|
|
63
61
|
linkRemoveCommand
|
|
64
62
|
};
|
|
65
|
-
//# sourceMappingURL=link-
|
|
63
|
+
//# sourceMappingURL=link-Y7OFHOUP.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/commands/link.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * `dev-cockpit link` \u2014 manage the project\u2192config mapping in\n * $XDG_DATA_HOME/dev-cockpit/manifest.json.\n *\n * Sub-commands:\n * link <config-path> register a mapping for the current cwd\n * link list show all registered mappings\n * link remove unregister the current cwd\n *\n * Path canonicalisation (symlink-resolved) happens inside the manifest\n * module \u2014 the same cwd reached via a symlinked alias hashes to the\n * same key as its real path.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport {\n canonical,\n listMappings,\n manifestPath,\n removeMapping,\n setMapping,\n} from '../core/manifest.js';\n\nexport interface LinkAddOptions {\n configPath: string;\n}\n\nexport function linkAddCommand(opts: LinkAddOptions): void {\n const cwd = process.cwd();\n const absConfig = path.resolve(cwd, opts.configPath);\n if (!fs.existsSync(absConfig)) {\n process.stderr.write(\n `dev-cockpit link: ${absConfig} doesn't exist. Create the config file first or pass a valid path.\\n`,\n );\n process.exit(1);\n }\n setMapping(cwd, absConfig);\n process.stdout.write(`dev-cockpit link: ${canonical(cwd)} \u2192 ${canonical(absConfig)}\\n`);\n}\n\nexport function linkListCommand(): void {\n const entries = listMappings();\n if (entries.length === 0) {\n process.stdout.write(\n `dev-cockpit link: no mappings registered (manifest at ${manifestPath()}).\\n`,\n );\n return;\n }\n const longest = Math.max(...entries.map((e) => e.workspace.length));\n for (const { workspace, config } of entries) {\n process.stdout.write(`${workspace.padEnd(longest)} \u2192 ${config}\\n`);\n }\n}\n\nexport function linkRemoveCommand(): void {\n const cwd = process.cwd();\n const removed = removeMapping(cwd);\n if (removed) {\n process.stdout.write(`dev-cockpit link: removed mapping for ${canonical(cwd)}\\n`);\n } else {\n process.stdout.write(\n `dev-cockpit link: no mapping for ${canonical(cwd)} (nothing to remove)\\n`,\n );\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;AAcA,OAAO,QAAQ;AACf,OAAO,UAAU;AAaV,SAAS,eAAe,MAA4B;AACzD,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,YAAY,KAAK,QAAQ,KAAK,KAAK,UAAU;AACnD,MAAI,CAAC,GAAG,WAAW,SAAS,GAAG;AAC7B,YAAQ,OAAO;AAAA,MACb,qBAAqB,SAAS;AAAA;AAAA,IAChC;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,aAAW,KAAK,SAAS;AACzB,UAAQ,OAAO,MAAM,qBAAqB,UAAU,GAAG,CAAC,WAAM,UAAU,SAAS,CAAC;AAAA,CAAI;AACxF;AAEO,SAAS,kBAAwB;AACtC,QAAM,UAAU,aAAa;AAC7B,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,OAAO;AAAA,MACb,yDAAyD,aAAa,CAAC;AAAA;AAAA,IACzE;AACA;AAAA,EACF;AACA,QAAM,UAAU,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,UAAU,MAAM,CAAC;AAClE,aAAW,EAAE,WAAW,OAAO,KAAK,SAAS;AAC3C,YAAQ,OAAO,MAAM,GAAG,UAAU,OAAO,OAAO,CAAC,aAAQ,MAAM;AAAA,CAAI;AAAA,EACrE;AACF;AAEO,SAAS,oBAA0B;AACxC,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,UAAU,cAAc,GAAG;AACjC,MAAI,SAAS;AACX,YAAQ,OAAO,MAAM,yCAAyC,UAAU,GAAG,CAAC;AAAA,CAAI;AAAA,EAClF,OAAO;AACL,YAAQ,OAAO;AAAA,MACb,oCAAoC,UAAU,GAAG,CAAC;AAAA;AAAA,IACpD;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/mount/compose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,IAAI,EAAE,oBAAoB,GACzB,MAAM,
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/mount/compose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,IAAI,EAAE,oBAAoB,GACzB,MAAM,CA6BR"}
|
package/dist/mount/symlinks.d.ts
CHANGED
|
@@ -20,10 +20,10 @@ export interface SymlinkReport {
|
|
|
20
20
|
*/
|
|
21
21
|
replaced: string[];
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* Entries that couldn't be applied — e.g. a real directory at the link path
|
|
24
|
+
* that resisted deletion (macOS `deny delete` ACL that survived even an ACL
|
|
25
|
+
* strip + retry), or `symlinkSync` failing for any other reason. Callers
|
|
26
|
+
* surface these to the user so they can intervene manually.
|
|
27
27
|
*/
|
|
28
28
|
skipped: string[];
|
|
29
29
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"symlinks.d.ts","sourceRoot":"","sources":["../../src/mount/symlinks.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"symlinks.d.ts","sourceRoot":"","sources":["../../src/mount/symlinks.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEnE,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;;OAMG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,QAAQ,EAAE,oBAAoB,GAC7B,aAAa,CAWf;AAmED,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,QAAQ,EAAE,oBAAoB,GAC7B,IAAI,CAWN;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,KAAK,EAAE,UAAU,CAAC;CACnB;AAED,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,QAAQ,EAAE,oBAAoB,GAC7B,UAAU,EAAE,CAuBd"}
|
package/dist/mount/types.d.ts
CHANGED
|
@@ -8,8 +8,21 @@
|
|
|
8
8
|
export interface MountEntry {
|
|
9
9
|
/** Absolute path on the host. */
|
|
10
10
|
hostPath: string;
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Absolute path inside the container. Required for `kind: 'bind'` (the
|
|
13
|
+
* default); omitted when `kind: 'symlink-only'`.
|
|
14
|
+
*/
|
|
15
|
+
containerPath?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Discriminator for how this mount is materialised.
|
|
18
|
+
*
|
|
19
|
+
* - `'bind'` (default): emit a docker-compose bind AND optionally manage
|
|
20
|
+
* an IDE-facing symlink via `MountSymlinkStrategy`.
|
|
21
|
+
* - `'symlink-only'`: no docker bind. Exists purely so the symlink
|
|
22
|
+
* strategy can place a host-side symlink (e.g. a wrapper-level
|
|
23
|
+
* `./project` symlink that redirects a pre-existing compose bind).
|
|
24
|
+
*/
|
|
25
|
+
kind?: 'bind' | 'symlink-only';
|
|
13
26
|
/**
|
|
14
27
|
* Optional metadata attached by profiles (e.g. logical name, category,
|
|
15
28
|
* source provenance). dev-cockpit treats this as opaque; profile hooks
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mount/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mount/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC;IAC/B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,iBAAkB,SAAQ,YAAY;IACrD,6EAA6E;IAC7E,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iEAAiE;IACjE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,MAAM,mBAAmB,GAAG,CAChC,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,KAC3B,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,eAAe,GAAG,IAAI,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACvE"}
|
package/docs/commands.md
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
`dev-cockpit` ships five core commands. A profile contributes its own commands via `setupCli(program)` — these register **first**, so a profile can take over a core command name (the matching core command is then skipped).
|
|
4
4
|
|
|
5
|
-
| Command
|
|
6
|
-
|
|
7
|
-
| `dev`
|
|
8
|
-
| `doctor`
|
|
9
|
-
| `init-config`
|
|
10
|
-
| `mount`
|
|
11
|
-
| `migrate-config`
|
|
5
|
+
| Command | What it does |
|
|
6
|
+
| ---------------- | --------------------------------------------------------------------- |
|
|
7
|
+
| `dev` | Boots the four-pane TUI (Targets / Output / Health / Help). |
|
|
8
|
+
| `doctor` | Runs every registered health check once and prints a status table. |
|
|
9
|
+
| `init-config` | Writes a `cockpit.yaml` (static template or interactive wizard). |
|
|
10
|
+
| `mount` | Manages a docker-compose bind-mount overlay (apply / status / clear). |
|
|
11
|
+
| `migrate-config` | Rewrites `cockpit.yaml` at the current `CONFIG_VERSION`. |
|
|
12
12
|
|
|
13
13
|
## `dev`
|
|
14
14
|
|
|
@@ -40,7 +40,7 @@ Writes a `cockpit.yaml` at the current directory.
|
|
|
40
40
|
## `mount`
|
|
41
41
|
|
|
42
42
|
```
|
|
43
|
-
dev-cockpit mount [-c <path>] [-s|--service <name>] [-q|--quiet]
|
|
43
|
+
dev-cockpit mount [-c <path>] [-s|--service <name>] [-q|--quiet]
|
|
44
44
|
dev-cockpit mount status [-c <path>]
|
|
45
45
|
dev-cockpit mount clear [-c <path>]
|
|
46
46
|
```
|
package/docs/config-reference.md
CHANGED
|
@@ -4,36 +4,37 @@ A `cockpit.yaml` lives at the root of your project. The cockpit reads it on star
|
|
|
4
4
|
|
|
5
5
|
## Top-level keys
|
|
6
6
|
|
|
7
|
-
| Key
|
|
8
|
-
|
|
9
|
-
| `version`
|
|
10
|
-
| `appName`
|
|
11
|
-
| `processes`
|
|
12
|
-
| `repos`
|
|
13
|
-
| `docker`
|
|
14
|
-
| `highlights`
|
|
15
|
-
| `health`
|
|
16
|
-
| `actions`
|
|
17
|
-
| `mount`
|
|
18
|
-
| `mounts`
|
|
19
|
-
| `help`
|
|
20
|
-
| `notifications` | object | no
|
|
21
|
-
| `defaultPane`
|
|
22
|
-
| `profile`
|
|
7
|
+
| Key | Type | Required | Notes |
|
|
8
|
+
| --------------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
9
|
+
| `version` | number | yes | Current schema version is `2`. Older versions migrate in memory (with a stderr warning); run `dev-cockpit migrate-config` to persist. |
|
|
10
|
+
| `appName` | string | yes | State-dir name (`$XDG_STATE_HOME/<appName>/<workspace-hash>/`) + OS-notification title prefix. |
|
|
11
|
+
| `processes` | array | no | Long-running commands streamed into the Output pane. See `processes:` below. |
|
|
12
|
+
| `repos` | array | no | Code-side rows in the Targets pane. |
|
|
13
|
+
| `docker` | object | no | `composeFile` + `services[]`. Omit on plain-Node projects. |
|
|
14
|
+
| `highlights` | array | no | Regex patterns applied to all output streams (process + docker). Each can carry an explicit `severity:` (else inferred). |
|
|
15
|
+
| `health` | array | no | Health check declarations — see `health:` below. |
|
|
16
|
+
| `actions` | array | no | Named, optionally key-bound shell commands surfaced via the `:` palette and the Targets pane. |
|
|
17
|
+
| `mount` | object | no | `overlayPath`, `manifestFile` and `service` overrides. Defaults: `<stateDir>/dev-mount-overlay.yml` (sibling to the manifest, keeps the wrapper repo clean), `mount.manifest.json`. |
|
|
18
|
+
| `mounts` | array | no | Explicit `{hostPath, containerPath, meta?}` entries for `dev-cockpit mount`. |
|
|
19
|
+
| `help` | object | no | Extra `sources[]` + `defaultPage`. |
|
|
20
|
+
| `notifications` | object | no | `enabled`, `onTransitionTo[]`, `exclude[]`. |
|
|
21
|
+
| `defaultPane` | enum | no | `repos` (default) \| `output` \| `health` \| `help`. Falls back to Output when the requested tab is hidden. |
|
|
22
|
+
| `profile` | object | no | Namespace for profile-specific extension keys (`profile.<appName>: { ... }`). Each profile validates its block via its `configSchemaExt` (see [ADR 0005](../adr/0005-strict-profile-namespace.md)). |
|
|
23
23
|
|
|
24
24
|
## `processes:`
|
|
25
25
|
|
|
26
26
|
```yaml
|
|
27
27
|
processes:
|
|
28
|
-
- id: vite
|
|
29
|
-
label: Vite dev
|
|
30
|
-
command: npm run dev
|
|
31
|
-
cwd: ./apps/web
|
|
32
|
-
env:
|
|
28
|
+
- id: vite # required, stable identifier; used as Output source tag and Targets row id
|
|
29
|
+
label: Vite dev # optional, displayed in Targets / Output
|
|
30
|
+
command: npm run dev # shell command; runs via sh -c (cmd /c on Windows)
|
|
31
|
+
cwd: ./apps/web # optional; relative to workspaceRoot
|
|
32
|
+
env: # optional; merged on top of process.env
|
|
33
33
|
DEBUG: '1'
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
Each process gets:
|
|
37
|
+
|
|
37
38
|
- A row in the Targets pane (kind: `process`) with a built-in `[r] Restart <id>` action (kill via SIGTERM, respawn) backed by the tagged-spawn lookup.
|
|
38
39
|
- Output lines tagged by `label` or `id`.
|
|
39
40
|
- Highlight matching against `config.highlights[]` — matched lines use the configured severity (overriding the default `info` for stdout / `warn` for stderr).
|
|
@@ -42,20 +43,22 @@ Each process gets:
|
|
|
42
43
|
|
|
43
44
|
```yaml
|
|
44
45
|
actions:
|
|
45
|
-
- id: test
|
|
46
|
-
label: Run tests
|
|
47
|
-
command: npm test
|
|
48
|
-
cwd: ./api
|
|
49
|
-
scope: global
|
|
50
|
-
key: t
|
|
46
|
+
- id: test # required, unique
|
|
47
|
+
label: Run tests # required, shown in the `:` palette + Targets action panel
|
|
48
|
+
command: npm test # required for YAML; profiles can supply `invoke:` instead (TS-only)
|
|
49
|
+
cwd: ./api # optional
|
|
50
|
+
scope: global # 'global' | 'repos' | 'repos:<rowId>' (default: 'global')
|
|
51
|
+
key: t # optional single keystroke; fires within scope (in addition to `:`)
|
|
51
52
|
```
|
|
52
53
|
|
|
53
54
|
Scope semantics:
|
|
55
|
+
|
|
54
56
|
- `global` — `:` palette only.
|
|
55
57
|
- `repos` — `:` palette AND fires on any selected Targets row when the keystroke matches.
|
|
56
58
|
- `repos:<id>` — fires only when that specific row is selected.
|
|
57
59
|
|
|
58
60
|
Built-in actions are synthesized automatically:
|
|
61
|
+
|
|
59
62
|
- Each docker service: `__builtin:restart-docker:<svc>` with `scope: repos:<svc>`, `key: r`.
|
|
60
63
|
- Each process: `__builtin:restart-process:<id>` with `scope: repos:<id>`, `key: r`.
|
|
61
64
|
|
|
@@ -69,30 +72,31 @@ See [health.md](./health.md). Brief shape:
|
|
|
69
72
|
health:
|
|
70
73
|
- id: app-up
|
|
71
74
|
label: app responsive
|
|
72
|
-
type: http-ok
|
|
73
|
-
url: http://localhost:3000/health
|
|
74
|
-
severity: error
|
|
75
|
-
triggers: [startup, fsevent]
|
|
76
|
-
notify: { onTransitionTo: ['error'] }
|
|
75
|
+
type: http-ok # container-running | port-open | http-ok | file-exists | exec-zero
|
|
76
|
+
url: http://localhost:3000/health # type-specific args
|
|
77
|
+
severity: error # ok | warn | error
|
|
78
|
+
triggers: [startup, fsevent] # optional; defaults to ['startup']
|
|
79
|
+
notify: { onTransitionTo: ['error'] } # optional per-check override
|
|
77
80
|
remediation:
|
|
78
81
|
key: R
|
|
79
82
|
label: restart app
|
|
80
83
|
command: docker compose restart app
|
|
81
|
-
cwd: .
|
|
84
|
+
cwd: . # optional
|
|
82
85
|
```
|
|
83
86
|
|
|
84
87
|
## `mount:` + `mounts:`
|
|
85
88
|
|
|
86
89
|
```yaml
|
|
87
|
-
mount:
|
|
90
|
+
mount: # path overrides — omit for defaults
|
|
88
91
|
# overlayPath: docker-compose.dev-cockpit.yml # default: <stateDir>/dev-mount-overlay.yml
|
|
89
|
-
|
|
90
|
-
manifestFile: mount.manifest.json
|
|
92
|
+
# set to keep the overlay in-repo (workspace-relative or absolute)
|
|
93
|
+
manifestFile: mount.manifest.json # basename within stateDir
|
|
94
|
+
# service: web # target compose service (default: first in docker.services)
|
|
91
95
|
|
|
92
|
-
mounts:
|
|
96
|
+
mounts: # explicit candidates
|
|
93
97
|
- hostPath: ./packages/api
|
|
94
98
|
containerPath: /srv/api
|
|
95
|
-
meta:
|
|
99
|
+
meta: # opaque to dev-cockpit; profile hooks read it
|
|
96
100
|
name: api
|
|
97
101
|
```
|
|
98
102
|
|
|
@@ -103,8 +107,8 @@ Full mount story: [mount.md](./mount.md).
|
|
|
103
107
|
```yaml
|
|
104
108
|
notifications:
|
|
105
109
|
enabled: true
|
|
106
|
-
onTransitionTo: []
|
|
107
|
-
exclude: []
|
|
110
|
+
onTransitionTo: [] # restrict to specific destination states; empty = all transitions
|
|
111
|
+
exclude: [] # `NotifiableEvent` strings to suppress
|
|
108
112
|
```
|
|
109
113
|
|
|
110
114
|
See [notifications.md](./notifications.md).
|
|
@@ -114,7 +118,7 @@ See [notifications.md](./notifications.md).
|
|
|
114
118
|
```yaml
|
|
115
119
|
help:
|
|
116
120
|
sources:
|
|
117
|
-
- ./docs
|
|
121
|
+
- ./docs # directory tree of markdown pages
|
|
118
122
|
defaultPage: getting-started
|
|
119
123
|
```
|
|
120
124
|
|
package/docs/health.md
CHANGED
|
@@ -4,24 +4,24 @@ A health check is a small predicate that decides whether something in your works
|
|
|
4
4
|
|
|
5
5
|
The cockpit re-runs health checks on three triggers:
|
|
6
6
|
|
|
7
|
-
| Trigger | When
|
|
8
|
-
|
|
9
|
-
| `startup` | once, at boot
|
|
10
|
-
| `fsevent` | when the watcher reports a file change (debounced ~500 ms)
|
|
11
|
-
| `lockfile` | when `composer.lock`, `package-lock.json`, or `yarn.lock` changes
|
|
12
|
-
| `docker` | when a docker event is signalled (e.g. by the docker subsystem)
|
|
7
|
+
| Trigger | When |
|
|
8
|
+
| ---------- | ----------------------------------------------------------------- |
|
|
9
|
+
| `startup` | once, at boot |
|
|
10
|
+
| `fsevent` | when the watcher reports a file change (debounced ~500 ms) |
|
|
11
|
+
| `lockfile` | when `composer.lock`, `package-lock.json`, or `yarn.lock` changes |
|
|
12
|
+
| `docker` | when a docker event is signalled (e.g. by the docker subsystem) |
|
|
13
13
|
|
|
14
14
|
Transitions (`ok → error`, `error → ok`) fire OS notifications according to the global `notifications:` block, optionally overridden per-check.
|
|
15
15
|
|
|
16
16
|
## Built-in check vocabulary
|
|
17
17
|
|
|
18
|
-
| Type | Required args
|
|
19
|
-
|
|
20
|
-
| `container-running` | `container`
|
|
21
|
-
| `port-open` | `port` (number)
|
|
22
|
-
| `http-ok` | `url`
|
|
23
|
-
| `file-exists` | `path`
|
|
24
|
-
| `exec-zero` | `command`
|
|
18
|
+
| Type | Required args | Optional args | Default triggers |
|
|
19
|
+
| ------------------- | --------------- | ---------------------------- | -------------------- |
|
|
20
|
+
| `container-running` | `container` | | `startup`, `docker` |
|
|
21
|
+
| `port-open` | `port` (number) | `host` (default `127.0.0.1`) | `startup` |
|
|
22
|
+
| `http-ok` | `url` | `expectStatus` (default 200) | `startup` |
|
|
23
|
+
| `file-exists` | `path` | | `startup`, `fsevent` |
|
|
24
|
+
| `exec-zero` | `command` | `args[]`, `cwd` | `startup` |
|
|
25
25
|
|
|
26
26
|
Defaults can be overridden by setting `triggers:` and `severity:` on the entry.
|
|
27
27
|
|
|
@@ -49,7 +49,7 @@ health:
|
|
|
49
49
|
label: start db
|
|
50
50
|
command: docker compose up -d db
|
|
51
51
|
notify:
|
|
52
|
-
onTransitionTo: [health-failed]
|
|
52
|
+
onTransitionTo: [health-failed] # only notify on going-down
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
## Remediations
|
|
@@ -65,11 +65,11 @@ The remediation `key` is a single uppercase letter. Pressing the key (lowercase
|
|
|
65
65
|
|
|
66
66
|
Per-check `notify:` overrides:
|
|
67
67
|
|
|
68
|
-
| Setting | Effect
|
|
69
|
-
|
|
70
|
-
| omitted | inherit global `notifications:` policy
|
|
71
|
-
| `notify: false` | always silent for this check
|
|
72
|
-
| `notify: { onTransitionTo: [health-failed] }` | only notify on the listed transition events
|
|
68
|
+
| Setting | Effect |
|
|
69
|
+
| --------------------------------------------- | ------------------------------------------- |
|
|
70
|
+
| omitted | inherit global `notifications:` policy |
|
|
71
|
+
| `notify: false` | always silent for this check |
|
|
72
|
+
| `notify: { onTransitionTo: [health-failed] }` | only notify on the listed transition events |
|
|
73
73
|
|
|
74
74
|
The session toggle (`n` keystroke) and global `notifications.enabled: false` always silence everything — per-check overrides cannot opt back in.
|
|
75
75
|
|
|
@@ -88,8 +88,16 @@ export const myProfile: Profile = {
|
|
|
88
88
|
label: 'Composer',
|
|
89
89
|
severity: 'error',
|
|
90
90
|
triggers: ['startup', 'lockfile'],
|
|
91
|
-
predicate: async (ctx) => {
|
|
92
|
-
|
|
91
|
+
predicate: async (ctx) => {
|
|
92
|
+
/* … */
|
|
93
|
+
},
|
|
94
|
+
remediation: {
|
|
95
|
+
key: 'R',
|
|
96
|
+
label: 'composer install',
|
|
97
|
+
run: async (ctx, root) => {
|
|
98
|
+
/* … */
|
|
99
|
+
},
|
|
100
|
+
},
|
|
93
101
|
},
|
|
94
102
|
],
|
|
95
103
|
};
|
|
@@ -104,7 +112,9 @@ import { runCockpit, buildHealthContext } from 'dev-cockpit';
|
|
|
104
112
|
|
|
105
113
|
await runCockpit({
|
|
106
114
|
profile: myProfile,
|
|
107
|
-
footerLegends: {
|
|
115
|
+
footerLegends: {
|
|
116
|
+
/* … */
|
|
117
|
+
},
|
|
108
118
|
health: {
|
|
109
119
|
workspaceRoot,
|
|
110
120
|
profileChecks: myProfile.healthChecks,
|
package/docs/init-config.md
CHANGED
|
@@ -9,11 +9,11 @@ dev-cockpit init-config -i [-f|--force] # interactive wizard
|
|
|
9
9
|
|
|
10
10
|
## Flags
|
|
11
11
|
|
|
12
|
-
| Flag
|
|
13
|
-
|
|
14
|
-
| `-i, --interactive`
|
|
15
|
-
| `--with-docker`
|
|
16
|
-
| `-f, --force`
|
|
12
|
+
| Flag | Default | Effect |
|
|
13
|
+
| ------------------- | ------- | ---------------------------------------------------------------------------------------- |
|
|
14
|
+
| `-i, --interactive` | off | Walk through prompts to populate the file. Skips the static template. |
|
|
15
|
+
| `--with-docker` | off | Uncomments the `docker:` block in the static template (ignored in `--interactive` mode). |
|
|
16
|
+
| `-f, --force` | off | Overwrites an existing `cockpit.yaml` instead of refusing. |
|
|
17
17
|
|
|
18
18
|
## Static template
|
|
19
19
|
|
|
@@ -23,20 +23,20 @@ dev-cockpit init-config -i [-f|--force] # interactive wizard
|
|
|
23
23
|
|
|
24
24
|
The recommended path the first time you set the cockpit up on a project. Eight steps, with project sniffing pre-populating sensible defaults so you usually just press enter:
|
|
25
25
|
|
|
26
|
-
| Step | Section
|
|
27
|
-
|
|
28
|
-
| 1
|
|
29
|
-
| 2
|
|
30
|
-
| 3
|
|
31
|
-
| 4
|
|
32
|
-
| 5
|
|
33
|
-
| 6
|
|
34
|
-
| 7
|
|
35
|
-
| 8
|
|
26
|
+
| Step | Section | What it asks + auto-detects |
|
|
27
|
+
| ---- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
28
|
+
| 1 | **App name** | Defaults to `package.json` `name`, then the cwd basename. |
|
|
29
|
+
| 2 | **Docker** | Detects `compose.yaml` / `docker-compose.yml` and parses its services. Offers them as a multi-select. Skip entirely for non-compose projects. |
|
|
30
|
+
| 3 | **Processes** | Surfaces `package.json` scripts (`dev`, `watch`, `start`, `serve`) as pre-checked candidates. Anything that runs forever and writes to stdout — `vite`, `tsc --watch`, `php artisan serve`, `tail -f storage/logs/laravel.log` — fits here. |
|
|
31
|
+
| 4 | **Targets** | Detects npm/yarn/pnpm workspaces; falls back to a single `.` entry. Each becomes a row in the Targets pane. The way to attach keystrokes to a repo is the Actions step (step 7), with `scope: repos:<id>` + `key:`. |
|
|
32
|
+
| 5 | **Highlights** | Regex patterns that re-colour matching Output lines. `error`-severity matches additionally feed the Recent Errors strip + OS notifications. Patterns now apply to process stdout/stderr too — not just docker logs. |
|
|
33
|
+
| 6 | **Health** | Test-and-fix pairs. Pick one of the five built-in types (`container-running`, `port-open`, `http-ok`, `file-exists`, `exec-zero`), supply the type-specific arg(s), then bind a single-keystroke remediation. Add as many checks as you like — same type repeats freely. `container-running` is hidden when no docker block was declared. |
|
|
34
|
+
| 7 | **Actions** | One-shot shell commands surfaced through the `:` palette and/or bound to a single keypress. Auto-seeds from `package.json` scripts (`test`, `build`, `lint`, `format`, `typecheck`) with sensible default keys (`t`, `b`, `l`, `f`). Custom actions can be added inline. Distinct from processes (long-running) and health (state-checked). |
|
|
35
|
+
| 8 | **Notifications** | Toggle native OS notifications on state transitions. |
|
|
36
36
|
|
|
37
37
|
After writing the file, the wizard offers to run `dev-cockpit doctor` immediately so you get instant feedback that the config parses + each declared health check has a baseline state.
|
|
38
38
|
|
|
39
|
-
The wizard scaffolds a
|
|
39
|
+
The wizard scaffolds a _working_ config. Anything more advanced (custom triggers, `expectStatus`, exec args, mounts, profile namespaces) is a hand-edit on the generated file.
|
|
40
40
|
|
|
41
41
|
## Profile-contributed steps
|
|
42
42
|
|
package/docs/mount.md
CHANGED
|
@@ -34,21 +34,27 @@ docker compose -f docker-compose.yml -f <stateDir>/dev-mount-overlay.yml up -d
|
|
|
34
34
|
|
|
35
35
|
## What gets written
|
|
36
36
|
|
|
37
|
-
| File
|
|
38
|
-
|
|
39
|
-
| Compose overlay | `<stateDir>/dev-mount-overlay.yml` | `config.mount.overlayPath`
|
|
40
|
-
| Manifest
|
|
37
|
+
| File | Default path | Configurable via |
|
|
38
|
+
| --------------- | ---------------------------------- | --------------------------- |
|
|
39
|
+
| Compose overlay | `<stateDir>/dev-mount-overlay.yml` | `config.mount.overlayPath` |
|
|
40
|
+
| Manifest | `<stateDir>/mount.manifest.json` | `config.mount.manifestFile` |
|
|
41
|
+
| Service | first in `docker.services` | `config.mount.service` |
|
|
41
42
|
|
|
42
|
-
`<stateDir>` lives under `$XDG_STATE_HOME/<appName>/<workspace-hash>/`. Both files share that location, so anything cockpit knows about
|
|
43
|
+
`<stateDir>` lives under `$XDG_STATE_HOME/<appName>/<workspace-hash>/`. Both files share that location, so anything cockpit knows about _this workspace's mounts_ sits in one dir — clean wrapper repo, no per-developer artefacts to gitignore.
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
### Pointing the overlay at a path your compose chain already expects
|
|
46
|
+
|
|
47
|
+
If the project's compose chain auto-discovers overrides at a fixed path — e.g. a Makefile wildcard like `$(wildcard $(COMPOSE_DIR)/web/docker-compose.dev-link.yml)`, or a `docker compose -f` include — the stateDir default won't be found by that glob (it's outside the repo). Tell `mount` to write the overlay where the chain looks for it:
|
|
45
48
|
|
|
46
49
|
```yaml
|
|
47
50
|
mount:
|
|
48
51
|
overlayPath: docker/compose/web/docker-compose.dev-link.yml
|
|
49
52
|
manifestFile: dev-link.manifest.json
|
|
53
|
+
service: web
|
|
50
54
|
```
|
|
51
55
|
|
|
56
|
+
Relative paths resolve against the workspace root; absolute paths are honoured verbatim. The Makefile include path and `mount.overlayPath` are two ends of the same contract — keep them next to each other (both committed in the wrapper repo, or both in the per-user cockpit.yaml) so they move together.
|
|
57
|
+
|
|
52
58
|
## Mount sources
|
|
53
59
|
|
|
54
60
|
Mounts come from two places, merged on `containerPath` (config wins on collision):
|
|
@@ -58,7 +64,7 @@ Mounts come from two places, merged on `containerPath` (config wins on collision
|
|
|
58
64
|
mounts:
|
|
59
65
|
- hostPath: ./packages/api
|
|
60
66
|
containerPath: /srv/api
|
|
61
|
-
meta:
|
|
67
|
+
meta: # optional opaque metadata (read by profile hooks + status)
|
|
62
68
|
name: api
|
|
63
69
|
type: package
|
|
64
70
|
```
|
|
@@ -73,7 +79,6 @@ dev-cockpit mount [options] # write overlay + manifest
|
|
|
73
79
|
-c, --config <path> # default: ./cockpit.yaml
|
|
74
80
|
-s, --service <name> # default: first in docker.services
|
|
75
81
|
-q, --quiet # skip interactive picker; apply all candidates
|
|
76
|
-
-e, --exclude <name> # exclude a candidate by meta.name (repeatable)
|
|
77
82
|
|
|
78
83
|
dev-cockpit mount status [options] # branch + dirty + broken-symlink table
|
|
79
84
|
dev-cockpit mount clear [options] # remove overlay + manifest + managed symlinks
|
|
@@ -225,4 +230,4 @@ If your wrapper previously used a different manifest filename (e.g. a profile th
|
|
|
225
230
|
1. **Adopt the new default**: run `mount` once. The new file replaces the legacy one (which is left orphaned in the state dir — safe to delete).
|
|
226
231
|
2. **Keep the legacy filename**: set `config.mount.manifestFile: dev-link.manifest.json` in cockpit.yaml.
|
|
227
232
|
|
|
228
|
-
Same applies to the overlay path — set `config.mount.overlayPath` if your wrapper expects a specific location for its compose stack.
|
|
233
|
+
Same applies to the overlay path — set `config.mount.overlayPath` if your wrapper expects a specific location for its compose stack. See "Pointing the overlay at a path your compose chain already expects" above.
|
package/docs/notifications.md
CHANGED
|
@@ -20,17 +20,17 @@ OS notifications fire on **state transitions only** — never on every check, ne
|
|
|
20
20
|
processes:
|
|
21
21
|
- id: lint
|
|
22
22
|
command: npx eslint . --watch
|
|
23
|
-
notify: false
|
|
23
|
+
notify: false # mute this item
|
|
24
24
|
|
|
25
25
|
health:
|
|
26
26
|
- id: api-up
|
|
27
27
|
type: http-ok
|
|
28
28
|
url: http://localhost:3000/health
|
|
29
29
|
notify:
|
|
30
|
-
onTransitionTo: [error]
|
|
30
|
+
onTransitionTo: [error] # only on going-down, not on recovery
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
3. **Session toggle** — press `n` in the cockpit to mute
|
|
33
|
+
3. **Session toggle** — press `n` in the cockpit to mute _all_ notifications for the current session (overrides config). The Health pane shows the current session state at the bottom.
|
|
34
34
|
|
|
35
35
|
## Events
|
|
36
36
|
|
package/docs/panes.md
CHANGED
|
@@ -17,11 +17,11 @@ Two-column layout when the terminal is at least 200 cols wide: row list on the l
|
|
|
17
17
|
|
|
18
18
|
### Row kinds
|
|
19
19
|
|
|
20
|
-
| Kind
|
|
21
|
-
|
|
22
|
-
| `repo`
|
|
23
|
-
| `docker`
|
|
24
|
-
| `process`
|
|
20
|
+
| Kind | Source | Built-in `r` |
|
|
21
|
+
| --------- | --------------------------------------------- | ------------------------------------ |
|
|
22
|
+
| `repo` | `config.repos[]` or `profile.reposProvider()` | none — declare an action |
|
|
23
|
+
| `docker` | `config.docker.services[]` | `docker compose restart <service>` |
|
|
24
|
+
| `process` | `config.processes[]` | kill + respawn (tagged spawn lookup) |
|
|
25
25
|
|
|
26
26
|
### Status glyphs
|
|
27
27
|
|
package/docs/processes.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
A process is a long-running command — `tsc --watch`, `vitest --watch`, `npm run dev`, `php artisan serve`, `tail -f some.log` — declared in `cockpit.yaml` under `processes:`. The cockpit spawns each process once at boot and streams its stdout / stderr into the Output pane, tagged by source.
|
|
4
4
|
|
|
5
5
|
Distinct from:
|
|
6
|
+
|
|
6
7
|
- **Actions** (one-shot shell commands surfaced via the `:` palette and per-row keys)
|
|
7
8
|
- **Health checks** (state predicates with one-keystroke remediation)
|
|
8
9
|
- **Docker tailing** (`config.docker` — already managed by docker compose)
|
|
@@ -11,11 +12,11 @@ Distinct from:
|
|
|
11
12
|
|
|
12
13
|
```yaml
|
|
13
14
|
processes:
|
|
14
|
-
- id: typecheck
|
|
15
|
-
label: tsc --watch
|
|
16
|
-
command: npx tsc --watch --noEmit
|
|
17
|
-
cwd: ./apps/web
|
|
18
|
-
env:
|
|
15
|
+
- id: typecheck # required, unique; used as the Output source tag and Targets row id
|
|
16
|
+
label: tsc --watch # optional; shown in Repos + Output
|
|
17
|
+
command: npx tsc --watch --noEmit # shell command; runs via sh -c (cmd /c on Windows)
|
|
18
|
+
cwd: ./apps/web # optional; relative to workspaceRoot
|
|
19
|
+
env: # optional; merged on top of process.env
|
|
19
20
|
DEBUG: '1'
|
|
20
21
|
```
|
|
21
22
|
|
|
@@ -30,6 +31,7 @@ You can shadow `r` with a custom action of the same scope + key — declared act
|
|
|
30
31
|
## Output + highlights
|
|
31
32
|
|
|
32
33
|
Each line from a process's stdout / stderr gets:
|
|
34
|
+
|
|
33
35
|
- The source label (or `id`) as a tag.
|
|
34
36
|
- Default severity: `info` for stdout, `warn` for stderr.
|
|
35
37
|
- Highlight matching against `config.highlights[]`. A matched pattern's `severity:` wins over the default — so a `pattern: 'boom', severity: error` highlight upgrades any line containing "boom" to `error`, which shows as `✗`-prefixed in Output and feeds the Recent Errors strip.
|