Skip to content

CLI Validator

The shoehorn validate command validates catalog manifests and Forge mold definitions before you commit, push, or apply them. Use it locally, in pre-commit hooks, and in CI to catch errors early.

There are two validators:

CommandWhat it validatesNeeds server?
shoehorn validate [file]Shoehorn or Backstage catalog manifestsYes (calls the Shoehorn API)
shoehorn validate mold [file]Forge mold YAML definitionsNo — fully offline

Both commands support reading from a file, a directory path, or stdin via -, and can emit plain text or JSON.

shoehorn validate validates Shoehorn or Backstage-format manifest files. Format is auto-detected.

Terminal window
# Validate a manifest file (text output)
shoehorn validate catalog-info.yaml
# Validate with JSON output
shoehorn validate .shoehorn/service.yml --format json
# Validate from stdin
cat catalog-info.yaml | shoehorn validate -
FlagDefaultDescription
--formattextOutput format: text or json
CodeMeaning
0Manifest is valid
1Validation errors found, or I/O error

Text (valid):

v catalog-info.yaml is valid

Text (invalid):

x catalog-info.yaml has validation errors:
- spec.owner: is required
- metadata.name: must be lowercase and kebab-case

JSON:

{
"file": "catalog-info.yaml",
"valid": false,
"errors": [
{ "field": "spec.owner", "message": "is required" },
{ "field": "metadata.name", "message": "must be lowercase and kebab-case" }
]
}
  • The file (or stdin) is capped at 10 MB to prevent memory exhaustion.
  • The command uses your active CLI profile credentials (shoehorn auth login) because it calls the Shoehorn validation API. Use --profile to validate against a specific environment.

shoehorn validate mold validates Forge mold definitions offline — no server is contacted. It checks YAML syntax, required fields, step structure, action and adapter names, and approval flow constraints.

Terminal window
# Validate a mold
shoehorn validate mold .shoehorn/molds/create-repo.yaml
# JSON output for CI parsing
shoehorn validate mold my-mold.yaml --format json
# Treat warnings as failures
shoehorn validate mold my-mold.yaml --strict
# From stdin
cat my-mold.yaml | shoehorn validate mold -
FlagDefaultDescription
--formattextOutput format: text or json
--strictfalseFail (non-zero exit) if any warnings are reported

Errors (always fail the command):

  • YAML syntax is parseable
  • Top-level fields: version, metadata.name are present
  • At least one of steps or actions is defined
  • Each step has an id and name, and exactly one of action or adapter (not both)
  • No duplicate step IDs across steps and rollback.steps
  • Action IDs are at least two dot-separated parts (e.g. github.repo.create) and the provider is one of github, deployment, system, catalog, repo
  • Adapter names are one of the known adapters: http, postgres, slack, github, docker, kubernetes, terraform, webhook, email, s3, gcs, file, git, catalog, log
  • Approval flow constraints:
    • auto_approve_after is at least 3600 seconds (1 hour) when set
    • At most 10 approval steps
    • Each approval step has a name and at least one approver, with at most 50 approvers per step

Warnings (only fail with --strict):

  • Missing recommended metadata.displayName, metadata.description, or metadata.category
  • Action IDs that use a valid provider but aren’t on the known built-in actions list (treated as custom actions)

Text (valid with a warning):

v create-repo.yaml is valid
warnings:
- metadata.description: is recommended for discoverability

Text (invalid):

x create-repo.yaml has errors:
errors:
- steps[0].id: is required
- steps[1]: must have either action or adapter, not both
- approvalFlow.auto_approve_after: must be at least 3600 seconds (1 hour), got 600

JSON:

{
"file": "create-repo.yaml",
"valid": false,
"errors": [
{ "field": "steps[0].id", "message": "is required" },
{ "field": "steps[1]", "message": "must have either action or adapter, not both" }
],
"warnings": [
{ "field": "metadata.description", "message": "is recommended for discoverability" }
]
}
CodeMeaning
0Mold is valid (and, with --strict, has no warnings)
1Errors found, --strict mode found warnings, or I/O error

Because both commands return a non-zero exit code on failure and support JSON output, they drop into any CI system. A minimal GitHub Actions job:

name: Validate catalog
on: [pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install shoehorn CLI
run: |
curl -fsSL https://github.com/shoehorn-dev/shoehorn-cli/releases/latest/download/shoehorn-linux-amd64 \
-o /usr/local/bin/shoehorn
chmod +x /usr/local/bin/shoehorn
- name: Validate catalog manifests
env:
SHOEHORN_TOKEN: ${{ secrets.SHOEHORN_TOKEN }}
run: |
shoehorn auth login --server https://shoehorn.example.com
shoehorn validate catalog-info.yaml --format json
- name: Validate molds (offline, strict)
run: |
for f in .shoehorn/molds/*.yaml; do
shoehorn validate mold "$f" --strict
done

The mold validator runs fully offline, so it doesn’t need SHOEHORN_TOKEN — you can run it on any branch, including from forks.