dotagents-cli 0.3.0__tar.gz → 0.3.2__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 (73) hide show
  1. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/.gitignore +4 -0
  2. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/CHANGELOG.md +100 -0
  3. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/PKG-INFO +9 -3
  4. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/README.md +8 -2
  5. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/pyproject.toml +1 -1
  6. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/AGENTS.md +79 -6
  7. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/__init__.py +1 -1
  8. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_agents.py +373 -10
  9. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_context.py +13 -6
  10. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_hooks.py +22 -4
  11. dotagents_cli-0.3.2/src/dotagents/_overlay/dotagents/hooks/preinvocation_antigravity_context.py +123 -0
  12. dotagents_cli-0.3.2/src/dotagents/_overlay/dotagents/hooks/pretooluse_codex_env.py +90 -0
  13. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/cli/__init__.py +19 -4
  14. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/cli/_common.py +42 -0
  15. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/cli/build_pyz.py +31 -0
  16. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/cli/context.py +6 -1
  17. dotagents_cli-0.3.2/src/dotagents/cli/env.py +435 -0
  18. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/cli/init.py +3 -15
  19. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/cli/overlays.py +11 -43
  20. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/tests/test_agents.py +1 -1
  21. dotagents_cli-0.3.2/tests/test_build_pyz.py +51 -0
  22. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/tests/test_context.py +72 -4
  23. dotagents_cli-0.3.2/tests/test_env_format.py +502 -0
  24. dotagents_cli-0.3.2/tests/test_wire_hooks.py +887 -0
  25. dotagents_cli-0.3.0/src/dotagents/cli/env.py +0 -168
  26. dotagents_cli-0.3.0/tests/test_env_format.py +0 -230
  27. dotagents_cli-0.3.0/tests/test_wire_hooks.py +0 -439
  28. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/LICENSE +0 -0
  29. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/build.py +0 -0
  30. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/api/agents.md +0 -0
  31. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/api/cli.md +0 -0
  32. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/api/context.md +0 -0
  33. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/api/env.md +0 -0
  34. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/api/hooks.md +0 -0
  35. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/api/merge.md +0 -0
  36. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/api/overlays.md +0 -0
  37. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/api/reference.md +0 -0
  38. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/api/resolve.md +0 -0
  39. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/api/scope.md +0 -0
  40. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/api/skills.md +0 -0
  41. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/api/sync.md +0 -0
  42. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/changelog.md +0 -0
  43. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/guide/authoring.md +0 -0
  44. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/guide/commands.md +0 -0
  45. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/guide/install.md +0 -0
  46. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/guide/overlays.md +0 -0
  47. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/guide/private-sync.md +0 -0
  48. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/docs/index.md +0 -0
  49. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/install.py +0 -0
  50. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/mkdocs.yml +0 -0
  51. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/__main__.py +0 -0
  52. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_env.py +0 -0
  53. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_merge.py +0 -0
  54. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_overlay/AGENTS.md +0 -0
  55. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_overlay/CLAUDE.md +0 -0
  56. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_overlay/README.md +0 -0
  57. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_overlay/dotagents/DECISIONS.md +0 -0
  58. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_overlay/dotagents/cmds/README.md +0 -0
  59. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_overlays.py +0 -0
  60. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_resolve.py +0 -0
  61. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_scope.py +0 -0
  62. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_skills.py +0 -0
  63. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_sync.py +0 -0
  64. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/src/dotagents/_wrappers.py +0 -0
  65. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/tests/test_audit_leak.py +0 -0
  66. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/tests/test_cmds_discovery.py +0 -0
  67. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/tests/test_env.py +0 -0
  68. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/tests/test_hooks.py +0 -0
  69. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/tests/test_overlays_command.py +0 -0
  70. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/tests/test_scope.py +0 -0
  71. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/tests/test_wrappers.py +0 -0
  72. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/tools/audit.py +0 -0
  73. {dotagents_cli-0.3.0 → dotagents_cli-0.3.2}/tools/cloud-setup.sh +0 -0
@@ -34,3 +34,7 @@ Thumbs.db
34
34
  .idea/
35
35
  .vscode/
36
36
  _staging/
