SmolDLC

The Pixelbadger Toolkit software delivery lifecycle
One human prompt, one release approval. Everything between is autonomous.

What is SmolDLC?

SmolDLC is the informal name for the minimal software delivery lifecycle running in this repository. It is small by design: the entire loop is automated after a single human act — writing a GitHub issue.

The chain runs from a GitHub issue all the way to a published NuGet package that anyone can install with a single command. A GitHub Actions workflow detects the new ticket and invokes a Claude Code agent to plan and implement it. A second agent performs a thorough code review. Deterministic CI checks the hygiene. Project automation handles the bookkeeping. No human ever edits a file or sits at a terminal waiting for a build.

This page describes the as-built system as of October 2026. The workflows are in .github/workflows/; the autonomous agent instructions live in CLAUDE.md.

The environment

Every step of this lifecycle runs in the cloud. There is no local machine, no terminal, and no device involvement of any kind. GitHub Actions spins up ephemeral Ubuntu runners on demand, installs the .NET 9 toolchain and the gh CLI, and invokes Claude Code headlessly via the anthropics/claude-code-action GitHub Action.

The only local tooling involved is a web browser to write a GitHub issue. Everything else — code generation, build, test, review, merge, and NuGet publication — happens in cloud runners. That is the "smol" in SmolDLC: a lean process with zero local infrastructure.

The human touchpoints

Everything else in this lifecycle is automated. These are the only two moments a person needs to act.

1

Write a GitHub issue

Describe the feature or bug in plain language. Label it status: to-do. That's it — the pipeline takes over from here. A GitHub Actions workflow detects the label, fires a Claude Code agent to plan and implement the work, opens a PR, runs review and CI, and merges automatically when everything passes.

2

Approve the release

After a merge that changes production code, the NuGet publish job waits in the nuget-publish environment. Click Review deployments → Approve on the run in the Actions tab to publish. Nothing reaches nuget.org without that click.

The full pipeline

Each stage below is labelled by who owns it.

Human

Write an issue

Create a GitHub issue describing the desired feature or bug fix. Apply the status: to-do label to mark it as ready.

GitHub Issues status: to-do
↓
GitHub Actions — agent build trigger

Label event fires agent build

Applying status: to-do to an issue triggers the agent-build.yml workflow. It spins up a runner, installs the toolchain, and invokes Claude Code as a headless agent. No terminal, no human waiting.

agent-build.yml on: issues labeled Claude Code CLI
↓
Claude (Sonnet) — autonomous agent

Plan (auto-accepted), then claim, branch, implement, and open a PR

Claude reads the issue and first enters a plan phase: it produces a structured implementation plan covering files to create or edit, test strategy, and version bump rationale. The plan is auto-accepted — no human approval gate — and Claude immediately executes it.

Claude relabels the issue status: in-progress, creates a feature/ branch, writes the code and tests, bumps the version, updates the README, and opens a PR with Closes #N in the body. All via the gh CLI and dotnet — no human file edits.

claude-sonnet-4-6 plan phase (auto-accepted) gh pr create dotnet build / test --permission-mode auto
↓ PR opened or pushed to GitHub
GitHub Actions — pr-checks.yml

PR checks — build, test, and review

1 · mechanical-checks

Pure bash, zero API cost. Enforces three invariants: version bumped if production code changed, test file paired with every new component, benchmark updated for watched algorithms.

2 · build-and-test

Restore → build → test → pack. Verifies the branch version is strictly greater than the published NuGet version.

3 · claude-review — runs after jobs 1 & 2 finish

Collects the logs of any failing job first and hands them to the reviewer — a failing check always blocks approval. Claude reads the diff, posts inline comments on specific lines, and writes a verdict (APPROVE or REQUEST_CHANGES) to a file. A plain step then submits it as a formal GitHub review from github-actions[bot], because the Claude app authored the PR and GitHub won't let an author approve or request changes on their own PR. Behaviour differs by push number:

First push — primary review

Full diff. Evaluates correctness, test quality, architecture (component-per-command pattern), security (prompt injection, path traversal), and README consistency.

Subsequent pushes — follow-up review

Verifies each prior comment was addressed. Checks for new regressions introduced by the fixes. Does not re-review already-accepted code.

pr-checks.yml claude-sonnet-5-5 review as github-actions[bot]
↓ github-actions[bot] submits the review decision
Claude (Sonnet) — autonomous iteration · only when changes requested

Fix & push

When claude-review requests changes, the claude-fix job in the same pr-checks.yml run fires. Claude reads the review, the inline comments, and any failing CI logs, reproduces and fixes each issue, runs the tests, and pushes once at the end. It runs with --permission-mode auto, so a safety classifier checks its actions rather than skipping permission checks. Points it disagrees with get a PR comment so the next review round sees its reasoning.

The fix runs as a job rather than reacting to a review event because reviews submitted with GITHUB_TOKEN don't trigger other workflows. A change request from a human reviewer still fires agent-build.yml, which iterates the same way.

↺  The push re-triggers pr-checks.yml from the top. claude-review now runs in follow-up mode — it verifies prior feedback was addressed and checks for new regressions only. This cycle repeats until the review approves. After 6 change requests without approval the loop stops and comments on the PR asking for a human.
pr-checks.yml — claude-fix --permission-mode auto claude-sonnet-5-5
↓ once claude-review approves and all checks are green
GitHub Actions — auto-merge

Squash merge to master

When claude-review approves and the mechanical checks and build are green, the auto-merge job in pr-checks.yml squash-merges the feature/ branch via gh pr merge --squash --delete-branch, pinned to the reviewed commit. A human's outstanding change request blocks the merge. auto-merge.yml still handles PRs approved by a human.

