Skip to content

Commit 1fdc38c

Browse files
zrosenbauerclaude
andcommitted
feat(packages/bundler): add bundler package with single-file output for bun compile
Introduce the `packages/bundler` package with autoload plugin, static command tree generation, and tsdown config mapping. Key design decisions: - Disable code splitting (`codeSplitting: false`) so rolldown inlines all dynamic imports into a single output file compatible with `bun build --compile` - Resolve `@kidd/utils/tag` to absolute path via `createRequire` so the virtual commands module can import it without relying on `alwaysBundle` - Prefer ESM entry via `mainFields: ['module', 'main']` to avoid UMD `require()` calls breaking in ESM context Also includes: new `packages/config` package, CLI restructuring (extract bundler/compiler into dedicated package), documentation updates, and example project configs. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 8871094 commit 1fdc38c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+5431
-6063
lines changed

.claude/rules/errors.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type Result<T, E = Error> = readonly [E, null] | readonly [null, T]
1818
1919
## Conventions
2020
21-
- Define domain-specific error interfaces with `_tag` discriminator and descriptive `reason` or `type` field
21+
- Define domain-specific error interfaces with a descriptive `type` or `reason` field
2222
- Create type aliases for domain results (e.g., `type ConfigResult<T> = Result<T, ConfigError>`)
2323
- Use `ok()` and `fail()` constructors where available (e.g., `HandlerResult` in kidd package)
2424
- Wrap async operations that can reject with a try/catch that returns a Result tuple
@@ -39,7 +39,6 @@ return [null, script]
3939