37
+
38
+ # `overlays` branch, checked out here as a worktree/clone for local editing
39
+ # (D77: example overlays split off this repo's main branch).
40
+ overlays/
@@ -7,6 +7,106 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.2] - 2026-07-25
11
+
12
+ ### Added
13
+
14
+ - feat: **`AntigravityAgent`** — context injection for Google's Antigravity
15
+ CLI/IDE (a separate product from Gemini CLI, despite sharing the `~/.gemini/`
16
+ namespace for some files). Antigravity's hooks have no `SessionStart`
17
+ equivalent — only `PreToolUse`/`PostToolUse`/`PreInvocation`/`PostInvocation`/
18
+ `Stop` — so a `PreInvocation` hook gated on `invocationNum == 0` behaves like a
19
+ one-shot context load instead of resending it every model turn. Wires into
20
+ `~/.gemini/config/hooks.json`. No detection marker exists for Antigravity, so
21
+ it's explicit-`--agents antigravity`-only, never auto-detected.
22
+ - feat: **Codex gets a `PreToolUse` env hook**, closing the one gap Codex had
23
+ versus Claude: Codex has no per-session env-persistence mechanism at any hook
24
+ event, so a deployed script prepends a guarded env-loader to every `Bash` tool
25
+ call via `updatedInput.command` — the same rewrite mechanism Claude's own
26
+ `PreToolUse` hook uses, confirmed directly against Codex's docs.
27
+ - feat: **`init` wires a PowerShell `PreToolUse` env hook on Windows**, closing
28
+ a real gap: `$CLAUDE_ENV_FILE` only reaches Claude's *Bash* tool
29
+ (`$env:CLAUDE_ENV_FILE` is empty inside a live PowerShell tool call, confirmed
30
+ directly) — a fresh PowerShell tool call gets none of the SessionStart env.
31
+ The hook prepends a guarded env-loader to a PowerShell tool call's own command,
32
+ shipped as an inline command string (never a `.ps1` file — a script file is
33
+ subject to PowerShell's execution policy, and dotagents has no code-signing
34
+ certificate; the inline form runs even under `Restricted`).
35
+ - feat: **`SessionStart`/`CwdChanged` now register two handlers each** — a
36
+ bash-syntax one and an explicit `shell: "powershell"` one — because Claude's
37
+ own hooks.md says the shell "defaults to bash, or to powershell on Windows
38
+ when Git Bash isn't installed": bash syntax fed to `powershell -Command` on
39
+ such a machine is a hard parse error, silently losing both env and context for
40
+ the whole session.
41
+ - feat: **`DotAgentsArgs`** (`dotagents.cli`, re-exported for overlay-shipped
42
+ commands) — one shared `-g/--global` + `--agents-dir` base class. `init` and
43
+ all four `overlays` subcommands now inherit it instead of independently
44
+ redeclaring the same fields, so scope resolution can't silently drift between
45
+ commands (one previously defaulted `agents_dir` eagerly to `Path.home() /
46
+ ".agents"`; harmless in practice, but needless).
47
+
48
+ ### Fixed
49
+
50
+ - fix: **`dotagents env --format powershell`/`cmd` left an already-POSIX `PATH`
51
+ unconverted**, the mirror of the export/dotenv/fish fix below going the other
52
+ direction. Found live: run from a genuine Windows PowerShell terminal whose
53
+ own inherited `PATH` already held WSL/MSYS-mount-style entries
54
+ (`/mnt/c/Program Files/...`), the emitted `${env:PATH} = '...'` was
55
+ syntactically valid PowerShell but a single opaque colon-joined string, not
56
+ the `;`-split list PowerShell's own PATH lookup needs — every subsequent
57
+ bare-command lookup broke for that session. Also handles the MIXED case
58
+ (dotagents' own native bin dirs prepended onto an already-POSIX inherited
59
+ PATH, one string with both separators at once), caught by sourcing real
60
+ output into a live PowerShell session and watching `git.exe` fail to
61
+ resolve before the second fix. A WSL-only segment with no Windows equivalent
62
+ (`/usr/bin`) is dropped rather than mangled into a broken relative path.
63
+ - fix: **the built `.pyz` degraded `-g` on any discovered command inheriting a
64
+ dotagents-defined base class** (first hit by `DotAgentsArgs` above) — duho's
65
+ AST introspection walks the full MRO for a command's flags, but the zipapp
66
+ source-repoint shim only ever covered built-in command modules, not a base
67
+ class's own module (`dotagents.cli._common`). `--global` degraded to the
68
+ name-derived `--global-scope` and `-g` vanished silently. Fixed, with new CI
69
+ coverage asserting the exact short flag survives a real built pyz.
70
+ - fix: **`harness_loads` relative entries matched by bare filename, not full
71
+ path** — a relative entry like Codex's `"AGENTS.md"` wrongly suppressed ANY
72
+ file sharing that basename anywhere on disk, including the unrelated
73
+ `~/.agents/AGENTS.md` user-store file Codex's harness never reads.
74
+ `dotagents context --agents codex` emitted an empty `sources: []` even with
75
+ real content present. Now resolved against `project_root` and compared by
76
+ full path, like the absolute (`~/`, `/`) forms already were.
77
+ - fix: `dotagents context --format json` crashed with `UnicodeEncodeError` on
78
+ any character outside Latin-1 (a bare `print()` encoding with the console's
79
+ codepage) — the same class of bug already fixed for the markdown path, just
80
+ never covered for JSON.
81
+ - fix: PowerShell format uses `${env:NAME}` (curly-brace form), not the bare
82
+ `$env:NAME` sigil — a handful of real Windows env vars have parens in their
83
+ names (`ProgramFiles(x86)`), and `$env:FOO(X86) = ...` is a PowerShell parse
84
+ error; the curly-brace form is valid for every name.
85
+
86
+ ## [0.3.1] - 2026-07-24
87
+
88
+ ### Fixed
89
+
90
+ - fix: **`dotagents env --format export`/`dotenv`/`fish` now emit a POSIX PATH on
91
+ Windows**, instead of the OS-native `C:\...;C:\...` form. This is the exact
92
+ command the Claude `SessionStart` hook appends into `$CLAUDE_ENV_FILE`, which
93
+ Claude sources before *every* subsequent Bash tool call in the session — an
94
+ unconverted PATH broke command lookup (`git`, `grep`, `head`, `python`, ...) for
95
+ the rest of the session once poisoned, not just once. PATH-shaped values are
96
+ now converted per segment: backslash to forward-slash, `;` to `:`, and a drive
97
+ letter to its MSYS mount point (`C:/...` -> `/c/...` — required for PATH
98
+ *lookups* specifically; slash direction alone does not work in MSYS2/Cygwin
99
+ bash). `PATHEXT` is dropped (no POSIX meaning). A handful of real Windows env
100
+ vars with parentheses in their names (`ProgramFiles(x86)`) are also dropped for
101
+ these formats — `export FOO(X86)=...` is a bash syntax error, not a bad value,
102
+ and aborts sourcing the rest of the file. `powershell`/`cmd`/`json`/`ini`/`yaml`
103
+ are unaffected.
104
+ - fix: a UNC PATH segment (`\\server\share\...`) no longer collapses to a single
105
+ leading slash (`/server/share/...`) during the POSIX conversion above — MSYS
106
+ requires the double-slash UNC root (`//server/share/...`) to resolve it.
107
+
108
+ Patch release: the PATH/POSIX-conversion fix above (the only change since 0.3.0).
109
+
10
110
  ## [0.3.0] - 2026-07-24
