Skip to content

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 24 Sep 17:17

Added

  • The package ships py.typed and declares Typing :: Typed; Python 3.14 is
    a supported version, and the project metadata links the issue tracker.
  • A yaml extra (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 --cache reuses 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 init points pi at the project's .agents/AGENTS.md
    through a managed block in .pi/APPEND_SYSTEM.md.
  • dotagents._resources holds the bundled base overlay (BASE_ROOT), the
    block template constants and base_agents_text; they are still importable
    from dotagents.cli._common.
  • Agent.include_entry and Agent.base_config_note describe what init
    writes for each harness.
  • dotagents path prints the bin dirs dotagents env puts on PATH
    (--lib: the lib dirs it puts on PYTHONPATH), 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, or overlays add / sync --setup-timeout; 0 means 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.py installs its dependencies only into a virtual environment.
    Elsewhere it lists the alternatives (a venv, pip install dotagents-cli,
    the release dotagents.pyz) and installs only with --bootstrap, which it
    still refuses for an externally managed (PEP 668) interpreter.
  • The root build.py helper is removed; use python -m dotagents build-pyz.
    Its bare-word argument parsing misread flags, and at the repository root it
    shadowed python -m build.
  • tools/cloud-setup.sh offers 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.
  • launch writes 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 remove deletes only active findings; a processed finding keeps
    its resolution and must be reopened first.
  • init, overlays and findings honour a pinned $AGENTS_PROJECT_ROOT
    only while the current directory is inside it. After a cd out of it they
    use the project the current directory is in (the nearest directory up with
    a .git or its own .agents) and warn; they used to write into the
    session's first project. env and context keep the pin.
  • context output on stdout and in JSON, and the context launch hands
    over, expand $<NAME>_OVERLAY_ROOT to the overlay's directory, so a
    harness without the dotagents env can follow overlay routing. A file
    written by context --write-agent, or merged by launch, keeps the
    variable, because it may be committed.
  • The skills listing names each skill's SKILL.md, and JSON skill entries
    gain a path key.
  • The base rule for a config miss ends at the findings queue: triage closes a
    finding with dotagents findings done -g <name> -r "<resolution>", and the
    resolution is the record. It no longer points at dotagents/DECISIONS.md,
    and it says where a finding that reports a fact rather than calling for a
    rule goes: a kb/ file routed from "Load on demand". An existing store picks the new wording up when its block is next rebuilt:
    dotagents overlays sync in a store with overlays installed, dotagents init in one without.
  • Existing stores keep the files an earlier init wrote. Delete
    dotagents/DECISIONS.md, dotagents/README.md, dotagents/AGENTS.md and
    dotagents/cmds/README.md if 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 to findings/ in 0.4.0), move it;
    until then every findings subcommand 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.env were 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 (and pre.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 init writes 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 next init or overlays add / remove /
    sync in that project. An overlays add into a store with no AGENTS.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 returns permissionDecision: "allow", the only
    documented way to rewrite a command without prompting on every call, so it
    auto-approves every PowerShell tool call; init -g wired it silently. A
    plain init removes 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/agents was drive-relative, and any local account could create it) and
    $AGENTS_SYSTEM_ROOT must 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 its bin/ on
    PATH.
  • overlays add, sync and remove link new skills into Claude's skills
    directory and remove the ones that are gone, when init has already wired
    Claude for that store. On Windows, a skill is linked with a directory
    junction before falling back to a copy.
  • init --dry-run reports what it would do ("would create …", "would refresh
    the block …"), including the wrapper scripts and the recorded base.
  • dotagents env also lists the overlay and store lib/ directories it puts on
    PYTHONPATH in AGENTS_PYTHONPATH, and after a cd into another project it
    takes the previous project's libraries off PYTHONPATH.
  • Overlay setup scripts run with the scope's assembled dotagents env (every
    overlay's lib/ on PYTHONPATH, bin/ on PATH), and command modules can
    import any overlay's lib/, even when dotagents runs from a plain shell.
  • An env.py value must be a JSON string: null unsets the variable, and any
    other type is skipped with a warning naming the key. dotagents env emits
    unset variables where the format has a way to (unset, set -e,
    $null, set "K=", null).
  • env.py is run as env.py --level <level>; --agent <level> is still
    passed for existing scripts.
  • In the Python API, get_environment and get_diff return an EnvChanges
    (still a dict of the variables set) whose removed names the variables a
    layer unset, and get_env_from_py no longer takes project_root; its
    level and global_scope are keyword-only.
  • dotagents env --format yaml double-quotes every value; ini is written for
    Python's configparser and dotenv for python-dotenv.
  • Each installed overlay keeps a record of the repo it came from and the files
    it installed. overlays sync fetches it from that repo again, not from
    whichever repo now offers the name first; --repo replaces the recorded
    source.
  • overlays sync refreshes overlay.toml, reports files that differ from the
    source as kept, removes files the source dropped when they are unmodified
    (--prune for edited ones), backs up whatever --overwrite or --prune
    replaces, and installs requirements added upstream.
  • overlays remove refuses an overlay another installed overlay requires,
    unless --force. overlays list and show flag unmet requirements, and
    show names the recorded source.
  • Overlay setup scripts get AGENTS_HOME set to the user store, plus
    AGENTS_SCOPE_ROOT and AGENTS_SCOPE for 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/tomli whenever one is available.
  • The downloadable dotagents.pyz is compressed: about 0.46 MB instead of
    1.4 MB.
  • build-pyz vendors 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.toml reads it from there.
  • overlays add, remove and show without an overlay name are a usage
    error (exit 2).
  • tools/cloud-setup.sh reads AGENTS_OVERLAYS_REMOTE and
    AGENTS_OVERLAYS_REF; the old DOTAGENTS_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's CONTEXT.md is left
    out of the assembled context; overlay.toml is the only manifest.

Removed

  • init writes no dotagents/ directory into a store: the base config is the
    AGENTS.md managed block, plus the Claude include and the agents' hooks.
    Gone are dotagents/DECISIONS.md (the per-install design log),
    dotagents/README.md, dotagents/AGENTS.md, and the empty
    dotagents/cmds/ with its README. A scope's dotagents/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 codex no longer writes a static [shell_environment_policy]
    snapshot into ~/.codex/config.toml: it pinned the project init ran from
    into Codex's global config and could leave the file unparseable. Codex gets
    the env from its PreToolUse hook, live. The next init that wires Codex's
    hooks removes a block an earlier release wrote and leaves the rest of the
    file alone.
  • Overlay.apply_to and Overlay.merge_rules_into; use
    recompose_overlay_block.
  • Scope.system_store (use Scope.system_root) and Scope.cmds_dir.
  • dotagents._scope.OverlaySource; use dotagents._sources.DirRepo.
  • The src, base_agents_text and force parameters of
    Agent.write_base_config, and the force parameter of
    Agent.write_context.
  • The dotagents.cli re-exports of AGENTS_DIR_ENV and BASE_ROOT; import
    them from dotagents._scope and dotagents._resources.

Fixed

  • A session started in the home directory walks the user store once; it ran
    every env.py twice and sent every AGENTS.md and CONTEXT.md twice.
    init and overlays run from the home directory target the user store
    instead of writing a project block over it.
  • context orders 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's AGENTS.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 --inline inlines 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.
  • context with several agents and an output file is an error instead of
    keeping only the last agent. --agents that names no known agent exits 2,
    harness ids such as claude-code are accepted, and an empty result gets no
    system-reminder wrapper.
  • --agents-dir after -- (an argument for the harness launch runs) no
    longer changes which command modules are discovered, and a project store
    named with --agents-dir no longer replaces the user store's commands.
  • A command module that imports but whose parser cannot be built (an
    unresolvable annotation, X | None on Python 3.9, a duplicate flag, or a
    flag the umbrella owns) no longer breaks every dotagents invocation; 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.
  • findings no 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 add refuses the names index and readme, which overwrote the
    finding with the index on a case-insensitive filesystem, and done and
    reopen no longer overwrite an existing file at the destination.
  • launch exits 128+N for a harness killed by signal N, instead of 256-N.
  • On Windows, launch refuses arguments that cmd.exe would run or expand for
    a .cmd or .bat harness (& | < > ^ % ! " or a newline) instead of
    passing them on rewritten.
  • The init, overlays subcommand, about and launch summaries in
    --help are whole sentences.
  • Private *.local.* and CLAUDE* files in a source tree no longer reach the
    wheel, the sdist or a locally built dotagents.pyz.
  • tools/cloud-setup.sh no longer deletes an existing ~/.agents that is not
    a git checkout (it moves it aside and prints where), refuses to rewrite a
    ~/.claude/settings.json it 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 init adds beside Claude Code's bash
    hooks decide whether to run the way Claude Code decides which shell to use.
    They checked for bash on PATH: a default Git install (only Git\cmd on
    PATH) got the context twice, and a box with WSL's bash.exe stub and no Git
    Bash got none.
  • The Claude Code and Codex hooks run dotagents by path instead of putting
    .agents/bin and the store's bin on PATH, which env --diff then
    persisted into the session: after a cd the first project's bin stayed
    ahead of everything.
  • The PowerShell env loader (init --powershell-env-hook) runs only for
    PowerShell tool calls, not before every tool call, and reads dotagents env
    as UTF-8: a non-ASCII value arrived garbled.
  • Re-running init keeps keys you added to a dotagents hook entry (a
    timeout, say) and no longer deletes malformed hook entries from your
    settings. dotagents' hooks are labelled dotagents: ..., so an unrelated
    hook with the same generic label is no longer mistaken for one of them.
  • A bin/dotagents wrapper run through a symlink finds its .pyz beside the
    real file, and dotagents.cmd works when the Python interpreter's path is
    not ASCII (a user folder with an accented name, say).
  • Re-running init on a store with overlays installed keeps their rules and
    routing in AGENTS.md's managed block; it used to rewrite the block from the
    bare base until the next overlays sync.
  • A base chosen with init --from is recorded in
    <store>/dotagents/config.toml, and a later plain init and every overlays add / remove / sync compose over it; they used to switch back to the
    bundled base. Delete the file's base line to return to the bundled one.
  • init --force keeps the original of every file it replaces. Adapters that
    write the same file in one run share one install_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.md is 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.
  • init from 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.cmd that did not exist, so
    PowerShell sessions got no env and, without bash, no context. Wrappers left
    pointing at a .pyz are replaced, with a warning. The PowerShell hooks also
    fall back to dotagents on PATH and do nothing when there is none.
  • context for Claude includes a project's committed root AGENTS.md when a
    CLAUDE file (such as the .claude/CLAUDE.md a project init writes) 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/bin on PATH as an
    absolute path. The relative .agents/bin they used was re-emitted into the
    session's PATH by dotagents env, where it resolved against whatever
    directory a later command ran in. Re-run dotagents init to 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's PATH builtin and did nothing. Both Codex hooks run under the
    interpreter init ran with, not a bare python3 / 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-run dotagents init --agents codex to update
    the hooks.
  • launch no 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
    committed AGENTS.md / GEMINI.md / .cursorrules. The context stays at
    $AGENTS_CONTEXT_FILE with a warning; launch --write-agent merges it anyway.
    The harness is resolved first, so a launch that fails with "not found" writes
    nothing. context --write-agent refuses -g.
  • The Claude CwdChanged hook 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-run dotagents init.
  • env --format powershell doubles 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).
  • env without --diff no longer prints inherited DOTAGENTS_* 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).
  • init writes the store's AGENTS.md itself, whatever agents are named;
    with --agents gemini,cursor,copilot it wrote none, and put GEMINI.md,
    .cursorrules and .github/copilot-instructions.md inside the store, where
    no harness looks. Gemini CLI now gets an @ import of the store's
    AGENTS.md in ~/.gemini/GEMINI.md (or the project's GEMINI.md); Cursor
    and Copilot get the context through context --write-agent or launch. An
    unknown --agents name is an error instead of a warning.
  • Adapters are told the scope init resolved 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_DIR when that is set.
  • A project-scope init no longer edits Codex's or Antigravity's global hook
    config (it turned dotagents on in every workspace); run init -g for them.
    Antigravity's hook runs under the interpreter init ran with.
  • context --write-agent / launch write Cursor's context to
    .cursor/rules/dotagents.mdc with alwaysApply: true (.cursorrules is
    legacy), and Cursor's and Copilot's own reading of the project's AGENTS.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.
  • env stamps no agent identity in a plain shell: a repository with an
    AGENTS.md made it export AGENT=codex to 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 init warns when it writes the Claude include (or Gemini's) into a
    file git does not ignore.
  • tools/cloud-setup.sh installs dotagents-cli by default; the dotagents
    name it used is not this project on PyPI.
  • overlays add / sync never delete a skill you placed or edited in the
    shared skills/ dir. A same-named skill already there is kept, with a
    warning; a published copy you edited is kept on sync unless you pass
    --overwrite, while an untouched copy still follows its overlay (the digest
    of each copy is recorded in skills/.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 remove deletes read-only files (git objects on
    Windows) and unlinks a symlinked overlay instead of failing half-way; an
    overlay that already carries a .git copy is removed cleanly.
  • dotagents with no subcommand logs its hint instead of raising when no
    parser has been built.
  • dotagents env puts the dotagents bin directories at the front of PATH
    in their precedence order even when the calling shell already had some of
    them, and drops empty and relative PATH entries, which resolved against
    whatever directory a later command ran in.
  • init --from accepts the forms the docs list: a dotagents checkout, a
    file:, http(s):, sftp:, s3: or zip: 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.json or hooks.json keeps a symlinked file a symlink and
    updates its target, and keeps the file's permissions.
  • init accepts a settings.json saved with a UTF-8 byte-order mark, and a
    corrupt settings file stops init before it writes anything instead of
    leaving a half-initialised store.
  • On Windows, dotagents launch never runs a harness from the current
    directory (a claude.cmd at a repository's root, say).
  • dotagents launch no longer passes the harness a variable an env layer
    unset; --dry-run lists them on an unset: 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 init warns when skills it links into .claude/skills/ are
    not gitignored.
  • On Python 3.9 and 3.10, tomli is 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 files build-pyz generates 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 on PATH.
  • Git Bash's own rewriting of PATH, HOME, TEMP and similar variables is
    no longer reported as an env file's changes, and a PATH an 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-dir emits 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 its PATH.
  • 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":
    sync no longer skips with success, add no longer installs without a
    dependency, and list warns 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; requires names and rules paths can no longer point outside
    the overlay; an unreadable rules file is a warning instead of a crash that
    blocked every later add and sync.
  • overlays add rolls back a new install whose setup fails and updates
    AGENTS.md for what did install; overlays remove unpublishes skills only
    after the overlay is deleted and always updates AGENTS.md.
  • overlays add and overlays sync refuse a source inside the store's own
    overlays/ directory, where a later remove would delete the only copy.
  • An overlays dry run says it would recompose or create AGENTS.md instead
    of reporting it as done.
  • On Windows, init names the PowerShell PreToolUse hook only when
    --powershell-env-hook wired 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