A merge made with GITHUB_TOKEN doesn't fire the push or pull_request events the post-merge workflows listen for, so the job dispatches them itself with gh workflow run. workflow_dispatch is exempt from that rule.

pr-checks.yml — auto-merge auto-merge.yml (human approvals) gh pr merge --squash gh workflow run
↓        ↓
Two post-merge workflows run
GitHub Actions — project automation

Close issues & apply release label

Reads the version from the .csproj, creates a release/vX.Y.Z label if it does not exist, then parses the PR body for Closes #N references. Each linked issue gets:

  • Label status: done added
  • Label status: in-progress removed
  • Release label release/vX.Y.Z added
  • Issue closed with a comment
project-automation.yml on: pull_request closed; workflow_dispatch
GitHub Actions — continuous delivery · human approval

Build, pack, publish & release

Triggered by the merge (only when production files changed). Runs a clean Release build and test, then waits for a human to approve the nuget-publish environment. Once approved it:

  • Packs the NuGet package
  • Logs in to nuget.org via trusted publishing (OIDC, short-lived key)
  • Pushes to nuget.org with --skip-duplicate
  • Tags the commit vX.Y.Z on GitHub
  • Creates a GitHub Release with auto-generated notes
publish-to-nuget.yml environment: nuget-publish dotnet nuget push gh release create
↓
Anyone, anywhere

Install the tool

The package is live on NuGet within minutes of the release approval.

$ dotnet tool install --global Pixelbadger.Toolkit
$ pbtk <topic> <action> [options]

Workflow reference

Workflow file Trigger Actor What it does
agent-build.yml Issue labeled status: to-do; or a human reviewer requests changes on a PR Claude Sonnet Invokes Claude Code headlessly with --permission-mode auto. Claude claims the ticket, creates a branch, implements the feature, and opens a PR. Also iterates on change requests from human reviewers; automated reviews are handled by claude-fix.
pr-checks.yml — claude-review job PR opened or synchronised (runs after mechanical checks and build pass) Claude Sonnet Reviews the full diff on the first push; on subsequent pushes focuses on whether prior feedback was addressed and checks for new regressions. Gets failing-job logs up front. Posts inline comments and writes a verdict, which is submitted as a formal review from github-actions[bot]. Never approves over red CI. Cancels in-progress runs when a new commit arrives.
pr-checks.yml — claude-fix job claude-review requested changes (same-repo PRs only) Claude Sonnet Runs Claude Code with --permission-mode auto to address every review point and CI failure, then pushes once, which re-runs pr-checks.yml. Stops after 6 rounds and asks for a human.
pr-checks.yml — auto-merge job claude-review approved and all checks green (feature/ branches) GitHub Actions (bash) Squash-merges the reviewed commit and deletes the branch, unless a human still has changes requested. Then dispatches project-automation.yml and, for production changes, publish-to-nuget.yml.
pr-checks.yml — mechanical-checks job PR opened or synchronised GitHub Actions (bash) Deterministic, zero-cost checks: version bump present, test file paired with every new component, benchmark updated for watched algorithms.
pr-checks.yml — build-and-test job PR targeting master (production paths only) GitHub Actions (.NET) Restore → build → test → pack. Also verifies the branch version is strictly greater than the published NuGet version.
auto-merge.yml PR review submitted by a human GitHub Actions (bash) Squash-merges the PR and deletes the feature branch once a human has approved it and all required checks are green. Reviews made with GITHUB_TOKEN don't trigger it, so automated approvals merge through the auto-merge job instead.
project-automation.yml PR merged to master; or dispatched by auto-merge with the PR number GitHub Actions (bash) Parses Closes #N from the PR body. Closes linked issues, applies status: done, removes status: in-progress, and tags with the release version.
publish-to-nuget.yml Push to master (production paths only); or dispatched by auto-merge / by hand NuGet CD Clean Release build → waits for approval in the nuget-publish environment → dotnet nuget push → git tag → GitHub Release with auto-generated release notes.

Kanban labels

Issue state is tracked entirely through GitHub labels. No external project management tool is needed.

LabelMeaningApplied by
status: to-do Issue is ready to be picked up Human (when writing the issue)
status: in-progress Claude is actively working on this Claude agent (on claim)
status: done Issue resolved and merged project-automation.yml (on merge)
release/vX.Y.Z Identifies which package version shipped this work project-automation.yml (on merge)

Cost model

The split between bash and AI is intentional. Mechanical invariants that can be expressed deterministically — version bump presence, test file pairing, benchmark coverage — are enforced in free bash. Both AI steps use Sonnet: the agent build (where implementation quality matters most) and the code review (where a cursory scan is not enough). Using the same capable model for both means the reviewer can evaluate the same kinds of nuance the author intended.

The pr-checks.yml workflow cancels an in-flight review job when a new commit arrives, so a fast iteration cycle does not stack up multiple simultaneous review runs. The fix agent pushes only once, at the end of its work, so it never cancels its own run mid-fix. The human-review iteration job in agent-build.yml uses a per-PR concurrency group, so only one agent iterates on a branch at a time.
Repository settings. Automated approval needs Allow GitHub Actions to create and approve pull requests enabled under Settings → Actions → General. Releases need a nuget-publish environment (Settings → Environments) with you as a required reviewer. Publishing uses NuGet trusted publishing, so no long-lived API key is stored: a policy on nuget.org trusts publish-to-nuget.yml in the nuget-publish environment, and the environment holds only the NUGET_USER secret (the nuget.org profile name).

Install

Once any feature branch merges to master the new version is available on NuGet within a few minutes. Install or upgrade with:

First install
$ dotnet tool install --global Pixelbadger.Toolkit
Upgrade to latest
$ dotnet tool update --global Pixelbadger.Toolkit
Verify
$ pbtk --help

Requires the .NET 9 SDK or Runtime.