Repository navigation
v8.0.0
[8.0.0] - 2026-09-30
Changed (breaking)
-
New naming: an app is built with
argsbarg({ … })from a spec ofcommands, and theCliprefix is gone.argsbarg({ … })validates the spec and returns the app (export const app = argsbarg({ … })insrc/app.ts, thenawait app.run());Appis exported as a type only. Commands either run (handler) or group subcommands (commands), and both are declared withcommand({ … }). The definition is the spec:app.spec,ctx.spec, andspecon hook/runtime contexts; spec helpers (generateOpenApi,schemaStrictnessWarnings,mcpSizeReport,packMcpBundle, …) takeapp.spec. Public types dropClibecause argsbarg serves HTTP and MCP too; it stays only where it means the CLI surface (CliExposureConfig,cliErrWithHelp, the"cli"invocation). Key renames:7.x 8.0 const program = { … } satisfies CliProgram; new Cli(program).run()export const app = argsbarg({ … }); await app.run()src/program.tssrc/app.tscli.program/ctx.program/ hookctx.programapp.spec/ctx.spec/ hookctx.specCliProgram/CliProgramHooksAppSpec/AppHooks{ … } satisfies CliLeaf/CliRoutercommand({ … })CliNode/CliLeaf/CliRouterCommand/RunnableCommand/CommandGroupCliOption/CliPositional/CliContextCommandOption/CommandPositional/CommandContextCliOptionKind/CliValueFormat/CliFallbackModeOptionKind/ValueFormat/FallbackModeCliSchemaValidationError/LeafInputError/CliJsonSchema/CliLeafInputsSchemaValidationError/InputError/JsonSchema/CommandInputsCliAppConfig/CliLocals/CliInvocationAppConfig/Locals/InvocationCliMcpServerConfig/CliHttpServerConfig/CliDocsConfig…McpServerConfig/HttpServerConfig/DocsConfig…CliCliExposureConfigCliExposureConfigisDocumentLeaf/buildLeafInputSchema/leafWireOptionsisDocumentCommand/buildCommandInputSchema/commandWireOptionscliSchemaExport/cliSchemaJsonschemaExport/schemaJsonValidation now happens when
argsbarg()runs (at import ofsrc/app.ts). The docs name the app's own config schemaSettingsso it doesn't clash with argsbarg'sAppConfigtype.declare module "argsbarg"augmentations useLocals/ServerState. User-facing messages say "command" / "command group" / "app root" instead of leaf / router / program root. -
Schemas are authored in Zod 4 (
zodis now a peer dependency).inputSchema,outputSchema,httpServer.errors.errorSchema, andmcpServer.errors.errorSchematake Zod schemas; argsbarg validates with Zod and emits JSON Schema (draft 2020-12) for MCPtools/list, OpenAPI, non-TTY help, anddocs cli-schema. Passing a JSON Schema object fails at startup with a migration error. -
program.appConfig.jsonSchemais replaced byprogram.appConfig.schema, which takes a Zod object schema (z.strictObjectrecommended). Without it, argsbarg still synthesizes an all-string schema fromentries. -
ctx.inputsfor a leaf withinputSchemais now the schema's parsed output: defaults and transforms are applied, and strict schemas reject unknown keys as before. -
Schema validation errors are Zod's messages prefixed by path, polished for agents: missing fields read
name: required, unknown keys list what is allowed ($: Unrecognized key: "titel" (allowed: action, doc, title)), and union/enum mismatches echo the rejected value (steps.0.kind: Invalid discriminator value. Expected 'alpha' | 'beta' (got "alfa")). This replaces argsbarg's union-narrowing rewrites. -
Partial config validation (
configure set, bootstrap) makes top-level keys optional via.partial(); nestedrequiredfields are no longer relaxed.
Removed (breaking)
argsbarg schemagen, the/** @sg */markers, and__generated__/artifacts: define schemas in Zod instead. Thets-json-schema-generatorand@cfworker/json-schemadependencies are gone (argsbarg has no runtime dependencies;zodis the only peer).- Subpath exports
argsbarg/cli,argsbarg/headless,argsbarg/http,argsbarg/mcp, andargsbarg/schemagen: import from"argsbarg"(everything they exported is on the root). - JSON Schema draft selection via
$schema(argsbarg emits draft 2020-12) and thecomma-listJSON Schema format registration. - The
consumers-schemagenrecipe;sqsp-i18n-tools-pocis no longer a tracked consumer.consumers-devnow forces the install, addszod, and removes the nested dev copy of zod; the newexamples-installrecipe reinstalls the in-repo examples. ctx.inputsAs<T>(): usectx.inputswithcommand.- The
CliHandlertype export (unused since handlers are typed throughcommand/program). kind: "json"leaves,isJsonLeaf, andJSON_LEAF_BODY_KEY: usekind: "document",isDocumentCommand, andDOCUMENT_LEAF_BODY_KEY.kind: "json"now fails at startup with a migration error.CliSkillConfig/program.skill(it had no effect since skill generation was removed).- The dedicated startup errors for long-removed
configuresettings (prefix,agentIntegration, and per-host skill/MCP targets). Unknown target keys still fail withconfigure.targets.<key> is not a valid target key.
Migration (7 → 8)
- Add
zod@^4to your dependencies. - Convert each
/** @sg */type toexport const X = z.strictObject({…})plusexport type X = z.infer<typeof X>, copying every JSDoc into.describe("…"). Agents read these descriptions, and Zod does not read JSDoc. - Pass the Zod schemas to
inputSchema/outputSchema/errorSchema, renameappConfig.jsonSchema→appConfig.schema, build the app withexport const app = argsbarg({…})insrc/app.ts(await app.run()inindex.ts), wrap every command incommand({…}), usectx.spec/app.specwhere you usedctx.program/cli.program, replacectx.inputsAs<T>()withctx.inputs(path params:ctx.pathParams), changekind: "json"tokind: "document", and dropskill: { … }. - Replace subpath imports with
"argsbarg", delete__generated__/, and remove theschemagenrecipes and gitignore rules. - Diff
docs cli-schemaoutput before and after to confirm every description survived. Seedocs/developing.md→ "Upgrading consumer apps to 8.0".
Added
command()infersctx.inputsfrominputSchemaand types the handler return fromoutputSchema. It is now the way to declare leaves;{ … } satisfies RunnableCommandis no longer documented or used in the templates (it still compiles, but its handler gets untypedctx.inputs).program()declares the program root: router roots keep their literal type, and a leaf root (one-command CLI) gets the samectx.inputsinference ascommand. It replacessatisfies Programin the docs and templates.command()also typesctx.inputsfor leaves without aninputSchema, from their ownoptions/positionalsliterals: presence flags areboolean, numbersnumber, enums theirchoicesunion, durationsnumber(ms), comma-listsstring[], and required or defaulted options are non-optional. Types only; runtime parsing is unchanged.CommandBase.options,positionals, andCommandOption.choicesaccept readonly arrays.- Leaves can declare
pathParams: z.strictObject({ id: z.string().describe(…) })for the:paramsegments above them: values are validated before the handler, typed asctx.pathParamswithcommand, and described in MCP tool schemas and OpenAPI path parameters. Startup checks that the keys match the route and are not also declared byinputSchema. The raw segments stay available asctx.rawPathParams. - Startup validation emits every schema eagerly, so schemas JSON Schema cannot represent (transforms,
z.date(), …) fail at startup with the leaf named. schemaStrictnessWarnings(program)(exported) lists input and config objects that accept unknown keys (z.objectinstead ofz.strictObject). The schema templates assert it is empty insrc/program.test.ts, and MCP and HTTP servers log each warning at startup (schema.strictness).- JSON Schema authoring guide rewritten for Zod (
docs/json-schema-subset.md), and ADR 4 (Zod as the schema layer) supersedes ADR 2. - The root export now includes every public type that was previously only reachable through the bundled
index.d.ts(RunnableCommand,CommandGroup,Command,JsonSchema, …), plus the HTTP server and Claude/Cursor plugin helpers.
Fixed
PUT/PATCHon:paramroutes (e.g./workspaces/:id) no longer fail withunknown property "id"when the leaf'sinputSchemais strict: path parameters the schema does not declare are left out of validation and merged intoctx.inputs(also available asctx.pathParams).- MCP tools under
:paramrouters (e.g.workspaces :id get) now list each path parameter as a required argument and route calls to the given value. Previously their input schemas omitted the parameter and calls routed the literal:idsegment, so agents could not address these routes. - Document leaves under
:paramroutes accept HTTP and MCP calls whose body carries the path parameters (they are validated as path parameters, not body fields). - OpenAPI request and response schemas no longer embed a root
$schema. - Copy templates are renamed and keyed by their directory:
examples/cli(default; wasfull-example),examples/api(wasfull-example-json), andexamples/agent-plugin(wasmcp-plugin).argsbarg create --template cli|api|agent-plugin(wascli/json/plugin);create-identity.tsstores the same key. The example apps inside areexample-cli,example-api, andexample-agent-plugin. The interactive picker now lists every template (it only offered two), andcreate --checkrecognizes all three. - The mcp-plugin example's Node bundle (
dist/mcp-plugin.mjs, which both plugin manifests run) is tracked in git; the root.gitignorehad excluded it.argsbarg create --template pluginnow buildsdist/<key>.mjs(just build) before the initial commit.