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.
.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.
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.
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.
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.
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.
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.
PR checks — build, test, and review
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.
Restore → build → test → pack. Verifies the branch version is strictly greater than the published NuGet version.
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:
Full diff. Evaluates correctness, test quality, architecture (component-per-command pattern), security (prompt injection, path traversal), and README consistency.
Verifies each prior comment was addressed. Checks for new regressions introduced by the fixes. Does not re-review already-accepted code.
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.
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.
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.
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: doneadded - Label
status: in-progressremoved - Release label
release/vX.Y.Zadded - Issue closed with a comment
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.orgwith--skip-duplicate - Tags the commit
vX.Y.Zon GitHub - Creates a GitHub Release with auto-generated notes
Install the tool
The package is live on NuGet within minutes of the release approval.
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.
| Label | Meaning | Applied 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.
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.
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:
Requires the .NET 9 SDK or Runtime.