codexmgr 0.1.1__tar.gz → 0.1.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 (57) hide show
  1. {codexmgr-0.1.1 → codexmgr-0.1.2}/.gitignore +4 -0
  2. {codexmgr-0.1.1 → codexmgr-0.1.2}/PKG-INFO +130 -8
  3. {codexmgr-0.1.1 → codexmgr-0.1.2}/README.md +127 -7
  4. {codexmgr-0.1.1 → codexmgr-0.1.2}/pyproject.toml +5 -2
  5. {codexmgr-0.1.1 → codexmgr-0.1.2}/src/codexmgr/__init__.py +1 -1
  6. {codexmgr-0.1.1 → codexmgr-0.1.2}/src/codexmgr/agents_file.py +15 -1
  7. codexmgr-0.1.2/src/codexmgr/agentsmd.py +210 -0
  8. {codexmgr-0.1.1 → codexmgr-0.1.2}/src/codexmgr/cli.py +61 -58
  9. codexmgr-0.1.2/src/codexmgr/cli_parser.py +239 -0
  10. codexmgr-0.1.2/src/codexmgr/health.py +210 -0
  11. codexmgr-0.1.2/src/codexmgr/mcp.py +293 -0
  12. codexmgr-0.1.2/src/codexmgr/mcp_apply.py +69 -0
  13. codexmgr-0.1.2/src/codexmgr/mcp_cli.py +190 -0
  14. codexmgr-0.1.2/src/codexmgr/mcp_discovery.py +120 -0
  15. codexmgr-0.1.2/src/codexmgr/mcp_fields.py +150 -0
  16. codexmgr-0.1.2/src/codexmgr/navigation.py +156 -0
  17. codexmgr-0.1.2/src/codexmgr/options.py +35 -0
  18. codexmgr-0.1.2/src/codexmgr/project.py +206 -0
  19. {codexmgr-0.1.1 → codexmgr-0.1.2}/src/codexmgr/project_config.py +7 -8
  20. codexmgr-0.1.2/src/codexmgr/skill_listing.py +152 -0
  21. {codexmgr-0.1.1 → codexmgr-0.1.2}/src/codexmgr/skills.py +17 -12
  22. codexmgr-0.1.2/src/codexmgr/sync.py +134 -0
  23. {codexmgr-0.1.1 → codexmgr-0.1.2}/src/codexmgr/toml_io.py +90 -69
  24. codexmgr-0.1.2/tests/test_agentsmd_list_cli.py +87 -0
  25. codexmgr-0.1.2/tests/test_agentsmd_tools_cli.py +111 -0
  26. codexmgr-0.1.2/tests/test_apply_check_cli.py +83 -0
  27. codexmgr-0.1.2/tests/test_cd_cli.py +145 -0
  28. codexmgr-0.1.2/tests/test_mcp_apply_cli.py +119 -0
  29. codexmgr-0.1.2/tests/test_mcp_cli.py +308 -0
  30. codexmgr-0.1.2/tests/test_skill_list_cli.py +52 -0
  31. codexmgr-0.1.2/tests/test_status_doctor_cli.py +164 -0
  32. {codexmgr-0.1.1 → codexmgr-0.1.2}/tests/test_toml_io.py +7 -0
  33. codexmgr-0.1.2/uv.lock +158 -0
  34. codexmgr-0.1.1/src/codexmgr/agentsmd.py +0 -96
  35. codexmgr-0.1.1/src/codexmgr/project.py +0 -74
  36. codexmgr-0.1.1/uv.lock +0 -86
  37. {codexmgr-0.1.1 → codexmgr-0.1.2}/.github/actions/install_package/action.yml +0 -0
  38. {codexmgr-0.1.1 → codexmgr-0.1.2}/.github/workflows/py_test.yml +0 -0
  39. {codexmgr-0.1.1 → codexmgr-0.1.2}/.github/workflows/version_publish_main.yml +0 -0
  40. {codexmgr-0.1.1 → codexmgr-0.1.2}/pytest.toml +0 -0
  41. {codexmgr-0.1.1 → codexmgr-0.1.2}/src/codexmgr/codex.py +0 -0
  42. {codexmgr-0.1.1 → codexmgr-0.1.2}/src/codexmgr/errors.py +0 -0
  43. {codexmgr-0.1.1 → codexmgr-0.1.2}/src/codexmgr/paths.py +0 -0
  44. {codexmgr-0.1.1 → codexmgr-0.1.2}/src/codexmgr/py.typed +0 -0
  45. {codexmgr-0.1.1 → codexmgr-0.1.2}/src/codexmgr/renderer.py +0 -0
  46. {codexmgr-0.1.1 → codexmgr-0.1.2}/tests/conftest.py +0 -0
  47. {codexmgr-0.1.1 → codexmgr-0.1.2}/tests/test_agents_file.py +0 -0
  48. {codexmgr-0.1.1 → codexmgr-0.1.2}/tests/test_cli.py +0 -0
  49. {codexmgr-0.1.1 → codexmgr-0.1.2}/tests/test_codex_cli.py +0 -0
  50. {codexmgr-0.1.1 → codexmgr-0.1.2}/tests/test_empty_skill_config_cli.py +0 -0
  51. {codexmgr-0.1.1 → codexmgr-0.1.2}/tests/test_home_resolution_cli.py +0 -0
  52. {codexmgr-0.1.1 → codexmgr-0.1.2}/tests/test_package_metadata.py +0 -0
  53. {codexmgr-0.1.1 → codexmgr-0.1.2}/tests/test_paths.py +0 -0
  54. {codexmgr-0.1.1 → codexmgr-0.1.2}/tests/test_python_compatibility.py +0 -0
  55. {codexmgr-0.1.1 → codexmgr-0.1.2}/tests/test_renderer.py +0 -0
  56. {codexmgr-0.1.1 → codexmgr-0.1.2}/tests/test_skills_cli.py +0 -0
  57. {codexmgr-0.1.1 → codexmgr-0.1.2}/tests/test_sync_cli.py +0 -0