11
111
 
12
112
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dotagents-cli
3
- Version: 0.3.0
3
+ Version: 0.3.2
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
@@ -62,6 +62,7 @@ Description-Content-Type: text/markdown
62
62
  # dotagents
63
63
 
64
64
  [![Test](https://img.shields.io/github/actions/workflow/status/jose-pr/dotagents/test.yml?branch=main&label=tests)](https://github.com/jose-pr/dotagents/actions/workflows/test.yml)
65
+ [![PyPI](https://img.shields.io/pypi/v/dotagents-cli.svg)](https://pypi.org/project/dotagents-cli/)
65
66
  [![Documentation](https://img.shields.io/badge/docs-online-blue.svg)](https://jose-pr.github.io/dotagents/)
66
67
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/jose-pr/dotagents/blob/main/LICENSE)
67
68
 
@@ -123,8 +124,13 @@ manifest read by the `dotagents overlays` subcommand, which manages overlays by
123
124
 
124
125
  ## Install
125
126
 
126
- **`dotagents init`** lays down the neutral base config; a self-contained downloadable
127
- `.pyz` needs no `pip install` at all.
127
+ ```bash
128
+ pip install dotagents-cli # gives you `import dotagents` and the `dotagents` command
129
+ ```
130
+
131
+ Or skip `pip` entirely with the self-contained downloadable `.pyz` (see below).
132
+
133
+ **`dotagents init`** lays down the neutral base config.
128
134
 
129
135
  `init` writes the `.agents/` scaffolding — the `AGENTS.md` managed block, the per-agent
130
136
  `<CLAUDE|ANTIGRAVITY|...>.md → @AGENTS.md` pattern, the design-log convention — and
@@ -1,6 +1,7 @@
1
1
  # dotagents
2
2
 
3
3
  [![Test](https://img.shields.io/github/actions/workflow/status/jose-pr/dotagents/test.yml?branch=main&label=tests)](https://github.com/jose-pr/dotagents/actions/workflows/test.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/dotagents-cli.svg)](https://pypi.org/project/dotagents-cli/)
4
5
  [![Documentation](https://img.shields.io/badge/docs-online-blue.svg)](https://jose-pr.github.io/dotagents/)
5
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/jose-pr/dotagents/blob/main/LICENSE)
6
7
 
@@ -62,8 +63,13 @@ manifest read by the `dotagents overlays` subcommand, which manages overlays by
62
63
 
63
64
  ## Install
64
65
 
65
- **`dotagents init`** lays down the neutral base config; a self-contained downloadable
66
- `.pyz` needs no `pip install` at all.
66
+ ```bash
67
+ pip install dotagents-cli # gives you `import dotagents` and the `dotagents` command
68
+ ```
69
+
70
+ Or skip `pip` entirely with the self-contained downloadable `.pyz` (see below).
71
+
72
+ **`dotagents init`** lays down the neutral base config.
67
73
 
68
74
  `init` writes the `.agents/` scaffolding — the `AGENTS.md` managed block, the per-agent
69
75
  `<CLAUDE|ANTIGRAVITY|...>.md → @AGENTS.md` pattern, the design-log convention — and
@@ -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.0"
12
+ version = "0.3.2"
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"
@@ -59,13 +59,86 @@ can read it without the source. Full docs: https://jose-pr.github.io/dotagents/
59
59
  `hooks.<Event>` is a **list of matcher-objects** each holding its own `hooks` list,
60
60
  not a flat command list. Foreign hooks are preserved verbatim, malformed entries
61
61
  are dropped rather than raising, and invalid JSON raises `SystemExit` instead of
62
- silently overwriting the user's file. Pure stdlib. Consumed by
62
+ silently overwriting the user's file. `shell` (Claude: `"bash"`/`"powershell"`,
63
+ picks the interpreter for the hook's own command) and `command_windows`
64
+ (Codex: emitted as `commandWindows`, a separate Windows-only command OVERRIDE,
65
+ not an interpreter choice) are both supported. Pure stdlib. Consumed by
63
66
  `ClaudeAgent.wire_hooks` (`~/.claude/settings.json`: env via `$CLAUDE_ENV_FILE`
64
- + context via stdout, plus `CwdChanged`) and `CodexAgent.wire_hooks`
65
- (`<CODEX_HOME|~/.codex>/hooks.json`: context only — no env-file equivalent — and
66
- never `config.toml`). Codex's hook JSON is structurally identical to Claude's, so
67
- the same merge serves both. Gemini/Cursor/Copilot keep the base no-op: no
68
- published schema to target.
67
+ + context via stdout, plus `CwdChanged`, plus a `PreToolUse` env-loader for the
68
+ PowerShell tool) and `CodexAgent.wire_hooks` (`<CODEX_HOME|~/.codex>/hooks.json`,
69
+ never `config.toml`: `SessionStart` context-only, plus a `PreToolUse` env-loader
70
+ matched on `matcher: "Bash"`). Codex's hook JSON is structurally identical to
71
+ Claude's, including the SAME `updatedInput.command` rewrite mechanism on
72
+ `PreToolUse` — confirmed directly against Codex's own docs
73
+ (learn.chatgpt.com/docs/hooks), not assumed from Claude parity.
74
+ Gemini/Cursor/Copilot keep the base no-op — Gemini CLI proper has no hook
75
+ mechanism documented at all (checked directly). **Antigravity is a separate
76
+ product** from Gemini CLI (Antigravity CLI/IDE/SDK family, shares only the
77
+ `~/.gemini/` namespace for some files) and DOES wire a hook: see
78
+ `AntigravityAgent.wire_hooks` below. `PreToolUse` there is still allow/deny/ask
79
+ only — no `updatedInput`, so no command-rewrite/env-loader path exists to hang
80
+ on it, unlike Claude/Codex. Revisit both conclusions if either framework changes.
81
+ - **`AntigravityAgent.wire_hooks`** (`<AGENTS_HOME_ANTIGRAVITY|~/.gemini/config>/hooks.json`,
82
+ keyed under a `"dotagents"` name per the docs' own example shape — a named-entry
83
+ object, not Claude/Codex's flat `hooks.<Event>`): wires a single `PreInvocation`
84
+ entry, context-only, no env mechanism. Antigravity's hooks
85
+ (antigravity.google/docs/hooks) have exactly five events — `PreToolUse`,
86
+ `PostToolUse`, `PreInvocation`, `PostInvocation`, `Stop` — no SessionStart
87
+ equivalent. `PreInvocation` fires every model turn (`invocationNum`, 0-indexed),
88
+ so the deployed script (`preinvocation_antigravity_context.py`,
89
+ `_overlay/dotagents/hooks/`) gates on `invocationNum == 0` to behave like a
90
+ one-shot SessionStart rather than resending context every turn. Output shape is
91
+ a bare `{"injectSteps": [{"ephemeralMessage": "..."}]}`, no `hookSpecificOutput`
92
+ wrapper — confirmed against the primary docs after an earlier pass here wrongly
93
+ concluded no useful injection was possible; `ephemeralMessage` is the one of the
94
+ three step types meant for free text (`toolCall` executes a tool,
95
+ `userMessage` impersonates the user). No detection marker exists anywhere in
96
+ Antigravity's docs, so `detect_env_vars = []` — explicit `--agents antigravity`
97
+ only, same posture as Codex's env-block precedent (writes touching an agent's
98
+ own live config are opt-in, never inferred).
99
+ - **`SessionStart`/`CwdChanged` register TWO handlers each**, bash-syntax
100
+ (default shell) and a PowerShell-native equivalent (`shell: "powershell"`).
101
+ hooks.md: `shell` "Defaults to bash, or to powershell on Windows when Git Bash
102
+ isn't installed" — verified directly that bash syntax fed to `powershell
103
+ -Command` on such a machine is a hard parse error, not a soft failure, so
104
+ every session there would silently get neither env nor context. Every handler
105
+ in a matched group fires unconditionally (hooks.md), so both always run; the
106
+ one whose interpreter is absent fails harmlessly. The PowerShell
107
+ `SessionStart` variant is context-only (`dotagents context`), not
108
+ env+context: `$CLAUDE_ENV_FILE`'s documented effect is "subsequent BASH
109
+ commands" regardless of which shell wrote it, so writing to it from a
110
+ PowerShell-shelled hook would feed nothing.
111
+ - **Windows only**: `ClaudeAgent._wire_powershell_pretooluse` additionally wires
112
+ a no-matcher `PreToolUse` hook (fires on every tool call), `shell:
113
+ "powershell"`, running `PRETOOLUSE_POWERSHELL_COMMAND` INLINE — deliberately
114
+ not a `.ps1` file, since a script file is subject to PowerShell's execution
115
+ policy (RemoteSigned/AllSigned/Restricted) and dotagents has no code-signing
116
+ certificate; verified directly that the inline form runs successfully even
117
+ under `Restricted`, which blocks every `.ps1` file outright. Closes a real
118
+ gap: `$CLAUDE_ENV_FILE` is Bash-tool-only (confirmed empirically that
119
+ `$env:CLAUDE_ENV_FILE` is empty inside a live PowerShell tool call), so the
120
+ SessionStart env half never reaches the PowerShell tool. Uses `PreToolUse`'s
121
+ `updatedInput` to prepend a guarded env-loader (`AGENTS_RUNTIME_SET`,
122
+ matching the precursor's convention) to a `PowerShell` tool call's own
123
+ command — not by trying to persist state across hook invocations, which are
124
+ each their own fresh process and cannot. Whether the guard is visible across
125
+ separate PowerShell tool calls is UNVERIFIED. Every literal `\` in the
126
+ command constant must be a raw string — a bare `\b` in a normal Python string
127
+ literal silently becomes a backspace character, corrupting the emitted path;
128
+ caught once by testing a draft through a real PowerShell spawn.
129
+ - **`CodexAgent._deploy_pretooluse_script`** covers the same env gap for Codex,
130
+ which has NO env-persistence mechanism at any hook event (not Bash-only like
131
+ Claude — none). Ships `pretooluse_codex_env.py` (`_overlay/dotagents/hooks/`),
132
+ deployed to `<codex-home>/hooks/` (create-or-refresh), wired as `PreToolUse`
133
+ with `matcher: "Bash"` — Codex's one shell tool, so (unlike Claude's
134
+ no-matcher hook) filtering happens at the settings level, no runtime
135
+ `tool_name` check needed in the script. A FILE, not inlined like Claude's:
136
+ Codex's docs show every hook example as `python3 <path>`, and a `.py` file
137
+ has no execution-policy/signing concern (PowerShell-specific). Sets
138
+ `commandWindows` to `python "<path>"` (not `python3`) — verified directly
139
+ that `python3` resolves to the Microsoft Store app-execution-alias stub and
140
+ fails outright on this dev machine (exit 49), the same trap noted elsewhere
141
+ for `py`/venv creation.
69
142
  - `_sync` — `PathSyncer` wrapper reproducing `install`'s backup/copy/report; requires
70
143
  `pathlib_next.Path` instances (not plain `pathlib.Path`) and a pre-created parent dir.
71
144
 
@@ -1,3 +1,3 @@
1
1
  """dotagents: installable CLI for the dotagents agent-config payload."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.3.2"