dotagents-cli 0.5.0__tar.gz → 0.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/.gitignore +3 -2
  2. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/CHANGELOG.md +39 -0
  3. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/PKG-INFO +5 -3
  4. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/README.md +3 -2
  5. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/guide/commands.md +15 -1
  6. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/guide/overlays.md +21 -9
  7. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/pyproject.toml +2 -2
  8. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/AGENTS.md +68 -59
  9. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/__init__.py +1 -1
  10. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_agents.py +179 -322
  11. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_context.py +15 -21
  12. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_env.py +45 -66
  13. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_fs.py +3 -5
  14. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_hooks.py +17 -27
  15. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_merge.py +6 -30
  16. dotagents_cli-0.5.1/src/dotagents/_overlay/dotagents/AGENTS.md +21 -0
  17. dotagents_cli-0.5.1/src/dotagents/_overlay/dotagents/README.md +50 -0
  18. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_overlay/dotagents/cmds/findings.py +3 -3
  19. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_overlay/dotagents/cmds/launch.py +2 -2
  20. dotagents_cli-0.5.1/src/dotagents/_overlay/dotagents/hooks/preinvocation_antigravity_context.py +125 -0
  21. dotagents_cli-0.5.1/src/dotagents/_overlay/dotagents/hooks/pretooluse_codex_env.py +82 -0
  22. {dotagents_cli-0.5.0/src/dotagents/_overlay → dotagents_cli-0.5.1/src/dotagents/_overlay/dotagents/templates}/AGENTS.md +1 -1
  23. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_overlays.py +55 -83
  24. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_scope.py +17 -20
  25. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_skills.py +4 -9
  26. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_sources.py +148 -33
  27. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_wrappers.py +1 -2
  28. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/cli/__init__.py +54 -90
  29. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/cli/_common.py +54 -65
  30. dotagents_cli-0.5.1/src/dotagents/cli/about.py +104 -0
  31. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/cli/build_pyz.py +50 -19
  32. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/cli/context.py +5 -7
  33. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/cli/env.py +71 -160
  34. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/cli/init.py +1 -1
  35. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/cli/overlays.py +16 -19
  36. dotagents_cli-0.5.1/tests/test_about.py +72 -0
  37. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_audit_leak.py +1 -1
  38. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_cmds_discovery.py +2 -2
  39. dotagents_cli-0.5.1/tests/test_init_base.py +88 -0
  40. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_sources.py +18 -16
  41. dotagents_cli-0.5.1/tests/test_sources_uri.py +164 -0
  42. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tools/audit.py +9 -7
  43. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tools/cloud-setup.sh +3 -3
  44. dotagents_cli-0.5.0/src/dotagents/_overlay/CLAUDE.md +0 -3
  45. dotagents_cli-0.5.0/src/dotagents/_overlay/README.md +0 -48
  46. dotagents_cli-0.5.0/src/dotagents/_overlay/dotagents/hooks/preinvocation_antigravity_context.py +0 -152
  47. dotagents_cli-0.5.0/src/dotagents/_overlay/dotagents/hooks/pretooluse_codex_env.py +0 -96
  48. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/LICENSE +0 -0
  49. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/build.py +0 -0
  50. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/api/agents.md +0 -0
  51. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/api/cli.md +0 -0
  52. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/api/context.md +0 -0
  53. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/api/env.md +0 -0
  54. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/api/fs.md +0 -0
  55. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/api/hooks.md +0 -0
  56. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/api/merge.md +0 -0
  57. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/api/overlays.md +0 -0
  58. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/api/reference.md +0 -0
  59. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/api/scope.md +0 -0
  60. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/api/skills.md +0 -0
  61. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/api/sources.md +0 -0
  62. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/changelog.md +0 -0
  63. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/guide/authoring.md +0 -0
  64. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/guide/install.md +0 -0
  65. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/guide/private-sync.md +0 -0
  66. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/docs/index.md +0 -0
  67. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/install.py +0 -0
  68. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/mkdocs.yml +0 -0
  69. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/__main__.py +0 -0
  70. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_overlay/dotagents/DECISIONS.md +0 -0
  71. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/src/dotagents/_overlay/dotagents/cmds/README.md +0 -0
  72. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/_shell.py +0 -0
  73. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_agents.py +0 -0
  74. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_build_pyz.py +0 -0
  75. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_context.py +0 -0
  76. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_env.py +0 -0
  77. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_env_cli_scope.py +0 -0
  78. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_env_format.py +0 -0
  79. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_env_safety.py +0 -0
  80. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_findings_cmd.py +0 -0
  81. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_hooks.py +0 -0
  82. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_last_mile.py +0 -0
  83. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_launch_cmd.py +0 -0
  84. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_overlays_cli.py +0 -0
  85. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_overlays_command.py +0 -0
  86. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_scope.py +0 -0
  87. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_wire_hooks.py +0 -0
  88. {dotagents_cli-0.5.0 → dotagents_cli-0.5.1}/tests/test_wrappers.py +0 -0
@@ -36,6 +36,7 @@ Thumbs.db
36
36
  .vscode/
37
37
  _staging/
38
38
 
39
- # `overlays` branch, checked out here as a worktree/clone for local editing
40
- # (D77: example overlays split off this repo's main branch).
39
+ # The `repo` branch (the example overlays, under overlays/<name>), checked out
40
+ # here as a worktree/clone for local editing (D77: split off main).
41
+ repo/
41
42
  overlays/