@@ -9,3 +9,7 @@ wheels/
9
9
  # Virtual environments
10
10
  .venv
11
11
  AGENTS.md
12
+ tasks.md
13
+ .thoughts
14
+ .plan
15
+ .agent
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codexmgr
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Manage project-local Codex configuration from reusable templates
5
5
  Keywords: agents,cli,codex,configuration,skills
6
6
  Classifier: Development Status :: 4 - Beta
@@ -13,8 +13,10 @@ Classifier: Programming Language :: Python :: 3.13
13
13
  Classifier: Topic :: Software Development
14
14
  Classifier: Typing :: Typed
15
15
  Requires-Python: >=3.11
16
+ Requires-Dist: tomlkit>=0.15.0
16
17
  Provides-Extra: dev
17
18
  Requires-Dist: pytest>=9.0.3; extra == 'dev'
19
+ Requires-Dist: pyyaml>=6.0.3; extra == 'dev'
18
20
  Description-Content-Type: text/markdown
19
21
 
20
22
  # codexmgr
@@ -22,12 +24,14 @@ Description-Content-Type: text/markdown
22
24
  `codexmgr` manages project-local Codex configuration from reusable templates.
23
25
  It keeps hand-written project instructions in `AGENTS.md` and generated Codex
24
26
  configuration in `.codex/` synchronized from a small declarative
25
- `.codex/codexmgr.toml` file.
27
+ `.codex/codexmgr.toml` file. It can also keep project-local MCP server
28
+ overrides in sync without editing the user Codex config.
26
29
 
27
30
  The tool is intentionally narrow:
28
31
 
29
32
  - compose reusable AGENTS.md instruction fragments
30
33
  - enable or disable Codex skills per project
34
+ - enable, disable, inspect, and update safe project-local MCP overrides
31
35
  - write reproducible lock data for the resolved project configuration
32
36
  - run `codex` with project `.codex/config.toml` values translated into `-c`
33
37
  overrides
@@ -91,8 +95,10 @@ This updates `.codex/codexmgr.toml`, runs `apply`, writes
91
95
 
92
96
  - `.codex/codexmgr.toml`: source configuration edited by CLI commands or by
93
97
  hand
94
- - `.codex/codexmgr.lock`: resolved template and skill state written by `apply`
98
+ - `.codex/codexmgr.lock`: resolved template, skill, and MCP state written by
99
+ `apply`
95
100
  - `.codex/config.toml`: Codex config updated with `[[skills.config]]` entries
101
+ and `[mcp_servers.<id>]` overrides
96
102
  - `AGENTS.md`: project instructions, with only the managed block replaced
97
103
 
98
104
  The managed AGENTS.md block is:
@@ -107,7 +113,8 @@ Manual content outside this block is preserved. If the block is missing,
107
113
 
108
114
  ## Project Configuration
109
115
 
110
- `.codex/codexmgr.toml` supports AGENTS.md templates and skill state:
116
+ `.codex/codexmgr.toml` supports AGENTS.md templates, skill state, and MCP
117
+ overrides:
111
118
 
112
119
  ```toml
113
120
  [agents_md]
@@ -116,6 +123,11 @@ src = ["coding", "/absolute/or/project-relative/template.toml"]
116
123
  [skills]
117
124
  enabled = ["review-helper"]
118
125
  disabled = ["experimental-skill", "skills/local-disabled"]
126
+
127
+ [mcp.servers.browsermcp]
128
+ enabled = true
129
+ bearer_token_env_var = "BROWSERMCP_TOKEN"
130
+ env_vars = ["BROWSER_ENV"]
119
131
  ```
