Repository navigation
v0.6.0
Added
- The package ships
py.typedand declaresTyping :: Typed; Python 3.14 is
a supported version, and the project metadata links the issue tracker. - A
yamlextra (pip install 'dotagents-cli[yaml]') installs PyYAML for YAML
overlay-repo registries; the error for a YAML registry without it names the
extra. dotagents env --cachereuses the previous output while the environment,
working directory, stores, overlays and env and lib files are unchanged, for
up to five minutes. The PowerShell and Codex env loaders use it, so a shell
command no longer re-runs every env file.- A project-scope
initpoints pi at the project's.agents/AGENTS.md
through a managed block in.pi/APPEND_SYSTEM.md. dotagents._resourcesholds the bundled base overlay (BASE_ROOT), the
block template constants andbase_agents_text; they are still importable
fromdotagents.cli._common.Agent.include_entryandAgent.base_config_notedescribe whatinit
writes for each harness.dotagents pathprints the bin dirsdotagents envputs onPATH
(--lib: the lib dirs it puts onPYTHONPATH), highest precedence first,
as a list,os.pathsep-joined,:-joined POSIX (/c/...on Windows) or
JSON, without running any env file.- An overlay's setup script is stopped after 300 seconds, or the manifest's
setup_timeout, oroverlays add/sync --setup-timeout;0means no
limit. A stopped script fails the install like any other failure.
Changed
- The license metadata is the SPDX expression
MIT(PEP 639). Building from
source needs hatchling 1.27 or later. install.pyinstalls its dependencies only into a virtual environment.
Elsewhere it lists the alternatives (a venv,pip install dotagents-cli,
the releasedotagents.pyz) and installs only with--bootstrap, which it
still refuses for an externally managed (PEP 668) interpreter.- The root
build.pyhelper is removed; usepython -m dotagents build-pyz.
Its bare-word argument parsing misread flags, and at the repository root it
shadowedpython -m build. tools/cloud-setup.shoffers the store token only to the store's own
remote, on its own git calls, and no longer writes a global github.com
credential helper to~/.gitconfig.launchwrites the assembled context to one file per agent and project
under<user store>/.cache/launch/, overwritten by the next launch, instead
of a per-process temp directory that a killed session left behind.findings removedeletes only active findings; a processed finding keeps
its resolution and must be reopened first.init,overlaysandfindingshonour a pinned$AGENTS_PROJECT_ROOT
only while the current directory is inside it. After acdout of it they
use the project the current directory is in (the nearest directory up with
a.gitor its own.agents) and warn; they used to write into the
session's first project.envandcontextkeep the pin.contextoutput on stdout and in JSON, and the contextlaunchhands
over, expand$<NAME>_OVERLAY_ROOTto the overlay's directory, so a
harness without the dotagents env can follow overlay routing. A file
written bycontext --write-agent, or merged bylaunch, keeps the
variable, because it may be committed.- The skills listing names each skill's
SKILL.md, and JSON skill entries
gain apathkey. - The base rule for a config miss ends at the findings queue: triage closes a
finding withdotagents findings done -g <name> -r "<resolution>", and the
resolution is the record. It no longer points atdotagents/DECISIONS.md,
and it says where a finding that reports a fact rather than calling for a
rule goes: akb/file routed from "Load on demand". An existing store picks the new wording up when its block is next rebuilt:
dotagents overlays syncin a store with overlays installed,dotagents initin one without. - Existing stores keep the files an earlier
initwrote. Delete
dotagents/DECISIONS.md,dotagents/README.md,dotagents/AGENTS.mdand
dotagents/cmds/README.mdif you no longer want them, keeping any decisions
you recorded wherever you keep notes. If you still keep a findings queue at
dotagents/findings/(the queue moved tofindings/in 0.4.0), move it;
until then everyfindingssubcommand reads it with--dir(dotagents findings list --dir <store>/dotagents/findings). - A project's root no longer contributes env files: a checkout's top-level
local.env/pre.local.envwere bash-sourced at every session start, so a
repository that committed one ran its commands in your session. Move your
local overrides to<project>/.agents/local.env(andpre.local.env), which
still resolve. A project's.agents/itself stays trusted, like a
harness's own.claude/settings.json; the install guide now describes what
runs from where. - A project
initwrites a minimal block into<project>/.agents/AGENTS.md
(a Startup line and empty sections for the project's overlays) instead of a
copy of the user store's rules, which every session then read twice. Existing
project blocks switch on the nextinitoroverlays add/remove/
syncin that project. Anoverlays addinto a store with noAGENTS.md
creates the block; it used to install the files and merge the routing nowhere. - On Windows, the Claude Code PowerShell-tool env loader is opt-in:
init --powershell-env-hook. It returnspermissionDecision: "allow", the only
documented way to rewrite a command without prompting on every call, so it
auto-approves every PowerShell tool call;init -gwired it silently. A
plaininitremoves one an earlier release wired. - The system store is walked only when it exists and only administrators can
write it: on POSIX/etc/agents(or$AGENTS_SYSTEM_ROOT) must be
root-owned and not group- or world-writable; on Windows there is no default
(/etc/agentswas drive-relative, and any local account could create it) and
$AGENTS_SYSTEM_ROOTmust be an absolute path whose ACL grants write only to
Administrators, SYSTEM or TrustedInstaller. A system store that fails the
check is skipped with a warning; a missing one no longer puts itsbin/on
PATH. overlays add,syncandremovelink new skills into Claude's skills
directory and remove the ones that are gone, wheninithas already wired
Claude for that store. On Windows, a skill is linked with a directory
junction before falling back to a copy.init --dry-runreports what it would do ("would create …", "would refresh
the block …"), including the wrapper scripts and the recorded base.dotagents envalso lists the overlay and storelib/directories it puts on
PYTHONPATHinAGENTS_PYTHONPATH, and after acdinto another project it
takes the previous project's libraries offPYTHONPATH.- Overlay setup scripts run with the scope's assembled
dotagents env(every
overlay'slib/onPYTHONPATH,bin/onPATH), and command modules can
import any overlay'slib/, even whendotagentsruns from a plain shell. - An
env.pyvalue must be a JSON string:nullunsets the variable, and any
other type is skipped with a warning naming the key.dotagents envemits
unset variables where the format has a way to (unset,set -e,
$null,set "K=",null). env.pyis run asenv.py --level <level>;--agent <level>is still
passed for existing scripts.- In the Python API,
get_environmentandget_diffreturn anEnvChanges
(still a dict of the variables set) whoseremovednames the variables a
layer unset, andget_env_from_pyno longer takesproject_root; its
levelandglobal_scopeare keyword-only. dotagents env --format yamldouble-quotes every value;iniis written for
Python's configparser anddotenvfor python-dotenv.- Each installed overlay keeps a record of the repo it came from and the files
it installed.overlays syncfetches it from that repo again, not from
whichever repo now offers the name first;--reporeplaces the recorded
source. overlays syncrefreshesoverlay.toml, reports files that differ from the
source as kept, removes files the source dropped when they are unmodified
(--prunefor edited ones), backs up whatever--overwriteor--prune
replaces, and installs requirements added upstream.overlays removerefuses an overlay another installed overlay requires,
unless--force.overlays listandshowflag unmet requirements, and
shownames the recorded source.- Overlay setup scripts get
AGENTS_HOMEset to the user store, plus
AGENTS_SCOPE_ROOTandAGENTS_SCOPEfor the store they are installed into. - A dot in an overlay name normalizes to
-like an underscore; names must end
in a letter or digit, and Windows device names are refused. - Overlays come only from
--repo, the environment repos and the stores'
registries; the bundled-overlays source tier is gone. - Overlay manifests are read with
tomllib/tomliwhenever one is available. - The downloadable
dotagents.pyzis compressed: about 0.46 MB instead of
1.4 MB. build-pyzvendors only pure-Python wheels, resolved for Python 3.9, so the
pyz no longer depends on the machine that built it. An extra that needs
native modules (sftp) fails the build with a message saying so.- The package version is kept only in
dotagents.__version__;
pyproject.tomlreads it from there. overlays add,removeandshowwithout an overlay name are a usage
error (exit 2).tools/cloud-setup.shreadsAGENTS_OVERLAYS_REMOTEand
AGENTS_OVERLAYS_REF; the oldDOTAGENTS_OVERLAYS_*names still work when
the new ones are unset.- The findings index is rewritten atomically.
- A
---frontmatter block at the top of an overlay'sCONTEXT.mdis left
out of the assembled context;overlay.tomlis the only manifest.
Removed
initwrites nodotagents/directory into a store: the base config is the
AGENTS.mdmanaged block, plus the Claude include and the agents' hooks.
Gone aredotagents/DECISIONS.md(the per-install design log),
dotagents/README.md,dotagents/AGENTS.md, and the empty
dotagents/cmds/with its README. A scope'sdotagents/cmds/is still where
your own command modules go; create it when you add your first one (the
docs' authoring guide shows how).init --agents codexno longer writes a static[shell_environment_policy]
snapshot into~/.codex/config.toml: it pinned the projectinitran from
into Codex's global config and could leave the file unparseable. Codex gets
the env from itsPreToolUsehook, live. The nextinitthat wires Codex's
hooks removes a block an earlier release wrote and leaves the rest of the
file alone.Overlay.apply_toandOverlay.merge_rules_into; use
recompose_overlay_block.Scope.system_store(useScope.system_root) andScope.cmds_dir.dotagents._scope.OverlaySource; usedotagents._sources.DirRepo.- The
src,base_agents_textandforceparameters of
Agent.write_base_config, and theforceparameter of
Agent.write_context. - The
dotagents.clire-exports ofAGENTS_DIR_ENVandBASE_ROOT; import
them fromdotagents._scopeanddotagents._resources.
Fixed
- A session started in the home directory walks the user store once; it ran
everyenv.pytwice and sent everyAGENTS.mdandCONTEXT.mdtwice.
initandoverlaysrun from the home directory target the user store
instead of writing a project block over it. contextorders overlay sources the way the managed block orders overlay
rules: priority, then manifest name, then directory. An overlay with a very
high priority no longer sorts after the store'sAGENTS.md.- The skills listing lets a project skill override a same-named user skill,
reads only the leading frontmatter, and joins a folded or literal
description instead of showing>. context --inlineinlines files referenced through
$<NAME>_OVERLAY_ROOT,${<NAME>_OVERLAY_ROOT},<NAME_OVERLAY_ROOT>and
<PROJECT_ROOT>; resolves each source's references against its own
directory; searches the project store for the project's references; and
never resolves a user-store reference into the project.contextwith several agents and an output file is an error instead of
keeping only the last agent.--agentsthat names no known agent exits 2,
harness ids such asclaude-codeare accepted, and an empty result gets no
system-reminder wrapper.--agents-dirafter--(an argument for the harnesslaunchruns) no
longer changes which command modules are discovered, and a project store
named with--agents-dirno longer replaces the user store's commands.- A command module that imports but whose parser cannot be built (an
unresolvable annotation,X | Noneon Python 3.9, a duplicate flag, or a
flag the umbrella owns) no longer breaks everydotagentsinvocation; it is
skipped with a warning naming its file. - Inside the
.pyz, a new built-in command can no longer lose its flags and
help to a hand-kept module list. findingsno longer fails on a note that is not UTF-8 (it is skipped and
left untouched), a UTF-8 BOM no longer hides a finding's frontmatter, and
--body-file -/--resolution-file -read stdin as UTF-8 instead of the
Windows ANSI code page. Paths print as UTF-8, so a non-Latin-1 path no
longer fails after the file was written.findings addrefuses the namesindexandreadme, which overwrote the
finding with the index on a case-insensitive filesystem, anddoneand
reopenno longer overwrite an existing file at the destination.launchexits 128+N for a harness killed by signal N, instead of 256-N.- On Windows,
launchrefuses arguments that cmd.exe would run or expand for
a.cmdor.batharness (& | < > ^ % ! "or a newline) instead of
passing them on rewritten. - The
init,overlayssubcommand,aboutandlaunchsummaries in
--helpare whole sentences. - Private
*.local.*andCLAUDE*files in a source tree no longer reach the
wheel, the sdist or a locally builtdotagents.pyz. tools/cloud-setup.shno longer deletes an existing~/.agentsthat is not
a git checkout (it moves it aside and prints where), refuses to rewrite a
~/.claude/settings.jsonit cannot parse, shows pip's errors, and removes
its recovery hook once the store is cloned or pulled.- The docs site redeploys for each release and after a changelog-only change.
- A release refuses to publish when its tag does not match the version it
built, and re-running a partially uploaded release no longer fails. - The Windows PowerShell handlers that
initadds beside Claude Code's bash
hooks decide whether to run the way Claude Code decides which shell to use.
They checked forbashon PATH: a default Git install (onlyGit\cmdon
PATH) got the context twice, and a box with WSL'sbash.exestub and no Git
Bash got none. - The Claude Code and Codex hooks run
dotagentsby path instead of putting
.agents/binand the store'sbinon PATH, whichenv --diffthen
persisted into the session: after acdthe first project'sbinstayed
ahead of everything. - The PowerShell env loader (
init --powershell-env-hook) runs only for
PowerShell tool calls, not before every tool call, and readsdotagents env
as UTF-8: a non-ASCII value arrived garbled. - Re-running
initkeeps keys you added to a dotagents hook entry (a
timeout, say) and no longer deletes malformed hook entries from your
settings. dotagents' hooks are labelleddotagents: ..., so an unrelated
hook with the same generic label is no longer mistaken for one of them. - A
bin/dotagentswrapper run through a symlink finds its.pyzbeside the
real file, anddotagents.cmdworks when the Python interpreter's path is
not ASCII (a user folder with an accented name, say). - Re-running
initon a store with overlays installed keeps their rules and
routing inAGENTS.md's managed block; it used to rewrite the block from the
bare base until the nextoverlays sync. - A base chosen with
init --fromis recorded in
<store>/dotagents/config.toml, and a later plaininitand everyoverlays add/remove/synccompose over it; they used to switch back to the
bundled base. Delete the file'sbaseline to return to the bundled one. init --forcekeeps the original of every file it replaces. Adapters that
write the same file in one run share oneinstall_backup/<timestamp>/, a
backup is never overwritten, and a file outside the store is backed up under
external/at its own path instead of over a same-named one. pi's own
AGENTS.mdis block-merged even under--force, like Claude's include.- Adding an overlay's routing no longer deletes the base block's line about a
named agent's~/.agents/<agent>.md. - The managed-block merge ignores marker lines inside fenced code (an example
of the markers in your notes no longer pairs with the real block), and finds a
block behind a UTF-8 byte-order mark instead of adding a second one. - A checkout's own top-level
dotagents/cmds/is no longer a command source;
only the stores'dotagents/cmds/(and overlays'cmds/) are. initfrom a plain (pip) install writes<store>/bin/dotagents[.cmd]
wrappers running"<python>" -m dotagents; it wrote none, and on Windows the
PowerShell hooks called a<store>\bin\dotagents.cmdthat did not exist, so
PowerShell sessions got no env and, without bash, no context. Wrappers left
pointing at a.pyzare replaced, with a warning. The PowerShell hooks also
fall back todotagentsonPATHand do nothing when there is none.contextfor Claude includes a project's committed rootAGENTS.mdwhen a
CLAUDE file (such as the.claude/CLAUDE.mda projectinitwrites) stops
Claude from reading it itself; it used to assume Claude always read it, so
the file reached neither. Claude's AGENTS.md is counted as loaded only when a
CLAUDE file@-includes it or none exists at or above its directory.- The Claude and Codex hooks put the project's
.agents/binonPATHas an
absolute path. The relative.agents/binthey used was re-emitted into the
session'sPATHbydotagents env, where it resolved against whatever
directory a later command ran in. Re-rundotagents initto update the hooks. - Codex's SessionStart hook runs
dotagents context --agents codex; without the
flag it assembled Claude's context and gave Codex nothing. It is now a small
Python script, like the PreToolUse one: on native Windows the shell line ran
as cmd.exe'sPATHbuiltin and did nothing. Both Codex hooks run under the
interpreterinitran with, not a barepython3/python. - Codex's PreToolUse env loader no longer breaks every shell command on native
Windows: Codex runs PowerShell there, which cannot parse its POSIX prefix, so
the hook now passes commands through unchanged (Windows Codex sessions get the
context, not the live env). Re-rundotagents init --agents codexto update
the hooks. launchno longer merges your context into a harness's instruction file that
git tracks, or under-g: for an agent with no append flag (Codex, Gemini,
Cursor, Copilot, pi on Windows) it wrote the user store's rules into a usually
committedAGENTS.md/GEMINI.md/.cursorrules. The context stays at
$AGENTS_CONTEXT_FILEwith a warning;launch --write-agentmerges it anyway.
The harness is resolved first, so a launch that fails with "not found" writes
nothing.context --write-agentrefuses-g.- The Claude
CwdChangedhook quotes the directory it pins into
$CLAUDE_ENV_FILE: a'in a directory name broke every later Bash command
of the session, and a crafted name ran commands. Re-rundotagents init. env --format powershelldoubles every character PowerShell reads as a single
quote ('and U+2018–U+201B): a’in a value ended the string, and the rest
ran as code in the PowerShell loader. A variable whose name contains}or a
backtick, which${env:…}cannot hold, is left out.- Plain env files under a path with non-ASCII characters,
$or backticks are
sourced; they were silently skipped (and$/ backticks in the path expanded). envwithout--diffno longer prints inheritedDOTAGENTS_*values, the
tool's own secrets.- A git overlay spec whose ref or location starts with
-is rejected: it was
passed to git as an option (@--upload-pack=<command>ran the command). initwrites the store'sAGENTS.mditself, whatever agents are named;
with--agents gemini,cursor,copilotit wrote none, and putGEMINI.md,
.cursorrulesand.github/copilot-instructions.mdinside the store, where
no harness looks. Gemini CLI now gets an@import of the store's
AGENTS.mdin~/.gemini/GEMINI.md(or the project'sGEMINI.md); Cursor
and Copilot get the context throughcontext --write-agentorlaunch. An
unknown--agentsname is an error instead of a warning.- Adapters are told the scope
initresolved instead of guessing it from
$AGENTS_HOME:init -g --agents-dir <dir>now writes Claude's include and
hooks to~/.claude, not beside<dir>. Claude's config goes to
$CLAUDE_CONFIG_DIRwhen that is set. - A project-scope
initno longer edits Codex's or Antigravity's global hook
config (it turned dotagents on in every workspace); runinit -gfor them.
Antigravity's hook runs under the interpreterinitran with. context --write-agent/launchwrite Cursor's context to
.cursor/rules/dotagents.mdcwithalwaysApply: true(.cursorrulesis
legacy), and Cursor's and Copilot's own reading of the project'sAGENTS.md
is no longer sent twice.- Claude's
@imports are followed the way Claude reads them: anywhere on a
line outside code spans and fences, at most four hops deep, and in the CLAUDE
files of the project root's ancestors too, so neither an inline import is
sent twice nor a fenced example dropped. envstamps no agent identity in a plain shell: a repository with an
AGENTS.mdmade it exportAGENT=codexto any shell that sourced it.- The Claude include is skipped when the entry file already includes the same
file under another spelling (@~/.agents/AGENTS.md, an absolute path). - A project
initwarns when it writes the Claude include (or Gemini's) into a
file git does not ignore. tools/cloud-setup.shinstallsdotagents-cliby default; thedotagents
name it used is not this project on PyPI.overlays add/syncnever delete a skill you placed or edited in the
sharedskills/dir. A same-named skill already there is kept, with a
warning; a published copy you edited is kept onsyncunless you pass
--overwrite, while an untouched copy still follows its overlay (the digest
of each copy is recorded inskills/.dotagents-published.json).- An overlay installed from a whole repository no longer copies the clone's
.git, nor tool caches (__pycache__,.mypy_cache,node_modules, …),
into the store.overlays removedeletes read-only files (git objects on
Windows) and unlinks a symlinked overlay instead of failing half-way; an
overlay that already carries a.gitcopy is removed cleanly. dotagentswith no subcommand logs its hint instead of raising when no
parser has been built.dotagents envputs the dotagentsbindirectories at the front ofPATH
in their precedence order even when the calling shell already had some of
them, and drops empty and relativePATHentries, which resolved against
whatever directory a later command ran in.init --fromaccepts the forms the docs list: a dotagents checkout, a
file:,http(s):,sftp:,s3:orzip:URI, and a git repository
(repo[@ref][#path]). Remote sources are fetched into the overlay cache,
failures are one-line errors instead of tracebacks, and the recorded base
never stores credentials from the URL.- Writing
settings.jsonorhooks.jsonkeeps a symlinked file a symlink and
updates its target, and keeps the file's permissions. initaccepts asettings.jsonsaved with a UTF-8 byte-order mark, and a
corrupt settings file stopsinitbefore it writes anything instead of
leaving a half-initialised store.- On Windows,
dotagents launchnever runs a harness from the current
directory (aclaude.cmdat a repository's root, say). dotagents launchno longer passes the harness a variable an env layer
unset;--dry-runlists them on anunset:line.- A skill copied into Claude's skills directory is refreshed when the overlay's
skill changes (it was reported as a conflict and stayed stale), and removing
an overlay no longer leaves a dangling link or stale copy of its skills. - A project-scope
initwarns when skills it links into.claude/skills/are
not gitignored. - On Python 3.9 and 3.10,
tomliis installed as a dependency and bundled in
the pyz, so overlay manifests and TOML registries are read by a real TOML
parser. - The pyz no longer ships pip's
bin/launchers, which carried the builder's
interpreter path, and filesbuild-pyzgenerates are LF on every OS. - Plain env files are sourced by Git's bash on Windows, not the WSL launcher,
which dropped them whenever WindowsApps came first onPATH. - Git Bash's own rewriting of
PATH,HOME,TEMPand similar variables is
no longer reported as an env file's changes, and aPATHan env file
extends comes back in Windows form. - A malformed
env.py(output that is not UTF-8, a key with=, a value with
NUL, or any exception) no longer crashes the whole env assembly. dotagents env --agents-diremits the store it actually walked as
AGENTS_HOME, and emitted roots are always absolute.- The export format uses plain POSIX single quotes for every value, including
ones with control characters. PATH-shaped values are converted between Windows and POSIX form only on
Windows, so pwsh on Linux keeps itsPATH.- Values in the yaml, ini and dotenv formats read back as given.
- A login fish shell is detected on macOS.
- On Windows, the system-store permission check works when dotagents runs from
PowerShell 7, and runs System32's PowerShell rather than one found in the
current directory. - A repo that cannot be loaded is an error instead of "overlay not found":
syncno longer skips with success,addno longer installs without a
dependency, andlistwarns per broken repo. A malformed or non-UTF-8
registry gives a clean error instead of a traceback. - Credentials in an http(s) registry URL no longer appear in a traceback; they
are sent as Basic auth and never forwarded on a redirect. URL query tokens
are masked in messages, cache directory names never contain credentials,
and cached git checkouts do not store them in.git/config. - The source cache under the user store is ignored by git, so a store kept in
git never records a cached checkout. - An
@in a local path or non-git URL is kept; a#in a store path no
longer breaks registry loading; relative git entries and relative entries
of s3, github and zip registries resolve beside their registry; the
standard-library http fetch honours#path. - Manifest escapes, underscored integers and
[table]sections are read
correctly;requiresnames andrulespaths can no longer point outside
the overlay; an unreadable rules file is a warning instead of a crash that
blocked every lateraddandsync. overlays addrolls back a new install whose setup fails and updates
AGENTS.mdfor what did install;overlays removeunpublishes skills only
after the overlay is deleted and always updatesAGENTS.md.overlays addandoverlays syncrefuse a source inside the store's own
overlays/directory, where a laterremovewould delete the only copy.- An
overlaysdry run says it would recompose or createAGENTS.mdinstead
of reporting it as done. - On Windows,
initnames the PowerShellPreToolUsehook only when
--powershell-env-hookwired it. - Overlay routing lands before the managed block's real end marker even when
the base template shows the marker inside a code fence.
Full Changelog: v0.5.1...v0.6.0