backstage-scaffolder

backstage-scaffolder is a skill for Claude Code from bendaamerahmed/backstage-idp-plugin. It costs 41 tokens per session (3,948 once invoked), scanned A, original, MIT.

A guide for creating Backstage Software Templates and custom scaffolder actions. Backstage is a developer portal, and its scaffolder creates projects or performs setup steps from reusable templates.

In plain words
What is it for?
Use it to define template inputs and steps, add custom actions, configure outputs and permissions, test dry runs, and investigate failed or stuck tasks.
Why use it?
It helps templates and setup actions work with Backstage's installed version, permission checks, backend structure, and failure handling.

Skill for Claude Code

Written for Claude Code: when-to-use in frontmatter.

Part of the backstage-idp plugin — 15 skills, 1 agent shipped together

Good fit Use it to define template inputs and steps, add custom actions, configure outputs and permissions, test dry runs, and investigate failed or stuck tasks.

Compare 6 skills from other repositories ↓
Install with agentmods
npx agentmods add skills/bendaamerahmed/backstage-idp-plugin/backstage-scaffolder
Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

Any agent
npx skills add bendaamerahmed/backstage-idp-plugin --skill backstage-scaffolder
Clone the repo
git clone --depth 1 https://github.com/bendaamerahmed/backstage-idp-plugin

Made for: Claude Code.

Or install backstage-idp, the plugin that ships this one along with the rest of its 15 skills, 1 agent.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for backstage-scaffolder