120
132
 
121
133
  Named AGENTS.md templates resolve from `$CODEXMGR_HOME/agentsmd/<name>.toml`.
@@ -163,10 +175,31 @@ keeps template mistakes visible during `apply`.
163
175
  ```bash
164
176
  codexmgr setup
165
177
  codexmgr apply
178
+ codexmgr apply --check
179
+ codexmgr apply --diff
180
+ codexmgr cd [--path | --explorer | --terminal]
181
+ codexmgr doctor
182
+ codexmgr status
183
+ codexmgr agentsmd list
184
+ codexmgr agentsmd show <name-or-template-path>
185
+ codexmgr agentsmd validate <name-or-template-path>
166
186
  codexmgr agentsmd add [--no-sync] <name-or-template-path>
167
187
  codexmgr agentsmd remove [--no-sync] <name-or-template-path>
188
+ codexmgr init-template agentsmd <name>
189
+ codexmgr skill list
168
190
  codexmgr skill enable [--no-sync] <name-or-skill-path>
169
191
  codexmgr skill disable [--no-sync] <name-or-skill-path>
192
+ codexmgr mcp list
193
+ codexmgr mcp show <server-id>
194
+ codexmgr mcp validate
195
+ codexmgr mcp enable [--no-sync] <server-id>
196
+ codexmgr mcp disable [--no-sync] <server-id>
197
+ codexmgr mcp set-token-env [--no-sync] <server-id> <ENV_VAR>
198
+ codexmgr mcp add-env-var [--no-sync] <server-id> <ENV_VAR>
199
+ codexmgr mcp remove-env-var [--no-sync] <server-id> <ENV_VAR>
200
+ codexmgr mcp set-env-header [--no-sync] <server-id> <HEADER> <ENV_VAR>
201
+ codexmgr mcp unset-env-header [--no-sync] <server-id> <HEADER>
202
+ codexmgr mcp set-field [--no-sync] <server-id> <field> <toml-value>
170
203
  codexmgr codex <args...>
171
204
  ```
172
205
 
@@ -174,8 +207,91 @@ codexmgr codex <args...>
174
207
 
175
208
  `apply` reads `.codex/codexmgr.toml`, resolves configured sources, writes
176
209
  `.codex/codexmgr.lock`, updates `.codex/config.toml` skill entries when a
177
- `[skills]` table is configured, and refreshes the generated `AGENTS.md` block
178
- when `[agents_md]` is configured.
210
+ `[skills]` table is configured, writes local `[mcp_servers.<id>]` overrides when
211
+ `[mcp]` is configured, and refreshes the generated `AGENTS.md` block when
212
+ `[agents_md]` is configured.
213
+
214
+ `apply --check` exits with a failure if generated files are out of sync without
215
+ writing them. `apply --diff` also avoids writing and prints unified diffs for
216
+ the expected generated-file changes.
217
+
218
+ `cd` launches a shell in `$CODEXMGR_HOME`. Use
219
+ `codexmgr cd --path` to print only the path, `codexmgr cd --explorer` to open
220
+ the directory in a file explorer, and `codexmgr cd --terminal` to open a new
221
+ terminal there.
222
+
223
+ `doctor` checks project setup, home environment variables, project TOML syntax,
224
+ referenced snippets, enabled skills, and stale generated files.
225
+
226
+ `status` prints the resolved homes, configured snippets and skills, and whether
227
+ generated files are in sync.
228
+
229
+ ## Project MCP Overrides
230
+
231
+ `codexmgr mcp ...` edits only project-local configuration:
232
+
233
+ - source state is stored in `.codex/codexmgr.toml` under
234
+ `[mcp.servers.<id>]`
235
+ - `apply` writes generated overrides into `.codex/config.toml` under
236
+ `[mcp_servers.<id>]`
237
+ - `$CODEX_HOME/config.toml` and `~/.codex/config.toml` are never modified
238
+
239
+ Mutating MCP commands require a project `.codex/` directory and run `apply`
240
+ automatically unless `--no-sync` is passed. They do not create or remove MCP
241
+ server definitions; use `codex mcp add` or direct Codex config editing for the
242
+ base server setup.
243
+
244
+ List MCP servers available from Codex and show any project override state:
245
+
246
+ ```bash
247
+ codexmgr mcp list
248
+ codexmgr mcp show context7
249
+ codexmgr mcp validate
250
+ ```
251
+
252
+ `codexmgr mcp list` shells out to `codex mcp list --json` for read-only
253
+ discovery. It does not edit user configuration.
254
+
255
+ Enable or disable an existing server without deleting its definition:
256
+
257
+ ```bash
258
+ codexmgr mcp disable context7
259
+ codexmgr mcp enable context7
260
+ ```
261
+
262
+ Update token and environment references without storing literal token values:
263
+
264
+ ```bash
265
+ codexmgr mcp set-token-env figma FIGMA_TOKEN
266
+ codexmgr mcp add-env-var context7 CONTEXT7_TOKEN
267
+ codexmgr mcp remove-env-var context7 CONTEXT7_TOKEN
268
+ codexmgr mcp set-env-header figma Authorization FIGMA_AUTH_HEADER
269
+ codexmgr mcp unset-env-header figma Authorization
270
+ ```
271
+
272
+ Set a small allowlist of non-secret fields from TOML literals:
273
+
274
+ ```bash
275
+ codexmgr mcp set-field context7 required true
276
+ codexmgr mcp set-field context7 enabled_tools '["search", "open"]'
277
+ codexmgr mcp set-field context7 default_tools_approval_mode '"prompt"'
278
+ ```
279
+
280
+ Supported `set-field` names are `required`, `startup_timeout_sec`,
281
+ `tool_timeout_sec`, `enabled_tools`, `disabled_tools`, and
282
+ `default_tools_approval_mode`. The direct `enable` and `disable` commands manage
283
+ the `enabled` field.
284
+
285
+ Literal API token writes are intentionally not part of this command surface;
286
+ prefer environment variable references such as `bearer_token_env_var`,
287
+ `env_vars`, and `env_http_headers`.
288
+
289
+ `agentsmd list` prints the named templates available under
290
+ `$CODEXMGR_HOME/agentsmd` in sorted order.
291
+
292
+ `agentsmd show` renders one template as AGENTS.md markdown without changing the
293
+ project configuration. `agentsmd validate` loads and renders a template to catch
294
+ TOML or template-shape errors before adding it.
179
295
 
