A Go CLI for a ticket-based engineering workflow using one shared local Docker image. The workflow starts from the repository where work is requested.
The CLI supports installation and reinstallation, version reporting, building and
inspecting the shared runtime, Codex/Claude account login, shared instruction
settings, local project initialization, ordered ticket discovery and interactive
provider sessions, and single-ticket or feature execution through checks, draft
PRs, CI and independent review, with a live dashboard of local runs.
New independent reviews default to high reasoning effort for both Claude and
Codex. Explicit --review-effort (or --reasoning), private model settings and
existing saved runs retain their selected effort. The diff-based pr-v1 policy
remains available as an explicit review_effort_policy setting; it is not the
new-run default.
Independent review recommendations can be accepted with delegated implementation
decisions, or automatically through an explicit persisted model default or
--auto-accept-recommendations. Required verification and publication gates
remain in place. Review-only entry points never start repairs automatically.
Completion usage reports cover only the current run/resume invocation, using prior
native checkpoints as subtraction baselines. They show model/role, requested effort and speed, elapsed
provider time, native token counts and observed subagents. Missing values are
omitted with a note; omitted does not mean zero. sdlc usage --run RUN_ID and
--json retain full-run session, subagent and measurement history. A resume that
starts no provider attempts reports no new agent usage. Provider time includes
setup, queueing and tools; it is not inference latency. Codex input includes cache
reads, while Claude input excludes cache reads/writes.
A completed independent review may report coverage limitations: these are retained as warnings at the human-review checkpoint. Findings still enter repair, and required human decisions and operational failures still stop the run.
Before starting another reviewer, SDLC checks whether the complete published Git tree, PR base and review scope match the last complete independent review without unresolved findings or questions. An empty commit, re-signing or changes followed by a complete revert can reuse that report. The original report keeps its original commit; a separate reuse record identifies the new publication. Current-head CI, Sonar policy and outstanding feedback still apply. Changed requirements, PR claims, source content, base or inspection gaps require review. Older reports without a retained content boundary conservatively require a review. Operational settings such as model effort and recommendation acceptance do not alone change scope.
When source changes, a later review can retain verified inspection from a complete prior review, including one that found defects. The correction owner reviews the exact old-to-new diff, prior finding/recommendation paths, and affected callers, contracts, tests and documentation. Deleted, renamed and reverted repair paths remain mandatory. Completion requires explicit affected-closure confirmation and an evidence-backed disposition for every prior concern. Inherited entries keep their source attempt; this is cumulative coverage, not another claimed full read. Broad, sensitive, contract or execution-context changes, missing proof and unbounded impact require full inspection. A reviewer can revoke inheritance and finish full inspection in the same session. Current-head CI, Sonar and outstanding feedback still gate readiness. No arbitrary repair-cycle cap is added.
Implementation self-review remains separate: the first assessment covers the
whole change. A verified receipt in the same implementation session lets later
feedback focus on new evidence or a bounded correction and its affected behaviour.
Successful command output stays in private durable evidence instead of being
repeated in prompts; command identities, exits, boundaries and failure details
remain available to the agent.
Adopt an existing open same-repository PR with sdlc adopt --pr PR_URL to assess
review comments and publish verified corrections; a local ticket is optional.
Use --start-at awaiting-feedback --human-reviewed to capture and park a PR
without starting agents or verification. Other entry points are checks, review
and the default feedback. Eligible unchanged stopped runs can use
sdlc resume --run RUN_ID --start-at awaiting-feedback.
Human PR comments can resume the original implementation session through checks
and a fresh independent review with sdlc resume --run RUN_ID --pr-feedback.
Supply private pasted or file feedback with
sdlc feedback --run RUN_ID [--file FILE].
A 👎 reaction from the run’s configured GitHub account excludes the comment and
its linked replies, including replies added later. A 🚀 reaction marks the comment and
its linked replies as already addressed, including replies added later. Unmarked conversations are
assessed together so that follow-up advice informs the fix. See the
feedback guide for reply linking
and account-verification rules.
A saved run stopped by a corroborated local numeric limit can continue with
sdlc resume --run RUN_ID --override-run-limits. The override persists without
resetting its session or accounting; provider holds and verification gates remain
enforced. See run-limit recovery.
Failed CI checks return bounded failure context to the original implementation
session automatically. Ordinary sdlc resume --run RUN_ID also refreshes an
eligible saved repair that stopped for missing CI context. Selected human context
can still be supplied with --ci-feedback-file FILE.
See CI context recovery.
Dedicated 1Password signing-key retrieval is implemented. Feature runs schedule dependencies
and independent tickets and reconcile owned PRs after human merges. Detached
controller supervision remains future work.
The first interactive frontend is available with sdlc shell. It keeps the
existing CLI commands, adds slash-command help and local ticket completion, and
uses the terminal's font and colours with a Robby Russell prompt. Read the
shell guide for project scope, onboarding, plan
review and independent terminal launches. The current beta baseline is
0.1.0-beta.131; changes are recorded in the changelog.
Future work is recorded in the feature backlog.
Ticket and feature runs retain usage metrics across
attempts and resumes. Read them with sdlc usage --since 7d --json.
New ticket and feature runs require a saved Headroom proxy address.
Configure it once with sdlc runtime headroom set --proxy-url http://127.0.0.1:8787;
new runs use it automatically. Existing runs keep their recorded route.
Follow the user guide for the full route: install, build, sign into Codex/Claude/GitHub, provision a dedicated 1Password signing authority, pair accounts and keys, configure a project, and start and monitor a ticket. Account setup is done once; each project needs reviewed checks and an account selection. The guide includes replacement, resume and history retention steps.
For a supervised trial on a disposable .NET repository, use the test runbook. The proposed host-harness skill defines how a harness can drive the current CLI while keeping its context small. It is not installed automatically. A single guided setup command is proposed follow-up work; current onboarding uses the documented commands.
From this clone, with Go 1.25 or later and a local Docker engine running Linux containers, select an existing directory on your PATH:
go run ./cmd/sdlc-install --bin-dir /PATH/TO/YOUR_BIN_DIRECTORY
sdlc --version
sdlc runtime status
sdlc auth login
sdlc auth login --provider claude
# Synthetic uses the pinned OpenCode client and a native API-key prompt:
sdlc auth login --provider synthetic
sdlc auth status --all
sdlc instructions show
sdlc interactive/PATH/TO/YOUR_BIN_DIRECTORY means a directory your shell searches for commands.
On macOS or Linux with Homebrew, use the local tap from a clean, committed clone:
python3 scripts/install_homebrew.pyThis installs local/sdlc/sdlc through Homebrew and prepares its runtime in one
command. Homebrew builds the CLI with its Go dependency and keeps the public
runtime sources in the Cellar. Python 3 and Git are required for the bootstrap.
Use --cli-only to migrate an existing receipt-verified native installation while
keeping its runtime. The previous executable is backed up in private state.
See Homebrew installation for updates
and recovery.
The installer builds the CLI and runtime in one command. It prepares the runtime
with the new CLI before replacing the installed executable. Use --cli-only to
install the host command while keeping the current runtime.
After installation, update from any directory or use /update in the shell:
sdlc update --dry-run
sdlc update
sdlc update --pullThe first command previews the local steps without building, fetching or writing.
update installs the current checkout; --pull first fast-forwards a clean
checkout from its configured upstream. Homebrew updates refresh the committed
snapshot, formula and checksum before upgrading; commit source changes first.
Native source installation also accepts dirty source without --pull.
The source and installation method are remembered in private installation
state. Default updates use the checkout's runtime pins, replacing any previous
local overrides. Use sdlc update --dependencies to select newer public
dependencies instead, or --cli-only to preserve the runtime. Reopen existing
shells after installation. Docker builds remain local; CI validates source.
Resumable saved runs and incomplete features in known projects block runtime
replacement and identify the work to finish. sdlc update --cli-only remains
available while that work is paused. Keep external projects registered so updates
can find their saved work.
sdlc runtime status checks the installed runtime dependencies for updates,
including the skills and agents catalogues. Use sdlc runtime status --offline
for local validation without network access. Older images need one rebuild with
the updated CLI to record their dependency inventory. See the
runtime status guide for coverage and failure
behaviour.
The default report lists major tools and image/catalogue pins, with summaries for
supporting packages. Use sdlc runtime status --all for individual bundled npm
dependencies and Debian updates.
After checking status, preview and apply dependency updates with:
sdlc runtime update --dry-run
sdlc runtime updateRuntime update resolves exact public releases, refreshes the installed packages and
rebuilds sdlc:local. It selects the candidate after tool, inventory and package
checks pass. Selected pins stay in private installation state; source pins and
login storage are preserved. Ordinary runtime build retains these local pins;
runtime build --source-pins explicitly returns to the checkout's pins. Named
builds can combine --dependencies with local skills and agents; see
named runtimes. See
runtime updates for release tracks and
dependencies controlled by their parent packages.
Login opens a browser flow through the terminal. Credentials stay in separate local Docker storage and survive CLI reinstallation and image rebuilds. These volumes are readable by Docker administrators; see the authentication guide.
Codex is the default provider for login, status and interactive sessions. Use
--provider claude to select Claude, or sdlc auth status --all to check both.
Use sdlc interactive or sdlc interactive --provider claude to open the native
provider CLI inside a disposable container. This first command starts in an empty
workspace. Use sdlc run for a captured project checkout.
Both default to full access inside Docker. Use --approval on-request for Codex
or --permission-mode manual for Claude to change their native approval modes;
see the interactive command guide.
From the project repository, prepare local settings with:
sdlc init
sdlc github use --profile personal
sdlc github statusThis discovers Git state, project files and ticket paths, protects private work
by ignoring the whole /.sdlc/ directory in Git's local exclude file, and creates
.sdlc/project.json. Review the
suggested checks before using them. .NET discovery reads required-check guidance, simple CI sequences
and runner manifests. New projects select checks from committed metadata at runtime.
Use sdlc init --force to switch existing settings to runtime discovery and refresh Docker-test settings;
other preferences and saved runs are preserved, and changed settings are backed up privately.
Initialization works without Docker or provider login;
github use saves the checked pair for this checkout in private external state.
Execution starts with sdlc run. See the
project initialization guide.
For a disposable .NET 10 .slnx project with an API, unit tests and Docker/Mongo
integration tests, use the smoke-test example.
Its public ticket template adds a count endpoint. The build and tests have passed
in credential-free SDLC workers; supervised private trials using this style of
project have also passed connected delivery and review/repair.
List a work folder's tickets in numeric filename order:
sdlc work --reference YOUR_WORK_REFERENCEThis inspects .sdlc/work/YOUR_WORK_REFERENCE/tickets/ without reading ticket
bodies or starting work. Content and dependency checks belong to execution.
See the ticket discovery guide.
Launch exactly one selected ticket:
sdlc run --reference YOUR_WORK_REFERENCE --ticket 01-add-api.md --dry-run
sdlc run --reference YOUR_WORK_REFERENCE --ticket 01-add-api.md \
--input .sdlc/work/YOUR_WORK_REFERENCE/specification.mdNew runs use Codex Sol 6.1 and Claude Sonnet 5.5 at low effort. Use
--reasoning low|medium|high|xhigh|max to select both lead roles' reasoning band,
or override each role's model and effort. --speed and --review-speed request
normal or fast service separately; fast is opt-in and provider costs differ.
The implementation account must be logged in. If the opposite reviewer has no
login, delivery proceeds through the draft PR and CI, then pauses at
awaiting_reviewer. Authenticate that provider and resume the recorded run.
A fresh run uses the saved repository pair, or the unique pair whose login owns
the repository. For an organisation or ambiguous account selection, run
github use --profile personal first. --github-profile can select a registered
pair for an unbound checkout; it cannot override a conflicting saved selection.
Each account has a separate native login and explicitly paired signing profile
on the shared image. The Docker
publisher signs every delivered commit with the dedicated approved key, uses the
captured project Git name/email, and publishes through native gh. It leaves the
PR draft and never merges. Read the run guide
and provider rules before a connected run. Supervised
private trials have passed delivery/review/repair with both implementation
providers. Later account/key pairing, history/dashboard changes and desktop
notification delivery still need separate validation.
During implementation on macOS and Linux, the agent can call a fixed diagnostic helper from its running native CLI session. It receives focused check results and bounded source corrections from a separate credential-free worker without ending its turn. These one-shot requests do not become permanent publication gates. The structured diagnostic handoff remains available on other hosts. The agent requests full checks when its candidate is ready and self-reviews its complete changes. The controller runs one required opposite-provider review after CI, with repair and another review when findings remain. CI waits for pending checks before returning a combined failure packet. Signing, full checks and independent review remain required. See the repair diagnostic workflow.
Run a whole feature from a clean checkout of the published integration branch:
sdlc run --reference YOUR_WORK_REFERENCE --all --parallel 2 --dry-run
sdlc run --reference YOUR_WORK_REFERENCE --all --parallel 2 --watchAn optional private plan.json declares ticket priorities, dependencies and path
prefixes that must run serially. Independent tickets can overlap; a ticket with
one dependency can start from its parent's signed, tested and reviewed draft PR.
Tickets with multiple dependencies can start from a separately checked, signed
combination of their ready parents and current integration. Their PRs target an
immutable derived branch so reviewers see only the dependent ticket's changes.
Use sdlc dependencies to amend the dependencies of an unstarted ticket in an
existing saved feature. It preserves the parent jobs and frozen execution
settings. See the dependency amendment guide.
As parents merge, SDLC rebuilds the combination and restacks the dependent work;
after all parents merge, it retargets the existing PR to integration. Restacking
changes commit IDs, but unchanged contexts are reused. Review dependent PRs early,
then wait for retargeting to integration before merging them.
--watch keeps the foreground controller monitoring human
merges; without it, SDLC runs currently unblocked work and exits. Repeat the
command to continue the saved feature. --alternate-providers alternates
implementers in planned ticket order, with the opposite provider reviewing each.
The dashboard still reports individual ticket runs. See the
feature run guide for plan format and restacking.
Feature orchestration has offline test coverage; a connected feature trial still
needs validation in an authorised disposable repository.
Watch registered runs across repositories from another terminal:
sdlc dashboard
sdlc dashboard --run RECORDED_RUN_ID --logs
sdlc progress --run RECORDED_RUN_ID
sdlc dashboard --json
sdlc dashboard --page 2
sdlc dashboard --notify desktop --soundsdlc progress --run ID tails labelled SDLC steps, checks, and provider agent
output. The shell follows this CLI feed after starting or resuming a job;
/progress --run ID attaches to existing work. Page Up pauses scrolling and End
returns to the newest output. Closing the view leaves the controller running.
The dashboard shows heartbeat status, current stage and model, questions, check
results and PR links. It puts attention items first and reads private run state
without contacting providers. Ten runs appear per page; completed work follows
questions, problems and active work. dashboard forget --run RUN_ID hides a
stopped run while preserving all saved work. Private report export and retention
are described in run history. Optional local macOS alerts
use --notify desktop --sound; add this to sdlc run for alerts without an open
dashboard. Closing the dashboard leaves controllers working. Headless
controllers remain attached to their original terminal; detached execution is
future work. See the dashboard guide.
Concurrent controllers use separate workspaces and native sessions. Calls to the same provider can overlap across tickets, folders and feature runs. Brief cache transactions protect login state without reserving a provider for model execution. See the concurrency guide.
SDLC uses Docker to limit what provider commands can reach. Interactive sessions
run as a non-root user with a read-only root filesystem, dropped Linux
capabilities, Docker's no-new-privileges restriction, and CPU, memory and
process limits.
They receive the selected provider's private cache and shared instructions.
The current session starts in an empty disposable workspace, with no host
repository, host home, SSH agent, work secrets or Docker socket mounted. Ticket
runs instead mount a captured checkout and the explicitly selected requirements.
Their configured checks run in separate workers without provider caches, host
signing material or publishing credentials. The controller publishes only a
verified committed tree.
This boundary is useful for trusted repositories too: their dependencies, installation scripts, build tools and tests can be compromised. Keeping that code away from unrelated host files reduces the damage it can cause. The host, Docker engine and runtime image remain trusted parts of the system; an attacker controlling them can inspect or alter sessions and credential storage. See Docker's security model.
The remaining risks are:
- Credentials inside the session are exposed to its code. Login, interactive and ticket provider sessions can read and update the selected provider's cache. Default full access removes native permission prompts, and network access currently has no destination allowlist. Malicious instructions or executable dependencies could steal credentials or transmit other accessible data. Manual approval is additional supervision; approving an installation command does not constrain its package scripts. Anthropic documents the same credential exposure in dev containers.
- Persistent storage remains sensitive. SDLC supplies no credential encryption. Docker administrators and an attacker with sufficient host access can read provider volumes. Claude's native cache may also retain account metadata and logs. Reinstalling or rebuilding preserves these volumes; deleting local storage does not establish provider-side revocation. Follow the login storage guidance.
- Container isolation can fail. Runtime or kernel vulnerabilities and unsafe host configuration can weaken the boundary. Docker bridge networking can reach services allowed by the host network; filesystem isolation does not isolate those services. Keep the host and container engine maintained.
- Pins and update checks do not establish safety. A pinned release or skill
can contain malicious code.
sdlc runtime statusreports version availability, not a vulnerability scan, malware check or endorsement of an update. - Unattended signing grants machine authority. A publisher that signs without desktop approval must hold usable signing capability and GitHub access. Compromising that publisher, its credential resolver or the Docker host can misuse them. Use a dedicated signing key and scoped credentials, and keep both away from repository code and test dependencies. The publisher is implemented with a read-only native GitHub login volume and tmpfs signing key; neither is mounted in provider or check workers. Native GitHub OAuth access can cover several repositories: a frozen destination limits intended operations, not what a stolen token could access. The explicit Service Account bootstrap file is plaintext, private host storage; OS credential-store integration and detached controller supervision remain future work. See the credential boundaries.
- Disposable state has operational costs. Current workspace changes are discarded on interactive-session exit; ticket checkpoints persist privately. Provider volumes have no storage quota, so session code can exhaust Docker's disk space. Deleting these volumes loses saved login state; losing installation metadata or switching engines can leave old sensitive volumes behind. Offline auth status cannot prove current account or model access.
Ticket checks receive their own disposable source copy. With --docker-tests
or the project setting "docker_tests": true,
new runs use a persistent privileged Docker-in-Docker test daemon with scoped
session sockets. Concurrent checks can reuse cached images while using the same
names and published ports. Required host-cached images and committed source
templates are reused; each run keeps its own writable source and resources.
Saved runs keep their original daemon mode. See the
Docker check cache guide for runtime rebuilding,
compatibility and cache lifetime. Privileged Docker is suitable only for trusted integration checks and
is not a boundary against hostile code. The authenticated provider still has a
shell: instructions to leave dependency installation and tests to the check
worker cannot prevent it from running repository code and exposing its cache.
Network destination restrictions and credential encryption remain unimplemented.
A dedicated execution VM or separate machine adds a boundary whose administrator
still remains trusted.
A carefully configured Claude dev container can provide comparable containment and can already offer tighter network controls. SDLC uses the same underlying container boundary. Its current value is a shared recorded runtime, consistent Codex/Claude launch settings, provider cache separation, shared instructions and dependency visibility. Disposable ticket work, independent validation and controlled publication are implemented for selected tickets and feature runs. Full access directly on the host exposes the files and services available to that host user. Running inside SDLC narrows that exposure, while retaining the risks listed above.
- User guide: full onboarding, ticket execution and recovery
- CLI installation and commands
- 1Password signing provisioning and setup
- GitHub profiles and unattended signing tests
- Agreed workflow and remaining work
- Development and validation
- Keeping public commits free of private material
- Provider usage rules and authentication boundaries
- Run history, private reports and dashboard removal
- Connected validation runbook
- Proposed host-harness SDLC skill
- Proposed unified onboarding command
- Research and earlier prototypes
A normal resume verifies the open PR's current head and actual target branch tip. GitHub's stored PR base revision can lag behind an updated branch, so it is kept as a separate publication lease rather than used to detect upstream changes. If the upstream has changed, it stops before agent work and reports how to rebase:
sdlc resume --run RUN_ID --rebaseThis performs git rebase --onto using the saved PR base boundary, replaying only
the child PR's existing commits. It handles an updated parent branch and a PR
retargeted to the default branch after its parent merged, including squash merges.
The workspace must be clean at the recorded published source revision (or its verified
local equivalent before publication signing). Commit messages and
authorship are retained; rewritten commits receive new SHAs and publication
signatures. Conflicts return to the original implementation session for resolution.
For a clean rebase, the controller compares the original and rebased PR changes,
retaining whitespace, modes and binary changes while ignoring changed blob IDs and
hunk positions. If equivalent, it signs and publishes the replay and monitors CI
for the new head without implementation, self-review or independent-review agents.
It does not claim new local checks or a new review. Conflicts, changed patches and
CI repairs retain the normal checks and review path. Publication uses
the recorded remote head as an exact lease. Recommendation policy and PR feedback
are unchanged; --rebase cannot be combined with feedback or acceptance options.
Use --dry-run for an offline plan; it does not query GitHub or modify history.
A passing Sonar quality gate does not mean the PR has no new issues. To repair
all unresolved new PR issues and duplication independently of gate thresholds,
set this local preference in .sdlc/project.json:
"sonar": {
"repair_policy": "all-new-issues-and-duplication"
}Normal CI monitoring and resume --pr-feedback refreshes apply the current local
policy, including existing saved runs and clean rebases. The controller validates
the exact PR analysis, collects all issue pages and file-level duplication counts,
then batches findings with pending human feedback when available. Corrections use
normal checks, signing, publication and review; readiness requires a clean analysis
of the new published head. No findings means no repair agent. An unchanged attempt
or unavailable/incomplete evidence is retained as a specific hold, not a clean pass.
The default remains advisory; use "repair_policy": "advisory" to opt out. This
policy covers new PR issues, not the repository backlog, and is independent of
review recommendation acceptance. It requires public SonarCloud analysis access;
GitHub credentials are never forwarded to Sonar. All configuration and receipts
stay local. No target-repository workflow changes or runtime rebuild are needed.
Standalone review-only checkpoints retain their inspection-only contract.
A resume retains successful work for its exact candidate, inputs and execution configuration. CI polling and publication retries do not start agents. A ready run whose CI becomes pending returns to polling; its completed review is retained. Feedback assessed as requiring no changes reuses its existing candidate boundary, including local feedback and accepted recommendations. Read-only diagnostic and human-question handoffs preserve that boundary until a source or required verification change invalidates it. Unanswered questions still block completion. Standalone checks and completed standalone reviews can retry a failed final PR boundary read without repeating their successful work. Check results stay provisional until the unchanged boundary is confirmed; failed teardown is never reusable. Changed candidates, inputs and check configuration retain fresh gates.
CI startup treats a confirmed empty or null check rollup as waiting for checks. If checks appear between GitHub reads, the next poll collects their outcomes. Final verification after independent review uses the same configured manual workflow evidence as ordinary CI polling. A completed full review is retained for its exact PR revision; resuming a failed final CI read rechecks CI without another reviewer turn. Errors retain their underlying cause. Changed revisions and failed checks still require the usual review or repair.
Synthetic can implement tickets through pinned OpenCode, with Codex review. See the Synthetic guide for authentication, models and runtime setup.
For a new single-ticket run or adoption, add --review-context pr-link to let
an independent reviewer choose its own focused reads. For example:
sdlc adopt --pr https://github.com/OWNER/REPO/pull/NUMBER \
--start-at review --review-context pr-linkThe launch prompt contains the PR URL, pinned base/head and a small review contract. The reviewer uses the exact local checkout; it receives no new GitHub credentials. Existing selected requirements, PR metadata, human feedback and controller check evidence are available on demand in a private snapshot file, not embedded in the launch prompt. This is reviewer-led inspection, not a web-only review. The review skill, structured results, coverage validation, cumulative repair reviews and unfinished-inspection continuation still apply.
packet remains the default. The choice is recorded in the run plan and ordinary
resume retains it; changing an existing run's mode is intentionally unsupported.
Compare separate runs at the same PR revision with sdlc usage --run RUN_ID:
include total input, cached input, output, context measurements where available,
duration, findings and coverage. A smaller launch prompt does not by itself prove
lower total usage or equal review effectiveness. No live savings are assumed.