README.md
[![agentmods](https://agentmods.dev/badge/skills/bendaamerahmed/backstage-idp-plugin/backstage-scaffolder/github.svg)](https://agentmods.dev/skills/bendaamerahmed/backstage-idp-plugin/backstage-scaffolder)
Your own site
<a href="https://agentmods.dev/skills/bendaamerahmed/backstage-idp-plugin/backstage-scaffolder"><img src="https://agentmods.dev/badge/skills/bendaamerahmed/backstage-idp-plugin/backstage-scaffolder/github.svg" alt="Measured on agentmods" height="20"></a>

Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.

agentmods 80×15 button for backstage-scaffolder

Your own site · 80×15
<a href="https://agentmods.dev/skills/bendaamerahmed/backstage-idp-plugin/backstage-scaffolder"><img src="https://agentmods.dev/badge/skills/bendaamerahmed/backstage-idp-plugin/backstage-scaffolder.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 41 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 3,948 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00041 $0.03948
Opus 5 $0.00020 $0.01974
Sonnet 5 $0.00008 $0.00790
Haiku 4.5 $0.00004 $0.00395

Measured 11d ago against content hash cedd58487222, method: parsed. Prices are Anthropic first-party input rates as of 2026-09-11, from the pricing page.

Security

Grade A, and why

backstage-scaffolder scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 11d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

plugins/backstage-idp/skills/backstage-scaffolder/SKILL.md · 104 lines

How it starts

The opening of the file, as written. The whole thing — 104 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Backstage Scaffolder

Write Template entities and custom scaffolder actions that survive review, run under the permission framework, and fail loudly instead of silently.

Preconditions

  • Release line from backstage.json; scaffolder packages resolved via yarn why @backstage/plugin-scaffolder-backend.
  • Backend generation: createBackend() + backend.add(import('@backstage/plugin-scaffolder-backend')) in packages/backend/src/index.ts is the new backend system. A packages/backend/src/plugins/scaffolder.ts router is legacy — migrate first (backstage-plugin-migrate) or register actions through the router's options and say so in your report.
  • Frontend generation matters only for custom field extensions: NFS uses FormFieldBlueprint + createFormField from @backstage/plugin-scaffolder-react/alpha. Read the installed package's exports rather than assuming the legacy registration shape.
  • @backstage/plugin-catalog-backend-module-scaffolder-entity-model present in the backend — without it kind: Template does not validate and no template appears.
  • Working SCM integrations in app-config.yaml for whichever host the template publishes to.
  • A local backend you may run. Any run that touches a real SCM org is an external mutation — stop and get authorization first.

Procedure

  1. Inventory before authoring. GET /api/scaffolder/v2/actions (or the /create/actions page) for installed actions and their input/output schemas; GET /api/scaffolder/v2/templating-extensions for available filters and globals. Never guess an action's input keys — they are published there.
  2. Start the entity. apiVersion: scaffolder.backstage.io/v1beta3, kind: Template, metadata.name, and spec.owner + spec.type. Body is spec.parameters, spec.steps, spec.output.
  3. Write spec.parameters as one FormStep or an array of them. Each step is JSON Schema (title, description, required, properties) with rjsf ui:* keys merged in — ui:autofocus, ui:emptyValue, ui:help, ui:widget, ui:options. Array elements become separate wizard pages; use them to keep any one page short. Custom validation messages follow ajv-errors.
  4. Use the built-in pickers instead of free-text strings.
    • ui:field: RepoUrlPicker with ui:options.allowedHosts (must match an integrations host), plus allowedOwners / allowedRepos to narrow. Value is a repo spec string like github.com?repo=x&owner=y, not a URL.
    • ui:field: OwnerPicker with ui:options.catalogFilter — either kind: [Group, User] or a list of full catalog API filters (metadata.annotations.github.com/team-slug: { exists: true }).
    • ui:field: EntityPicker for arbitrary catalog entities; RepoBranchPicker and RepoOwnerPicker for autocomplete, both of which require requestUserCredentials (and host for the owner picker) to function.
    • Set ui:options.requestUserCredentials: { secretsKey: USER_OAUTH_TOKEN, additionalScopes: { github: [workflow] } } when the template must act as the user; consume it as ${{ secrets.USER_OAUTH_TOKEN }}. Requires a configured auth provider and ScmAuthApi (backstage-auth).
  5. Route every credential through secrets, never parameters.
    • ui:field: Secret keeps the value out of the task record and REST responses and masks it in the review step. Read it as ${{ secrets.name }}${{ parameters.name }} will be undefined.
    • For programmatic task creation declare spec.secrets.schema with required/properties. A missing secret then fails task creation with 400 and secrets.X is required, instead of mid-run.
    • Org-wide values belong in scaffolder.defaultEnvironment in app-config.yaml, read as ${{ environment.parameters.* }} and ${{ environment.secrets.* }}. Environment secrets are masked in logs and never reach the frontend.
  6. Write spec.steps as id, name, action, input, with optional if and each. Use camelCase step and action ids: a dash makes ${{ steps.my-action.output.x }} evaluate to NaN, and the bracket form ${{ steps['my-action'].output.x }} is the only workaround. With each, the iteration value is ${{ each.value }} (or ${{ each.value.field }}), and the step's outputs become an array.
  7. Prefer built-ins over custom code.
    • Shipped in @backstage/plugin-scaffolder-backend: fetch:plain, fetch:plain:file, fetch:template, fetch:template:file, catalog:register, catalog:write, debug:log, debug:wait, fs:delete, fs:rename, fs:readdir.
    • Publish/PR actions come from @backstage/plugin-scaffolder-backend-module-{github,gitlab,azure,bitbucket-cloud,bitbucket-server,gerrit,gitea}; add one with yarn --cwd packages/backend add <pkg> then backend.add(import('<pkg>')).
    • Community actions live under @backstage-community/plugin-scaffolder-backend-module-*. Read the handler before installing one.
  8. Template the skeleton with fetch:template. Inside skeleton files the variables are ${{ values.x }} — only template.yaml itself sees ${{ parameters.x }} — and they must be passed explicitly through input.values. Use copyWithoutTemplating for files whose own ${{ }} syntax must survive (GitHub Actions workflows, Helm charts), targetPath to place output in a subdirectory, and replace: true only when overwriting existing workspace files is intended.
  9. Glue steps with expressions.
    • ${{ }} is evaluated by Nunjitsu, a deliberately reduced subset of Nunjucks. Check its compatibility guide before using any Nunjucks tag or filter; do not assume full Nunjucks.
    • Built-in filters: parseRepoUrl, parseEntityRef (accepts { defaultKind, defaultNamespace }), pick('name'), projectSlug. Custom filters and globals are registered from a backend module against scaffolderTemplatingExtensionPoint.
    • ${{ user.entity }} gives the caller's catalog User entity — useful for gitAuthorName / gitAuthorEmail — and requires a sign-in resolver that maps to a catalog user.
  10. Handle failure paths explicitly. After a step fails, later steps are skipped unless their if invokes ${{ always() }} or ${{ failure() }}. Any template that creates external resources before a step that can fail needs a failure() cleanup step; if: ${{ true }} will not run.
  11. Finish with spec.output. links take title plus url, or icon + entityRef for a catalog link; text items take title + content markdown. Both accept a per-item if. Source values from ${{ steps['publish'].output.remoteUrl }} / ${{ steps['register'].output.entityRef }}.
  12. Gate sensitive parameters and steps with backstage:permissions: { tags: [<tag>] } on the parameter step or the step, then enforce in the policy (step 15). backstage:featureFlag hides parameters or fields but cannot gate spec.steps[].if — expose a boolean parameter and branch on it instead.
  13. Scaffold custom actions, do not hand-roll. yarn backstage-cli newscaffolder-backend-module generates the package, module.ts, an action and a test.
    • createTemplateAction from @backstage/plugin-scaffolder-node takes id (namespaced provider:entity:verb, camelCase segments), description, examples, supportsDryRun, schema.input / schema.output, handler.
    • Current schemas are per-property zod callbacks — contents: z => z.string({ description: '...' }). The accepted schema shape has changed across releases, so read createTemplateAction's type from the installed package before writing it.
    • examples: TemplateExample[] (YAML strings of a steps snippet) is what renders on /create/actions. Without it, template authors cannot discover the action's usage.
  14. Register the action in createBackendModule, whose option shape you read from the installed @backstage/backend-plugin-api types — currently pluginId, moduleId and register.
    • Depend on scaffolderActionsExtensionPoint from @backstage/plugin-scaffolder-node and call scaffolder.addActions(myAction(...)).
    • Pass core services (coreServices.rootConfig, coreServices.cache, coreServices.discovery, coreServices.auth) as deps and close over them in the action factory; never reach for globals inside a handler.
    • Inside the handler use only ctx: ctx.input, ctx.output(key, value), ctx.logger, ctx.workspacePath, ctx.createTemporaryDirectory(), ctx.isDryRun, ctx.metadata.name, ctx.checkpoint (experimental idempotency — version the key whenever its return type changes, or a retried task fails on the stale cached value).
    • Resolve every path with resolveSafeChildPath(ctx.workspacePath, ctx.input.filename) from @backstage/backend-plugin-api.
  15. Enforce permissions in the policy (backstage-permissions). Without one, every signed-in user may execute every template and every action.
    • Permissions from @backstage/plugin-scaffolder-common/alpha: templateParameterReadPermission, templateStepReadPermission, actionExecutePermission, taskCreatePermission, taskReadPermission, taskCancelPermission.
    • Decisions and rules from @backstage/plugin-scaffolder-backend/alpha: createScaffolderTemplateConditionalDecision + scaffolderTemplateConditions.hasTag; createScaffolderActionConditionalDecision + scaffolderActionConditions.hasActionId / hasProperty; createScaffolderTaskConditionalDecision + scaffolderTaskConditions.isTaskOwner.
    • Rules compose with not / allOf / anyOf — e.g. deny debug:log only when hasProperty({ key: 'message', value: 'not-this!' }).
  16. Register the template as a Locationcatalog.locations with rules: [{ allow: [Template] }], or /catalog-import. Restrict which repositories may contribute Template entities: scaffolder jobs run on the backend host with the backend's credentials, so template authorship is a privileged capability.

Read the full file on GitHub · 104 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 11d ago First seen · 104 lines · 41 tokens per session scan A cedd58487222

Subscribe to this mod's changes

backstage-scaffolder is a skill published in the GitHub repository bendaamerahmed/backstage-idp-plugin (1 stars, last pushed 1mo ago), licensed MIT. It adds 41 tokens to every session and 3,948 once invoked, about $0.0002 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.

Related

Other skills, from other repositories

catchup

Summarize and review what changed while you were away. Use after a weekend, vacation, or flight to check missed PRs, git commits, Linear tickets, and meetings — one prioritized brief, not a firehose.

oliver-kriska/claude-elixir-phoenix · 48 tokens

plan

Plan features spanning multiple domains: billing (Stripe), auth (RBAC), real-time (Presence), webhooks, jobs (Oban). Use when designing interconnected systems or converting review findings into tasks.

oliver-kriska/claude-elixir-phoenix · 42 tokens

work

Execute Elixir/Phoenix plan tasks with progress tracking. Use after /phx:plan to implement features with mix compile and mix test verification after each step, or --continue to resume interrupted work.

oliver-kriska/claude-elixir-phoenix · 43 tokens

phx-deps-update

Bump outdated Hex deps — inventory, snapshot changelogs, update, fix breaks, split reviewable PRs (patches bundled, majors solo). Use to upgrade/bump Elixir dependencies or when versions fall behind. NOT for deps.get failures (phx-investigate).

oliver-kriska/claude-elixir-phoenix · 62 tokens

new-work

Create and manage todo tracking documents for features, bugs, and multi-step tasks. Use when starting new work that benefits from a persistent record of decisions, progress, and context.

posit-dev/skills · 38 tokens

chief-operating-officer

Owns execution: how work actually gets done across the organization, including process, program management, capacity, vendors, supply chain, and service delivery. Use this when execution is the problem rather than strategy, to design or fix a process, to resolve cross-functional handoff failures, to plan capacity, to…

cbrock84/headcount · 94 tokens