180
296
  `agentsmd add` validates that the template exists before writing config.
181
297
  Repeated adds keep one source entry.
@@ -183,6 +299,12 @@ Repeated adds keep one source entry.
183
299
  `agentsmd remove` removes a configured template source and fails if the source
184
300
  is not present.
185
301
 
302
+ `init-template agentsmd` creates a starter template under
303
+ `$CODEXMGR_HOME/agentsmd` and refuses to overwrite an existing template.
304
+
305
+ `skill list` prints available `$CODEX_HOME/skills/*/SKILL.md` entries and marks
306
+ configured skills as enabled, disabled, or missing.
307
+
186
308
  `skill enable` and `skill disable` keep enabled and disabled lists mutually
187
309
  exclusive. Repeated commands keep one entry.
188
310
 
@@ -212,8 +334,8 @@ uv build
212
334
  ```
213
335
 
214
336
  The package is typed (`py.typed`) and the test suite covers CLI behavior,
215
- template rendering, TOML writing, skill resolution, Codex command generation,
216
- home-directory resolution, and package metadata.
337
+ template rendering, TOML writing, skill resolution, generated-file sync checks,
338
+ Codex command generation, home-directory resolution, and package metadata.
217
339
 
218
340
  ## Release Notes
219
341
 
@@ -3,12 +3,14 @@
3
3
  `codexmgr` manages project-local Codex configuration from reusable templates.
4
4
  It keeps hand-written project instructions in `AGENTS.md` and generated Codex
5
5
  configuration in `.codex/` synchronized from a small declarative
6
- `.codex/codexmgr.toml` file.
6
+ `.codex/codexmgr.toml` file. It can also keep project-local MCP server
7
+ overrides in sync without editing the user Codex config.
7
8
 
8
9
  The tool is intentionally narrow:
9
10
 
10
11
  - compose reusable AGENTS.md instruction fragments
11
12
  - enable or disable Codex skills per project
13
+ - enable, disable, inspect, and update safe project-local MCP overrides
12
14
  - write reproducible lock data for the resolved project configuration
13
15
  - run `codex` with project `.codex/config.toml` values translated into `-c`
14
16
  overrides
@@ -72,8 +74,10 @@ This updates `.codex/codexmgr.toml`, runs `apply`, writes
72
74
 
73
75
  - `.codex/codexmgr.toml`: source configuration edited by CLI commands or by
74
76
  hand
75
- - `.codex/codexmgr.lock`: resolved template and skill state written by `apply`
77
+ - `.codex/codexmgr.lock`: resolved template, skill, and MCP state written by
78
+ `apply`
76
79
  - `.codex/config.toml`: Codex config updated with `[[skills.config]]` entries
80
+ and `[mcp_servers.<id>]` overrides
77
81
  - `AGENTS.md`: project instructions, with only the managed block replaced
78
82
 
79
83
  The managed AGENTS.md block is:
@@ -88,7 +92,8 @@ Manual content outside this block is preserved. If the block is missing,
88
92
 
89
93
  ## Project Configuration
90
94
 
91
- `.codex/codexmgr.toml` supports AGENTS.md templates and skill state:
95
+ `.codex/codexmgr.toml` supports AGENTS.md templates, skill state, and MCP
96
+ overrides:
92
97
 
93
98
  ```toml
