Part III · Reference · Chapter 1

CLI reference

The commands SpellCraft ships with, how plugins add their own, and the flags each one accepts.

SpellCraft’s CLI is deliberately small. Most of what you can run comes from the plugins you installed, which is why the help output differs between projects.

npx spellcraft --help

generate <filename>

Evaluates a manifest and writes the result.

npx spellcraft generate manifest.jsonnet

Runs every plugin’s init, evaluates the file, then writes each top-level key to render/. See Rendering output.

FlagEffect
--ext-str name=valueBind std.extVar("name") to a string. Repeatable
--ext-code name=<expr>Bind std.extVar("name") to a Jsonnet expression. Repeatable
--skip-module-cleanup, -sKeep the generated .spellcraft/modules aggregate for inspection
npx spellcraft generate manifest.jsonnet --ext-str stage=prod --ext-code replicas=2+1

The two external-variable flags are spelled the way jsonnet(1) spells them, and the difference between them is the usual one: --ext-code’s value is evaluated, so --ext-code stage=prod fails with an unknown variable where --ext-str stage=prod gives you the string.

doc

Regenerates API documentation in the current package’s README.md.

npx spellcraft doc

Reads the doc comments in module.libsonnet and the commands registered by module.js, and replaces the content between marker comments:

<!-- SPELLCRAFT_DOCS_API_START -->
<!-- SPELLCRAFT_DOCS_API_END -->

<!-- SPELLCRAFT_DOCS_CLI_START -->
<!-- SPELLCRAFT_DOCS_CLI_END -->

Without those markers the command does nothing and says so. The generated plugin template includes them.

Doc comments are JSDoc-flavoured, and @example blocks become fenced Jsonnet:

{
  /**
   * Prefixes a resource name with the target environment.
   *
   * @param {string} name - the unqualified resource name
   * @returns {string} the name, prefixed
   * @example
   * local module = import "@you/your-plugin/module.libsonnet";
   * { name: module.resourceName("artifacts") }
   */
  resourceName(name):: std.native("@you/your-plugin:resourceName")(name),
}

Commands from plugins

Plugins register commands through cliExtensions. Installed ones appear in --help automatically. Notable examples:

All four below come from @c6fc/spellcraft-plugins, from three different nodes of it:

CommandFrom
terraform-apply, terraform-destroyplugins.terraform
aws-identityplugins.aws.auth
aws-exportcredentialsplugins.aws.auth
gcp-identityplugins.gcp.auth

Environment variables

VariableEffect
SPELLCRAFT_DEBUGReport dependencies that were considered as plugins and skipped
AWS_PROFILE, AWS_REGIONRead by plugins.aws.auth
SPELLCRAFT_ASSUMEROLERole ARN for plugins.aws.auth to assume for the whole render
SPELLFRAME_GCP_IMPERSONATEService account for plugins.gcp.auth to impersonate
GOOGLE_CLOUD_PROJECTProject for plugins.gcp.auth, ahead of gcloud’s configured one
Debugging a plugin that will not load

Set SPELLCRAFT_DEBUG=1. Discovery skips unresolvable dependencies silently by design — most dependencies are not plugins — so this is the way to see what was passed over and why.