Repository navigation
v26.11.3
This release installs devkit with one command, runs its
hooks from a pinned copy, gives you a live dashboard, puts the crew under one enforced RACI (who is Responsible,
Accountable, Consulted, and Informed for each kind of work), holds irreversible actions until you grant them, protects
devkit's own state from agents, carries a session's work through compaction, backs up branches that exist only on
this Mac when that starts no CI run, explains what fills your disk and frees it item by item, and makes the audit trail
verifiable and exportable.
What changes for you
devkit refuses more in this release. Each refusal says why and names the command to use instead.
- You run
dev install,dev update, andinstall.shyourself, in a terminal. Agents are refused them.
dev installrefuses a checkout with uncommitted tracked changes or code that does not compile, and pins only a
published release or a commit whosebin/dev ci --runpassed;--unverified --why "…"overrides that, and the
override is audited. - Agents cannot change devkit's state, configuration, or install. Writes to
~/.local/state/devkit,
~/.config/devkit/config.json, and~/.local/share/devkit,dev config set safeguards.*oraudit.*, and
dev config editare refused to every agent. You change safeguards in a terminal. ADEVKIT_*variable added to
theenvblock of a Claude Code settings file (user, project, or local) is refused and removed. - devkit cannot be pointed elsewhere by an agent. The guard refuses
HOME,DEVKIT_CONFIG,DEV_ROOT, or
DEVKIT_SESSIONset fordev, and a swappeddevlink or anotherdevearlier on thePATH. devkit reads a
non-standardDEVKIT_CONFIGorDEV_ROOTonly from a command you run in a terminal with no agent among its parent processes. - Four escape hatches moved.
dev commit,dev push,dev pr create, anddev releaseno longer read
DEVKIT_SKIP_SECRET_SCANorDEVKIT_LOCAL_CI_PASSEDfrom their environment. Pass--ci-passed(recorded as
attested), or let a realdev ci --runlift the push budget.dev gitanddev ghno longer read
DEVKIT_FLAKYorDEVKIT_CROSS_PROJECTfrom theirs; rerun a flaky CI run with
dev run rerun <id> --flaky "<reason>". In the main session, a hatch still works as a prefix of the command
itself, such asDEVKIT_SKIP_SECRET_SCAN=1 git commit, where the guard sees it and records it asguard.bypass;
the next prompt names it, andDEVKIT_GUARD=offis recorded once per session and shown when a session starts. - Irreversible actions wait for your grant. In the main session, these need a line you type on its own,
grant <action> <target>: merging a pull request (grant merge 142), releasing a version, also by pushing its tag
(grant release v26.11.3), a force push or a push to the default branch, a comment, review, or edit on a pull
request or an issue, publishing a package, a deploy, a write through an API, and an MCP tool that sends, creates,
or deletes something outside this Mac. The refusal names the exact line. A grant is used once, holds only in the
repository of the session you typed it in, and expires after 30 minutes. A push of another branch and a new pull
request are recorded, not held. For its first week on a Mac the gate only records what it would refuse, then it enforces;
safeguards.irreversible_mainsets it. - Some actions are yours alone, in every setting. Lifting an embargo (
dev branch embargo --lift),
dev backup --public, and a change to a project's backup policy wait for a line you type:grant embargo <branch>
orgrant backup <project>(grant developer-only <target>works too). The gate's first audit week does not let
them through, and crew members never run them. - An agent's push or pull request of an embargoed branch needs your
grant embargo <branch>. A push or pull
request from a folder the guard can only learn when it runs (cd "$X" && git push,GIT_DIR=$G git push) is
refused while any project on this Mac has an embargo; the agent writes the folder out instead. - A decision is yours only in your own words. It counts when you answer the question dialog, or type a line of
your own:approve D3,approve D3: B, orgrant push feat/invoice-export. Without that, an answer the tech lead
records is marked unverified, and an irreversible decision stays pending.dev crew mode auto --approvetakes one
target per action (push feat/*) and never pre-approves publish, deploy, a developer-only action, or a command the
guard cannot name. - Crew members are named by role. devkit's output, briefs, and refusals write a member as Backend engineer
(Tank) and the main session as the tech lead. A final message or a member's report whose prose names a member
without the role is sent back once; the role alone is fine, in any language (canary.roles). devoptions are read exactly. Everydevcommand refuses an abbreviated option (--schedfor
--scheduled), and a word after--is an argument, as the guard reads it.dev pr readyneeds local CI evidence for HEAD, because marking a draft ready starts its one CI run. When every
check of a pull request was skipped,dev pr checksreports no checks yet (exit code 8) anddev pr mergewaits for
the real run.- Only the tech lead plans and decides.
dev progress start,assign,begin,reopen,skip, anddone, and
dev crew decideandmode, are refused from a crew member and from a script. A seconddev progress starton a
live run needs--replace --why "…". - The RACI is enforced.
dev progress assignrefuses a member who is not Responsible for the step's kind of work,
anddev progress donerefuses to end a run before each Accountable member approved;--why "…"overrides both
and is recorded.dev progress startandaddrefuse unknown, ambiguous, or duplicate step names and dependency
cycles, and no step starts before its dependencies are done. - Crew members are held tighter. They are refused every escape hatch (
DEVKIT_*variables,env -i,
--ci-passed,--no-verify,dev config set, new secret-scan exceptions). A review or read-only member's shell
runs only a read-only allowlist; add your project's own checks withsafeguards.readonly_commands. Members never
merge, release, tag, publish, deploy, write through an API, or force-push. A member pushes a branch, backs one up,
or opens a pull request only in a step allowed it (dev progress assign --allow push,pr), and only with your grant
for that action or a decision of yours that names it; the step keeps the target and the repository that evidence
covers, and opens nothing else. When a review or read-only member's shell call writes files, the tech lead gets a
message, which names the working member whose scope holds a file, and the member's step ends unverified until the
tech lead checks the diff. In the session scratchpad, each member writes only in its ownscratchpad/<member>/
folder. - A member's step ends done only on evidence. That is a Check ✓ in its report, or its own
dev progress step --check. Otherwise the step shows as unverified, for the tech lead to close with evidence or
reopen (dev progress reopen <step> --why "…"). - Approvals are explicit. Each finished step owes a verdict from the Accountable member of its kind of work,
given after the work, for example by the Check ✓ of a review step that follows it. Nobody approves their own work:
when the approver did it, the Code reviewer (Seraph) approves code and configuration, and the tech lead the rest. An
approval needs the ✓ itself, so "tests not run" approves nothing, and a step with no approver cannot be approved
until its kind of work is declared (dev progress assign … --activity <id>).
dev progress step --approves "<steps>"anddev crew ask --decision --approves "<steps>"name the work a Check or
your answer approves. - Running a devkit hook by hand is refused in every session, because a hook event typed through a shell could
forge your prompt or answer. - Audit records are kept 13 months, on this Mac and in the handoff copy; this Mac used to keep two years.
dev config validaterefuses anaudit.retention.floor_monthsunder 3. dev ls,dev du, anddev statusshow what is on this Mac. A footer counts the other projects of the
portfolio, anddev ls --alllists them with thedev clonecommand for each.dev gcis the old name ofdev free. Without arguments it prints the plan to free space instead of a
cleanup dry run, anddev gc 3frees item 3 of that plan.dev gc --applystill runs the unattended cleanup.dev dashboardstarts a local server and opens a one-time sign-in link instead of writing a file.
dev dashboard --export <file>writes the static page.
Added
Install and update
- A one-line install:
curl -fsSL https://raw.githubusercontent.com/fireflysoftwaresolutions/devkit/main/install.sh | bash
installs Homebrew, git, Python, and the GitHub CLI when they are missing, clones the newest devkit release into
~/Development/fireflysoftwaresolutions/devkit, signs you in to GitHub, and starts the setup wizard. Its questions
come from the terminal even through the pipe; without a terminal (CI), it runs without questions and says how to
finish. It says first that devkit is for macOS (Apple Silicon and Intel) and stops on any other system. New:
--no-setup,--help, and theDEVKIT_HOME,DEVKIT_REPO, andDEVKIT_REFvariables. Each step says in one
plain sentence what it does and why; a failed step is named, with the command to run again; and the run ends with
what you have now and what to do first. - A first install for people who are not developers: a step-by-step guide in Getting started, with what you
see at each step. Pressing Return at every question gives a working setup: the GitHub sign-in uses HTTPS and the
browser, so it asks no questions about protocols or tokens, and the wizard's first screen says what devkit and the
handoff repository are. - A pinned, read-only copy runs the hooks and the guard.
dev installcopies the checkout's commit to
~/.local/share/devkit/releases/<version>-<sha>, read-only and with a SHA-256 manifest. The hooks, the status line,
~/.local/bin/dev, the scheduled jobs, and the Desktop launcher run that copy, so an edit to the checkout, broken
or malicious, no longer changes the guard of every session at once.dev doctorfails on a changed copy or a hook
that runs elsewhere,dev install --version <version>rolls back, and the newest three copies and any in use are
kept.dev updatepins the new release. - First-task tutorials for every surface: Claude Code (Terminal and the IDEs), Claude Desktop's Code tab, Codex
CLI, and Codex in the ChatGPT app, plus a page on Claude Desktop chat and Cowork. Each shows what you see on the way:
the status block, progress updates, approvals, the crew graph, and the dashboard. Where to use devkit compares the
surfaces. Codex is not verified live yet.
The live dashboard
dev dashboardis a live, read-only app on this Mac. It starts a local server (or reuses one of the same
version), opens a one-time sign-in link, and pushes each change to the open page, which updates in place: the
route, the filters, the scroll position, and an open drawer stay.--no-openprints the link,--statusand
--stopmanage the server, and--export <file>and--pathwrite the static page. The server stops after 30
minutes with no open page (dashboard.idle_minutes). It answers only GET and HEAD on 127.0.0.1, with a token or a
same-site cookie, under a content security policy that allows only its own scripts.- Background work: decisions waiting for you first, every run with its steps and owners, CI results with the
first error and the next action, and scheduled jobs with their failed, overdue, and not-scheduled states. - One drawer for every detail, the connected task (who has it, what blocks it, what is next), the crew with
role-first names, and a live indicator with reconnecting and offline banners. No data is never "on track," every
count names its window, and a contradiction shows where it occurs, with its fix. The navigation never scrolls
sideways, from 320 to 1,600 pixels wide.
The crew
- A RACI for every kind of work, led by the tech lead. Each of 34 kinds of work has one Responsible member, one
Accountable member, and the members Consulted and Informed (dev crew raci). The tech lead (Morpheus) routes every
development request by it. Nobody approves their own kind of work: the Security engineer approves CI/CD, the Code
reviewer approves security code, the Product owner approves UX, the Security engineer approves compliance, and the
tech lead approves incidents. - Roles first, everywhere. The crew views, the progress update and its Crew line, messages, decisions,
delegation, dispatch, scope and slot refusals, the continuity texts, and every brief's report header write a member
as Backend engineer (Tank). The guard's refusals call the main session the tech lead. Stored names and the ids in
commands (--to tank) do not change. The end-of-turn role check holds the prose to it (see What changes for you). - A procedure for every member: phases, the skills and devkit commands to use, a gate, and a proof that devkit
checks. Each brief carries the knowledge of its kind of work (skills and devkit guides), the stack skills of its
files, and the known pitfalls for the task. - Kinds of work in any language. A step's kind of work comes from what you declare (
--activityon
dev progress assign,[id]in a plan spec), then from the member's role, then from its files. Words are only the
last guess and never refuse work. Lessons work the same way: they carry anchors (files, commands, kinds of work,
error signatures, stack), set withdev lesson add --file,--command, and--error, ordev lesson anchor. - The crew gates. When a member stops, devkit reads its transcript and sends it back once for a missing proof, a
skill it did not load, unfinished work, a test that cannot fail, or a missing lesson after repeated refusals.
crew.gates.enforce: falseonly records them. - Lanes and helpers. Each member's lane binds to its own launch, so members launched together never take each
other's name or step, and a step binds to a working lane only when that lane's launch names it. A member may launch
narrow helpers, which get its tools and files, take a slot, and stop atprogress.max_depth(2). - Crew slots.
progress.max_parallel(4) sets how many members work at once, and your recorded usage lowers it:
progress.quota_stepskeeps a share of the slots from 50, 70, and 85 % usage, the 5-hour and the weekly windows
both count and the lower limit wins, and one member works at a time fromprogress.quota_percent(90). A
review-only or read-only member costs half a slot and the Lookup scout (Sparks) nothing (progress.slot_weights).
progress.reserve(1) keeps a slot for what you ask while the crew works.dev crew nextranks the ready steps by
critical path, then your latest request, then age, and records that order; a launch out of it needs
dev crew next --first <step> --why "…". The slots in use and why the limit is lower show indev crew,
dev crew next, and the status block's Crew line, and each change of the limit is audited (crew.limit). A member
stopped with TaskStop frees its slot at once. A team'spolicy/progress.jsoncan set a ceiling, and you change the
keys withdev config set, in a terminal. - Who is calling. A call ledger records which agent made each shell call, so a
devcommand knows whether the
tech lead or a member ran it, and two sessions in one repository each update their own run. - New commands:
dev crew graph(the live session as one graph;--mermaid,--json),dev crew rules(every
crew rule and the check that enforces it),dev crew raci --set,dev crew set, anddev crew history(the team's
changes, kept in the handoff repository with who and why),dev crew decisions --ask,dev task reopen --why, and
dev agents rules [--section]. - The status block gains optional Crew and You bullets, and
dev statusshows each on its own rows. - Claude Desktop chat and Cowork get the full global rules through the extension's new
devkit_rulestool.
Continuity
- A session keeps its work through compaction, resume, and
/clear, on Claude Code and Codex. Before a
compaction, devkit writes a checkpoint: the run and its current step, the crew working now, the decisions and
messages waiting, your last 5 requests, and git. In Claude Code's main session it also tells the summarizer what to
keep. After the compaction or a resume, the session gets the continuity brief first (at most 4 KB), and in Claude
Code the next hook names what the summary left out ("Not in the summary"). A member whose own context was compacted
gets a reminder of its role, step, scope, and report format. After/clear, the new session hears of the old
session's open run and getsdev session carry. See Continuity. - Your requests stay private to the session. They are kept redacted, cut to 1,000 characters, only for turns of
development work, for 7 days at most, and only the session's own provider sees their text. The summary itself is
never stored.dev session forgetdeletes the records. devkit_resume, a read-only tool of the devkit extension, gives Claude Desktop chat and Cowork the same brief for
a project's latest session, with your request text only when the app is that session's provider.- The global instructions tell the agent that devkit's record wins over a summary, and what to keep when it writes
one.
Branches, backups, and pull requests
- The branch map: one row per local branch with its upstream, how far it is ahead of and behind the upstream and
the default branch, the commits that exist only on this Mac and the branch that carries them, its last backup, an
embargo, its worktree, its pull request, its linked task, and whether its work is safe off this Mac, with the
reason.dev branch lsprints it (--json),dev statushas a Branches section,dev overviewcounts the
branches not backed up and embargoed, the handoff note's generated block lists the branches, the session-start
context names the branches only on this Mac, and the dashboard has a Branches tab on each project page. dev backup [<branch>…] [--all]copies the commits that exist only on this Mac to the remote, under the same
branch name, when that push starts no CI run. It reads the CI configuration of the commit it sends (GitHub
Actions, GitLab, Bitbucket, and Azure) to tell. It never pushes the default branch, a long-lived branch (main,
master,develop,trunk,gh-pages), or a branch a workflow deploys from, never forces, and stops at a
diverged remote branch with the commands to resolve it. Its WIP, embargo, security-fix, and secret checks read
exactly the commits the push target lacks, also when another remote has them, and it reads visibility and pull
requests on the repository the branch's remote names.--accept-cipushes anyway and counts against the push
budget.dev syncbacks up the branches
that need it every hour and at the end of a session, for commits older thanbackup.after_minutes(30);
backup.auto: falseturns that off.- A backup policy per project:
dev backup policy on|off|ask --why "…"records it in the project's handoff note,
for every machine and the team. Without one, a private repository is on and a public one is ask:dev backup
asks you once, in your own terminal, and records the answer.dev syncand agents are never asked and never
publish. - Embargoes:
dev branch embargo <branch> --why "…" [--until …]holds the pushes of a branch, and of the commits
it held after a merge, until you lift it (--lift): from its project, its git folders and worktrees, temporary
clones, and folders that are no project (see Known limits). An embargo is kept in the handoff note's metadata, so every
machine sees it, and a note devkit cannot read stops every backup. On a public repository, a branch whose commits
read as a security fix is not backed up: devkit suggests an embargo, anddev backup --publicpushes it anyway. - Draft pull requests early, CI once. With
delivery.draft_pron,dev pr createopens a draft unless
--ready, and a draft needs no local CI evidence where the workflows skip drafts.dev pr readychecks the
evidence for HEAD, then marks the draft ready, which starts its one CI run.dev ci auditflags workflows that run
every job on drafts or skip drafts withoutready_for_review, and--fixanddev ci initwrite the draft gate. - The push budget counts only pushes that start CI. devkit reads whether a push starts a run, and counts it on
any doubt. dev task startlinks the task to the branch it runs on, in the private handoff, so task ids stay out of branch
names.
Commit messages
- One template for every commit:
config/git/commit-template.txt, with the header, why, what changed, and how it
was verified, then theRefs:andBREAKING CHANGE:trailers.dev commit --why "…" --verified "…"writes it,
--body(repeatable) adds what changed,--refsand--breakingadd the trailers, andRefs:comes from the
ticket of the task started on the branch. A message that names a devkit task id is refused. - The template in your editor:
dev setupasks whether new commit messages open with it, the git step of
dev installsetscommit.templatein each repository that has none of its own, anddev setup commit-template
asks again (--removetakes it out). See Git and GitHub › Commits.
The terminal
- Project aliases:
dev alias <alias> [project],dev alias rm <alias>, anddev aliasto list them, shared
with the team through the handoff repository. Names match by exact id or alias, then repository name, then start,
then any part; a tie lists every match with its command instead of guessing.dev status,go,open,
wt new --repo,claude, andcodexaccept them, sodev status devkitworks from any folder. - A new
dev status: it shows Needs you first, then Right now, the last update in full, details, and the footer. It wraps
at 100 columns, fits 80, and reads the same withNO_COLOR;--jsonreturns the same data. dev configis a report: each difference says whether it is new in this devkit version, changed outside
devkit, or removed outside devkit, and names the fix.dev config --checkprints one line and exits 1 on a
difference.- A devkit helper in your shell prompt, if you want it:
dev setup promptasks first, in your own terminal only
(an agent's call changes nothing), anddev installasks once. Inside a devkit project it shows the project's
alias, how many crew members are working, your branch's checks, and a question that waits for you; outside, nothing.
Nothing runs when the prompt is drawn: the hooks (a tool call at most every 5 seconds; a prompt, the end of a turn,
and a member that starts or stops at once),dev status,dev alias,dev prompt refresh, and CI watch results
write its facts to a cache, which a zsh function reads (0.13 ms per prompt, measured). The function reads the cache
only when it is a regular file of yours that nobody else can write, and takes only digits from it as numbers.
Members count while their heartbeat is under 15 minutes old, the checks hide when you leave their branch, and after
24 hours without a refresh only the alias stays. Starship gets a marked block instarship.toml, saved first; plain
zsh gets devkit's own block, so~/.zshrcis not edited; oh-my-posh and Powerlevel10k get snippets.
dev setup prompt --removetakes it out, anddev promptshows what it shows here. See
The prompt helper. dev config set <key> <value>changes one key in a terminal: it validates the value, writes the file
atomically, prints the old and the new value, and recordsdev.config.setin the audit trail. Agents are refused.- devkit keeps the whole status block of a final message (up to 8,000 characters), not its first 700.
- Shell completion covers every command and the verbs of
dev task,progress,crew, andagents. dev doctorchecks that the skills the crew names are installed for each agent. The setup wizard offers optional
skill groups for the tools you pick, such asiacfor Terraform.dev sessionshows and manages what devkit keeps of a session through compaction,/clear, and resume:
briefprints it (--latestfor the project's newest session with an open run),carrymoves the run into this
session after/clear,compactions <transcript>counts a Claude Code transcript's compactions, andforget
deletes the records.brief,carry, andforgetare the tech lead's. See Continuity for the hooks that fill
these records.
Disk
dev duexplains what fills your disk. For each project on this Mac: the main checkout, managed worktrees,
Claude Code and Codex worktrees, and copies outside the layout, each with its largest ignored folders. Then
Colima's disk and the space macOS has not got back, agent data and caches with whether each is safe to clear, and a
plan to free space, ranked by size, with each item's safety, risk, and command. It deletes nothing, and answers in
under 2 seconds from its cache (--refresh,--plan,--json, or one project by name). See
Disk use.dev free <n>frees items of that plan by number, or every safe one with--safe. It lists what it deletes,
asks once, checks again at that moment for changed files, unpushed commits, and programs working in the folder,
and deletes nothing when a newer measurement changed the plan you saw. It keeps a build folder that holds files git
tracks, never prunes Docker volumes, and records every deletion in the audit trail.dev docker trimgives Colima's free space back to macOS without deleting anything.
The audit trail
- Schema v2: every record has a sortable id, who acted (and the crew member, lane, and launch), the project,
branch, run, and step, a category and severity, the reason for an override, and its evidence. Older records still
read. See The audit trail. - A hash chain: each record is linked to the one before it, and
dev audit verifyreports the first edited,
removed, or inserted record, using the published copy as the anchor. - Retention you set:
audit.retention.local_months,team_months, andfloor_months,audit.holdfor a legal
hold, andaudit.level(security,changes, orall). A team policy in the handoff repository can only raise
them. - Queries and exports:
dev audit show,stats, andconfig, filters by date, project, member, category,
severity, outcome, and text,dev audit exportas JSONL, CSV, OCSF, or CEF, andaudit.forwardto a file or
syslog. - Personal data: the audit trail page says what is recorded and never recorded, who receives it, how long it is
kept, and how the people recorded use their GDPR rights.
Changed
- A first
dev setupon a Mac with no projects asks which languages to set up, with Python and Node preselected,
instead of installing Java, PHP, Node, and Python without asking. - Claude Code:
attribution.sessionUrlisfalse, so cloud and Remote Control sessions add noClaude-Session
trailer either; the deprecatedincludeCoAuthoredBykey is removed; andBASH_DEFAULT_TIMEOUT_MSis 5 minutes,
so a test suite or a build in the foreground is not cut off at 2. - Codex:
analytics.enabledisfalse.dev doctoralso reads whether your Codex account adds commit and PR
attribution (an account setting, not aconfig.tomlkey) from your newest session. dev doctorreads Claude Desktop's own switch for bypass mode in the Code tab (Settings → Code → Allow bypass
permissions mode) and says whether it is allowed, off, or not offered for the signed-in account.dev updatefollows releases: a checkout at a release tag moves to the newestvYY.MM.PATCHtag (compared as
numbers, so 26.11.10 is newer than 26.11.2) and then runsdev install; at the newest release already, it says so
and changes nothing. A checkout on a branch still getsgit pull --ff-only. It refuses, with nothing changed, while
tracked files have local changes or when the checkout is at a commit that is neither a release nor a branch.- The wizard's line prompts say so when no terminal can answer and every question takes its default. Without a
GitHub sign-in, the wizard says why it needs one and prints the exact command. - The PostToolUse hook shows the status block right after a call that usually ends a turn (a subagent launch, a
monitor, a background command, or a closingdevcommand), with the project and branch filled in. A note
written after the last tool call no longer lands before the block, so the Stop hook does not have to send
the turn back. - Lessons are recalled by what a call does. A session gets the catalog of kinds of work, skills, and lesson
anchors at its start. A tool call is reminded of the lessons anchored on its command or file, and its output of
those whose error signature it shows, each at most once an hour; every refusal names the lessons of the call it
refuses.dev sleepmerges lessons that share anchors, and with background AI on (ai.*, opt-in, with a daily
budget), a small model also merges lessons written in different languages. - Skill rules trigger on files, commands, and declared kinds of work, and a turn counts as development work from
what it did, never from your words. - The dashboard counts a run as working while the run or any of its crew lanes reported in the last 30 minutes,
"of about" is the plan's current total (active time plus the time left), lists show a step's title without codes
such as F4, and a member's step that stopped without evidence shows as unverified, for the tech lead to check, never
under Needs you. - Fewer turns sent back. Before the end of a turn, and after every commit, devkit lists the end-of-turn items
still open (the handoff note, required skills, tests that cannot fail, untracked stubs), each once per turn, so the
agent settles them before the Stop hook would. The handoff gate sends a turn back only at
handoff.block_after_commits(5) commits newer than the note, when the oldest ishandoff.block_after_minutes(60)
old, or after a milestone: the end of a run, a work item closed, a push, a pull request, or a release. An
intermediate step is not a milestone, a milestone counts only the commits made before it, and while crew members
work the main session gets the reminder only. Each send-back is audited asstop.blockand each item settled after
a reminder asstop.prevented;dev canaryopens with the turns sent back per day and rule. Codex gets the same
reminder after a shell call, not verified live yet. - devkit's own test suite is hermetic. Run it as a package,
python3 -m unittest discover -s tests -t .:
tests/__init__.pygives the run a temporary home and refuses, and records, any access to your real devkit state,
configuration, install, handoff repository, or agent homes. CI, the contributing guide, and the docs use that
command, and the consistency checks keep them on it. - Estimates are rounded to 5 minutes, and to the minute under 10 minutes, on the dashboard and in
dev progress:
of about 2h00m, not 1h59m. Measured times stay exact. - Each hook reconciles its session's own run: a member that stopped without saying so, a lost launch, or a run whose
session ended is marked as such, so the run, its slots, and the dashboard stay true. dev doctor's fix for a full disk namesdev free.
Fixed
- The audit trail's copy in the handoff repository never grows past 45 MB in one file: a month that would pass it is
held, with a warning in the trail and indev doctor, instead of growing toward GitHub's 100 MB limit and stopping
every handoff push. Daily, compressed audit files replace the monthly ones in 26.11.5. dev installno longer stops at the skills step on a fresh clone or a release archive: git keeps no empty folder, so
devkit's ownagents/skillsfolder is missing there, and the step now links the third-party skills without it.install.shworks on Intel Macs: it finds Homebrew in/usr/localas well as/opt/homebrew, and runs the wizard
with Homebrew's Python frombrew --prefixinstead of a fixed/opt/homebrew/bin/python3. On Apple Silicon, it adds
Homebrew to~/.zprofilewhen Homebrew was not on thePATH, so new terminals findbrew,gh, and the toolchain.
The shell profile anddev setupalso find Java and Docker's CLI plugins under Homebrew's real prefix.- Hooks and
devcommands no longer lose each other's changes: one lock per session covers its session and run
records, so of 8 crew questions asked at once, all 8 are kept (it was 1), and an ended session no longer comes back. - Crew members launched together no longer swap names, lanes, or steps.
- A step assigned to a member who is already working waits for its dependencies instead of starting.
- The Stop hook waits while crew members are still working on a plan, instead of sending the tech lead back each
turn. - Crew message and decision ids stay unique past 200, so an answer no longer reaches the wrong member.
- A crew member working in a worktree of the same repository can edit the files of its scope.
- Read-only crew commands (
graph,show,raci), commit messages, and heredocs that only mention a lane command
are no longer refused to members. - The prompt hook no longer logs an error on every prompt and loses the turn's class.
- A reply with no tool calls (a status question, "continue") counts as the previous turn's kind, so a missing status
block there is scored. dev doctorinforms, instead of failing, about a crew skill from an optional group you have not turned on.- The
devkit_audittool shows who acted again, anddevkit_task_updatesays that it changes tasks and that only
the audit trail, not the guard, covers it. dev statusshows a saved status block's Crew and You lines on their own rows and wraps long values.- The irreversible-action gate's audit record failed on every write, so a crew member got the gate's error text
instead of its refusal. Records are written now, and a record that fails cannot change the gate's decision. - Review and read-only members can run
dev test prove, which works in a temporary copy of the checkout. - The Accountable or a Consulted member of a kind of work could take it without
--whyand then approve it. Only
the Responsible member takes it now; the others need--why, which is recorded. dev gc <n>is recorded in the audit trail as a deletion, while listing aliases and printing the plan to free
space are not recorded, because they only read.- Review readiness. A review step waited forever behind a member's unverified step, which only that review could
approve. A review step now starts on unverified work, and its Check ✓ ends done the steps it follows that its
member approves; every other step still waits for done or skipped. One rule tells a review step everywhere: its
kind of work is review, or its member works review-only. - Step binding. A step assigned to a member whose lane was still running could close done when that lane ended,
with none of its work. A lane's ending now closes only the steps its evidence is about: the step its launch names,
a step itsdev progress step --step "<name>"names, or one its report names. Its other steps go back to pending. - A file that a working member changed during a review member's shell call no longer counts against the reviewer:
it is flagged as possible, and the message names the member whose scope holds it. grant unknown cmd-<hash>, which a refusal of a command the guard cannot name asks for, recorded nothing, so the
command could never run. The grant opens that one command, once.- A decision's options reached no audit record, so every answer read as free text. Records now keep the option an
answer names. dev test,dev test prove, anddev ci --run --resumerun a test folder that is a Python package from the
repository root, so its__init__.pysetup runs.dev stubsneeds the stub word and its time word in one clause, so a comment that says nothing is stubbed is not a
finding.- The status block that
dev progress stepprints rounds estimates like the dashboard. - A member's
dev crew askordev progress stepwhose message comes from a quoted heredoc reaches its lane
instead of being refused.
Security
- devkit trusts only its own Codex hooks. Before, it told Codex to trust every new hook in
~/.codex/hooks.jsonat
each session start and every 6 hours, so a hook an agent wrote there would later run outside the guard. Now a hook
counts as devkit's only when it matches exactly what devkit renders (event, matcher, command, timeout); any other
hook stays untrusted, anddev doctorlists it among the hooks devkit did not write. - The guard sees what a command really runs: through wrapper flags that take a value (
nice -n 5,env -u X,
sudo -u me,exec -a x), interpreter flags (python3 -u bin/dev), arithmetic shifts that looked like heredocs,
git and gh aliases, shell scripts run by their path, andgit push --repo=<url>.env -Sis refused, because the
guard cannot see the command it runs. - Writes with a relative path from devkit's state or configuration folder, or from a folder that holds them, are
refused. - A
WebFetchURL that carries a secret is refused. - Your approvals cannot be forged. devkit reads your answers and grants only from the session's own transcript,
where Claude Code writes it; an event that names another file records nothing and is audited as
crew.evidence-refused, and a prompt or answer replayed through a hook counts once. Agents cannot write, move,
or delete Claude Code transcripts or Codex sessions. A program an agent runs that loads devkit's code to reach these
functions or devkit's state is refused, also when it loads them through the agent's own files (three levels deep)
or through code decoded at run time. On Codex, devkit reads no transcript yet, so a grant or an answer you type
there opens nothing: run irreversible actions on Codex yourself, in a terminal. - A "no" never opens an irreversible action. A decision that leads to a release, merge, push, or deploy opens it
only when your answer chooses the option that performs it (--performs, else the one option that reads yes or
approve, else the recommended one); before, any verified answer opened it,approve D1: noincluded. Any other
answer opens nothing and is audited ascrew.grant-refused, with the decision and the option, never your text.
dev crew askrefuses a--performsthat names an option reading as not doing it (B: no), and the question
you are asked names the choice that runs the action and its target:D1 · Release now? (choosing “A: release” runs release v26.11.4). - The irreversible-action gate sees more: the repository that
gh -R,--repo, orGH_REPOnames (so a grant for
one repository never covers another), commands run throughscript,watch, GNUparallel,sem,arch,
flock,unbuffer,chronic, oryarn workspace, targets thatxargsappends,curlmethods inside short-flag
clusters (-sXPOST), andnpm -w <pkg> publish. - A forged hook event can no longer end a working member's lane and free its slot.
- The audit redactor closes the 14 gaps a probe of 32 fake secrets found (among them names like
AWS_SECRET_ACCESS_KEY, quoted values,--passwordflags, PGP private keys, and Stripe, GitLab, Hugging Face,
Google OAuth, Docker, Slack, and Azure tokens), and also knows Bearer tokens, JWTs, npm and PyPI tokens, Google API
keys, and URL credentials. It also redactscurl -u,sshpass -p,mysql -p,docker login -p,
gh secret set --body,Authorization: token,passphrase=,credentials:, and a value piped byechoor
printfinto--password-stdinor--with-token. The redactor knows these shapes and no others: a secret in a
shape it does not know can still reach a record, so keep secrets out of commands. - Records hold less about people. Crew message text, decision questions, and the user name in home folders are left
out; a decision's answer is kept only when it names one of the options (otherwise its length), and your approval
lines only by their length. Records written before are cleaned the same way when read, anddev audit verifystill
checks them as stored. - The dashboard server checks the
Hostheader, sendsbase-uriandform-actionrules in its content security
policy, keeps its token out of process arguments, and reads files only inside the handoff repository. Search
results and the command palette open a link only after the page's URL check, so ajavascript:ordata:link in
the data cannot run, in the static export either. - The guard was hardened over three red-team rounds. Each way around it that a round found is closed, and a test
intests/test_red_team.pyortests/test_red_team_2.pykeeps it closed. The classes closed:- A command whose program or subcommand is known only when it runs is the
unknownaction: a crew member never
runs it, and the main session runs it once withgrant unknown cmd-<hash>, which the refusal names. - A command that git or gh hands to a pager is judged as the command it is, and agents may not write a pager or
any other git setting that runs a command (in any scope, from the environment, or in a repository's own.git
folder, whose config and hooks agents can no longer write). - A nested agent session that would run without devkit's hooks or sandbox is refused, also when a package runner
or a program's own code starts it, and agents may not pass a Codex profile. - Running one of devkit's hooks by hand, and
dev config lockandunlock, are refused from every tool call. - An MCP tool that merges, pushes, or approves counts as an external action, like one that creates or sends.
devflags are read the way devkit's parser reads them, so an abbreviation or a word after--hides nothing.- A heredoc that macOS's bash ends earlier than zsh fails closed, and text inside an interpreter's string literals
is no longer read as program names. - A backup is a push to the guard, granted per branch, and the push budget counts only pushes that start CI.
- A command whose program or subcommand is known only when it runs is the
- devkit runs isolated.
bin/devrunspython3 -I -S, and so does every devkit process it starts (hooks in
the background, the MCP server's calls, scheduled jobs, the wizard, the CI watcher, the dashboard server, the
Desktop launcher), so aPYTHONPATH, a planted module, a user site folder, or a.pthfile cannot load code into
it. The guard refuses Python's code-loading variables on a devkit call and on a nested agent session. - The gates fail closed. When the irreversible-action gate itself fails while it enforces, a command that names an
irreversible action is refused (guard.irreversiblewith a gate error), and so is an MCP call. A crew member's
shell command that devkit cannot check against its lane is refused instead of run unchecked. Other handlers still
fail open, with aguard.failopenrecord. - A grant a step uses for a push or a pull request covers only its own target pattern in its own repository.
- The dashboard server reads a project's branch map at most every 5 seconds and two at once, answering more with
429, so a client cannot start unbounded git reads. - An agent's push from a folder that is no project (a temporary clone, a folder made in the same command, one a
sourced file picks) is refused while any project has an embargo, and a push from inside a git folder, or through
env -Corsudo -D, is judged as that folder's project, so its embargo holds.
Known limits
- The guard is a seatbelt, not a sandbox. It catches an agent's mistakes and the common forms of prompt
injection, but a determined program can still find a form it does not recognize. Keep your own review; see
Guard rules › What the guard is and is not. - Developer grants on Codex are not confirmed yet. devkit reads no Codex transcript, so a grant or an answer you
type in Codex opens nothing: run irreversible actions there yourself, in a terminal. - Agents use your credentials. devkit works with the GitHub account you are signed in to with
ghand your own
tokens and keys; there is no separate identity for agents, by design. The guard and your grants hold the
irreversible actions. - An embargo holds pushes from its own project only. It holds pushes from the embargoed project, its git folders
and worktrees, temporary clones, and unknown folders; a copy of its commits in another project's folder is not
held yet (26.11.4).
Removed
- The word lists: skill rules no longer match your prompt (15 patterns removed), the prompt hook no longer looks for
corrections in it, anddev lesson scanno longer lists corrections. - The static-file-only
dev dashboard: the static page isdev dashboard --export <file>.