johnieskills

Builds type-safe command-line tools with 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 should I use?" questions.

$ npx skills add johnie/skills --skill stricli
skills/stricli/references/auto-complete.mdGitHub

Shell Auto-Complete

Add shell auto-complete support with @stricli/auto-complete.

Current Support

Upstream Stricli currently supports:

  • bash

Do not claim built-in zsh or fish support unless upstream docs change.

Install the Package

npm install @stricli/auto-complete
# pnpm add / bun add also work

Standalone Install / Uninstall Flow

The official management command is package-based and usually invoked with npx.

Install

npx @stricli/auto-complete@latest install --shell bash my-cli __my_cli_bash_complete
# pnpm dlx / bunx also work

Uninstall

npx @stricli/auto-complete@latest uninstall --shell bash my-cli
# pnpm dlx / bunx also work

The install command wires a target command (my-cli) to a bash completion command (__my_cli_bash_complete).

Built-In Commands in Your App

@stricli/auto-complete exposes:

  • buildInstallCommand(targetCommand, commands)
  • buildUninstallCommand(targetCommand, shells)

Use them to add hidden install/uninstall commands to your own CLI.

import {
  buildInstallCommand,
  buildUninstallCommand,
} from "@stricli/auto-complete";
import { buildApplication, buildRouteMap } from "@stricli/core";

import { statusCommand } from "./commands/status";

const routes = buildRouteMap({
  routes: {
    status: statusCommand,
    install: buildInstallCommand("my-cli", {
      bash: "__my_cli_bash_complete",
    }),
    uninstall: buildUninstallCommand("my-cli", {
      bash: true,
    }),
  },
  docs: {
    brief: "Example CLI",
    hideRoute: {
      install: true,
      uninstall: true,
    },
  },
});

// Register help/helpAll/version integrations as in the SKILL.md quick start;
// `versionInfo` in the config object is the deprecated 1.2.x form.
export const app = buildApplication(routes, { name: "my-cli" });

This mirrors the current upstream guidance and generated app structure.

Package Layout Pattern

The upstream generator typically creates:

  • one main CLI binary
  • one bash-completion helper binary
  • a postinstall hook that runs the completion installer

Representative pattern:

{
  "bin": {
    "my-cli": "dist/cli.js",
    "__my_cli_bash_complete": "dist/bash-complete.js"
  },
  "scripts": {
    "postinstall": "npx @stricli/auto-complete@latest install --shell bash my-cli __my_cli_bash_complete"
  }
}

If you mention alternatives, keep npm first but note that the same idea can be adapted for pnpm dlx or bunx.

Best Practices

  • keep install/uninstall commands hidden from standard help with docs.hideRoute (users should not see internal completion plumbing)
  • use the upstream bash-only model unless official docs add more shells
  • prefer the generator or upstream package layout for first-time setup
  • avoid inventing script-generation APIs that are not in the public package docs