@@ -7,6 +7,45 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.5.1] - 2026-09-12
11
+
12
+ ### Added
13
+
14
+ - `dotagents about`: `dotagents-cli <version>` and then, one per line, every
15
+ package bundled with it and its version -- from a `.pyz` exactly what
16
+ `build-pyz` vendored (recorded in `dotagents/_bundle.json` at build time),
17
+ from a plain install the dependencies present. `--json` adds where it runs
18
+ from and the Python.
19
+ - Overlay sources and repos can be any path `pathlib_next` speaks. With the
20
+ `uri` extra (`dotagents-cli[uri]`; `[http]`, `[sftp]`, `[s3]` add the schemes'
21
+ clients) an `http(s)://` directory listing, an `sftp`, `s3`, `dav` or
22
+ `github` tree is a directory of overlays or one overlay, a file is a
23
+ registry, an archive (`zip:<archive-uri>!/<inner>`, `tar:`, `archive:`, the
24
+ archive local or at a URL) is a tree too, and a relative registry entry resolves against the registry's
25
+ URL; remote content is materialized into `<user store>/.cache/overlays/uri/`
26
+ once per run. `file://` is a local path. Without the extra an `http(s)://`
27
+ registry file still works through the standard library, and anything else
28
+ names the extra it needs. `build-pyz --extras uri,http` vendors the extra
29
+ into the zipapp. `GitCache` is now `SourceCache`.
30
+
31
+ ### Changed
32
+
33
+ - The base config's first line, "Startup: annotate that you read `…`", names
34
+ the actual path of the `AGENTS.md` it is in (`init` renders it per store, and
35
+ every `overlays add` / `remove` / `sync` recompose keeps it), not a literal
36
+ `~/.agents/AGENTS.md` that a relocated store or a project's own file never
37
+ was. The base overlay is `dotagents/` only: the block template is
38
+ `dotagents/templates/AGENTS.md`, `<store>/dotagents/AGENTS.md` is
39
+ the working notes for that directory (read when working in it, not by
40
+ default), `<store>/dotagents/README.md` the user-facing one, and `init` no
41
+ longer writes a `<store>/CLAUDE.md` or a store-root README (no harness read
42
+ the former; the include `init` writes into `~/.claude/CLAUDE.md` is the real
43
+ one). Existing stores keep the files they have.
44
+ - The example overlays' branch is `repo` (was `overlays`); its layout is the
45
+ same, `overlays/<name>` at the branch root. Specs that named the branch
46
+ change one word: `https://github.com/jose-pr/dotagents.git@repo#overlays/net`.
47
+ The cloud bootstrap's `DOTAGENTS_OVERLAYS_REF` default follows.
48
+
10
49
  ## [0.5.0] - 2026-09-10
11
50
 
12
51
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: dotagents-cli
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: The dotagents CLI: install and manage a portable ~/.agents config for AI coding agents
5
5
  Project-URL: Homepage, https://github.com/jose-pr/dotagents/
6
6
  Project-URL: Repository, https://github.com/jose-pr/dotagents
@@ -44,6 +44,7 @@ Requires-Python: >=3.9
44
44
  Requires-Dist: duho<0.6,>=0.5.0
45
45
  Requires-Dist: pathlib-next<0.10,>=0.9.0
46
46
  Provides-Extra: dev
47
+ Requires-Dist: pathlib-next[http]; extra == 'dev'
47
48
  Requires-Dist: pytest; extra == 'dev'
48
49
  Provides-Extra: docs
49
50
  Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
@@ -107,7 +108,7 @@ them. Everything else is repo infrastructure.
107
108
 
108
109
  The **example overlays** — the `flows` workflow set, per-language `kb/` + templates,
109
110
  `references`, `release`, `private-sync`, `net`, `recovery`, `tools` — live on a separate
