@duyquangnvx/create-agent-cli 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -0
- package/README.md +3 -3
- package/agents-section.md +5 -0
- package/dist/bin.js +2301 -1209
- package/package.json +4 -3
- package/partials/global/skillCheck.md +1 -1
- package/template/AGENTS.md +4 -7
- package/template/package.json +1 -1
- package/template/scripts/release.ts +1 -1
- package/template/skills/{{binName}}/SKILL.md +3 -3
- package/template/src/cli.ts +14 -26
- package/template/test/cli.test.ts +27 -15
- package/template/tsdown.config.ts +1 -1
- package/template/src/build.ts +0 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,82 @@ What changed in each release of `@duyquangnvx/agent-cli` (the Runtime) and `@duy
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## v0.18.0 (2026-10-28)
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `render` and `renderPlan` are optional on every Command. Without `render`, text prints the data as [TOON](https://github.com/toon-format/toon), or nothing when there is none, and a List Command prints `page.items` that way before the page footer; without `renderPlan`, `--dry-run` prints `Would run <command line>:` and under it the Plan as TOON, indented two spaces, then `outputs` and `cost` as before. `--json` and `--fields` output are unchanged. The Scaffolder's `greet` declares no `render`, so it prints `greeting: "Hello, Ana!"`.
|
|
12
|
+
- A `CliError` takes `next`, an ordered list of Next steps beside its `hint`: each is the words after the CLI's name, such as `["archive", "--yes"]`, or `ctx.rerun({ remove?, add? })`, the caller's own line with each flag in `remove` dropped along with its value and the words in `add` placed before any `--`, keeping its `< <name file>` redirect. The Runtime builds each into a shell-quoted line starting with the Run-as. Text prints each on its own `run:` line after the hint; `--json` adds `next: string[]` to the error, absent when there are none, and each `AggregateError` leaf keeps its own. Under `runCli`, a Next step that names no Command or an unknown flag fails the run as a bug (exit 70) naming it; the built CLI does not check. `NextStep`, `Rerun` and `CommandLineChange` are exported, and the docs' example `links` gives its lines as Next steps.
|
|
13
|
+
- A second entry, `@duyquangnvx/agent-cli/testing`, exports `fakeClock({ busy?, onWake? })` to pass as `runCli`'s `clock`: its time moves only when every task waits on it, and waits for file reads and writes, so deadlines, `ctx.poll` and waits finish at once and in order. `busy` holds time while work Node cannot see is running; `onWake` runs as each sleep ends. The docs' example imports it.
|
|
14
|
+
- A Command and a CLI with several Commands take `secrets: [{ name, get }]`, `get` saying where to obtain the key. After the `tools` check and before `plan`, `run` or `start`, `--dry-run` included, a run whose declared Secret is unset in the environment and in the CLI's `.env` fails with the new Runtime code `SECRET_MISSING` (exit 2), naming every missing one with its `get` and the `.env` path. `doctor` gains a `secrets` row over the CLI's and every Command's Secrets, naming where each came from and never its value, and failing `doctor` for a missing one. Help JSON gives each Command `secrets: { name, get }[]`. The type `SecretDeclaration` is exported. The docs' example `links check` declares `LINKS_TOKEN`, which replaces its `token` row.
|
|
15
|
+
- `@duyquangnvx/agent-cli/testing` exports `checkExamples(cli)`. It checks every example of every Command, nested, single-command and Built-in alike: the line tokenizes as a POSIX shell would (a `< file` redirect allowed), starts with the CLI's name, routes to a Command, and passes that Command's schemas. It throws one error listing each example that does not, with the reason. The Scaffolder's test and the docs' example `links` test call it.
|
|
16
|
+
- `defineCli({ skill })` takes `{ page: "<https URL>" }`, the page of a Skill Hub where each user copies their own install line. `doctor`'s `skill` row then gives no fix for a missing copy or one that states no version, and its message names the page; `update` names it as a Notice. A copy older than the CLI still gets `npx -y skills update <name>`. `defineCli` throws on a page that is not an `https` URL.
|
|
17
|
+
- The Scaffolder's `--skill-hub-api` with `--skill-page` scaffolds a CLI on an API Skill Hub: `skillHub: { api }`, `skill: { page }`, and a README line naming the page. Either flag without the other is a usage error, `SKILL_PAGE_MISSING` or `SKILL_HUB_API_MISSING`, and passing both hub kinds is `SKILL_HOMES_CONFLICT`.
|
|
18
|
+
- `@duyquangnvx/agent-cli` ships its docs in `docs/`: an index, principles, getting started, a guide per topic, a map from each export to the `.d.ts` file that documents it, and the example `links` with its tests. Beside them, `agents-section.md` is the Agents section that points a repo's `AGENTS.md` at those docs, between `<!-- BEGIN:@duyquangnvx/agent-cli -->` and `<!-- END:@duyquangnvx/agent-cli -->`.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **Breaking:** a Command that declares `output` must return the schema's input type from `run`, `apply` or `start`, and its `render` receives the schema's output. Before printing, the Runtime parses returned and delivered data with the schema: data it rejects fails the run as a bug (exit 70) and prints no data, even when the Command caught an error around `ctx.deliver`, and its defaults and transforms show in what prints, under `--json` and in text. A Command without `output`, and a List Command's `rows`, are unchanged.
|
|
23
|
+
- **Breaking:** a Command no longer declares `name`, and declaring it fails type checking. The Runtime labels a Command by its path in `commands`: a declaration error names `voices list`, and a spilled file ends in `-voices-list`. A single-command CLI's Command takes the CLI's name. The checks that named a Command (a Standard flag name, `force`, an array arg, `orStdin`, a boolean array option) now throw from `defineCli` rather than `defineCommand`. The scaffolded template drops `name`.
|
|
24
|
+
- **Breaking:** `agentCli({ ports?, project?, errors? })` takes the ports factory, the Project file and the Error table as values, and `defineCli` no longer accepts them. `ctx.ports` is the type the factory returns and `ctx.project.settings` the Project file schema's output, so `agentCli` takes no type parameters; without `ports`, `ctx.ports` is empty. `agentCli` returns `cliError(code, init, options?)`, typed by the table, and the package no longer exports `cliError(table, code, init)`. An Error table that redeclares a Runtime code makes `agentCli` throw rather than `defineCli`. The scaffolded template and the Runtime's docs use the new form.
|
|
25
|
+
- **Breaking:** `ctx.timeout` is gone: `ctx.deadline(ms, { ignoreStop: true })` does what it did, aborting once `ms` have passed whether or not Ctrl-C or the run deadline stopped the run. The docs teach it for a billed call inside `runToEnd`.
|
|
26
|
+
- **Breaking:** the Runtime codes are no longer exported as loose constants (`INTERRUPTED`, `DEADLINE_EXCEEDED`, `PERMISSION_DENIED` and the rest); each is on the exported `runtimeCodes` object, as `runtimeCodes.INTERRUPTED`. The docs and their example use it.
|
|
27
|
+
- **Breaking:** `defineCli` takes `manifest`, the parsed `package.json`, in place of `name`, `version`, `description` and `engines`. The CLI's name is the manifest's `bin` key when it has exactly one, else the unscoped package name. `install` is `"global"`, `"dependency"` or `{ mode: "dependency", lockstep }`, its package being `manifest.name` and a Global install's registry `manifest.publishConfig.registry`; `defineCli` throws when a Global install's manifest lacks that registry. The new `CliManifest` and `InstallDeclaration` types are exported.
|
|
28
|
+
- **Breaking:** `defineCli` no longer takes `build`. The Runtime reads the build stamp from the `__AGENT_CLI_BUILD__` global the bundler defines, and without it, as in an unbundled run, `--version` prints no stamp. The scaffolded template drops `src/build.ts`, and its `tsdown.config.ts` defines `__AGENT_CLI_BUILD__` in place of `__BUILD__`.
|
|
29
|
+
- **Breaking:** `ctx.secret(name)` accepts only the names in the running Command's `secrets` and returns a `Secret`, never `undefined`; reading a name a Command does not declare, or reading any from a `doctor` row's `ctx`, fails type checking, and one reached past the type fails the run as a bug (exit 70), set or not. `PortsBase.secret` still takes any name and may return `undefined`.
|
|
30
|
+
- **Breaking:** an example starts with the CLI's name, and help and `--help --json` print it with that name replaced by the Run-as, so under a Dependency install it reads `npx -q --no-install <bin> ...`. An example already written with the Run-as prints as written and fails `checkExamples`. The Built-in Commands' examples and the scaffolded template's start with the bare name.
|
|
31
|
+
- **Breaking:** a Command declares the Error table codes it throws as `errors: [...]`, and help JSON gives each Command `errors: { code, class }[]`; a single-Command CLI's root `errors` keeps the Error table's shape but holds only the codes its Command declares. A run ending in a table code the running Command does not declare, directly or as an `AggregateError` leaf, fails as a bug (exit 70) naming the code and the Command, so a Command without `errors` may throw none of the table's codes; Runtime codes are never listed, and failures of `doctor` and its rows are not checked. `defineCli` throws on an `errors` entry the table lacks. The new `ctx.fail(code, init, options?)` returns a `CliError` for a declared code, typed by its `details`, for the Command to throw as `throw ctx.fail(...)`; `cliError` builds the same error for helpers outside a Command. The scaffolded template's `card` and the docs' example `links` declare their codes.
|
|
32
|
+
- `Context` and `ServeContext` take a third type parameter, the Command's `Needs` (`{ secretName, errors }`), which types `ctx.secret` and `ctx.fail`; `Needs` is exported. A helper that takes a plain `Context<Ports>` gets a `ctx` whose `secret` and `fail` accept nothing.
|
|
33
|
+
- **Breaking:** a Secret's name typed `string`, as one held in a plain `const` object is, fails type checking in `secrets`, since it would let `ctx.secret` take any name; a Command written inline in `defineCli` keeps its names literal.
|
|
34
|
+
- **Breaking:** the Runtime's failures during a run give their lines as Next steps, and their hints say when to run them without naming a line: `INTERRUPTED`, `DEADLINE_EXCEEDED` (from `ctx.deadline` and from a Command's `deadline`), `OUTPUT_EXISTS` and a guarded output's `ALREADY_EXISTS` (adding `--force`), `NOT_CONFIRMED` (adding `--yes`), `CONFIRMATION_REQUIRED` and `CONFIRMATION_MISMATCH` (with the right `--confirm`), `TOOL_MISSING` (each missing tool's `install`, then the rerun), `SECRET_MISSING`, `PROJECT_INVALID`, `NEEDS_OPERATOR`, and `PERMISSION_DENIED` and `DISK_FULL` where they asked for a rerun. The hints of `INTERRUPTED` and of a billed call's deadline still warn against running it blindly. A Command's `deadline.resume(input, rerun)` takes `ctx.rerun` in place of `ctx.commandLine` and returns a Next step, which the run's `DEADLINE_EXCEEDED` gives under the hint `run the Next step to continue the work`; returning a string fails type checking.
|
|
35
|
+
- **Breaking:** the Built-in Commands, `doctor` and List Command pages give their lines as Next steps. `update`'s `REGISTRY_UNREACHABLE`, `REGISTRY_AUTH`, `INSTALL_FAILED` and `NPM_FAILED` give the caller's line, their hints ending `then run it again`; `INSTALL_FAILED` then gives the `npm install --global` line, and `NOT_GLOBAL_INSTALL` gives it alone. A `doctor` problem with a fix gives the fix, then `doctor` as typed, under the hint `run the Next steps in order`. A rendered page ends `N shown; run the Next step for the next page` and a `run:` line in place of ``next page: `<line>` ``; the `--json` page's `next` is unchanged. The scaffolded template's `LANGUAGE_UNSUPPORTED` gives the English card as a Next step.
|
|
36
|
+
- `runCli`'s `env` is optional: without it the run sees an empty env, never the shell's. `cwd` stays required.
|
|
37
|
+
- The Runtime's docs and both READMEs teach Next steps, `secrets`, `errors`, `ctx.fail` and `checkExamples`, and the docs' "A Command is done when" checks them.
|
|
38
|
+
- The Runtime's docs, the README and the scaffolded `AGENTS.md` teach `render` as optional, `defineCli({ manifest, install })` and `runCli` without `env`; the docs' example `links check` prints its data as TOON, and its tests and the scaffolded test drop `env: {}`.
|
|
39
|
+
- **Breaking:** the Scaffolder's `--skill-hub` is now `--skill-hub-git`, which writes `skillHub: { git }` in `scripts/release.ts`. The scaffolded template is on `@duyquangnvx/release` 0.5.0 and awaits `release()`.
|
|
40
|
+
- **Breaking:** the agent-cli skill is no longer published to the Skill Hub; the docs the Runtime ships replace it. The scaffolded `AGENTS.md` ends with the Runtime's Agents section, and its `## Coding standards` no longer restates how to declare Commands, which the docs cover.
|
|
41
|
+
- `skill install`, `doctor`'s `agents` row and `skill install --help` call a Packaged skill's part of `AGENTS.md` its Agents section instead of its block.
|
|
42
|
+
|
|
43
|
+
### Removed
|
|
44
|
+
|
|
45
|
+
- **Breaking:** `ctx.commandLine` is gone; `ctx.rerun(change)` gives the caller's line, as a Next step.
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
|
|
49
|
+
- Under `--json`, a Command that returns no data prints `null`, which is valid JSON, rather than `undefined`.
|
|
50
|
+
- A reader that closes stdout or stderr early, as `| head` does, no longer crashes the CLI with Node's `Unhandled 'error' event` stack and exit 1. The rest of that stream's output is dropped, the Command runs to its end, and the CLI exits with the run's own exit code.
|
|
51
|
+
|
|
52
|
+
### Upgrade from v0.17.0
|
|
53
|
+
|
|
54
|
+
Take these steps in order; `pnpm typecheck` finds every site the first eight leave behind.
|
|
55
|
+
|
|
56
|
+
1. In the module that calls `agentCli`, move `ports`, `project` and `errors` out of `defineCli` into that call and delete its type parameters: `agentCli<Ports, Settings>()` becomes `agentCli({ ports, project, errors })`. Export the `cliError` it returns beside `defineCommand` and `defineCli`, as the template's `src/cli.ts` and the docs' `example/define.ts` do.
|
|
57
|
+
2. Import `cliError` from that module wherever a Command throws, and drop its first argument: `cliError(errors, "CODE", init)` becomes `cliError("CODE", init)`.
|
|
58
|
+
3. In `defineCli`, replace `name`, `version`, `description` and `engines` with `manifest` (`import manifest from "../package.json" with { type: "json" }`), and replace the install object with `install: "global"`, `install: "dependency"`, or `{ mode: "dependency", lockstep }` with lockstep packages. A Global install's `package.json` needs `publishConfig.registry`.
|
|
59
|
+
4. Delete `src/build.ts` and the `build` line of `defineCli`, and in `tsdown.config.ts` rename the `define` key `__BUILD__` to `__AGENT_CLI_BUILD__`.
|
|
60
|
+
5. Delete `name` from every Command.
|
|
61
|
+
6. Replace each `ctx.timeout(ms)` with `ctx.deadline(ms, { ignoreStop: true })`.
|
|
62
|
+
7. Import `runtimeCodes` in place of each Runtime code constant, and write `runtimeCodes.CODE` where `CODE` stood.
|
|
63
|
+
8. Make each Command's `deadline.resume` return a Next step: `(_input, commandLine) => commandLine(change)` becomes `(_input, rerun) => rerun(change)`, and a line written by hand becomes the words after the CLI's name, such as `["archive", "--yes"]`.
|
|
64
|
+
9. Correct each Command whose data does not match its `output` schema: `pnpm typecheck` names those it can see, and `pnpm test` the rest, which now exit 70. An object schema strips keys it does not declare, so declare every key the data should print, or make the schema `z.looseObject`.
|
|
65
|
+
10. Under a Dependency install, start each Command's `examples` with the bare CLI name instead of `npx -q --no-install <bin>`, then call `checkExamples(cli)` from `@duyquangnvx/agent-cli/testing` in a test and fix each example it lists.
|
|
66
|
+
11. For each Command that calls `ctx.secret(name)`, add `secrets: [{ name, get }]` with the name inline, or its object declared `as const`, and drop its `undefined` branch, since the Runtime now fails the run first. Move a `doctor` row that only reports a key into the CLI's `secrets`; the `secrets` row reports it.
|
|
67
|
+
12. List in each Command's `errors` every code of the Error table it throws, those its helpers and ports throw included (a shared store's `CORRUPT_DATA` goes on every Command that reads the store), then run `pnpm test`: a code left out now exits 70 and names the Command. Inside a Command, `throw ctx.fail(code, init)` in place of `throw cliError(code, init)` makes an undeclared code a type error.
|
|
68
|
+
13. Move each command line out of a hint into the error's `next`: a line naming a Command becomes the words after the CLI's name, such as `["archive", "--yes"]`, and `ctx.commandLine(change)` becomes `ctx.rerun(change)`. Reword the hint to say whether and when to run the Next steps rather than quote them.
|
|
69
|
+
14. Update each test that asserts a line in a hint of the Runtime's, `doctor`'s or a Built-in Command's, or a rendered page's ``next page:`` line, to read the Next step instead: the error's `next` under `--json`, or its `run:` line in text.
|
|
70
|
+
15. Remove the agent-cli skill: `npx skills remove agent-cli -g`. Then append `node_modules/@duyquangnvx/agent-cli/agents-section.md` to the CLI repo's `AGENTS.md`, markers included, so sessions there find the Runtime's docs.
|
|
71
|
+
|
|
72
|
+
## v0.17.0 (2026-10-27)
|
|
73
|
+
|
|
74
|
+
### Added
|
|
75
|
+
|
|
76
|
+
- A fifth Effect, `act`, for a Command that changes the state of a program already running, such as a page in a browser tab, rather than files or remote services. It is declared as a read Command is, with `run` and the new `ActCommand` type, and cannot declare a Plan or `rows`. Its help says so and that running it again may act again, its `--help --json` gives `"effect": "act"`, and of the Standard flags it gets only `--json`. The agent-cli skill says when to pick `act` over `read` and `write`.
|
|
77
|
+
- The Scaffolder's `AGENTS.md` names the `act` and `serve` Effects beside `read`, `write` and `destructive`.
|
|
78
|
+
|
|
79
|
+
### Upgrade from v0.16.0
|
|
80
|
+
|
|
81
|
+
- Nothing to do.
|
|
82
|
+
|
|
7
83
|
## v0.16.0 (2026-10-27)
|
|
8
84
|
|
|
9
85
|
### Changed
|
package/README.md
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
Creates a new Agent CLI repository already wired to [`@duyquangnvx/agent-cli`](https://www.npmjs.com/package/@duyquangnvx/agent-cli):
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
|
-
pnpm create @duyquangnvx/agent-cli <name> --description "One line saying what it does" --skill-hub https://github.com/<owner>/skills.git
|
|
6
|
+
pnpm create @duyquangnvx/agent-cli <name> --description "One line saying what it does" --skill-hub-git https://github.com/<owner>/skills.git
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
The new repository has an Error table, a port, two example Commands (one writing a file at a cost) and their test, a bundled build that stamps the commit and build time into `--version`, CI, a release script, a CHANGELOG, an `AGENTS.md`, and a skeleton skill for the new CLI whose setup reference installs, checks and updates it, so a user installs the skill first and lets their agent do the rest. `--skill-hub` names the Skill Hub each release commits that skill to and agents install it from; `--dependency` instead starts a CLI each project pins as a devDependency, run as `npx -q --no-install <name>`, whose skill ships inside the package for its `skill install` to copy into the project. Pass `--dry-run` to see what it would write.
|
|
9
|
+
The new repository has an Error table, a port, two example Commands (one writing a file at a cost) and their test, a bundled build that stamps the commit and build time into `--version`, CI, a release script, a CHANGELOG, an `AGENTS.md` whose Agents section points Coding agents at the Runtime's docs in `node_modules`, and a skeleton skill for the new CLI whose setup reference installs, checks and updates it, so a user installs the skill first and lets their agent do the rest. `--skill-hub-git` names the git Skill Hub each release commits that skill to and agents install it from, and `--skill-hub-api` with `--skill-page` an API Skill Hub that gives each user their own install line from that page; `--dependency` instead starts a CLI each project pins as a devDependency, run as `npx -q --no-install <name>`, whose skill ships inside the package for its `skill install` to copy into the project. Pass `--dry-run` to see what it would write.
|
|
10
10
|
|
|
11
|
-
See the [repository](https://github.com/duyquangnvx/cli-for-agent) for an overview and the [
|
|
11
|
+
See the [repository](https://github.com/duyquangnvx/cli-for-agent) for an overview and the [Runtime's docs](https://github.com/duyquangnvx/cli-for-agent/blob/main/packages/agent-cli/docs/README.md) for how to build on it.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<!-- BEGIN:@duyquangnvx/agent-cli -->
|
|
2
|
+
## agent-cli
|
|
3
|
+
|
|
4
|
+
This CLI is built on `@duyquangnvx/agent-cli`, the Runtime. Before you change a Command, a `doctor` row, a test or the release, read `node_modules/@duyquangnvx/agent-cli/docs/README.md` and the pages it names: they describe the installed version, which your training data likely predates.
|
|
5
|
+
<!-- END:@duyquangnvx/agent-cli -->
|