94
99
  [agents_md]
@@ -97,6 +102,11 @@ src = ["coding", "/absolute/or/project-relative/template.toml"]
97
102
  [skills]
98
103
  enabled = ["review-helper"]
99
104
  disabled = ["experimental-skill", "skills/local-disabled"]
105
+
106
+ [mcp.servers.browsermcp]
107
+ enabled = true
108
+ bearer_token_env_var = "BROWSERMCP_TOKEN"
109
+ env_vars = ["BROWSER_ENV"]
100
110
  ```
101
111
 
102
112
  Named AGENTS.md templates resolve from `$CODEXMGR_HOME/agentsmd/<name>.toml`.
@@ -144,10 +154,31 @@ keeps template mistakes visible during `apply`.
144
154
  ```bash
145
155
  codexmgr setup
146
156
  codexmgr apply
157
+ codexmgr apply --check
158
+ codexmgr apply --diff
159
+ codexmgr cd [--path | --explorer | --terminal]
160
+ codexmgr doctor
161
+ codexmgr status
162
+ codexmgr agentsmd list
163
+ codexmgr agentsmd show <name-or-template-path>
164
+ codexmgr agentsmd validate <name-or-template-path>
147
165
  codexmgr agentsmd add [--no-sync] <name-or-template-path>
148
166
  codexmgr agentsmd remove [--no-sync] <name-or-template-path>
167
+ codexmgr init-template agentsmd <name>
168
+ codexmgr skill list
149
169
  codexmgr skill enable [--no-sync] <name-or-skill-path>
150
170
  codexmgr skill disable [--no-sync] <name-or-skill-path>
171
+ codexmgr mcp list
172
+ codexmgr mcp show <server-id>
173
+ codexmgr mcp validate
174
+ codexmgr mcp enable [--no-sync] <server-id>
175
+ codexmgr mcp disable [--no-sync] <server-id>
176
+ codexmgr mcp set-token-env [--no-sync] <server-id> <ENV_VAR>
177
+ codexmgr mcp add-env-var [--no-sync] <server-id> <ENV_VAR>
178
+ codexmgr mcp remove-env-var [--no-sync] <server-id> <ENV_VAR>
179
+ codexmgr mcp set-env-header [--no-sync] <server-id> <HEADER> <ENV_VAR>
180
+ codexmgr mcp unset-env-header [--no-sync] <server-id> <HEADER>
181
+ codexmgr mcp set-field [--no-sync] <server-id> <field> <toml-value>
151
182
  codexmgr codex <args...>
