dotagents-cli 0.3.2__tar.gz → 0.3.4__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.
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/CHANGELOG.md +81 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/PKG-INFO +5 -5
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/README.md +1 -1
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/build.py +3 -3
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/api/reference.md +0 -1
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/guide/commands.md +14 -2
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/install.py +2 -2
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/mkdocs.yml +0 -1
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/pyproject.toml +3 -3
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/AGENTS.md +33 -11
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/__init__.py +1 -1
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_agents.py +20 -8
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_merge.py +6 -2
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_scope.py +1 -1
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/cli/__init__.py +7 -15
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/cli/_common.py +32 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/cli/build_pyz.py +15 -17
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/cli/context.py +27 -6
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/cli/env.py +31 -7
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/tests/test_agents.py +18 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/tests/test_build_pyz.py +19 -1
- dotagents_cli-0.3.4/tests/test_env_cli_scope.py +263 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/tests/test_env_format.py +12 -12
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/tools/audit.py +7 -5
- dotagents_cli-0.3.2/docs/api/sync.md +0 -3
- dotagents_cli-0.3.2/src/dotagents/_sync.py +0 -72
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/.gitignore +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/LICENSE +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/api/agents.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/api/cli.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/api/context.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/api/env.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/api/hooks.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/api/merge.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/api/overlays.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/api/resolve.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/api/scope.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/api/skills.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/changelog.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/guide/authoring.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/guide/install.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/guide/overlays.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/guide/private-sync.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/docs/index.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/__main__.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_context.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_env.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_hooks.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_overlay/AGENTS.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_overlay/CLAUDE.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_overlay/README.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_overlay/dotagents/DECISIONS.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_overlay/dotagents/cmds/README.md +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_overlay/dotagents/hooks/preinvocation_antigravity_context.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_overlay/dotagents/hooks/pretooluse_codex_env.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_overlays.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_resolve.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_skills.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/_wrappers.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/cli/init.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/src/dotagents/cli/overlays.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/tests/test_audit_leak.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/tests/test_cmds_discovery.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/tests/test_context.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/tests/test_env.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/tests/test_hooks.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/tests/test_overlays_command.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/tests/test_scope.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/tests/test_wire_hooks.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/tests/test_wrappers.py +0 -0
- {dotagents_cli-0.3.2 → dotagents_cli-0.3.4}/tools/cloud-setup.sh +0 -0
|
@@ -7,6 +7,87 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.4] - 2026-08-16
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- chore: raise the dependency floors and scope them to a minor series —
|
|
15
|
+
`duho>=0.5.0,<0.6` (was `>=0.4.0`) and `pathlib_next>=0.9.0,<0.10` (was
|
|
16
|
+
`>=0.8.0`). Both are pre-1.0, where a minor bump is the signal that the
|
|
17
|
+
documented API broke, so the ceiling is what keeps the next one from arriving
|
|
18
|
+
unannounced. Neither floor sits above its `.0` patch: the suite and a CLI
|
|
19
|
+
smoke pass at exactly duho 0.5.0 and pathlib_next 0.9.0, so nothing here needs
|
|
20
|
+
an API added later in either series. The one 0.5.0 behavior change that
|
|
21
|
+
reaches this CLI's surface is list-typed *option* fields taking one value per
|
|
22
|
+
occurrence instead of `nargs="*"` — `--agents` and `--cmdspath` are unaffected,
|
|
23
|
+
since the documented forms are the comma list (`--agents a,b`, split by the
|
|
24
|
+
command itself) and the repeated flag, both of which behave the same either
|
|
25
|
+
way. Exercised end to end against duho 0.5.4 / pathlib_next 0.9.2 on Python
|
|
26
|
+
3.9 and 3.14. The `[uri]`/`[http]`/`[sftp]`/`[s3]` extras stay unversioned
|
|
27
|
+
passthroughs to `pathlib_next`'s own extras.
|
|
28
|
+
- chore: `build-pyz`'s vendored pins moved with those floors — the `.pyz` now
|
|
29
|
+
bundles duho 0.5.0 and pathlib_next 0.9.0 (was 0.4.0 / 0.8.0), the minimum the
|
|
30
|
+
package claims to support rather than the latest patch. These pins are a
|
|
31
|
+
second copy of the dependency versions and had drifted a full minor series
|
|
32
|
+
behind, so the shipped zipapp bundled versions `pip install dotagents-cli`
|
|
33
|
+
would have refused. The rebuilt `.pyz` keeps full flag/help/positional
|
|
34
|
+
fidelity through the zipapp shim.
|
|
35
|
+
|
|
36
|
+
## [0.3.3] - 2026-08-16
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- feat: `env` and `context` gained **`--agents-dir`** (from the shared
|
|
41
|
+
`DotAgentsArgs` base) to override the store for one run. Their `-g/--global`
|
|
42
|
+
keeps its existing, narrower meaning here — *skip the project-level files* —
|
|
43
|
+
and now says so in `--help`.
|
|
44
|
+
|
|
45
|
+
### Removed
|
|
46
|
+
|
|
47
|
+
- **`build-pyz` no longer bundles the repo's `tools/`** as `dotagents/_tools`
|
|
48
|
+
inside the built `.pyz`, and the `--tools-dir` flag is gone with it. Nothing
|
|
49
|
+
read `_tools`: the compiled `audit`/`leak-check` wrappers that shelled out to
|
|
50
|
+
it no longer exist. Every shipped artifact carried the dead weight while
|
|
51
|
+
`tools/audit.py` claimed it was "not shipped in the `.pyz`" — now true.
|
|
52
|
+
- **`dotagents._sync`** — a `pathlib_next.PathSyncer` wrapper that existed only
|
|
53
|
+
to back the `install` subcommand's backup/copy report. `install` was removed
|
|
54
|
+
in 0.3.x; the module has had no callers since, no tests, and a return
|
|
55
|
+
annotation that disagreed with what it returned. `pathlib_next` remains a
|
|
56
|
+
dependency (duho, and `--from` URI support). Its API-reference page went with
|
|
57
|
+
it.
|
|
58
|
+
|
|
59
|
+
### Fixed
|
|
60
|
+
|
|
61
|
+
- docs: a cluster of "docs say X, tree does Y" corrections — `tools/audit.py`
|
|
62
|
+
no longer claims to ship as a bundled `audit` command module (it is repo CI
|
|
63
|
+
tooling and there is no `dotagents audit`) and its `--root` help names the
|
|
64
|
+
real default; `install.py`'s usage line drops the removed `install` and the
|
|
65
|
+
never-existing `audit`; the README's `tools/` row says where `leak-check`
|
|
66
|
+
actually lives; the API header names the real `_overlays` exports
|
|
67
|
+
(`install_overlay_dir` / `apply_overlay` / `run_overlay_setup`) and the real
|
|
68
|
+
package-data dirs (`_overlay` / `_overlays_src`, never a `skeleton/`); and
|
|
69
|
+
`_merge._extract_block`'s docstring now says it returns the block *including*
|
|
70
|
+
its marker lines, which is what it has always done and what callers rely on.
|
|
71
|
+
- fix: **`stamp_identity` no longer pretends to emit `AGENTS_AGENT`.** The line
|
|
72
|
+
sourced the value from `$AGENTS_AGENT` and only assigned when that same key
|
|
73
|
+
was unset, so it could never emit anything — while the docstring and the
|
|
74
|
+
shipped API header both advertised the var. Line removed; the API header's
|
|
75
|
+
"emitted by the identity/env layer" list now drops both `AGENTS_AGENT` and
|
|
76
|
+
`AGENTS_CODE_SESSION_ID` (the latter was deliberately never emitted) and says
|
|
77
|
+
so explicitly, so nothing branches on a var that never arrives.
|
|
78
|
+
- fix: **`dotagents env` and `dotagents context` now resolve their roots instead
|
|
79
|
+
of hardcoding them.** Both took `Path.cwd()` as the project root and
|
|
80
|
+
`~/.agents` as the user store, so `$AGENTS_PROJECT_ROOT` (or the agent-native
|
|
81
|
+
`$CLAUDE_PROJECT_DIR`) and `$AGENTS_HOME` were ignored by the two commands
|
|
82
|
+
that most needed them — a `SessionStart` hook runs `dotagents context` from
|
|
83
|
+
wherever the session happens to start, so a pinned project root was silently
|
|
84
|
+
dropped and a relocated store was never read. They now use
|
|
85
|
+
`_scope.project_root_default()` and the new
|
|
86
|
+
`dotagents.cli.resolve_user_store()` (`--agents-dir` → `$AGENTS_HOME` →
|
|
87
|
+
legacy `$DOTAGENTS_AGENTS_DIR` → `~/.agents`), matching what the package's own
|
|
88
|
+
`resolve_scope` docstring and command discovery already promised. Behavior is
|
|
89
|
+
unchanged when none of the vars are set.
|
|
90
|
+
|
|
10
91
|
## [0.3.2] - 2026-07-25
|
|
11
92
|
|
|
12
93
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: dotagents-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
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
|
|
@@ -41,8 +41,8 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
41
41
|
Classifier: Programming Language :: Python :: 3.13
|
|
42
42
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
43
43
|
Requires-Python: >=3.9
|
|
44
|
-
Requires-Dist: duho
|
|
45
|
-
Requires-Dist: pathlib-next
|
|
44
|
+
Requires-Dist: duho<0.6,>=0.5.0
|
|
45
|
+
Requires-Dist: pathlib-next<0.10,>=0.9.0
|
|
46
46
|
Provides-Extra: dev
|
|
47
47
|
Requires-Dist: pytest; extra == 'dev'
|
|
48
48
|
Provides-Extra: docs
|
|
@@ -102,7 +102,7 @@ them. Everything else is repo infrastructure.
|
|
|
102
102
|
| --- | --- |
|
|
103
103
|
| `src/dotagents/` | The installable `dotagents` CLI (`init`/`overlays`/`context`/`env`/`build-pyz`) — that is the whole shipped surface; commands beyond it come from overlays or your own `cmds/` modules |
|
|
104
104
|
| `src/dotagents/_overlay/` | The **base overlay** `init` writes: `AGENTS.md` scaffolding, `CLAUDE.md`, `dotagents/DECISIONS.md` (empty design-log index), and an empty `dotagents/cmds/` dir — your drop-in point for your own command modules. Neutral — imposes no flows, ships no command |
|
|
105
|
-
| `tools/` |
|
|
105
|
+
| `tools/` | Repo tooling, not shipped: `audit.py` (CI structure check) and `cloud-setup.sh`. `leak-check` is not here either — it is a personal command module you keep in your own private `.agents/dotagents/cmds/` |
|
|
106
106
|
| `install.py` | Thin shim over `dotagents.cli.main()`, kept at this filename for muscle memory |
|
|
107
107
|
|
|
108
108
|
The **example overlays** — the `flows` workflow set, per-language `kb/` + templates,
|
|
@@ -41,7 +41,7 @@ them. Everything else is repo infrastructure.
|
|
|
41
41
|
| --- | --- |
|
|
42
42
|
| `src/dotagents/` | The installable `dotagents` CLI (`init`/`overlays`/`context`/`env`/`build-pyz`) — that is the whole shipped surface; commands beyond it come from overlays or your own `cmds/` modules |
|
|
43
43
|
| `src/dotagents/_overlay/` | The **base overlay** `init` writes: `AGENTS.md` scaffolding, `CLAUDE.md`, `dotagents/DECISIONS.md` (empty design-log index), and an empty `dotagents/cmds/` dir — your drop-in point for your own command modules. Neutral — imposes no flows, ships no command |
|
|
44
|
-
| `tools/` |
|
|
44
|
+
| `tools/` | Repo tooling, not shipped: `audit.py` (CI structure check) and `cloud-setup.sh`. `leak-check` is not here either — it is a personal command module you keep in your own private `.agents/dotagents/cmds/` |
|
|
45
45
|
| `install.py` | Thin shim over `dotagents.cli.main()`, kept at this filename for muscle memory |
|
|
46
46
|
|
|
47
47
|
The **example overlays** — the `flows` workflow set, per-language `kb/` + templates,
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
Thin root-level wrapper over ``dotagents build-pyz`` (``dotagents.cli.build_pyz``):
|
|
5
5
|
it vendors ``duho`` + ``pathlib_next`` into the archive (via ``pip install --target``,
|
|
6
|
-
using **the Python that runs this script**), copies the ``dotagents`` package
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
using **the Python that runs this script**), copies the ``dotagents`` package, strips
|
|
7
|
+
caches/metadata, and packages a runnable zipapp. The result needs no ``pip install``
|
|
8
|
+
on the target machine. The repo's ``tools/`` is CI tooling and is NOT bundled.
|
|
9
9
|
|
|
10
10
|
Usage:
|
|
11
11
|
python build.py # -> dist/dotagents.pyz
|
|
@@ -21,4 +21,3 @@ form its API. Generated from docstrings, organized by module:
|
|
|
21
21
|
- **[Hooks](hooks.md)** — additive, idempotent merge of dotagents' hooks into an
|
|
22
22
|
agent's own settings/config file.
|
|
23
23
|
- **[Skills](skills.md)** — publishing an overlay's skills into a scope's shared dir.
|
|
24
|
-
- **[Sync](sync.md)** — the `PathSyncer` backup/copy wrapper for `install`.
|
|
@@ -155,7 +155,14 @@ dotagents context --write-agent # write each agent's native confi
|
|
|
155
155
|
- `--write-agent` — write each agent's native config file instead of `[output]`.
|
|
156
156
|
- `--agents <a,b>` — which agents to generate for (default: the active agent).
|
|
157
157
|
- `--format markdown|system-reminder|json` — output shape.
|
|
158
|
-
- `-g` / `--global` —
|
|
158
|
+
- `-g` / `--global` — skip the project-level context files (the store is unaffected).
|
|
159
|
+
- `--agents-dir <dir>` — user store override for this run.
|
|
160
|
+
|
|
161
|
+
Roots: the store is `--agents-dir` → `$AGENTS_HOME` → `~/.agents`, and the project
|
|
162
|
+
root is `$AGENTS_PROJECT_ROOT` → `$CLAUDE_PROJECT_DIR` → the cwd. A `SessionStart`
|
|
163
|
+
hook runs this from wherever the session started, so pinning
|
|
164
|
+
`AGENTS_PROJECT_ROOT` is what keeps the assembled context the same in every
|
|
165
|
+
subdirectory.
|
|
159
166
|
|
|
160
167
|
## env
|
|
161
168
|
|
|
@@ -174,7 +181,12 @@ python -m dotagents env --diff --format json # only vars that differ from the
|
|
|
174
181
|
(`bat`/`batch`, `set "KEY=value"`), `fish` (`set -gx KEY value`). Data forms:
|
|
175
182
|
`json`, `ini`, `yaml`. An explicit `--format` always wins.
|
|
176
183
|
- `--diff` — emit only the change set vs. the caller's environment.
|
|
177
|
-
- `-g` / `--global` —
|
|
184
|
+
- `-g` / `--global` — skip the project-level env files (the store is unaffected).
|
|
185
|
+
- `--agents-dir <dir>` — user store override for this run.
|
|
186
|
+
|
|
187
|
+
Roots resolve exactly as for `context` above (`$AGENTS_HOME` /
|
|
188
|
+
`$AGENTS_PROJECT_ROOT`, both of which `env` also emits — so a subprocess reading
|
|
189
|
+
them agrees with the parent that wrote them).
|
|
178
190
|
|
|
179
191
|
!!! warning
|
|
180
192
|
`env` output is sensitive by design — it prints resolved values. Treat the
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""Entry point for the dotagents CLI (init /
|
|
2
|
+
"""Entry point for the dotagents CLI (init / overlays / context / env / build-pyz).
|
|
3
3
|
|
|
4
4
|
Thin front over ``dotagents.cli.main()``, kept at this filename so existing
|
|
5
5
|
muscle-memory/docs pointing at ``python install.py`` still work.
|
|
@@ -14,7 +14,7 @@ bare ``pip`` off PATH) guarantees the install lands in *this* Python, so the
|
|
|
14
14
|
import that follows actually sees it. When everything is already importable it
|
|
15
15
|
just dispatches -- no pip is ever run.
|
|
16
16
|
|
|
17
|
-
Usage: python install.py <init|
|
|
17
|
+
Usage: python install.py <init|overlays|context|env|build-pyz|...> [options]
|
|
18
18
|
Run `python install.py --help` for the full subcommand/flag reference.
|
|
19
19
|
"""
|
|
20
20
|
import os
|
|
@@ -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.3.
|
|
12
|
+
version = "0.3.4"
|
|
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"
|
|
@@ -30,8 +30,8 @@ classifiers = [
|
|
|
30
30
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
31
31
|
]
|
|
32
32
|
dependencies = [
|
|
33
|
-
"duho>=0.
|
|
34
|
-
"pathlib_next>=0.
|
|
33
|
+
"duho>=0.5.0,<0.6",
|
|
34
|
+
"pathlib_next>=0.9.0,<0.10",
|
|
35
35
|
]
|
|
36
36
|
|
|
37
37
|
[project.optional-dependencies]
|
|
@@ -11,8 +11,17 @@ can read it without the source. Full docs: https://jose-pr.github.io/dotagents/
|
|
|
11
11
|
`duho.app` with the discovered command set. Also the `dotagents` console script
|
|
12
12
|
(`[project.scripts]`).
|
|
13
13
|
- `dotagents.cli.Dotagents(LoggingArgs, Cli)` — the umbrella CLI class.
|
|
14
|
+
- `dotagents.cli.DotAgentsArgs` — mix-in base carrying the shared `-g/--global` +
|
|
15
|
+
`--agents-dir` pair and `resolve_scope()`; an overlay-shipped command module
|
|
16
|
+
should inherit it (as the FIRST base) rather than redeclare the flags.
|
|
17
|
+
- `dotagents.cli.resolve_user_store(agents_dir=None) -> Path` — the USER store
|
|
18
|
+
root: `agents_dir` (`--agents-dir`) → `$AGENTS_HOME` → legacy
|
|
19
|
+
`$DOTAGENTS_AGENTS_DIR` → `~/.agents`. Use it (not `resolve_scope`) when the
|
|
20
|
+
store is always the user store and the project scope only adds/removes tiers,
|
|
21
|
+
as in `env` / `context`.
|
|
14
22
|
- Compiled command classes live in `dotagents.cli.<name>` (`init`, `overlays`,
|
|
15
|
-
`context`, `env`, `build_pyz`); each is a `class X(LoggingArgs, Cmd)`
|
|
23
|
+
`context`, `env`, `build_pyz`); each is a `class X(LoggingArgs, Cmd)` — or
|
|
24
|
+
`class X(DotAgentsArgs)`, which is that pair transitively — with a
|
|
16
25
|
`__call__`. That is the WHOLE shipped surface — dotagents bundles no command
|
|
17
26
|
module of its own. `link` / `sync` left the package with their logic (D85): the
|
|
18
27
|
opt-in **private-sync** overlay ships them, renamed `link-project` /
|
|
@@ -30,8 +39,9 @@ can read it without the source. Full docs: https://jose-pr.github.io/dotagents/
|
|
|
30
39
|
|
|
31
40
|
- `_agents` — `Agent` base type + per-agent adapters; `stamp_identity(...)` emits the
|
|
32
41
|
standardized `AGENTS_*` / `AGENT` identity vars.
|
|
33
|
-
- `_overlays` — `
|
|
34
|
-
`
|
|
42
|
+
- `_overlays` — `install_overlay_dir` (copy an overlay into a scope, self-describing)
|
|
43
|
+
/ `apply_overlay` (lay its files down) / `read_manifest` / `find_setup_script` /
|
|
44
|
+
`run_overlay_setup`; installs an overlay's files and collects its `routing` / `rules`
|
|
35
45
|
contributions to the managed `AGENTS.md` block. `DEFAULT_PRIORITY = 500`.
|
|
36
46
|
- `_scope` — `resolve_scope(global_scope, agents_dir=None)` and `resolve_source(...)`;
|
|
37
47
|
scope = *where installed overlays live* (user = the configurable store, project =
|
|
@@ -139,8 +149,6 @@ can read it without the source. Full docs: https://jose-pr.github.io/dotagents/
|
|
|
139
149
|
that `python3` resolves to the Microsoft Store app-execution-alias stub and
|
|
140
150
|
fails outright on this dev machine (exit 49), the same trap noted elsewhere
|
|
141
151
|
for `py`/venv creation.
|
|
142
|
-
- `_sync` — `PathSyncer` wrapper reproducing `install`'s backup/copy/report; requires
|
|
143
|
-
`pathlib_next.Path` instances (not plain `pathlib.Path`) and a pre-created parent dir.
|
|
144
152
|
|
|
145
153
|
## Environment variables
|
|
146
154
|
|
|
@@ -174,13 +182,25 @@ Tool-internal / secret vars (`DOTAGENTS_*` — kept; read, **never printed**):
|
|
|
174
182
|
- `DOTAGENTS_AUDIT_PATTERNS` — path to the machine-local audit-pattern file (tooling).
|
|
175
183
|
|
|
176
184
|
Emitted by the identity/env layer (safe to branch on in env files):
|
|
177
|
-
`AGENTS_HARNESS`, `AGENTS_VENDOR`, `AGENTS_MODEL`, `
|
|
178
|
-
`
|
|
185
|
+
`AGENTS_HARNESS`, `AGENTS_VENDOR`, `AGENTS_MODEL`, `AGENT`, `AGENTS_PROXY`,
|
|
186
|
+
`AGENTS_WEBFETCH_PROXY_URL`, plus the two
|
|
179
187
|
scope roots — `AGENTS_HOME` (the user store, `agents_dir`/`~/.agents`) and
|
|
180
188
|
`AGENTS_PROJECT_ROOT` (this project's root). Both are seeded only if unset, so a
|
|
181
|
-
harness/env can pin them.
|
|
189
|
+
harness/env can pin them. Deliberately NOT emitted, despite looking like they
|
|
190
|
+
would be: `AGENTS_AGENT` (a named persona — nothing derives one, so there is
|
|
191
|
+
nothing to emit) and `AGENTS_CODE_SESSION_ID` (dropped with the precursor's
|
|
192
|
+
blanket `CLAUDE_*`→`AGENTS_*` rewrite). Do not branch on either. `resolve_scope` READS `AGENTS_PROJECT_ROOT` (then the
|
|
182
193
|
agent-native `CLAUDE_PROJECT_DIR`, then cwd) for the project scope's root.
|
|
183
194
|
|
|
195
|
+
Every command READS both back, so the pin actually holds: `env` and `context`
|
|
196
|
+
resolve their user store through `cli.resolve_user_store()` (`--agents-dir` →
|
|
197
|
+
`$AGENTS_HOME` → legacy `$DOTAGENTS_AGENTS_DIR` → `~/.agents`) and their project
|
|
198
|
+
root through `_scope.project_root_default()` — neither is taken from the cwd or a
|
|
199
|
+
hardcoded home. This matters for hook-invoked runs: a `SessionStart` hook runs
|
|
200
|
+
`dotagents context` / `dotagents env` from wherever the session started, and only
|
|
201
|
+
the pinned root makes that cwd-independent. `-g/--global` on these two means
|
|
202
|
+
*skip the project tier*, not *use a different store*.
|
|
203
|
+
|
|
184
204
|
## Gotchas
|
|
185
205
|
|
|
186
206
|
- **Python 3.9 floor.** Files using bare `X | Y` unions in runtime-evaluated positions
|
|
@@ -191,8 +211,10 @@ agent-native `CLAUDE_PROJECT_DIR`, then cwd) for the project scope's root.
|
|
|
191
211
|
`cli.main()` calls `_repoint_zipapp_sources()` first, extracting the built-in command
|
|
192
212
|
modules to real temp files. Discovered `cmds` modules are extracted by
|
|
193
213
|
`_package_data_dir` before import, so they need no repoint.
|
|
194
|
-
- **Package data in a `.pyz`.** `_package_data_dir()` resolves
|
|
195
|
-
|
|
196
|
-
a
|
|
214
|
+
- **Package data in a `.pyz`.** `_package_data_dir(name)` resolves a package-data dir
|
|
215
|
+
by name — `_overlay` (the base overlay `init` writes) and `_overlays_src` (bundled
|
|
216
|
+
example overlays, when a build includes them) — via `importlib.resources` (a
|
|
217
|
+
zip-backed `Traversable` is extracted to a temp dir once), never
|
|
218
|
+
`Path(__file__).exists()` (always False in a zipapp).
|
|
197
219
|
- **`pathlib_next` needs `typing_extensions` on Python < 3.10** (an upstream gap); a
|
|
198
220
|
3.9 environment must `pip install typing_extensions`.
|
|
@@ -490,10 +490,18 @@ class AntigravityAgent(Agent):
|
|
|
490
490
|
# PreToolUse hooks do.
|
|
491
491
|
#
|
|
492
492
|
# No `shell`/`commandWindows`-equivalent field is documented for Antigravity
|
|
493
|
-
# hook commands at all (checked directly, absent) -- the emitted command
|
|
494
|
-
#
|
|
495
|
-
#
|
|
496
|
-
#
|
|
493
|
+
# hook commands at all (checked directly, absent) -- the emitted command must
|
|
494
|
+
# therefore work via a bare interpreter invocation with no shell assumptions,
|
|
495
|
+
# and there is exactly ONE string to get right for every platform.
|
|
496
|
+
#
|
|
497
|
+
# It emits `python "<path>"`. That is NOT what Codex does, despite the
|
|
498
|
+
# similar shape: Codex emits `python3` and overrides it to `python` through
|
|
499
|
+
# its `commandWindows` field, precisely because `python3` is the POSIX name
|
|
500
|
+
# and `python3` on Windows hits the Store app-execution-alias stub. With no
|
|
501
|
+
# second field available here, one name has to cover both, and `python` is
|
|
502
|
+
# the one that works on Windows -- but a POSIX box that ships only `python3`
|
|
503
|
+
# (still common) gets a hook that cannot start. Known gap, no fix available
|
|
504
|
+
# inside the hook entry itself; see `.agents/plans/` for the follow-up.
|
|
497
505
|
PRETOOLUSE_HOOK_SCRIPT = "preinvocation_antigravity_context.py"
|
|
498
506
|
|
|
499
507
|
def wire_hooks(
|
|
@@ -964,13 +972,19 @@ def stamp_identity(
|
|
|
964
972
|
Emits ``AGENTS_HARNESS`` (the harness_id, e.g. ``claude-code`` -- NOT the
|
|
965
973
|
short name), ``AGENTS_VENDOR``, ``AGENT`` (= AGENTS_HARNESS, aligning with
|
|
966
974
|
the emerging ecosystem marker used by Goose/Amp; agentsmd/agents.md#136),
|
|
967
|
-
and, when derivable, ``AGENTS_MODEL`` (from the adapter's vendor model var)
|
|
968
|
-
and ``AGENTS_AGENT`` (a named persona, from $AGENTS_AGENT if already set).
|
|
975
|
+
and, when derivable, ``AGENTS_MODEL`` (from the adapter's vendor model var).
|
|
969
976
|
|
|
970
977
|
Never emits a var it cannot source (no empty ``AGENTS_MODEL=``). Does NOT
|
|
971
978
|
clobber a value already set in ``environ`` -- an explicit user/harness value
|
|
972
979
|
wins. The deliberate curated mapping replaces the precursor's blanket
|
|
973
980
|
``CLAUDE_*``->``AGENTS_*`` rewrite (no ``AGENTS_CODE_SESSION_ID`` junk).
|
|
981
|
+
|
|
982
|
+
``AGENTS_AGENT`` (a named persona) is NOT emitted and never was: the line
|
|
983
|
+
that claimed to "surface an already-selected persona" read the value from
|
|
984
|
+
the same key its own not-already-set guard required to be absent, so it was
|
|
985
|
+
unreachable in both directions. A persona would have to be DERIVED from
|
|
986
|
+
something (e.g. a ``<store>/<agent>.md``), which was never ported -- until
|
|
987
|
+
it is, nothing may branch on this var.
|
|
974
988
|
"""
|
|
975
989
|
active = resolve_active_agent(environ, explicit=explicit, root=root)
|
|
976
990
|
|
|
@@ -984,7 +998,5 @@ def stamp_identity(
|
|
|
984
998
|
_set("AGENTS_VENDOR", active.vendor)
|
|
985
999
|
_set("AGENT", active.harness_id or active.name)
|
|
986
1000
|
_set("AGENTS_MODEL", active.resolve_model(environ))
|
|
987
|
-
# A named persona (~/.agents/<agent>.md); only surface one already selected.
|
|
988
|
-
_set("AGENTS_AGENT", environ.get("AGENTS_AGENT"))
|
|
989
1001
|
|
|
990
1002
|
return identity
|
|
@@ -18,8 +18,12 @@ END_MARKER = "<!-- dotagents:end -->"
|
|
|
18
18
|
def _extract_block(
|
|
19
19
|
text: str, begin_marker: str = BEGIN_MARKER, end_marker: str = END_MARKER
|
|
20
20
|
) -> str:
|
|
21
|
-
"""Return the managed block
|
|
22
|
-
|
|
21
|
+
"""Return the managed block from a base-overlay/template file that is itself
|
|
22
|
+
fully marker-wrapped -- the inner text INCLUDING both marker lines.
|
|
23
|
+
|
|
24
|
+
The markers are part of the returned string on purpose: callers write this
|
|
25
|
+
straight into a target file, and the block has to stay detectable there (the
|
|
26
|
+
merge finds an existing block by marker presence alone)."""
|
|
23
27
|
start = text.index(begin_marker)
|
|
24
28
|
end = text.index(end_marker)
|
|
25
29
|
return text[start : end + len(end_marker)]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Scope and overlay-source resolution for ``dotagents overlays``.
|
|
2
2
|
|
|
3
3
|
Two orthogonal axes the ``overlays`` command needs, kept out of ``cli.py`` (which
|
|
4
|
-
only wires args) to match ``_overlays.py`` / ``_skills.py
|
|
4
|
+
only wires args) to match ``_overlays.py`` / ``_skills.py``:
|
|
5
5
|
|
|
6
6
|
* **Scope** -- *where installed overlays live*. ``user`` is ``<agents_dir>/`` (the
|
|
7
7
|
configurable store, default ``~/.agents``); ``project`` is ``<project>/.agents/``.
|
|
@@ -51,6 +51,8 @@ from dotagents import __version__
|
|
|
51
51
|
# Re-export shared helpers so `dotagents.cli.<name>` keeps resolving for both the
|
|
52
52
|
# command modules and external importers (`dotagents._overlays`, `dotagents._scope`).
|
|
53
53
|
from dotagents.cli._common import ( # noqa: F401
|
|
54
|
+
AGENTS_DIR_ENV,
|
|
55
|
+
AGENTS_DIR_ENV_LEGACY,
|
|
54
56
|
BASE_PLAIN_FILES,
|
|
55
57
|
BASE_ROOT,
|
|
56
58
|
DotAgentsArgs,
|
|
@@ -60,6 +62,7 @@ from dotagents.cli._common import ( # noqa: F401
|
|
|
60
62
|
_package_data_dir,
|
|
61
63
|
_resolve_from,
|
|
62
64
|
_run_overlay_setup,
|
|
65
|
+
resolve_user_store,
|
|
63
66
|
)
|
|
64
67
|
|
|
65
68
|
# Import each built-in command class to register it as a compiled subcommand.
|
|
@@ -128,13 +131,6 @@ CMDS_PATH_ENV = "AGENTS_CMDS_PATH"
|
|
|
128
131
|
#: back-compat: DOTAGENTS_CMDS_PATH is deprecated, removable next release.
|
|
129
132
|
CMDS_PATH_ENV_LEGACY = "DOTAGENTS_CMDS_PATH"
|
|
130
133
|
|
|
131
|
-
#: The configurable user-scope store (D58). Discovery resolves the user scope's
|
|
132
|
-
#: cmds dir through this, not a hardcoded ~/.agents, when set. This is the same
|
|
133
|
-
#: var `dotagents env` emits (D79).
|
|
134
|
-
AGENTS_DIR_ENV = "AGENTS_HOME"
|
|
135
|
-
#: back-compat: DOTAGENTS_AGENTS_DIR is deprecated, removable next release.
|
|
136
|
-
AGENTS_DIR_ENV_LEGACY = "DOTAGENTS_AGENTS_DIR"
|
|
137
|
-
|
|
138
134
|
|
|
139
135
|
class Dotagents(LoggingArgs, Cli):
|
|
140
136
|
"""Umbrella CLI for installing and building the dotagents config."""
|
|
@@ -225,20 +221,16 @@ def _cmds_dirs() -> "list[Path]":
|
|
|
225
221
|
(an overlay may SHIP a command; a user/project can still override it).
|
|
226
222
|
|
|
227
223
|
The store location is configurable (D58/D79): the user scope resolves through
|
|
228
|
-
|
|
224
|
+
`resolve_user_store()` (`$AGENTS_HOME`, legacy `$DOTAGENTS_AGENTS_DIR`, default
|
|
225
|
+
`~/.agents`) -- the same resolver `env`/`context` use, so every user-store
|
|
226
|
+
reader agrees; the project scope is `<cwd>/.agents`.
|
|
229
227
|
`include_missing=True` (precursor semantics): every level's cmds dir is offered
|
|
230
228
|
and the caller's `_discover_dir` skips the ones that don't exist."""
|
|
231
229
|
from dotagents import _resolve, _scope
|
|
232
230
|
|
|
233
|
-
agents_dir = (
|
|
234
|
-
os.environ.get(AGENTS_DIR_ENV)
|
|
235
|
-
or os.environ.get(AGENTS_DIR_ENV_LEGACY)
|
|
236
|
-
or None
|
|
237
|
-
)
|
|
238
|
-
user = _scope.resolve_scope(global_scope=True, agents_dir=agents_dir)
|
|
239
231
|
resolved = _resolve.get_file_paths(
|
|
240
232
|
{"default": "dotagents/cmds", "overlay": "cmds"},
|
|
241
|
-
agents_dir=
|
|
233
|
+
agents_dir=resolve_user_store(),
|
|
242
234
|
project_root=_scope.project_root_default(),
|
|
243
235
|
global_scope=False,
|
|
244
236
|
include_missing=True,
|
|
@@ -21,6 +21,38 @@ from duho import Cmd, LoggingArgs
|
|
|
21
21
|
|
|
22
22
|
_extracted_dirs_cache: "dict[str, Path]" = {}
|
|
23
23
|
|
|
24
|
+
#: The configurable user-scope store (D58). Every reader of the user store
|
|
25
|
+
#: resolves it through this var (default `~/.agents`) rather than hardcoding the
|
|
26
|
+
#: home path -- this is the same var `dotagents env` emits (D79). Defined HERE
|
|
27
|
+
#: rather than in `cli/__init__` so command modules can use it without importing
|
|
28
|
+
#: the umbrella (import cycle); `cli/__init__` re-exports both names.
|
|
29
|
+
AGENTS_DIR_ENV = "AGENTS_HOME"
|
|
30
|
+
#: back-compat: DOTAGENTS_AGENTS_DIR is deprecated, removable next release.
|
|
31
|
+
AGENTS_DIR_ENV_LEGACY = "DOTAGENTS_AGENTS_DIR"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def resolve_user_store(agents_dir: "Optional[Path]" = None) -> Path:
|
|
35
|
+
"""The USER store root, in precedence order: an explicit ``agents_dir``
|
|
36
|
+
(``--agents-dir``) -> ``$AGENTS_HOME`` -> the legacy
|
|
37
|
+
``$DOTAGENTS_AGENTS_DIR`` -> ``~/.agents`` (D58/D79/D80).
|
|
38
|
+
|
|
39
|
+
Distinct from :meth:`DotAgentsArgs.resolve_scope`, which answers "which scope
|
|
40
|
+
do I install INTO" and returns ``<project>/.agents`` for the project scope.
|
|
41
|
+
Commands that always walk from the user store and merely *include or skip*
|
|
42
|
+
project-level files -- ``env`` and ``context``, whose Contract-A walk takes
|
|
43
|
+
the user store as ``agents_dir`` and the project root separately -- want this
|
|
44
|
+
instead: the store never becomes the project dir, whatever ``-g`` says.
|
|
45
|
+
|
|
46
|
+
Never logs or prints the raw env value (Leakage rule); only the resolved path
|
|
47
|
+
is ever reported.
|
|
48
|
+
"""
|
|
49
|
+
if agents_dir:
|
|
50
|
+
return Path(agents_dir).expanduser()
|
|
51
|
+
value = os.environ.get(AGENTS_DIR_ENV) or os.environ.get(AGENTS_DIR_ENV_LEGACY)
|
|
52
|
+
if value:
|
|
53
|
+
return Path(value).expanduser()
|
|
54
|
+
return Path.home() / ".agents"
|
|
55
|
+
|
|
24
56
|
|
|
25
57
|
class DotAgentsArgs(LoggingArgs, Cmd):
|
|
26
58
|
"""Shared ``-g/--global`` + ``--agents-dir`` fields for any command whose scope
|
|
@@ -6,7 +6,6 @@ import subprocess
|
|
|
6
6
|
import sys
|
|
7
7
|
import tempfile
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import Optional
|
|
10
9
|
|
|
11
10
|
from duho import Cmd, LoggingArgs
|
|
12
11
|
|
|
@@ -29,28 +28,34 @@ class BuildPyz(LoggingArgs, Cmd):
|
|
|
29
28
|
"Shebang line to embed in the pyz."
|
|
30
29
|
("--python",)
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
# These two are a SECOND copy of the dependency versions declared in
|
|
32
|
+
# `pyproject.toml`'s `[project] dependencies`, and the two must move
|
|
33
|
+
# together: the zipapp bundles what the package claims to support, so a
|
|
34
|
+
# stale pin here ships an artifact `pip install dotagents-cli` would refuse.
|
|
35
|
+
# Pin the FLOOR of each declared range, not the latest patch -- the .pyz then
|
|
36
|
+
# exercises the minimum the metadata promises.
|
|
37
|
+
duho_version: str = "0.5.0"
|
|
33
38
|
"Pinned duho version to vendor."
|
|
34
39
|
("--duho-version",)
|
|
35
40
|
|
|
36
|
-
pathlib_next_version: str = "0.
|
|
41
|
+
pathlib_next_version: str = "0.9.0"
|
|
37
42
|
"Pinned pathlib_next version to vendor."
|
|
38
43
|
("--pathlib-next-version",)
|
|
39
44
|
|
|
40
|
-
tools_dir: Optional[Path] = None
|
|
41
|
-
"Repo tools/ dir (required tooling) to bundle as _tools (default: autodetected)."
|
|
42
|
-
("--tools-dir",)
|
|
43
|
-
|
|
44
45
|
def __call__(self) -> int:
|
|
45
46
|
import zipapp
|
|
46
47
|
|
|
47
48
|
# This module lives at src/dotagents/cli/build_pyz.py, so the repo root
|
|
48
49
|
# is parents[3] (cli -> dotagents -> src -> repo) and the dotagents
|
|
49
50
|
# package dir is parents[1].
|
|
51
|
+
#
|
|
52
|
+
# The repo's `tools/` is NOT bundled. It used to ride along as
|
|
53
|
+
# `dotagents/_tools` for compiled `audit`/`leak-check` wrappers that
|
|
54
|
+
# shelled out to it; both wrappers are gone (audit is repo CI tooling,
|
|
55
|
+
# leak-check is a personal command module), nothing reads `_tools`, and
|
|
56
|
+
# `tools/audit.py`'s own docstring says it is not shipped in the .pyz --
|
|
57
|
+
# which is only true now that this stopped copying it.
|
|
50
58
|
repo_root = Path(__file__).resolve().parents[3]
|
|
51
|
-
tools_src = Path(self.tools_dir) if self.tools_dir else (repo_root / "tools")
|
|
52
|
-
if not tools_src.exists():
|
|
53
|
-
raise SystemExit("error: repo tools/ not found at %s (pass --tools-dir)" % tools_src)
|
|
54
59
|
|
|
55
60
|
with tempfile.TemporaryDirectory(prefix="dotagents-pyz-") as tmp:
|
|
56
61
|
stage = Path(tmp) / "stage"
|
|
@@ -109,13 +114,6 @@ class BuildPyz(LoggingArgs, Cmd):
|
|
|
109
114
|
)
|
|
110
115
|
self._logger_.info("stamped __version__ = %s (from pyproject.toml)", version)
|
|
111
116
|
|
|
112
|
-
tools_dest = dotagents_pkg_dest / "_tools"
|
|
113
|
-
shutil.copytree(
|
|
114
|
-
tools_src,
|
|
115
|
-
tools_dest,
|
|
116
|
-
ignore=shutil.ignore_patterns("__pycache__", "*.pyc"),
|
|
117
|
-
)
|
|
118
|
-
|
|
119
117
|
for path in stage.rglob("*.dist-info"):
|
|
120
118
|
shutil.rmtree(path, ignore_errors=True)
|
|
121
119
|
for path in stage.rglob("__pycache__"):
|
|
@@ -4,7 +4,7 @@ import sys
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from typing import Optional
|
|
6
6
|
|
|
7
|
-
from
|
|
7
|
+
from dotagents.cli._common import DotAgentsArgs, resolve_user_store
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def _write_stdout(text: str) -> None:
|
|
@@ -27,8 +27,21 @@ def _write_stdout(text: str) -> None:
|
|
|
27
27
|
buffer.flush()
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
class Context(
|
|
31
|
-
"""Assemble the effective context for agents (Plan 04).
|
|
30
|
+
class Context(DotAgentsArgs):
|
|
31
|
+
"""Assemble the effective context for agents (Plan 04).
|
|
32
|
+
|
|
33
|
+
Roots (both configurable, never hardcoded -- D58/D79/D80): the user store is
|
|
34
|
+
``--agents-dir`` -> ``$AGENTS_HOME`` -> legacy ``$DOTAGENTS_AGENTS_DIR`` ->
|
|
35
|
+
``~/.agents`` (:func:`~dotagents.cli._common.resolve_user_store`), and the
|
|
36
|
+
project root is ``$AGENTS_PROJECT_ROOT`` -> ``$CLAUDE_PROJECT_DIR`` -> the cwd
|
|
37
|
+
(:func:`~dotagents._scope.project_root_default`). This matters most here: the
|
|
38
|
+
SessionStart hook runs ``dotagents context`` from wherever the session happens
|
|
39
|
+
to start, so a pinned project root is the only thing that keeps the assembled
|
|
40
|
+
context stable across subdirectories.
|
|
41
|
+
|
|
42
|
+
``-g/--global`` means **skip the project-level context files**, NOT "resolve a
|
|
43
|
+
different store" -- same narrowed meaning as ``dotagents env``'s (and unlike
|
|
44
|
+
``DotAgentsArgs.resolve_scope``, which is deliberately not used here)."""
|
|
32
45
|
|
|
33
46
|
_parsername_ = "context"
|
|
34
47
|
|
|
@@ -36,10 +49,17 @@ class Context(LoggingArgs, Cmd):
|
|
|
36
49
|
"Output format: markdown, system-reminder, or json."
|
|
37
50
|
("--format",)
|
|
38
51
|
|
|
52
|
+
# Inherited from `DotAgentsArgs`; help restated because this command's `-g` is
|
|
53
|
+
# narrower than the base's and its store is always the user store (see the
|
|
54
|
+
# matching comment in `cli/env.py`).
|
|
39
55
|
global_scope: bool = False
|
|
40
|
-
"
|
|
56
|
+
"Skip project-level context files (the store root is unaffected)."
|
|
41
57
|
("--global", "-g")
|
|
42
58
|
|
|
59
|
+
agents_dir: "Optional[Path]" = None
|
|
60
|
+
"User store root override (default: $AGENTS_HOME, else ~/.agents)."
|
|
61
|
+
("--agents-dir",)
|
|
62
|
+
|
|
43
63
|
agents: "list[str]" = []
|
|
44
64
|
"List of agents to generate context for (e.g. claude,gemini). Default: active agent."
|
|
45
65
|
("--agents",)
|
|
@@ -56,11 +76,12 @@ class Context(LoggingArgs, Cmd):
|
|
|
56
76
|
def __call__(self) -> int:
|
|
57
77
|
from dotagents import _agents
|
|
58
78
|
from dotagents import _context
|
|
79
|
+
from dotagents import _scope
|
|
59
80
|
import json
|
|
60
81
|
import os
|
|
61
82
|
|
|
62
|
-
project_root =
|
|
63
|
-
agents_dir =
|
|
83
|
+
project_root = _scope.project_root_default()
|
|
84
|
+
agents_dir = resolve_user_store(self.agents_dir)
|
|
64
85
|
|
|
65
86
|
agent_names = []
|
|
66
87
|
if self.agents:
|