CommandSpec unstable
The CommandSpec module projects one command path of an Effect CLI command
tree into plain data for documentation tooling such as reference pages or
JSON schemas. It is lossless where Completions.fromCommand is deliberately
not: hidden flags and unlisted subcommands are included and marked, every
effective flag says where it comes from, primitive types are not collapsed,
and defaults and fallbacks are reported structurally without running
handlers, prompts, Config lookups or effectful defaults.
Constructors
Projects one command path of a command tree into a Spec.
When to use
Use when generating reference documentation or machine-readable schemas
for a CLI from its Command definition, in a build step, without running
the CLI.
Details
path names the commands from the root down, root name first, exactly as
HelpDoc.commandPath does. Only canonical names match: a subcommand alias
in the path, an unknown segment, a different root name or an empty path all
yield Option.none() rather than the deepest matching ancestor.
Each flag or argument entry describes one Single parameter together with
the combinators on the path from the parameter's root to it, outermost
first. A combinator applied outside an orElse applies to every
alternative; one applied inside a branch applies to that branch only.
Combinators beneath a variadic describe each item and do not contribute to
required or fallbacks.
The call is pure and synchronous. Handlers, prompts, Config lookups and
effectful defaults are reported as Fallback values and never run.
See
- Spec for the returned shape
Signature
declare function resolve(command: Any, path: readonly Array<string>, options?: ResolveOptions): Option<Spec>Example Listing the required flags of a subcommand
import { Option } from "effect"import { Command, CommandSpec, Flag } from "effect/cli"
const push = Command.make("push", { dbUrl: Flag.String("db-url"), dryRun: Flag.Boolean("dry-run").pipe(Flag.withDefault(false))})const cli = Command.make("app").pipe( Command.withSharedFlags({ profile: Flag.String("profile").pipe(Flag.optional) }), Command.withSubcommands([push]))
const spec = Option.getOrThrow(CommandSpec.resolve(cli, ["app", "push"], { builtIns: [] }))
const surface = spec.flags.map((flag) => [flag.name, flag.scope._tag, flag.required])surface // => [["db-url", "Local", true], ["dry-run", "Local", false], ["profile", "Inherited", false]]Models
The input surface of one positional argument. required and fallbacks
follow the same branch-local rules as Flag.
Signature
interface Argument { readonly annotations: Context<never>; readonly description: string | undefined; readonly fallbacks: readonly Array<Fallback>; readonly metavar: string | undefined; readonly name: string; readonly required: boolean; readonly type: Type; readonly typeName: string; readonly variadic: VariadicBounds | undefined;}How a parameter obtains a value when it is absent, described without being
evaluated. See Param.Fallback.
Signature
type Fallback = Param.FallbackThe input surface of one flag as the user types it. Transformations applied
to the parsed value (map, withSchema, filter) are transparent, and a
parameter built with orElse yields one entry per alternative.
Signature
interface Flag { readonly aliases: readonly Array<string>; readonly annotations: Context<never>; readonly description: string | undefined; readonly fallbacks: readonly Array<Fallback>; readonly hidden: boolean; readonly metavar: string | undefined; readonly name: string; readonly negation: string | undefined; readonly optionalValue: string | undefined; readonly required: boolean; readonly scope: Scope; readonly type: Type; readonly typeName: string; readonly variadic: VariadicBounds | undefined;}Options for resolve.
Signature
interface ResolveOptions { readonly builtIns?: readonly Array<GlobalFlag<any>>;}Where an effective flag is declared.
Details
Local flags are declared on the resolved command itself. Inherited
flags come from withSharedFlags on the ancestor at declaredBy. Global
flags carry the path of the command that declared them with
withGlobalFlags, or undefined for a built-in.
A nearer Local or Inherited flag hides an inherited flag of the same
name. A Global flag is always listed, even when a local or inherited flag
shares its name, because the parser still routes its other names and
aliases to the global flag.
Signature
type Scope = { readonly _tag: "Local";} | { readonly _tag: "Inherited"; readonly declaredBy: ReadonlyArray<string>;} | { readonly _tag: "Global"; readonly declaredBy: ReadonlyArray<string> | undefined; readonly kind: "Action" | "Setting";}Everything known about one command path.
Signature
interface Spec { readonly alias: string | undefined; readonly annotations: Context<never>; readonly arguments: readonly Array<Argument>; readonly description: string | undefined; readonly examples: readonly Array<Example>; readonly flags: readonly Array<Flag>; readonly name: string; readonly path: readonly Array<string>; readonly shortDescription: string | undefined; readonly subcommands: readonly Array<Subcommand>; readonly unlisted: boolean;}A direct subcommand of the resolved command.
Signature
interface Subcommand { readonly alias: string | undefined; readonly description: string | undefined; readonly group: string | undefined; readonly name: string; readonly shortDescription: string | undefined; readonly unlisted: boolean;}The primitive type a parameter parses, one variant per Primitive.
Signature
type Type = { readonly _tag: "Boolean";} | { readonly _tag: "String";} | { readonly _tag: "Int";} | { readonly _tag: "Finite";} | { readonly _tag: "Date";} | { readonly _tag: "Choice"; readonly values: ReadonlyArray<string>;} | { readonly _tag: "Path"; readonly pathType: Primitive.PathType;} | { readonly _tag: "Redacted";} | { readonly _tag: "FileText";} | { readonly _tag: "FileParse";} | { readonly _tag: "FileSchema";} | { readonly _tag: "KeyValuePair";} | { readonly _tag: "Never";}Repeat bounds of a variadic parameter. undefined means unbounded on that side.
Signature
interface VariadicBounds { readonly max: number | undefined; readonly min: number | undefined;}