152
183
  ```
153
184
 
@@ -155,8 +186,91 @@ codexmgr codex <args...>
155
186
 
156
187
  `apply` reads `.codex/codexmgr.toml`, resolves configured sources, writes
157
188
  `.codex/codexmgr.lock`, updates `.codex/config.toml` skill entries when a
158
- `[skills]` table is configured, and refreshes the generated `AGENTS.md` block
159
- when `[agents_md]` is configured.
189
+ `[skills]` table is configured, writes local `[mcp_servers.<id>]` overrides when
190
+ `[mcp]` is configured, and refreshes the generated `AGENTS.md` block when
191
+ `[agents_md]` is configured.
192
+
193
+ `apply --check` exits with a failure if generated files are out of sync without
194
+ writing them. `apply --diff` also avoids writing and prints unified diffs for
195
+ the expected generated-file changes.
196
+
197
+ `cd` launches a shell in `$CODEXMGR_HOME`. Use
198
+ `codexmgr cd --path` to print only the path, `codexmgr cd --explorer` to open
199
+ the directory in a file explorer, and `codexmgr cd --terminal` to open a new
200
+ terminal there.
201
+
202
+ `doctor` checks project setup, home environment variables, project TOML syntax,
203
+ referenced snippets, enabled skills, and stale generated files.
204
+
205
+ `status` prints the resolved homes, configured snippets and skills, and whether
206
+ generated files are in sync.
207
+
208
+ ## Project MCP Overrides
209
+
210
+ `codexmgr mcp ...` edits only project-local configuration:
211
+
212
+ - source state is stored in `.codex/codexmgr.toml` under
213
+ `[mcp.servers.<id>]`
214
+ - `apply` writes generated overrides into `.codex/config.toml` under
215
+ `[mcp_servers.<id>]`
216
+ - `$CODEX_HOME/config.toml` and `~/.codex/config.toml` are never modified
217
+
218
+ Mutating MCP commands require a project `.codex/` directory and run `apply`
219
+ automatically unless `--no-sync` is passed. They do not create or remove MCP
220
+ server definitions; use `codex mcp add` or direct Codex config editing for the
221
+ base server setup.
222
+
223
+ List MCP servers available from Codex and show any project override state:
224
+
225
+ ```bash
226
+ codexmgr mcp list
227
+ codexmgr mcp show context7
228
+ codexmgr mcp validate
229
+ ```
230
+
231
+ `codexmgr mcp list` shells out to `codex mcp list --json` for read-only
232
+ discovery. It does not edit user configuration.
233
+
234
+ Enable or disable an existing server without deleting its definition:
235
+
236
+ ```bash
237
+ codexmgr mcp disable context7
238
+ codexmgr mcp enable context7
239
+ ```
240
+
241
+ Update token and environment references without storing literal token values:
242
+
243
+ ```bash
244
+ codexmgr mcp set-token-env figma FIGMA_TOKEN
245
+ codexmgr mcp add-env-var context7 CONTEXT7_TOKEN
246
+ codexmgr mcp remove-env-var context7 CONTEXT7_TOKEN
247
+ codexmgr mcp set-env-header figma Authorization FIGMA_AUTH_HEADER
248
+ codexmgr mcp unset-env-header figma Authorization
249
+ ```
250
+
251
+ Set a small allowlist of non-secret fields from TOML literals:
252
+
253
+ ```bash
254
+ codexmgr mcp set-field context7 required true
255
+ codexmgr mcp set-field context7 enabled_tools '["search", "open"]'
256
+ codexmgr mcp set-field context7 default_tools_approval_mode '"prompt"'
257
+ ```
258
+
259
+ Supported `set-field` names are `required`, `startup_timeout_sec`,
260
+ `tool_timeout_sec`, `enabled_tools`, `disabled_tools`, and
261
+ `default_tools_approval_mode`. The direct `enable` and `disable` commands manage
262
+ the `enabled` field.
263
+
264
+ Literal API token writes are intentionally not part of this command surface;
265
+ prefer environment variable references such as `bearer_token_env_var`,
266
+ `env_vars`, and `env_http_headers`.
267
+
268
+ `agentsmd list` prints the named templates available under
269
+ `$CODEXMGR_HOME/agentsmd` in sorted order.
270
+
271
+ `agentsmd show` renders one template as AGENTS.md markdown without changing the
272
+ project configuration. `agentsmd validate` loads and renders a template to catch
273
+ TOML or template-shape errors before adding it.
160
274
 
161
275
  `agentsmd add` validates that the template exists before writing config.
162
276
  Repeated adds keep one source entry.
@@ -164,6 +278,12 @@ Repeated adds keep one source entry.
164
278
  `agentsmd remove` removes a configured template source and fails if the source
165
279
  is not present.
166
280
 
281
+ `init-template agentsmd` creates a starter template under
282
+ `$CODEXMGR_HOME/agentsmd` and refuses to overwrite an existing template.
283
+
284
+ `skill list` prints available `$CODEX_HOME/skills/*/SKILL.md` entries and marks
285
+ configured skills as enabled, disabled, or missing.
286
+
167
287
  `skill enable` and `skill disable` keep enabled and disabled lists mutually
168
288
  exclusive. Repeated commands keep one entry.
169
289
 
@@ -193,8 +313,8 @@ uv build
193
313
  ```
194
314
 
195
315
  The package is typed (`py.typed`) and the test suite covers CLI behavior,
196
- template rendering, TOML writing, skill resolution, Codex command generation,
197
- home-directory resolution, and package metadata.
316
+ template rendering, TOML writing, skill resolution, generated-file sync checks,
317
+ Codex command generation, home-directory resolution, and package metadata.
198
318
 
199
319
  ## Release Notes
200
320
 
@@ -1,10 +1,12 @@
1
1
  [project]
2
2
  name = "codexmgr"
3
- version = "0.1.1"
3
+ version = "0.1.2"
4
4
  description = "Manage project-local Codex configuration from reusable templates"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
7
- dependencies = []
7
+ dependencies = [
8
+ "tomlkit>=0.15.0",
9
+ ]
8
10
  keywords = ["codex", "cli", "configuration", "agents", "skills"]
9
11
  classifiers = [
10
12
  "Development Status :: 4 - Beta",
@@ -24,6 +26,7 @@ codexmgr = "codexmgr.cli:entrypoint"
24
26
  [project.optional-dependencies]
25
27
  dev = [
26
28
  "pytest>=9.0.3",
29
+ "pyyaml>=6.0.3",
27
30
  ]
28
31
 
29
32
  [build-system]
@@ -2,4 +2,4 @@
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "0.1.1"
5
+ __version__ = "0.1.2"
@@ -19,10 +19,24 @@ def write_managed_agents_md(path: Path, generated_markdown: str) -> None:
19
19
  None. The file is written with UTF-8 encoding.
20
20
  """
21
21
  current = path.read_text(encoding="utf-8") if path.exists() else ""
22
- updated = _replace_block(current, generated_markdown)
22
+ updated = render_managed_agents_md(current, generated_markdown)
23
23
  path.write_text(updated, encoding="utf-8")
24
24
 
25
25
 
26
+ def render_managed_agents_md(current: str, generated_markdown: str) -> str:
27
+ """Render AGENTS.md content with an updated managed block.
28
+
29
+ Args:
30
+ current: Existing AGENTS.md content, or an empty string for a new file.
31
+ generated_markdown: Markdown content for the managed block.
32
+
33
+ Returns:
34
+ Full AGENTS.md content with the codexmgr managed block replaced or
35
+ appended.
36
+ """
37
+ return _replace_block(current, generated_markdown)
38
+
39
+
26
40
  def _replace_block(current: str, generated_markdown: str) -> str:
27
41
  """Replace or append the generated block in AGENTS.md content.
28
42
 
@@ -0,0 +1,210 @@
1
+ """Manage configured AGENTS.md template sources and rendered output."""
2
+
3
+ from pathlib import Path
4
+ from typing import Any
5
+
6
+ from .agents_file import write_managed_agents_md
7
+ from .errors import CommandError
8
+ from .options import list_toml_options
9
+ from .paths import agents_md_path, config_path, resolve_template
10
+ from .project_config import (
11
+ agents_md_sources,
12
+ load_required_project_config,
13
+ require_codex_dir,
14
+ set_agents_md_sources,
15
+ )
16
+ from .renderer import render_agents_markdown
17
+ from .toml_io import load_optional_toml_file, load_toml_file, write_toml_file
18
+
19
+
20
+ def add_agentsmd(reference: str, cwd: Path, codexmgr_home: Path) -> str:
21
+ """Add an AGENTS.md template reference to project configuration.
22
+
23
+ Args:
24
+ reference: Named template or TOML path to add.
25
+ cwd: Project directory whose codexmgr.toml should be updated.
26
+ codexmgr_home: codexmgr home used to validate named template references.
27
+
28
+ Returns:
29
+ The reference that was added or already present.
30
+ """
31
+ require_codex_dir(cwd)
32
+ resolve_template(reference, cwd, codexmgr_home)
33
+
34
+ config = load_optional_toml_file(config_path(cwd))
35
+ sources = agents_md_sources(config)
36
+ if reference not in sources:
37
+ sources.append(reference)
38
+ set_agents_md_sources(config, sources)
39
+ write_toml_file(config_path(cwd), config)
40
+ return reference
41
+
42
+
43
+ def remove_agentsmd(source_id: str, cwd: Path) -> str:
44
+ """Remove an AGENTS.md template reference from project configuration.
45
+
46
+ Args:
47
+ source_id: Source identifier or reference to remove.
48
+ cwd: Project directory whose codexmgr.toml should be updated.
49
+
50
+ Returns:
51
+ The removed source identifier.
52
+ """
53
+ config = load_required_project_config(cwd)
54
+ sources = agents_md_sources(config)
55
+ if source_id not in sources:
56
+ raise CommandError(f"Source not found in codexmgr.toml: {source_id}")
57
+
58
+ set_agents_md_sources(config, [source for source in sources if source != source_id])
59
+ write_toml_file(config_path(cwd), config)
60
+ return source_id
61
+
62
+
63
+ def list_agentsmd_options(codexmgr_home: Path) -> list[str]:
64
+ """List named AGENTS.md template options available to add.
65
+
66
+ Args:
67
+ codexmgr_home: codexmgr home directory containing the ``agentsmd``
68
+ template store.
69
+
70
+ Returns:
71
+ Sorted template names that can be passed to ``codexmgr agentsmd add``.
72
+ """
73
+ return list_toml_options(codexmgr_home / "agentsmd")
74
+
75
+
76
+ def show_agentsmd(reference: str, cwd: Path, codexmgr_home: Path) -> str:
77
+ """Render one AGENTS.md template reference as markdown.
78
+
79
+ Args:
80
+ reference: Named template or TOML path to render.
81
+ cwd: Project directory used to resolve path references.
82
+ codexmgr_home: codexmgr home used to resolve named references.
83
+
84
+ Returns:
85
+ Rendered markdown for the template.
86
+ """
87
+ source_id, template_data = _load_template(reference, cwd, codexmgr_home)
88
+ return render_agents_markdown({source_id: template_data})
89
+
90
+
91
+ def validate_agentsmd(reference: str, cwd: Path, codexmgr_home: Path) -> str:
92
+ """Validate that one AGENTS.md template can be loaded and rendered.
93
+
94
+ Args:
95
+ reference: Named template or TOML path to validate.
96
+ cwd: Project directory used to resolve path references.
97
+ codexmgr_home: codexmgr home used to resolve named references.
98
+
99
+ Returns:
100
+ Source identifier for the valid template.
101
+ """
102
+ source_id, template_data = _load_template(reference, cwd, codexmgr_home)
103
+ render_agents_markdown({source_id: template_data})
104
+ return source_id
105
+
106
+
107
+ def init_agentsmd_template(name: str, codexmgr_home: Path) -> Path:
108
+ """Create a starter named AGENTS.md template.
109
+
110
+ Args:
111
+ name: Bare template name to create.
112
+ codexmgr_home: codexmgr home where the template should be created.
113
+
114
+ Returns:
115
+ Path to the created template file.
116
+ """
117
+ _validate_template_name(name)
118
+ template_dir = codexmgr_home / "agentsmd"
119
+ template_dir.mkdir(parents=True, exist_ok=True)
120
+ path = template_dir / f"{name}.toml"
121
+ if path.exists():
122
+ raise CommandError(f"Template already exists: {path}")
123
+ path.write_text(_starter_template(), encoding="utf-8")
124
+ return path
125
+
126
+
127
+ def resolve_locked_agents_md(
128
+ config: dict[str, Any],
129
+ cwd: Path,
130
+ codexmgr_home: Path,
131
+ ) -> dict[str, Any]:
132
+ """Resolve configured AGENTS.md sources into lock data.
133
+
134
+ Args:
135
+ config: Parsed .codex/codexmgr.toml content.
136
+ cwd: Project directory used to resolve path sources.
137
+ codexmgr_home: codexmgr home used to resolve named sources.
138
+
139
+ Returns:
140
+ Resolved source data keyed by source identifier.
141
+ """
142
+ locked_sources: dict[str, Any] = {}
143
+ for reference in agents_md_sources(config):
144
+ source_id, template_path = resolve_template(reference, cwd, codexmgr_home)
145
+ if source_id in locked_sources:
146
+ raise CommandError(f"Duplicate AGENTS.md source identifier: {source_id}")
147
+ template_data = load_toml_file(template_path)
148
+ if not template_data:
149
+ raise CommandError(f"Template is empty: {template_path}")
150
+ locked_sources[source_id] = template_data
151
+ return locked_sources
152
+
153
+
154
+ def write_agents_md(cwd: Path, locked_sources: dict[str, Any]) -> None:
155
+ """Write resolved AGENTS.md lock data to the managed block.
156
+
157
+ Args:
158
+ cwd: Project directory whose root AGENTS.md should be updated.
159
+ locked_sources: Resolved source data keyed by source identifier.
160
+ """
161
+ write_managed_agents_md(agents_md_path(cwd), render_agents_markdown(locked_sources))
162
+
163
+
164
+ def _load_template(
165
+ reference: str,
166
+ cwd: Path,
167
+ codexmgr_home: Path,
168
+ ) -> tuple[str, dict[str, Any]]:
169
+ """Load a named or path-backed AGENTS.md template.
170
+
171
+ Args:
172
+ reference: Named template or TOML path to load.
173
+ cwd: Project directory used to resolve path references.
174
+ codexmgr_home: codexmgr home used to resolve named references.
175
+
176
+ Returns:
177
+ Source identifier and parsed TOML data.
178
+ """
179
+ source_id, template_path = resolve_template(reference, cwd, codexmgr_home)
180
+ template_data = load_toml_file(template_path)
181
+ if not template_data:
182
+ raise CommandError(f"Template is empty: {template_path}")
183
+ return source_id, template_data
184
+
185
+
186
+ def _validate_template_name(name: str) -> None:
187
+ """Validate a starter template name.
188
+
189
+ Args:
190
+ name: Candidate bare template name.
191
+
192
+ Returns:
193
+ None. ``CommandError`` is raised for invalid names.
194
+ """
195
+ if not name or "/" in name or "\\" in name or name.endswith(".toml"):
196
+ raise CommandError(f"Template name must be a bare name: {name}")
197
+
198
+
199
+ def _starter_template() -> str:
200
+ """Return starter TOML content for a new AGENTS.md template.
201
+
202
+ Returns:
203
+ A minimal renderable template document.
204
+ """
205
+ return (
206
+ "[instructions]\n"
207
+ 'text = """\n'
208
+ "- Replace this with reusable project guidance.\n"
209
+ '"""\n'
210
+ )