johnie/skills · Archived

stricli

Build type-safe TypeScript CLIs with Bloomberg's Stricli framework. Use when the project already depends on `@stricli/core` or the user names Stricli — authoring a new CLI, changing typed flags/positionals/parsers, wiring subcommand routing via `buildRouteMap`, testing via `run(app, argv, context)`, or configuring bash auto-complete via `@stricli/auto-complete`. For the `cleye` argv parser use the cleye skill instead; skip for commander/yargs/oclif/minimist and for generic "which CLI framework …

First seen Jan 24, 2026

Installation

$ npx skills add johnie/skills --skill stricli

Summary

  • Build type-safe TypeScript CLIs with Bloomberg's Stricli framework.
  • Use when the project already depends on `@stricli/core` or the user names Stricli — authoring a new CLI, changing typed flags/positionals/parsers, wiring subcommand routing via `buildRouteMap`, testing via `run(app, argv, context)`, or configuring bash auto-complete via `@stricli/auto-complete`.
  • For the `cleye` argv parser use the cleye skill instead; skip for commander/yargs/oclif/minimist and for generic "which CLI framework should I use?" questions.

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from johnie/skills.

npx skills add johnie/skills

Browse all from johnie/skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 2
License MIT
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Allowed toolsBash(npx @stricli/create-app*), Bash(npm install @stricli/*), Bash(pnpm add @stricli/*), Bash(tsc *), Bash(pnpm exec tsc *), Read, Write, Edit, Grep, Glob

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 10,060 B
  • docs SUMMARY.md 541 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 11 installs

SKILL.md

Stricli CLI Framework

Stricli is Bloomberg's type-safe CLI framework for TypeScript. Strongly-typed flags and positional arguments, explicit command routing, automatic help generation, and an isolated CommandContext per run.

Reference files live in ${CLAUDESKILLDIR}/references/.

When NOT to use

  • The user has an existing CLI on a different framework (commander, yargs, oclif, minimist) — this skill doesn't migrate, and the APIs don't translate.
  • The project uses cleye — different library, non-transferable API. Use the cleye skill.
  • Generic "which CLI framework should I use?" — that's a design conversation, not a Stricli question.
  • Non-TypeScript CLIs — Stricli's core value is its compile-time type safety.
  • Runtime debugging of an installed CLI (not developing it) — use shell/debugging tooling.

Core API surface

Stricli's public API is intentionally narrow. If something isn't listed here or in the references, assume it doesn't exist — checking the upstream repo is faster than guessing, and invented APIs compile until they don't.

Entry point Purpose
`buildCommand({ func \ loader, parameters, docs })` Define a single command
buildRouteMap({ routes, docs, aliases?, defaultCommand? }) Compose subcommands
buildApplication(rootCommandOrRouteMap, config, integrations?) Wrap with app-level config (name, scanner, …); third argument registers integrations (1.3.0+)
run(app, inputs, context) Execute the app against tokenized input + a runtime context
CommandContext The shape that runtime context extends
help(config) / version(config) Built-in integrations for --help / --version (1.3.0+)

Version awareness

Check the installed @stricli/core before using version-gated API. The integrations argument, lifecycle hooks, and the exported help/version factories arrived in 1.3.0; withNegated on boolean flags and defaults on variadic flags arrived in 1.2.5. The rest of this skill applies across the 1.x line. Details in [references/integrations.md](references/integrations.md).

Installation

Upstream docs assume Node + npm. Stay agnostic to the user's package manager — pnpm and bun work equally well.

npm install @stricli/core              # required
npm install @stricli/auto-complete     # optional, bash completion
# pnpm add / bun add work the same way

Scaffolding a new app

npx @stricli/create-app@latest my-app
# pnpm dlx / bunx work the same way

The generator produces the reference directory layout. For hand-written apps, follow the quick start below.

Quick start: single-command CLI

1. Define the command

import { buildCommand, type CommandContext } from "@stricli/core";

interface GreetFlags {
  readonly shout?: boolean;
}

export const greetCommand = buildCommand({
  docs: { brief: "Print a greeting" },
  parameters: {
    flags: {
      shout: {
        kind: "boolean",
        brief: "Uppercase the greeting",
        optional: true,
      },
    },
    positional: {
      kind: "tuple",
      parameters: [
        { brief: "Name to greet", parse: String, placeholder: "name" },
      ],
    },
  },
  func(this: CommandContext, flags: GreetFlags, name: string) {
    const message = `Hello, ${name}!`;
    this.process.stdout.write(
      `${flags.shout ? message.toUpperCase() : message}\n`
    );
  },
});

2. Build the application

import { buildApplication, help, version } from "@stricli/core";
import { version as currentVersion } from "../package.json";
import { greetCommand } from "./commands/greet";

const formatting = {
  useAliasInUsageLine: false,
  onlyRequiredInUsageLine: false,
  caseStyle: "original",
} as const;

export const app = buildApplication(
  greetCommand,
  { name: "my-cli" },
  {
    help: help({
      brief: "Print help information and exit",
      defaultForRouteMap: true,
      formatting,
    }),
    helpAll: help({
      brief:
        "Print help information (including hidden commands/flags) and exit",
      alias: "H",
      hidden: true,
      includeHidden: true,
      formatting,
    }),
    version: version({
      brief: "Print version information and exit",
      info: { currentVersion },
    }),
  }
);

On 1.3.0+ the version integration is the primary way to enable --version; the config key versionInfo: { currentVersion } (with no third argument) is the legacy 1.2.x form and is @deprecated on 1.3.0, though it still works. Passing the third argument replaces every default, which is why help and helpAll are re-registered above.

3. Run it

import { run } from "@stricli/core";
import { app } from "./app";

await run(app, process.argv.slice(2), { process });

Parameter model

  • Flag kinds: parsed, enum, boolean, counter. Everything else is expressed via parse / variadic on a parsed flag, not a new kind.
  • Positional modes: tuple (fixed-shape, typed per-position) or array (variadic homogeneous).
  • Variadic: set variadic: true for repeated occurrences, or variadic: "," (or any separator) for delimited input. It's a property, not a kind.

Full details in [references/parameters.md](references/parameters.md). Parser specifics (built-ins, custom, async) in [references/parsers.md](references/parsers.md).

Recommended workflow

Single-command CLI

buildCommand → buildApplication(command, config) → run(app, argv, context).

Multi-command CLI

Define commands independently, compose with buildRouteMap, add aliases / defaultCommand where UX benefits. See [references/routing.md](references/routing.md).

Large CLIs — prefer the loader pattern

For commands whose implementation is expensive to import (heavy transitive deps, slow module-level work), use loader instead of inline func. Stricli resolves the loader only when that command is actually invoked, keeping startup fast.

import { buildCommand, numberParser } from "@stricli/core";

export const analyzeCommand = buildCommand({
  docs: { brief: "Analyze a report" },
  parameters: {
    flags: {
      depth: {
        kind: "parsed",
        parse: numberParser,
        brief: "Traversal depth",
        optional: true,
        default: "1",
      },
    },
  },
  loader: async () => import("./impl"),
});

Rule of thumb: func for a few-line handler you don't mind parsing at app start; loader when the implementation (or its imports) would dominate cold start for unrelated commands. See [references/routing.md](references/routing.md).

Context and testing

  • Runtime context extends CommandContext. Inject logger / clients / clocks there — not module-level singletons — so tests can swap them.
  • Command handlers receive context through this.
  • Test either end-to-end via run(app, inputs, ctx) with a fake context, or import the command's implementation directly for pure unit tests.

See [references/context.md](references/context.md) and [references/examples.md](references/examples.md) (including Testing Error Paths for parser/missing-arg/enum-error tests).

Auto-complete

@stricli/auto-complete supports bash only. Integrate via the standalone install/uninstall flow plus buildInstallCommand() / buildUninstallCommand() added to your app. Details in [references/auto-complete.md](references/auto-complete.md).

Upstream conventions worth keeping

  • strict: true in tsconfig.json. Stricli leans on inference — loose mode loses the whole value proposition.
  • --version appears only when a version integration is registered (1.3.0+) or the legacy versionInfo config key is set (1.2.x; deprecated on 1.3.0).
  • --helpAll is built-in and surfaces hidden commands and flags.
  • Reserved short flags: -h (help), -H (helpAll), -v (version, when enabled).
  • On 1.3.0+, passing the integrations argument to buildApplication replaces the defaults — re-register help, helpAll, and version or you lose those flags. See [references/integrations.md](references/integrations.md).
  • Upstream docs are npm-first; show pnpm / bun equivalents when the user uses them.

References

  • [routing.md](references/routing.md) — buildCommand, buildRouteMap, buildApplication, run, lazy loaders, aliases, default commands
  • [parameters.md](references/parameters.md) — flag kinds and positional modes
  • [parsers.md](references/parsers.md) — built-in / custom / async parsers
  • [context.md](references/context.md) — CommandContext, custom context, testing, exit codes
  • [integrations.md](references/integrations.md) — integrations, lifecycle hooks, application flags, customizing help/version (1.3.0+)
  • [auto-complete.md](references/auto-complete.md) — bash auto-complete integration
  • [examples.md](references/examples.md) — composite patterns, end-to-end apps, testing error paths

External