4040
```ts
4141
interface ConfigError {
42-
readonly _tag: 'ConfigError'
4342
readonly type: 'invalid_toml' | 'missing_field' | 'unknown_workspace'
4443
readonly message: string
4544
}

CLAUDE.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ pnpm test # Run package tests
5656
- Built with `tsdown` (`dts: true`, `format: 'esm'`, `clean: true`, `outDir: 'dist'`)
5757
- TypeScript: `target: ES2022`, `module: ESNext`, `moduleResolution: bundler`, `strict: true`, `isolatedDeclarations: true`
5858
- `vitest` for tests (test files in `test/**/*.test.ts`)
59-
- `_tag` discriminated unions on factory-created objects
6059
- All public properties `readonly`
6160
- Config validated with Zod at boundaries
6261
- Explicit return types on all exported functions (required by `isolatedDeclarations`)

assets/logo-icon.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣤⣶⣶⣶⣶⣶⣶⣤⣤⣀⡀
2+
⠀⠀⠀⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⣀
3+
⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀
4+
⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
5+
⠀⠀⠀⢀⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⡀
6+
⠀⠀⢠⣿⣿⣿⣿⣿⣿⠏⠉⠙⠛⠛⠋⠁⠀⠀⠈⠙⠛⠛⠋⠉⠹⣿⣿⣿⣿⣿⣿⡄
7+
⠀⠀⢸⣿⣿⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣼⣿⣿⣿⣿⣿⡇
8+
⠀⣠⣾⣿⣿⡏⠁⢀⡴⠶⠟⢛⣛⣛⣛⠛⠶⢦⣄⠀⠀⣀⣤⠾⠋⠀⠈⢹⣿⣿⣷⣄
9+
⢰⣿⣿⣿⣿⣿⠀⣿⢰⣿⣿⣿⠟⠻⣿⣿⣿⣦⢹⡿⠿⠛⠉⠀⠀⠀⠀⣿⣿⣿⣿⣿⡆
10+
⠈⢿⣿⣿⣿⡟⠀⢻⡘⣿⣿⣿⡄⠘⢿⣿⣿⠇⡾⠁⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⡿⠁
11+
⠀⢀⣿⣿⣯⡀⠀⠈⢳⡙⣿⣿⣭⢠⣾⣿⠏⡼⠁⠀⠀⠀⠀⠀⠀⠀⠀⢀⣽⣿⣿⡀
12+
⢠⣿⣿⣿⣿⣿⡄⠀⠀⠙⣮⣙⠛⠟⣛⣥⠞⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⡄
13+
⠘⣿⣿⣿⣿⣿⠃⠀⠀⠀⠀⠉⠛⠛⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⠃
14+
⠀⠈⣿⣿⣟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣻⣿⣿⠁
15+
⢀⣾⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣷⡀
16+
⠸⣿⣿⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⣿⠇
17+
⠀⠙⠻⠿⠟⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠻⠿⠟⠋

assets/logo.txt

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,23 @@
1-
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣶⣾⣿⣿⣿⣶⣶⣶⣶⣄
2-
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄
3-
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⡀
4-
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⠛⠋⠉⠛⠻⣿⣿⣿⣿⣿⣿⣷
5-
⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⡇
6-
⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⡀
7-
⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣿⣿⣿⣿⣿⣧
8-
⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣿⣿⡆
9-
⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⣿⣿⣿⣷
10-
⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣆
11-
⠀⠀⠀⠀⠀⠀⢹⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣿⣿⡿
12-
⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⡆
13-
⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⡇
14-
⠀⠀⠀⢀⣾⠿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣿⣿⡟
15-
⠀⠀⠀⣾⠁⠀⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁
16-
⠀⠀⠀⢿⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⣼⠛⣿⣿⣿⣿⠿⢿⣏⣦
17-
⠀⠀⣀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⢃⠇⠀⠀⠀⠀⠀⠀⠀⢰⠏⢀⣿⣿⣿⣿⣶⣦⣿⣿⣧⣄
18-
⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠋⠣⡀⠀⠀⠀⠀⠀⠀⠀⣿⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⡁
19-
⣿⣿⣿⣿⣿⠛⠙⣿⣿⣿⣿⣗⡉⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣴⣿⣿⣿⣷⣤⣽⡛⡄
20-
⠸⣿⣿⣿⣿⠀⠀⣿⣿⣿⣿⡉⠉⠁⠀⠀⠀⠀⠀⠀⠀⢹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⡇
21-
⣶⣿⣿⣿⠃⠀⣰⣿⢻⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃
22-
⠛⢫⣿⣷⡶⢾⣿⣷⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⡀⠀⠉⠈⢉⣿⣿⣿⣿⣿⡄⠇⣿
23-
⠈⣿⡅⢠⡞⠋⣽⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⠷⠶⢿⡿⠟⣿⢿⣿⣿⣿⣤⡟
24-
⠀⠘⣿⠏⠀⣼⣿⣏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣄⣿⠿⣿⡟
25-
⠀⠀⢹⡇⠀⣿⡇⠈⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⠁
26-
⠀⠀⠘⠀⠀⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⡏
1+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣤⣤⣤⣤⣴⣶⣶⣤⣤⣤⣤⣄⣀⡀
2+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣤⣀
3+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣄
4+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀
5+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄
6+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷
7+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠀⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣄
8+
⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⠀⠉⠙⠛⠛⠛⠛⠋⠀⠀⠀⠀⠀⠉⠛⠛⠛⠛⠛⠉⠁⠈⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧
9+
⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡿⠁⠀⠀⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿
10+
⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⠿⠿⠟⠋⣀⣤⣴⠶⠶⠶⠶⠶⠶⣤⣤⣀⠀⠀⠀⠀⠀⢀⣴⡟⠁⠀⠀⠀⠀⠈⠛⠿⠿⢿⣿⣿⣿⣿
11+
⠀⠀⠀⠀⠀⠀⣠⣶⣿⣿⣿⣿⣇⠀⠀⠀⣾⢫⣴⣶⣶⣿⡿⣿⣿⣶⣶⣬⠹⣷⣴⣶⠶⠿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣷⣦⡀
12+
⠀⠀⠀⠀⠀⣸⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⣿⠸⣿⣿⣿⡏⠀⢤⣿⣿⣿⣿⢡⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣿⣷
13+
⠀⠀⠀⠀⠀⢹⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠸⣧⠻⣿⣿⡿⠆⠀⣹⣿⣿⢃⡾⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿
14+
⠀⠀⠀⠀⠀⠀⠻⣿⣿⣿⣿⣿⠟⠀⠀⠀⠀⠘⢷⣝⠿⣿⣧⣾⣿⠟⣡⡞⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣿⣿⣿⠟⠁
15+
⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠙⠳⢦⣬⣥⡶⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣿⣿⣿⣯⡀
16+
⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣆
17+
⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿
18+
⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢿⣿⣿⣿⣿⣿⣿⠏
19+
⠀⠀⠀⠀⠀⠀⠈⢻⣿⣿⣿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠹⣿⣿⣿⣿⠁
20+
⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣷⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣦⡀
21+
⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⣿⣿⣷
22+
⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⣿⣿⣿⡟
23+
⠀⠀⠀⠀⠀⠀⠙⠿⣿⣿⣿⡿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠿⣿⣿⣿⡿⠟

assets/yargs.txt

Lines changed: 0 additions & 19 deletions
This file was deleted.

contributing/concepts/architecture.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ The framework primitives:
9999
| Module | Purpose |
100100
| --------------- | ---------------------------------------------------------- |
101101
| `cli.ts` | Entry function that wires yargs, config, and context |
102-
| `command.ts` | Factory for creating typed commands with `_tag: 'Command'` |
102+
| `command.ts` | Factory for creating typed commands |
103103
| `middleware.ts` | Factory and pipeline runner for middleware composition |
104104
| `autoloader.ts` | Auto-discovery and dynamic import of command files |
105105
| `context/` | Context creation, types, and error handling |
@@ -224,7 +224,7 @@ sequenceDiagram
224224

225225
## Command System
226226

227-
Commands are created with the `command()` factory and identified by `_tag: 'Command'`:
227+
Commands are created with the `command()` factory:
228228

229229
```ts
230230
export default command({
@@ -272,7 +272,7 @@ commands/
272272

273273
**Discovery rules:**
274274

275-
- Files must export a default `Command` (`_tag === 'Command'`)
275+
- Files must export a default `Command` (created via `command()`)
276276
- Extensions: `.ts` or `.js` (not `.d.ts`)
277277
- Ignored: files starting with `_` or `.`, files named `index`
278278
- Subdirectories become parent commands; `index.ts` in a subdirectory becomes the parent handler
@@ -298,7 +298,7 @@ kidd uses two error strategies depending on the layer:
298298
| Layer | Strategy | Type |
299299
| ------------ | ----------------------------------- | ------------------------------------------ |
300300
| Lib/internal | `Result<T, E>` tuples | `[error, null]` or `[null, value]` |
301-
| Context/CLI | `ContextError` (thrown at boundary) | `{ _tag: 'ContextError', code, exitCode }` |
301+
| Context/CLI | `ContextError` (thrown at boundary) | `{ code, exitCode }` |
302302

303303
**Result tuples** are used for expected failures (config parsing, validation, file I/O). Chain with early returns:
304304

@@ -312,10 +312,10 @@ if (error) return [error, null]
312312
## Design Decisions
313313

314314
1. **Immutable by default** -- All context properties are deeply readonly; only `ctx.store` is mutable (for middleware data flow)
315-
2. **Factories over classes** -- All components are factory functions returning objects with `_tag` discriminators
315+
2. **Factories over classes** -- All components are factory functions returning plain objects
316316
3. **Result tuples over throw** -- Expected failures use `Result<T, E>`; `ContextError` is the only thrown type at the CLI boundary
317317
4. **Module augmentation** -- `KiddArgs`, `KiddConfig`, `KiddStore` interfaces allow typed extensions without generics threading
318-
5. **Discriminated unions** -- All domain types use `_tag` for exhaustive pattern matching via `ts-pattern`
318+
5. **Discriminated unions** -- Domain types use `type` fields or symbol-based tags for exhaustive pattern matching via `ts-pattern`
319319
6. **Lazy subcommand loading** -- Commands accept `Promise<CommandMap>` from `autoload()` for deferred imports
320320
7. **Zod at boundaries** -- Runtime config, args, and external data validated with Zod schemas
321321
8. **Sensitive data redaction** -- Deep object redaction and regex pattern sanitization built into the context

contributing/concepts/cli.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ kidd uses [yargs](https://yargs.js.org) for command routing and [`@clack/prompts
88

99
## Commands
1010

11-
Commands are created with the `command()` factory. Each command receives a `_tag: 'Command'` discriminator and defines a description, optional args schema, optional subcommands, and a handler function.
11+
Commands are created with the `command()` factory. Each command defines a description, optional args schema, optional subcommands, and a handler function.
1212

1313
| Property | Type | Description |
1414
| ------------- | ----------------------------------------- | ----------------------------------------------------- |
@@ -210,7 +210,7 @@ commands/
210210

211211
**Rules:**
212212

213-
- Files must have a default export with `_tag === 'Command'`
213+
- Files must have a default export created via `command()`
214214
- Extensions: `.ts` or `.js` (not `.d.ts`)
215215
- Ignored: files starting with `_` or `.`, files named `index` (used as parent handlers)
216216
- Subdirectories become parent commands with nested subcommands
@@ -221,7 +221,7 @@ Errors propagate from handlers to the terminal through a single path:
221221

222222
```
223223
Handler calls ctx.errors.fail(message)
224-
-> Throws ContextError { _tag, code, exitCode, message }
224+
-> Throws ContextError { code, exitCode, message }
225225
-> Middleware chain unwinds (post-handler code skipped)
226226
-> CLI boundary catches ContextError
227227
-> Logs error message via @clack/prompts

0 commit comments

Comments
 (0)