110
- [`overlays` branch](https://github.com/jose-pr/dotagents/tree/overlays), not in `main`'s
111
+ [`repo` branch](https://github.com/jose-pr/dotagents/tree/repo), not in `main`'s
111
112
  tree: they are swappable payloads, not part of the tool. `dotagents overlays add <name>`
112
113
  resolves them from there (or from any `--repo`). See the
113
114
  [docs](https://jose-pr.github.io/dotagents/) for what each ships.
@@ -163,7 +164,8 @@ overlay's skills into the shared skills dir. See below.
163
164
  `dotagents overlays` manages opt-in overlays **by name**, resolving each name against
164
165
  **repos** in order — the first that offers the name wins. A repo is always a
165
166
  **collection** of overlays: a directory (each subdirectory an overlay, e.g. a checkout of
166
- the [`overlays` branch](https://github.com/jose-pr/dotagents/tree/overlays)) or a
167
+ the [`repo` branch](https://github.com/jose-pr/dotagents/tree/repo), whose overlays sit
168
+ under `overlays/<name>`) or a
167
169
  JSON/TOML/YAML registry file mapping names to **sources**. It lives at a local path, an
168
170
  `http(s)://` URL (a registry file, fetched), or inside a git repository named
169
171
  `<repo>[@<branch|tag|commit>][#<path>]`, where the path picks the directory or registry
@@ -46,7 +46,7 @@ them. Everything else is repo infrastructure.
46
46
 
47
47
  The **example overlays** — the `flows` workflow set, per-language `kb/` + templates,
48
48
  `references`, `release`, `private-sync`, `net`, `recovery`, `tools` — live on a separate
49
- [`overlays` branch](https://github.com/jose-pr/dotagents/tree/overlays), not in `main`'s
49
+ [`repo` branch](https://github.com/jose-pr/dotagents/tree/repo), not in `main`'s
50
50
  tree: they are swappable payloads, not part of the tool. `dotagents overlays add <name>`
51
51
  resolves them from there (or from any `--repo`). See the
52
52
  [docs](https://jose-pr.github.io/dotagents/) for what each ships.
@@ -102,7 +102,8 @@ overlay's skills into the shared skills dir. See below.
102
102
  `dotagents overlays` manages opt-in overlays **by name**, resolving each name against
103
103
  **repos** in order — the first that offers the name wins. A repo is always a
104
104
  **collection** of overlays: a directory (each subdirectory an overlay, e.g. a checkout of
105
- the [`overlays` branch](https://github.com/jose-pr/dotagents/tree/overlays)) or a
105
+ the [`repo` branch](https://github.com/jose-pr/dotagents/tree/repo), whose overlays sit
106
+ under `overlays/<name>`) or a
106
107
  JSON/TOML/YAML registry file mapping names to **sources**. It lives at a local path, an
107
108
  `http(s)://` URL (a registry file, fetched), or inside a git repository named
108
109
  `<repo>[@<branch|tag|commit>][#<path>]`, where the path picks the directory or registry
@@ -11,13 +11,14 @@ by default (the `<cwd>/.agents` store, when run inside a project) or **user** wi
11
11
 
12
12
  | Command | What it does |
13
13
  | --- | --- |
14
- | `init` | Lay down the neutral base config; block-merge `AGENTS.md`/`CLAUDE.md`; `--bin-dir` also writes a PATH wrapper. |
14
+ | `init` | Lay down the neutral base config; block-merge `AGENTS.md` (its first line names the file's own path); `--bin-dir` also writes a PATH wrapper. |
15
15
  | `overlays` | Manage opt-in overlays by name: `add` / `remove` / `list` / `sync` / `show`. |
16
16
  | `context` | Assemble the effective context for one or more agents. |
17
17
  | `env` | Assemble the chained env-file layers + identity vars, in a chosen format. |
18
18
  | `build-pyz` | Build the self-contained `dotagents.pyz` zipapp. |
19
19
  | `findings` | Per-scope findings queue: `add` / `list` / `show` / `done` / `reopen` / `remove` / `index` / `path`. |
20
20
  | `launch` | Start an agent's CLI with the `env` exported and the `context` handed over; everything after `--` goes to the agent. |
21
+ | `about` | `dotagents-cli <version>`, then every package bundled in the `.pyz` (or installed beside a plain install) with its version. |
21
22
 
22
23
  That table is the **whole** shipped surface; `findings` and `launch` are the two bundled
23
24
  command modules (discovered from the package itself, overridable by a same-named module
@@ -355,6 +356,19 @@ project's `.agents` — and `sync-project` no longer reads like `overlays sync`.
355
356
 
356
357
  See [Private sync](private-sync.md) for the full walkthrough.
357
358
 
359
+ ## about
360
+
361
+ ```bash
362
+ dotagents about # dotagents-cli 0.5.0 / duho 0.5.0 / pathlib_next 0.9.0 ...
363
+ dotagents about --json # the same, plus where it runs from and the Python
364
+ ```
365
+
366
+ One `<distribution> <version>` per line, the CLI first. From a built `.pyz` the
367
+ list is exactly what `build-pyz` vendored (it records the names and versions in
368
+ `dotagents/_bundle.json` before stripping the `dist-info` dirs the zipapp would
369
+ otherwise carry, so `--extras uri,http` shows up here as `uritools`, `requests`
370
+ and friends); from a plain install it is the dependencies actually present.
371
+
358
372
  ## build-pyz
359
373
 
360
374
  ```bash
@@ -19,7 +19,7 @@ an installed overlay — an already-present file is skipped.
19
19
  ## Example overlays
20
20
 
21
21
  The example overlays below live on this repo's separate
22
- [`overlays` branch](https://github.com/jose-pr/dotagents/tree/overlays), not in `main` —
22
+ [`repo` branch](https://github.com/jose-pr/dotagents/tree/repo), not in `main` —
23
23
  they are **payloads riding on dotagents**, not part of the tool, so you swap them for
24
24
  your own. Name a checkout of that branch as a repo to install any with
25
25
  `dotagents overlays add <name> --repo <overlays-checkout>/overlays`.
@@ -67,7 +67,7 @@ first repo that offers the name wins. A repo is **always a collection** of overl
67
67
  in one of two shapes:
68
68
 
69
69
  - a **directory of overlays** — each subdirectory is an overlay, `<dir>/<name>/` (a
70
- checkout of the `overlays` branch, any folder);
70
+ checkout of the `repo` branch has them under `overlays/`, any folder);
71
71
  - a **registry** — a JSON, TOML or YAML file mapping `<name-or-alias>` to the
72
72
  **source** of that one overlay (the whole document, or its `overlays` key).
73
73
 
@@ -78,17 +78,29 @@ force git); `<ref>` is a branch, tag or commit; `<path>` is inside it. The two d
78
78
  in what the path names:
79
79
 
80
80
  - for a **repo**, the collection: a directory (of overlays) or a registry file in the
81
- checkout, the checkout root with no path; an `http(s)://` location is a registry
82
- file, fetched;
81
+ checkout, the checkout root with no path;
83
82
  - for a **source**, the overlay: the path is the overlay's root directory, and with no
84
83
  path **the repository root is the overlay**.
85
84
 
85
+ A `scheme://` location that is not git is a **pathlib_next path**. With the `uri`
86
+ extra (`pip install 'dotagents-cli[uri]'`; `[http]`, `[sftp]`, `[s3]` add the schemes'
87
+ own clients) any scheme pathlib_next speaks works like a local path: an `http(s)://`
88
+ directory listing, an `sftp`, `s3`, `dav` or `github` tree is a directory of overlays
89
+ as a repo or one overlay as a source, a file is a registry; an archive is a tree too —
90
+ `zip:<archive-uri>!/<inner path>` (`tar:`, or `archive:` to auto-detect), the archive
91
+ itself local (`file:`) or at any URL: `zip:https://h/overlays.zip!/overlays`. Remote content is
92
+ materialized into `<user store>/.cache/overlays/uri/`, synced once per run, and used
93
+ from there; `file://` is a local path, no copy. Without the extra, an `http(s)://`
94
+ location can still be a registry file (fetched with the standard library), and
95
+ anything else says which extra it needs. The `.pyz` vendors none of this unless built
96
+ with `build-pyz --extras uri,http`.
97
+
86
98
  A source written as a **relative path** (`./python`, `../shared/net`, `overlays/rust`)
87
99
  is relative to the registry it is in: the registry file's directory for a local file,
88
100
  and for a registry inside a git checkout the **same repository at the same ref**, with
89
101
  the path joined onto the registry file's directory (`overlays/reg.toml` saying `./rust`
90
- means `<repo>@<ref>#overlays/rust`). A registry fetched over `http(s)` has no overlays
91
- beside it, so a relative entry there is an error.
102
+ means `<repo>@<ref>#overlays/rust`), and for a registry at a URL the URL beside it
103
+ (`https://h/cfg/reg.json` saying `./rust` means `https://h/cfg/rust`).
92
104
 
93
105
  Checkouts are cached under `<user store>/.cache/overlays/` and refreshed on every
94
106
  `add`/`sync`.
@@ -104,8 +116,8 @@ The repos, in order:
104
116
  ```toml
105
117
  # ~/.agents/dotagents.toml
106
118
  [overlays]
107
- engineering = "https://github.com/you/dotagents.git@overlays#overlays/engineering"
108
- python = "https://github.com/you/dotagents.git@overlays#overlays/python"
119
+ engineering = "https://github.com/you/dotagents.git@repo#overlays/engineering"
120
+ python = "https://github.com/you/dotagents.git@repo#overlays/python"
109
121
  mytool = "git@github.com:you/mytool-overlay.git@v2" # no path: the repo root is the overlay
110
122
  local = "~/src/overlays/local" # a local overlay directory
111
123
  mine = "./overlays/mine" # relative to this file: ~/.agents/overlays/mine
@@ -113,7 +125,7 @@ mine = "./overlays/mine" # relative to thi
113
125
 
114
126
  ```bash
115
127
  dotagents overlays add engineering -g # from the registry above
116
- dotagents overlays add net --repo https://github.com/you/dotagents.git@overlays#overlays/net
128
+ dotagents overlays add net --repo https://github.com/you/dotagents.git@repo#overlays/net
117
129
  dotagents overlays sync -g # refetches git-sourced overlays
118
130
  ```
119
131
 
@@ -9,7 +9,7 @@ build-backend = "hatchling.build"
9
9
  # redirect/placeholder before someone else does, but the CLI ships under -cli.
10
10
  [project]
11
11
  name = "dotagents-cli"
12
- version = "0.5.0"
12
+ version = "0.5.1"
13
13
  authors = [{ name = "Jose A." }]
14
14
  description = "The dotagents CLI: install and manage a portable ~/.agents config for AI coding agents"
15
15
  readme = "README.md"
@@ -39,7 +39,7 @@ uri = ["pathlib_next[uri]"]
39
39
  http = ["pathlib_next[http]"]
40
40
  sftp = ["pathlib_next[sftp]"]
41
41
  s3 = ["pathlib_next[s3]"]
42
- dev = ["pytest"]
42
+ dev = ["pytest", "pathlib_next[http]"]
43
43
  docs = [
44
44
  "mkdocs>=1.5",
45
45
  "mkdocs-material>=9.5",
@@ -27,7 +27,10 @@ can read it without the source. Full docs: https://jose-pr.github.io/dotagents/
27
27
  managed block over what remains — the un-merge), `list`, `sync` (`--copy`
28
28
  honoured, `--overwrite` replaces changed files), `show` (manifest, setup,
29
29
  skills, files, `--json`) — `context`, `env`, `build_pyz` (a checkout only:
30
- a clear error elsewhere)); each is a `class X(LoggingArgs, Cmd)` — or
30
+ a clear error elsewhere), `about` (`dotagents-cli <version>` then one
31
+ `<distribution> <version>` per line: from a `.pyz` what `build-pyz` vendored,
32
+ recorded in `dotagents/_bundle.json` at build time since the zipapp carries
33
+ no dist-info; from a plain install the runtime packages present)); each is a `class X(LoggingArgs, Cmd)` — or
31
34
  `class X(DotAgentsArgs)`, which is that pair transitively — with a
32
35
  `__call__`. Plus TWO bundled command modules under
33
36
  `_overlay/dotagents/cmds/`: `findings.py` (`dotagents findings`: a per-scope
@@ -41,9 +44,9 @@ can read it without the source. Full docs: https://jose-pr.github.io/dotagents/
41
44
  means no append flag and the context is merged into `Agent.context_target`
42
45
  as `context --write-agent` does — then runs `Agent.launch_command` resolved
43
46
  on the exported PATH, or `--command`). `init` copies neither into the store —
44
- the bundled dir is always a discovery source. `link` / `sync` left the package with their logic (D85): the
45
- opt-in **private-sync** overlay ships them, renamed `link-project` /
46
- `sync-project`, from its own `cmds/` + `lib/_link.py`. A personal command module
47
+ the bundled dir is always a discovery source. `link-project` / `sync-project`
48
+ are shipped by the opt-in **private-sync** overlay from its own `cmds/` +
49
+ `lib/_link.py` (D85), not by the package. A personal command module
47
50
  dropped into a scope's `dotagents/cmds/` is discovered like any other, so private
48
51
  tooling never has to live in the repo (D84). `audit` is repo CI tooling
49
52
  (`tools/audit.py`), not a command.
@@ -105,13 +108,12 @@ can read it without the source. Full docs: https://jose-pr.github.io/dotagents/
105
108
  default). `-g` resolves the store through `resolve_user_store`
106
109
  (`--agents-dir` → `$AGENTS_HOME` → `~/.agents`), never the literal
107
110
  home dir; `--agents-dir` overrides the store in EITHER scope. The library
108
- functions take a `Scope` only — no keyword-triple compatibility form: the CLI
109
- is the public surface, the package internals have one caller.
111
+ functions take a `Scope` only.
110
112
  Installed overlays are **discovered** by presence (`Overlay.discover(scope.overlay_root)`
111
113
  for one scope, `Overlay.installed(...)` for what a session uses), not tracked in
112
114
  a registry. Nothing overlay-only lives here (name rules and discovery are
113
115
  `Overlay`'s).
114
- - `_context` — assemble the effective per-agent context (Plan 04):
116
+ - `_context` — assemble the effective per-agent context:
115
117
  `assemble_context(agent, scope, *, inline=False)` /
116
118
  `assemble_context_data(agent, scope, *, inline=False)`. Sources are the contract-A
117
119
  walk (overlay `CONTEXT.md`s first, sorted by manifest `priority`, lower
@@ -121,7 +123,7 @@ can read it without the source. Full docs: https://jose-pr.github.io/dotagents/
121
123
  and one `<NAME_OVERLAY_ROOT>` per installed overlay (user store + project)
122
124
  expand. **Inlining the on-demand `.md` files a source mentions is opt-in**
123
125
  (`inline=True` / `context --inline`): the base rules say to read them only
124
- when a task needs them, and inlining every mention made a 100 KB session
126
+ when a task needs them, so inlining every mention would bloat the session
125
127
  payload. Skills are listed, never inlined.
126
128
  - `_env` — chained env-file assembly + `env.py` execution (frozen contract B):
127
129
  `get_environment(scope, *, base_env, explicit, logger)` / `get_diff(scope, ...)`
@@ -132,24 +134,24 @@ can read it without the source. Full docs: https://jose-pr.github.io/dotagents/
132
134
  `lib` onto PYTHONPATH the same way (`get_lib_paths`; not part of contract B), so
133
135
  an `env.py` and every subprocess can import an overlay's `lib/`; then two tiers
134
136
  (`pre.env*` then `env*`), later-overrides-earlier. Identity seeded before the
135
- chain; proxy vars applied after. **Amended 2026-09-09:** the project-root level
137
+ chain; proxy vars applied after. The project-root level
136
138
  resolves only `pre.local.env` / `local.env` — a checkout's own top-level
137
- `env.py` / `env` is never executed or sourced (it ran at every session start,
138
- i.e. code execution from any cloned repo); only regular files count (a venv
139
+ `env.py` / `env` is never executed or sourced (that would be code execution
140
+ from any cloned repo at session start); only regular files count (a venv
139
141
  dir named `env` is not an env file); a plain file whose `source` fails
140
142
  contributes nothing (`source F || exit 1`, so the failure is visible); bash's
141
143
  own `PWD`/`OLDPWD`/`SHLVL`/`MSYSTEM*` are never reported as a file's changes.
142
144
  - **`Scope.paths(*names, include_missing=False)`** — the Contract-A precedence
143
- walk / filename resolution (there is no `_resolve` module any more), store by
145
+ walk / filename resolution, store by
144
146
  store over `Scope.stores` — system (`Scope.system_root`, `/etc/agents` or
145
147
  `$AGENTS_SYSTEM_ROOT`), user, project — each store's overlays first, then the
146
148
  store itself; then project-root. The project store and project-root exist
147
149
  only in a project scope (`overlays add` installs into the project store by
148
- default, since 2026-09-09 walked like any other). Each
150
+ default; it is walked like any other). Each
149
151
  tuple is `(level, path, root)`; an overlay entry's `level` is the overlay's
150
152
  dir name and `root` its dir (`root is None` for every other level — that is
151
153
  the overlay test). `LEVEL_NAMES` are reserved as overlay names.
152
- - `_merge` — managed-block merge for `init`'s `AGENTS.md` / `CLAUDE.md`, delimited by
154
+ - `_merge` — managed-block merge for `init`'s `AGENTS.md`, delimited by
153
155
  `<!-- dotagents:begin -->` / `<!-- dotagents:end -->` marker LINES (a prose
154
156
  mention of a marker is not a marker; `find_block` returns the span). A begin
155
157
  with no end after it is refused; a base without markers is a usage error.
@@ -171,8 +173,14 @@ can read it without the source. Full docs: https://jose-pr.github.io/dotagents/
171
173
  `.github/copilot-instructions.md`, pi `.pi/APPEND_SYSTEM.md`, Antigravity
172
174
  `.agents/rules/dotagents.md`),
173
175
  `write_base_config(dest, ...)` (Claude also writes the `@` include into
174
- `~/.claude/CLAUDE.md` or `<project>/.claude/CLAUDE.md` — THE last mile; the
175
- store's own `CLAUDE.md` is kept for the skeleton but no harness reads it).
176
+ `~/.claude/CLAUDE.md` or `<project>/.claude/CLAUDE.md` — THE last mile; no
177
+ `<store>/CLAUDE.md` is written). The base overlay is
178
+ `_overlay/dotagents/` only: `templates/AGENTS.md` (the block
179
+ TEMPLATE, rendered by `cli._common.base_agents_text(src, dest)` —
180
+ `{{AGENTS_MD}}` becomes the actual path of the store's `AGENTS.md`, so
181
+ "annotate that you read `…`" names the real file; `init` and every recompose
182
+ use it), `AGENTS.md` (dev notes for that directory, read when working in it),
183
+ `README.md` (user-facing), `DECISIONS.md`, `cmds/`, `hooks/`.
176
184
  The user scope is whatever `resolve_user_store()` returns, never the literal
177
185
  `~/.agents`.
178
186
  - `_skills` — publish an overlay's `skills/<name>/` into a scope's shared skills dir
@@ -200,16 +208,15 @@ can read it without the source. Full docs: https://jose-pr.github.io/dotagents/
200
208
  PowerShell tool) and `CodexAgent.wire_hooks` (`<CODEX_HOME|~/.codex>/hooks.json`,
201
209
  never `config.toml`: `SessionStart` context-only, plus a `PreToolUse` env-loader
202
210
  matched on `matcher: "Bash"`). Codex's hook JSON is structurally identical to
203
- Claude's, including the SAME `updatedInput.command` rewrite mechanism on
204
- `PreToolUse` — confirmed directly against Codex's own docs
205
- (learn.chatgpt.com/docs/hooks), not assumed from Claude parity.
206
- Gemini/Cursor/Copilot keep the base no-op — Gemini CLI proper has no hook
207
- mechanism documented at all (checked directly). **Antigravity is a separate
211
+ Claude's, including the same `updatedInput.command` rewrite mechanism on
212
+ `PreToolUse` (learn.chatgpt.com/docs/hooks).
213
+ Gemini/Cursor/Copilot keep the base no-op — Gemini CLI documents no hook
214
+ mechanism. **Antigravity is a separate
208
215
  product** from Gemini CLI (Antigravity CLI/IDE/SDK family, shares only the
209
216
  `~/.gemini/` namespace for some files) and DOES wire a hook: see
210
- `AntigravityAgent.wire_hooks` below. `PreToolUse` there is still allow/deny/ask
217
+ `AntigravityAgent.wire_hooks` below. `PreToolUse` there is allow/deny/ask
211
218
  only — no `updatedInput`, so no command-rewrite/env-loader path exists to hang
212
- on it, unlike Claude/Codex. Revisit both conclusions if either framework changes.
219
+ on it, unlike Claude/Codex. Revisit if either framework changes.
213
220
  - **`AntigravityAgent.wire_hooks`** (`<AGENTS_HOME_ANTIGRAVITY|~/.gemini/config>/hooks.json`,
214
221
  keyed under a `"dotagents"` name per the docs' own example shape — a named-entry
215
222
  object, not Claude/Codex's flat `hooks.<Event>`): wires a single `PreInvocation`
@@ -221,30 +228,28 @@ can read it without the source. Full docs: https://jose-pr.github.io/dotagents/
221
228
  `_overlay/dotagents/hooks/`) gates on `invocationNum == 0` to behave like a
222
229
  one-shot SessionStart rather than resending context every turn. Output shape is
223
230
  a bare `{"injectSteps": [{"ephemeralMessage": "..."}]}`, no `hookSpecificOutput`
224
- wrapper — confirmed against the primary docs after an earlier pass here wrongly
225
- concluded no useful injection was possible; `ephemeralMessage` is the one of the
231
+ wrapper; `ephemeralMessage` is the one of the
226
232
  three step types meant for free text (`toolCall` executes a tool,
227
- `userMessage` impersonates the user). No detection marker exists anywhere in
228
- Antigravity's docs, so `detect_env_vars = []` — explicit `--agents antigravity`
229
- only, same posture as Codex's env-block precedent (writes touching an agent's
233
+ `userMessage` impersonates the user). Antigravity's docs define no detection
234
+ marker, so `detect_env_vars = []` — explicit `--agents antigravity`
235
+ only, as for Codex (writes touching an agent's
230
236
  own live config are opt-in, never inferred).
231
237
  - **`SessionStart`/`CwdChanged` register TWO handlers each ON WINDOWS**,
232
238
  bash-syntax (default shell) and a PowerShell-native equivalent (`shell:
233
239
  "powershell"`); **POSIX hosts get the bash handler only**, and `init` there
234
- RETRACTS PowerShell entries an earlier install wrote (`_hooks.remove_hook`,
235
- keyed by status message) — Claude Code on Linux ran such an entry through
236
- bash, a syntax error every session (measured in WSL, 2026-09-10). The gate
240
+ REMOVES any PowerShell entries present (`_hooks.remove_hook`,
241
+ keyed by status message) — Claude Code on Linux runs such an entry through
242
+ bash, a syntax error every session. The gate
237
243
  is `ClaudeAgent._is_windows()` (`os.name == "nt"`, a seam tests patch; never
238
244
  "is pwsh installed"). hooks.md: `shell` "Defaults to bash, or to powershell
239
- on Windows when Git Bash isn't installed" — verified directly that bash
240
- syntax fed to `powershell -Command` on such a machine is a hard parse error,
245
+ on Windows when Git Bash isn't installed" — bash
246
+ syntax fed to `powershell -Command` is a hard parse error,
241
247
  not a soft failure, so every session there would silently get neither env
242
248
  nor context. Every handler in a matched group fires unconditionally
243
- (hooks.md), so on Windows both always run —
244
- and on a box with BOTH interpreters both used to succeed, injecting the same
245
- context twice per session (two identical 100 KB payloads, measured
246
- 2026-09-09). The PowerShell variants therefore **select themselves: they run
247
- only when `bash` is not on PATH** (`Get-Command bash`). The PowerShell
249
+ (hooks.md), so on Windows both always run; the PowerShell variants therefore
250
+ **select themselves: they run only when `bash` is not on PATH**
251
+ (`Get-Command bash`), otherwise a box with both interpreters would inject the
252
+ same context twice per session. The PowerShell
248
253
  `SessionStart` variant is context-only (`dotagents context`), not
249
254
  env+context: `$CLAUDE_ENV_FILE`'s documented effect is "subsequent BASH
250
255
  commands" regardless of which shell wrote it, so writing to it from a
@@ -252,28 +257,27 @@ can read it without the source. Full docs: https://jose-pr.github.io/dotagents/
252
257
  store as `$AGENTS_HOME`, else `~/.agents` (bash: `${AGENTS_HOME:-$HOME/.agents}`),
253
258
  and the bash `CwdChanged` handler re-pins `AGENTS_PROJECT_ROOT` into
254
259
  `$CLAUDE_ENV_FILE` when the new cwd carries a `.agents/` (the SessionStart pin
255
- is only-if-unset, so without this a `cd` into another project kept the first
256
- project's root for the rest of the session).
260
+ is only-if-unset, so without this a `cd` into another project would keep the
261
+ first project's root for the rest of the session).
257
262
  - **Windows only**: `ClaudeAgent._wire_powershell_pretooluse` additionally wires
258
263
  a no-matcher `PreToolUse` hook (fires on every tool call), `shell:
259
264
  "powershell"`, running `PRETOOLUSE_POWERSHELL_COMMAND` INLINE — deliberately
260
265
  not a `.ps1` file, since a script file is subject to PowerShell's execution
261
266
  policy (RemoteSigned/AllSigned/Restricted) and dotagents has no code-signing
262
- certificate; verified directly that the inline form runs successfully even
263
- under `Restricted`, which blocks every `.ps1` file outright. Closes a real
264
- gap: `$CLAUDE_ENV_FILE` is Bash-tool-only (confirmed empirically that
265
- `$env:CLAUDE_ENV_FILE` is empty inside a live PowerShell tool call), so the
267
+ certificate; the inline form runs even
268
+ under `Restricted`, which blocks every `.ps1` file outright. It is needed
269
+ because `$CLAUDE_ENV_FILE` is Bash-tool-only (`$env:CLAUDE_ENV_FILE` is
270
+ empty inside a PowerShell tool call), so the
266
271
  SessionStart env half never reaches the PowerShell tool. Uses `PreToolUse`'s
267
- `updatedInput` to prepend a guarded env-loader (`AGENTS_RUNTIME_SET`,
268
- matching the precursor's convention) to a `PowerShell` tool call's own
272
+ `updatedInput` to prepend a guarded env-loader (`AGENTS_RUNTIME_SET`)
273
+ to a `PowerShell` tool call's own
269
274
  command — not by trying to persist state across hook invocations, which are
270
275
  each their own fresh process and cannot. Each PowerShell TOOL call is a fresh
271
276
  process too, so the guard never carries over and the loader runs on every
272
277
  call: it therefore runs `env --diff` (the change set), not the whole
273
278
  environment through `Invoke-Expression`. Every literal `\` in the
274
279
  command constant must be a raw string — a bare `\b` in a normal Python string
275
- literal silently becomes a backspace character, corrupting the emitted path;
276
- caught once by testing a draft through a real PowerShell spawn.
280
+ literal silently becomes a backspace character, corrupting the emitted path.
277
281
  - **`CodexAgent._deploy_pretooluse_script`** covers the same env gap for Codex,
278
282
  which has NO env-persistence mechanism at any hook event (not Bash-only like
279
283
  Claude — none). Ships `pretooluse_codex_env.py` (`_overlay/dotagents/hooks/`),
@@ -283,10 +287,9 @@ can read it without the source. Full docs: https://jose-pr.github.io/dotagents/
283
287
  `tool_name` check needed in the script. A FILE, not inlined like Claude's:
284
288
  Codex's docs show every hook example as `python3 <path>`, and a `.py` file
285
289
  has no execution-policy/signing concern (PowerShell-specific). Sets
286
- `commandWindows` to `python "<path>"` (not `python3`) — verified directly
287
- that `python3` resolves to the Microsoft Store app-execution-alias stub and
288
- fails outright on this dev machine (exit 49), the same trap noted elsewhere
289
- for `py`/venv creation.
290
+ `commandWindows` to `python "<path>"` (not `python3`): on Windows `python3`
291
+ can resolve to the Microsoft Store app-execution-alias stub and fail
292
+ outright (exit 49).
290
293
 
291
294
  ## Environment variables
292
295
 
@@ -313,15 +316,21 @@ Config / path / sync vars (`AGENTS_*`, non-secret — read, and some emitted):
313
316
  before the default; both after `--repo` and before the stores'
314
317
  `dotagents.{json,toml,yaml}` registries and the bundled `overlays/`.
315
318
  `_sources` is the module; `resolve_source(repos, scope=)` the entry point.
319
+ A non-git `scheme://` location is a pathlib_next `UriPath` when the `uri`
320
+ extra is installed (`_sources.uri_path_class()`), materialized by
321
+ `SourceCache.materialize` into `<store>/.cache/overlays/uri/` (a directory
322
+ synced with `PathSyncer(remove_missing=True)`, a file copied, once per
323
+ process); `file://` is local; without the extra only an http(s) REGISTRY
324
+ works (stdlib fetch).
316
325
  - `AGENTS_CMDS_PATH` — extra command-module search paths (os.pathsep-split).
317
326
  - `AGENTS_OVERLAY_DIR` — set for an overlay's setup script (its own installed dir).
318
327
  - `AGENTS_REMOTE` / `AGENTS_SYNC_MESSAGE` — private-store sync (tokenless remote URL /
319
328
  commit message).
320
329
 
321
- The `DOTAGENTS_*` spellings of these are gone (0.5.0): readers take the `AGENTS_*`
322
- name only, and setters emit it only.
330
+ Readers take the `AGENTS_*` name only, and setters emit it only; there is no
331
+ `DOTAGENTS_*` spelling of any of these.
323
332
 
324
- Tool-internal / secret vars (`DOTAGENTS_*` — kept; read, **never printed**):
333
+ Tool-internal / secret vars (`DOTAGENTS_*` — read, **never printed**):
325
334
 
326
335
  - `DOTAGENTS_AGENTS_TOKEN` — **secret** (fine-grained PAT) for private-store auth.
327
336
  - `DOTAGENTS_CLI_INSTALL` — pip spec to install the CLI itself (tool-specific).
@@ -352,8 +361,8 @@ with every level's existing `lib` prepended (both except project-root; the
352
361
  formatter treats any `*PATH` var as a path list for Windows/POSIX conversion).
353
362
  Deliberately NOT emitted, despite looking like they
354
363
  would be: `AGENTS_AGENT` (a named persona — nothing derives one, so there is
355
- nothing to emit) and `AGENTS_CODE_SESSION_ID` (dropped with the precursor's
356
- blanket `CLAUDE_*`→`AGENTS_*` rewrite). Do not branch on either. `resolve_scope` READS `AGENTS_PROJECT_ROOT` (then the
364
+ nothing to emit) and `AGENTS_CODE_SESSION_ID`. Do not branch on either.
365
+ `resolve_scope` READS `AGENTS_PROJECT_ROOT` (then the
357
366
  agent-native `CLAUDE_PROJECT_DIR`, then cwd) for the project scope's root.
358
367
 
359
368
  Every command READS both back, so the pin actually holds: `env` and `context`
@@ -381,7 +390,7 @@ the pinned root makes that cwd-independent. `-g/--global` on these two means
381
390
  zip-backed `Traversable` is extracted once), never `Path(__file__).exists()`
382
391
  (always False in a zipapp). Everything a `.pyz` run extracts — package data
383
392
  and the repointed module sources — lives under ONE per-process scratch dir
384
- (`_common._scratch_dir()`), removed at interpreter exit; a `mkdtemp` per item
385
- with no cleanup had littered a dev box's `%TEMP%` with 632 directories.
393
+ (`_common._scratch_dir()`), removed at interpreter exit, so a `.pyz` run
394
+ leaves nothing behind in `%TEMP%`.
386
395
  - **`pathlib_next` needs `typing_extensions` on Python < 3.10** (an upstream gap); a
387
396
  3.9 environment must `pip install typing_extensions`.
@@ -1,3 +1,3 @@
1
1
  """dotagents: installable CLI for the dotagents agent-config payload."""
2
2
 
3
- __version__ = "0.5.0"
3
+ __version__ = "0.5.1"