Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @kjanat
30 changes: 23 additions & 7 deletions .zed/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,38 @@
],
"languages": {
"JavaScript": {
"formatter": [
{ "language_server": { "name": "biome" } },
{ "language_server": { "name": "dprint" } },
{
"external": {
"command": "bunx",
"arguments": ["dprint", "fmt", "--stdin", "{buffer_path}"]
}
}
],
"code_actions_on_format": {
"source.fixAll.biome": true,
"source.organizeImports.biome": true
},
"language_servers": ["vtsls", "tsgo", "biome", "deno"]
"language_servers": ["typescript", "biome", "oxlint", "deno"]
Comment thread
coderabbitai[bot] marked this conversation as resolved.
},
"TypeScript": {
"formatter": [
{ "language_server": { "name": "biome" } },
{ "language_server": { "name": "dprint" } },
{
"external": {
"command": "bunx",
"arguments": ["dprint", "fmt", "--stdin", "{buffer_path}"]
}
}
],
"code_actions_on_format": {
"source.fixAll.biome": true,
"source.organizeImports.biome": true
},
"language_servers": ["vtsls", "tsgo", "biome", "deno", "vue-language-server"]
"language_servers": ["typescript", "biome", "oxlint", "deno", "vue-language-server"]
}
},
"lsp": {
Expand All @@ -42,11 +62,7 @@
}
},
"dprint": {
"binary": {
"path": "bunx",
"ignore_system_version": true,
"arguments": ["dprint", "lsp"]
}
"binary": { "path": "bunx", "arguments": ["dprint", "lsp"] }
},
"json-language-server": {
"settings": {
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
Schema-first, fully typed TypeScript CLI framework. Zero runtime deps. In-repo exports point at
`src/*.ts`; published Node defaults point at `dist/*.mjs`, while Bun and Deno keep source exports.

Read `@DISCOVERIES.md` before planning, editing, or running task workflows.
Read @DISCOVERIES.md before planning, editing, or running task workflows.

## STRUCTURE

Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

### Added

- **Standard Schema v1 validation** — `flag.custom(schema)` and
`arg.custom(schema)` accept any conforming validator (including callable,
sync, and async schemas) with inferred output types and no runtime
dependency. Validation runs after source resolution, so argv, env, config,
prompt, stdin, and default values behave consistently; array flags and
variadic args validate each element.
- **`isMainModule(import.meta)`**: Compatibility helper for consumers whose
ambient `ImportMeta` interface omits `main`. Projects with normal Node, Bun,
or Deno runtime typings can keep using the conventional
Expand All @@ -25,6 +31,12 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
ambient `ImportMeta` interface to pass both TypeScript/Deno checks and JSR
publish validation.

### Removed

- **Internal schema DSL** — the private template-literal parser, validator, and
JSON Schema converter were replaced by direct definition-schema objects,
removing roughly 1,500 lines without changing the generated schema.

## [3.0.0-rc.11] - 2026-07-15

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion biome.jsonc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "node_modules/@biomejs/biome/configuration_schema.json",
"$schema": "node_modules/biome/configuration_schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
Expand Down
136 changes: 70 additions & 66 deletions bun.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions docs/guide/arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ argTypes.custom;
// ^?
```

`arg.custom()` also accepts any [Standard Schema v1](https://standardschema.dev/schema)
validator. Its output type is inferred, sync and async validators are supported, and validation
runs after CLI, env, stdin, or default resolution. A variadic custom argument validates each
resolved element separately.

## Declaration

```ts twoslash
Expand Down
18 changes: 18 additions & 0 deletions docs/guide/flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,24 @@ flag.custom((value) => {
The parse function receives the raw string value and returns the parsed type.
Thrown errors become validation errors with the flag name in context.

### Standard Schema Validators

`flag.custom()` also accepts any [Standard Schema v1](https://standardschema.dev/schema)
validator, including Zod, Valibot, and ArkType schemas:

```ts
import { flag } from '@kjanat/dreamcli';
import { z } from 'zod';

const port = flag.custom(z.coerce.number().int().min(1).max(65_535));
// inferred type: number | undefined
```

Standard Schema validation runs after source resolution, so the same sync or async validator
handles CLI, env, config, prompt, and default values. Validation issues become
`CONSTRAINT_VIOLATED` errors. When used as a `flag.array()` element, the validator runs once per
resolved element.

## Propagation

Flags marked with `.propagate()` are inherited by all subcommands:
Expand Down
16 changes: 11 additions & 5 deletions examples/gh/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@kjanat/dreamcli": "link:@kjanat/dreamcli"
"@kjanat/dreamcli": "file:../.."
},
"devDependencies": {
"@types/bun": "catalog:",
"typescript": "catalog:"
"@types/bun": "latest",
"typescript": "latest"
Comment thread
kjanat marked this conversation as resolved.
},
"packageManager": "bun@1.3.12",
"engines": {
"bun": "^1.3"
},
Expand All @@ -34,6 +33,13 @@
"name": "bun",
"version": "^1.3",
"onFail": "error"
}
},
"packageManager": [
{
"name": "bun",
"onFail": "error",
"version": "^1.3"
}
]
}
}
2 changes: 1 addition & 1 deletion examples/gh/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { pr } from './commands/pr.ts';
* Command registration order determines the order shown in `--help`.
*/
export const gh = cli('gh')
.manifest({ from: import.meta.url })
.manifest({ from: import.meta, files: ['package.json'] })
.command(auth)
.command(pr)
.command(issue)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@
},
"devDependencies": {
"@arethetypeswrong/core": "^0.18.5",
"@biomejs/biome": "<=2.5.2 || >=2.5.4",
"@iarna/toml": "^2.2.5",
"@shikijs/transformers": "^4.3.1",
"@shikijs/vitepress-twoslash": "^4.3.1",
Expand All @@ -123,6 +122,7 @@
"@types/node": "catalog:",
"@typescript/native": "catalog:",
"@vitest/coverage-v8": "^4.1.10",
"biome": "npm:@biomejs/biome@^2.5.4",
"dprint": "^0.55.1",
"floating-vue": "^5.2.2",
"knip": "^6.25.0",
Expand Down
1 change: 1 addition & 0 deletions src/core/cli/root-help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ function completionsFlagSchema(shells: readonly string[]): FlagSchema {
valueHint: undefined,
prompt: undefined,
parseFn: undefined,
standard: undefined,
deprecated: undefined,
propagate: false,
negation: undefined,
Expand Down
1 change: 1 addition & 0 deletions src/core/completion/shells/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ function createSyntheticRootFlag(description: string): FlagSchema {
valueHint: undefined,
prompt: undefined,
parseFn: undefined,
standard: undefined,
deprecated: undefined,
propagate: false,
negation: undefined,
Expand Down
Loading
Loading