code-agnostic 0.3.11__tar.gz → 0.3.13__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 (164) hide show
  1. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/PKG-INFO +31 -17
  2. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/README.md +30 -16
  3. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/__init__.py +1 -1
  4. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/__main__.py +3 -1
  5. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/agents/opencode.py +7 -2
  6. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/codex/config_repository.py +17 -2
  7. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/codex/schema.json +34 -24
  8. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/opencode/config_repository.py +18 -5
  9. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/opencode/schema.json +65 -38
  10. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/commands/agents.py +2 -1
  11. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/commands/apps.py +3 -1
  12. code_agnostic-0.3.13/code_agnostic/cli/commands/projects.py +78 -0
  13. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/commands/rules.py +2 -1
  14. code_agnostic-0.3.13/code_agnostic/cli/commands/skills.py +192 -0
  15. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/commands/status.py +20 -2
  16. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/helpers.py +13 -1
  17. code_agnostic-0.3.13/code_agnostic/core/project_repository.py +10 -0
  18. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/core/repository.py +90 -0
  19. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/executor.py +122 -41
  20. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/imports/service.py +70 -0
  21. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/mcp_service.py +10 -3
  22. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/models.py +15 -0
  23. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/planner.py +143 -1
  24. code_agnostic-0.3.13/code_agnostic/project_artifacts.py +39 -0
  25. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/skills/compilers.py +8 -1
  26. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/status.py +98 -1
  27. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/tui/renderers.py +105 -31
  28. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/tui/tables.py +39 -3
  29. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/workspace_artifacts.py +1 -1
  30. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic.egg-info/PKG-INFO +31 -17
  31. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic.egg-info/SOURCES.txt +5 -0
  32. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/pyproject.toml +1 -1
  33. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_agents.py +15 -0
  34. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_apply_target.py +4 -4
  35. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_apps.py +2 -0
  36. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_mcp.py +33 -0
  37. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_module_organization.py +1 -1
  38. code_agnostic-0.3.13/tests/test_cli_projects.py +227 -0
  39. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_rules.py +15 -0
  40. code_agnostic-0.3.13/tests/test_cli_skills.py +334 -0
  41. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_status.py +13 -1
  42. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_workspaces.py +3 -0
  43. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_planner_executor.py +17 -9
  44. code_agnostic-0.3.13/tests/test_project_config_sync.py +242 -0
  45. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_workspace_config_sync.py +58 -4
  46. code_agnostic-0.3.11/code_agnostic/cli/commands/skills.py +0 -70
  47. code_agnostic-0.3.11/tests/test_cli_skills.py +0 -96
  48. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/LICENSE +0 -0
  49. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/agents/__init__.py +0 -0
  50. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/agents/claude.py +0 -0
  51. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/agents/codex.py +0 -0
  52. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/agents/compilers.py +0 -0
  53. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/agents/models.py +0 -0
  54. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/agents/parser.py +0 -0
  55. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/__init__.py +0 -0
  56. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/app_id.py +0 -0
  57. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/apps_service.py +0 -0
  58. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/claude/__init__.py +0 -0
  59. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/claude/config_repository.py +0 -0
  60. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/claude/mapper.py +0 -0
  61. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/claude/service.py +0 -0
  62. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/codex/__init__.py +0 -0
  63. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/codex/mapper.py +0 -0
  64. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/codex/schema_repository.py +0 -0
  65. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/codex/service.py +0 -0
  66. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/common/__init__.py +0 -0
  67. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/common/compiled_planning.py +0 -0
  68. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/common/framework.py +0 -0
  69. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/common/interfaces/__init__.py +0 -0
  70. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/common/interfaces/mapper.py +0 -0
  71. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/common/interfaces/repositories.py +0 -0
  72. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/common/interfaces/service.py +0 -0
  73. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/common/loader.py +0 -0
  74. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/common/models.py +0 -0
  75. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/common/schema.py +0 -0
  76. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/common/symlink_planning.py +0 -0
  77. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/common/utils.py +0 -0
  78. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/cursor/__init__.py +0 -0
  79. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/cursor/config_repository.py +0 -0
  80. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/cursor/mapper.py +0 -0
  81. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/cursor/schema.json +0 -0
  82. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/cursor/schema_repository.py +0 -0
  83. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/cursor/service.py +0 -0
  84. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/opencode/__init__.py +0 -0
  85. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/opencode/mapper.py +0 -0
  86. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/opencode/schema_repository.py +0 -0
  87. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/apps/opencode/service.py +0 -0
  88. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/__init__.py +0 -0
  89. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/aliases.py +0 -0
  90. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/commands/__init__.py +0 -0
  91. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/commands/apply.py +0 -0
  92. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/commands/explain_lossiness.py +0 -0
  93. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/commands/import_.py +0 -0
  94. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/commands/mcp.py +0 -0
  95. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/commands/plan.py +0 -0
  96. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/commands/restore.py +0 -0
  97. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/commands/validate.py +0 -0
  98. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/commands/workspaces.py +0 -0
  99. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/cli/options.py +0 -0
  100. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/constants.py +0 -0
  101. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/core/__init__.py +0 -0
  102. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/core/workspace_repository.py +0 -0
  103. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/errors.py +0 -0
  104. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/generated_artifacts.py +0 -0
  105. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/git_exclude_service.py +0 -0
  106. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/imports/__init__.py +0 -0
  107. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/imports/adapters.py +0 -0
  108. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/imports/filesystem.py +0 -0
  109. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/imports/models.py +0 -0
  110. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/lossiness.py +0 -0
  111. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/rules/__init__.py +0 -0
  112. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/rules/compilers.py +0 -0
  113. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/rules/models.py +0 -0
  114. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/rules/parser.py +0 -0
  115. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/rules/repository.py +0 -0
  116. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/skills/__init__.py +0 -0
  117. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/skills/models.py +0 -0
  118. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/skills/parser.py +0 -0
  119. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/spec/__init__.py +0 -0
  120. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/spec/loaders.py +0 -0
  121. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/spec/schemas/agent.v1.schema.json +0 -0
  122. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/spec/schemas/mcp.base.schema.json +0 -0
  123. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/spec/schemas/mcp.v1.schema.json +0 -0
  124. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/spec/schemas/rule.v1.schema.json +0 -0
  125. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/spec/schemas/skill.v1.schema.json +0 -0
  126. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/tui/__init__.py +0 -0
  127. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/tui/enums.py +0 -0
  128. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/tui/import_selector.py +0 -0
  129. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/tui/sections.py +0 -0
  130. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/utils.py +0 -0
  131. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/validation.py +0 -0
  132. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic/workspaces.py +0 -0
  133. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic.egg-info/dependency_links.txt +0 -0
  134. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic.egg-info/entry_points.txt +0 -0
  135. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic.egg-info/requires.txt +0 -0
  136. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/code_agnostic.egg-info/top_level.txt +0 -0
  137. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/setup.cfg +0 -0
  138. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_aliases.py +0 -0
  139. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_apply_apps.py +0 -0
  140. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_apply_codex.py +0 -0
  141. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_apply_cursor.py +0 -0
  142. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_explain_lossiness.py +0 -0
  143. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_flags.py +0 -0
  144. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_git_exclude.py +0 -0
  145. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_import.py +0 -0
  146. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_import_interactive.py +0 -0
  147. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_plan.py +0 -0
  148. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_restore.py +0 -0
  149. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_validate.py +0 -0
  150. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_cli_workspace_resolution.py +0 -0
  151. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_common_mcp_to_dto.py +0 -0
  152. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_common_repository.py +0 -0
  153. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_compiled_planning.py +0 -0
  154. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_dto_to_common_mcp.py +0 -0
  155. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_git_exclude_service.py +0 -0
  156. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_mcp_service.py +0 -0
  157. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_planner_rules.py +0 -0
  158. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_symlink_planning.py +0 -0
  159. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_sync_plan_model.py +0 -0
  160. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_transactional_executor.py +0 -0
  161. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_utils.py +0 -0
  162. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_version.py +0 -0
  163. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_workspace_repo_status.py +0 -0
  164. {code_agnostic-0.3.11 → code_agnostic-0.3.13}/tests/test_workspaces.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-agnostic
3
- Version: 0.3.11
3
+ Version: 0.3.13
4
4
  Summary: Centralized hub for LLM coding config: MCP, skills, rules, and agents.
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -54,7 +54,7 @@ AI coding tools each want config in a different place and format. When you use m
54
54
 
55
55
  ~/.config/opencode/ Compiled & synced for OpenCode
56
56
  ~/.cursor/ Compiled & synced for Cursor
57
- ~/.codex/ Compiled & synced for Codex
57
+ ~/.codex/ Compiled & synced for Codex (or CODEX_HOME)
58
58
  ~/.claude.json and ~/.claude/ Compiled & synced for Claude Code
59
59
  ```
60
60
 
@@ -66,18 +66,19 @@ Today the implementation is still mixed: some assets are compiled and some are s
66
66
 
67
67
  ## Scope model
68
68
 
69
- `code-agnostic` has two managed source scopes today:
69
+ `code-agnostic` has three managed source scopes:
70
70
 
71
71
  - global source config under `~/.config/code-agnostic/`, synced to enabled
72
72
  user-level app config;
73
73
  - workspace source config under `~/.config/code-agnostic/workspaces/<name>/`,
74
- propagated into repos inside a registered workspace.
74
+ propagated into repos inside a registered workspace;
75
+ - project source config under `~/.config/code-agnostic/projects/<name>/`,
76
+ synced to exactly one registered project directory.
75
77
 
76
- Project-local skill folders that users create directly inside a repo, such as
77
- `.agents/skills` or `.opencode/skills`, are app-native inputs but are not
78
- managed as source by `code-agnostic` yet. First-class project-scoped installs
79
- are planned so a single registered project can have managed local source config
80
- without bypassing the hub.
78
+ Workspace sync may generate repo-local outputs, but those outputs are not
79
+ source. Project-local skill folders generated inside a repo, such as
80
+ `.agents/skills` or `.opencode/skills`, are also generated outputs; install
81
+ skills into managed project source first, then run `plan` / `apply`.
81
82
 
82
83
  ## Install
83
84
 
@@ -142,9 +143,9 @@ that are omitted or rejected for a selected target.
142
143
 
143
144
  Cursor workspace propagation writes repo-local MCP, skills, and agents when those resources exist in the workspace source config.
144
145
 
145
- OpenCode workspace configs include the shared workspace `AGENTS.md` natively via `instructions`, so repos under the workspace get both repo-local and shared workspace instructions. Codex repos receive workspace instructions through a generated `AGENTS.override.md`, which is added to each repo's `.git/info/exclude`. Claude Code receives workspace instructions through generated `CLAUDE.local.md` files, never by editing committed `CLAUDE.md`.
146
+ OpenCode workspace configs write project-root `opencode.json` files that include the shared workspace `AGENTS.md` natively via `instructions`, so repos under the workspace get both repo-local and shared workspace instructions. Codex repos receive workspace instructions through a generated `AGENTS.override.md`, which is added to each repo's `.git/info/exclude`. Claude Code receives workspace instructions through generated `CLAUDE.local.md` files, never by editing committed `CLAUDE.md`.
146
147
 
147
- Cursor documents `AGENTS.md` support in project roots and subdirectories. `code-agnostic` does not copy or link the shared workspace `AGENTS.md` into child repos; Cursor will load repo-local or nested `AGENTS.md` files that already exist in the opened project. Codex documents nested `AGENTS.md` discovery, but not a native config include for an extra workspace file.
148
+ Cursor documents `AGENTS.md` support in project roots and subdirectories. `code-agnostic` does not copy or link the shared workspace `AGENTS.md` into child repos; Cursor will load `AGENTS.md` files that already exist in the opened project. Codex documents nested `AGENTS.md` discovery, but not a native config include for an extra workspace file.
148
149
 
149
150
  ## Features
150
151
 
@@ -229,16 +230,27 @@ code-agnostic skills list
229
230
  code-agnostic agents list
230
231
  ```
231
232
 
232
- Manual skill install today:
233
+ Install a local skill directory into managed source:
233
234
 
234
235
  ```bash
235
- mkdir -p ~/.config/code-agnostic/skills
236
- cp -R ./my-skill ~/.config/code-agnostic/skills/my-skill
236
+ code-agnostic skills install ./my-skill --global
237
+ code-agnostic skills install ./my-skill --workspace myworkspace
238
+ code-agnostic projects add --name myproject --path .
239
+ code-agnostic skills install ./my-skill --project myproject
237
240
  code-agnostic plan
238
241
  code-agnostic apply
239
242
  ```
240
243
 
241
- Global skills live under `~/.config/code-agnostic/skills`. Workspace-local skills live under `~/.config/code-agnostic/workspaces/<name>/skills` and can be inspected with `code-agnostic skills list -w <name>`. Codex generated skill outputs are written to `~/.agents/skills`, while Codex agents and config remain under `~/.codex`. Claude Code generated skills and agents are written under `~/.claude/skills` and `~/.claude/agents`, with workspace copies under repo-local `.claude/skills` and `.claude/agents`.
244
+ Global skills live under `~/.config/code-agnostic/skills`. Workspace-local
245
+ skills live under `~/.config/code-agnostic/workspaces/<name>/skills` and can be
246
+ inspected with `code-agnostic skills list -w <name>`. Project-local skills live
247
+ under `~/.config/code-agnostic/projects/<name>/skills` and are generated into
248
+ the registered project directory by `plan` / `apply`. Codex generated skill
249
+ outputs are written to `~/.agents/skills`, while Codex agents and config remain
250
+ under `CODEX_HOME` when set, defaulting to `~/.codex`. Claude Code generated
251
+ skills and agents are written under `~/.claude/skills` and `~/.claude/agents`,
252
+ with workspace/project copies under repo-local `.claude/skills` and
253
+ `.claude/agents`.
242
254
 
243
255
  Project-local skills are not first-class source inputs in `code-agnostic` yet. If a target app discovers repo-local skill folders such as `.agents/skills`, `.opencode/skills`, or user-created `.claude/skills`, treat those as unmanaged app inputs. Workspace sync writes only the exact generated paths recorded in `.sync-state.json`.
244
256
 
@@ -249,10 +261,12 @@ code-agnostic skills install ./my-skill --apply
249
261
  ```
250
262
 
251
263
  That command should copy the skill into the source of truth and then run the normal compiler/apply flow.
264
+ See [docs/project-scoped-skills.md](docs/project-scoped-skills.md) for the
265
+ first implementation slice.
252
266
 
253
267
  ### Workspaces
254
268
 
255
- Register workspace directories. Workspace rules are compiled into a canonical `AGENTS.md` at the workspace root. Repos keep their own repo-specific `AGENTS.md`; Codex receives the workspace rules through generated, git-excluded `AGENTS.override.md` files, while OpenCode workspace configs reference the shared workspace file through `instructions`. Claude receives generated `CLAUDE.local.md` files and project MCP entries in `~/.claude.json["projects"][absolute_repo_path]["mcpServers"]`. Workspace source config, skills, and agents are propagated into repo-local generated paths for OpenCode, Cursor, Codex, and Claude; user-created project-local skill folders remain unmanaged until project-scoped installs are supported.
269
+ Register workspace directories. Workspace rules are compiled into a canonical `AGENTS.md` at the workspace root. Repos keep their own repo-specific `AGENTS.md`; Codex receives the workspace rules through generated, git-excluded `AGENTS.override.md` files, while OpenCode workspace configs write project-root `opencode.json` files that reference the shared workspace file through `instructions`. Claude receives generated `CLAUDE.local.md` files and project MCP entries in `~/.claude.json["projects"][absolute_repo_path]["mcpServers"]`. Workspace source config, skills, and agents are propagated into repo-local generated paths for OpenCode, Cursor, Codex, and Claude; user-created project-local skill folders remain unmanaged until project-scoped installs are supported.
256
270
 
257
271
  Cursor propagation intentionally stays to repo-local MCP, skills, and agents; it does not copy the shared workspace `AGENTS.md` into child repos.
258
272
 
@@ -316,12 +330,12 @@ The compiler migration is documented in:
316
330
  - [x] MCP add/remove/list commands
317
331
  - [x] Rules system with YAML frontmatter and per-editor compilation
318
332
  - [x] Cross-compilation for skills and agents
333
+ - [x] Planner integration for cross-compiled skills and agents
319
334
  - [x] Per-workspace git-exclude customization
320
335
  - [x] Interactive TUI for import selection
321
336
  - [x] Claude Code support
322
337
  - [ ] Project-scoped skill installs and sync
323
338
  - [ ] `rules add` / `skills add` / `agents add` commands (open `$EDITOR` with template)
324
- - [ ] Planner integration for cross-compiled skills and agents
325
339
  - [ ] Shell auto-complete
326
340
  - [ ] Full TUI mode (command palette + menus)
327
341
 
@@ -29,7 +29,7 @@ AI coding tools each want config in a different place and format. When you use m
29
29
 
30
30
  ~/.config/opencode/ Compiled & synced for OpenCode
31
31
  ~/.cursor/ Compiled & synced for Cursor
32
- ~/.codex/ Compiled & synced for Codex
32
+ ~/.codex/ Compiled & synced for Codex (or CODEX_HOME)
33
33
  ~/.claude.json and ~/.claude/ Compiled & synced for Claude Code
34
34
  ```
35
35
 
@@ -41,18 +41,19 @@ Today the implementation is still mixed: some assets are compiled and some are s
41
41
 
42
42
  ## Scope model
43
43
 
44
- `code-agnostic` has two managed source scopes today:
44
+ `code-agnostic` has three managed source scopes:
45
45
 
46
46
  - global source config under `~/.config/code-agnostic/`, synced to enabled
47
47
  user-level app config;
48
48
  - workspace source config under `~/.config/code-agnostic/workspaces/<name>/`,
49
- propagated into repos inside a registered workspace.
49
+ propagated into repos inside a registered workspace;
50
+ - project source config under `~/.config/code-agnostic/projects/<name>/`,
51
+ synced to exactly one registered project directory.
50
52
 
51
- Project-local skill folders that users create directly inside a repo, such as
52
- `.agents/skills` or `.opencode/skills`, are app-native inputs but are not
53
- managed as source by `code-agnostic` yet. First-class project-scoped installs
54
- are planned so a single registered project can have managed local source config
55
- without bypassing the hub.
53
+ Workspace sync may generate repo-local outputs, but those outputs are not
54
+ source. Project-local skill folders generated inside a repo, such as
55
+ `.agents/skills` or `.opencode/skills`, are also generated outputs; install
56
+ skills into managed project source first, then run `plan` / `apply`.
56
57
 
57
58
  ## Install
58
59
 
@@ -117,9 +118,9 @@ that are omitted or rejected for a selected target.
117
118
 
118
119
  Cursor workspace propagation writes repo-local MCP, skills, and agents when those resources exist in the workspace source config.
119
120
 
120
- OpenCode workspace configs include the shared workspace `AGENTS.md` natively via `instructions`, so repos under the workspace get both repo-local and shared workspace instructions. Codex repos receive workspace instructions through a generated `AGENTS.override.md`, which is added to each repo's `.git/info/exclude`. Claude Code receives workspace instructions through generated `CLAUDE.local.md` files, never by editing committed `CLAUDE.md`.
121
+ OpenCode workspace configs write project-root `opencode.json` files that include the shared workspace `AGENTS.md` natively via `instructions`, so repos under the workspace get both repo-local and shared workspace instructions. Codex repos receive workspace instructions through a generated `AGENTS.override.md`, which is added to each repo's `.git/info/exclude`. Claude Code receives workspace instructions through generated `CLAUDE.local.md` files, never by editing committed `CLAUDE.md`.
121
122
 
122
- Cursor documents `AGENTS.md` support in project roots and subdirectories. `code-agnostic` does not copy or link the shared workspace `AGENTS.md` into child repos; Cursor will load repo-local or nested `AGENTS.md` files that already exist in the opened project. Codex documents nested `AGENTS.md` discovery, but not a native config include for an extra workspace file.
123
+ Cursor documents `AGENTS.md` support in project roots and subdirectories. `code-agnostic` does not copy or link the shared workspace `AGENTS.md` into child repos; Cursor will load `AGENTS.md` files that already exist in the opened project. Codex documents nested `AGENTS.md` discovery, but not a native config include for an extra workspace file.
123
124
 
124
125
  ## Features
125
126
 
@@ -204,16 +205,27 @@ code-agnostic skills list
204
205
  code-agnostic agents list
205
206
  ```
206
207
 
207
- Manual skill install today:
208
+ Install a local skill directory into managed source:
208
209
 
209
210
  ```bash
210
- mkdir -p ~/.config/code-agnostic/skills
211
- cp -R ./my-skill ~/.config/code-agnostic/skills/my-skill
211
+ code-agnostic skills install ./my-skill --global
212
+ code-agnostic skills install ./my-skill --workspace myworkspace
213
+ code-agnostic projects add --name myproject --path .
214
+ code-agnostic skills install ./my-skill --project myproject
212
215
  code-agnostic plan
213
216
  code-agnostic apply
214
217
  ```
215
218
 
216
- Global skills live under `~/.config/code-agnostic/skills`. Workspace-local skills live under `~/.config/code-agnostic/workspaces/<name>/skills` and can be inspected with `code-agnostic skills list -w <name>`. Codex generated skill outputs are written to `~/.agents/skills`, while Codex agents and config remain under `~/.codex`. Claude Code generated skills and agents are written under `~/.claude/skills` and `~/.claude/agents`, with workspace copies under repo-local `.claude/skills` and `.claude/agents`.
219
+ Global skills live under `~/.config/code-agnostic/skills`. Workspace-local
220
+ skills live under `~/.config/code-agnostic/workspaces/<name>/skills` and can be
221
+ inspected with `code-agnostic skills list -w <name>`. Project-local skills live
222
+ under `~/.config/code-agnostic/projects/<name>/skills` and are generated into
223
+ the registered project directory by `plan` / `apply`. Codex generated skill
224
+ outputs are written to `~/.agents/skills`, while Codex agents and config remain
225
+ under `CODEX_HOME` when set, defaulting to `~/.codex`. Claude Code generated
226
+ skills and agents are written under `~/.claude/skills` and `~/.claude/agents`,
227
+ with workspace/project copies under repo-local `.claude/skills` and
228
+ `.claude/agents`.
217
229
 
218
230
  Project-local skills are not first-class source inputs in `code-agnostic` yet. If a target app discovers repo-local skill folders such as `.agents/skills`, `.opencode/skills`, or user-created `.claude/skills`, treat those as unmanaged app inputs. Workspace sync writes only the exact generated paths recorded in `.sync-state.json`.
219
231
 
@@ -224,10 +236,12 @@ code-agnostic skills install ./my-skill --apply
224
236
  ```
225
237
 
226
238
  That command should copy the skill into the source of truth and then run the normal compiler/apply flow.
239
+ See [docs/project-scoped-skills.md](docs/project-scoped-skills.md) for the
240
+ first implementation slice.
227
241
 
228
242
  ### Workspaces
229
243
 
230
- Register workspace directories. Workspace rules are compiled into a canonical `AGENTS.md` at the workspace root. Repos keep their own repo-specific `AGENTS.md`; Codex receives the workspace rules through generated, git-excluded `AGENTS.override.md` files, while OpenCode workspace configs reference the shared workspace file through `instructions`. Claude receives generated `CLAUDE.local.md` files and project MCP entries in `~/.claude.json["projects"][absolute_repo_path]["mcpServers"]`. Workspace source config, skills, and agents are propagated into repo-local generated paths for OpenCode, Cursor, Codex, and Claude; user-created project-local skill folders remain unmanaged until project-scoped installs are supported.
244
+ Register workspace directories. Workspace rules are compiled into a canonical `AGENTS.md` at the workspace root. Repos keep their own repo-specific `AGENTS.md`; Codex receives the workspace rules through generated, git-excluded `AGENTS.override.md` files, while OpenCode workspace configs write project-root `opencode.json` files that reference the shared workspace file through `instructions`. Claude receives generated `CLAUDE.local.md` files and project MCP entries in `~/.claude.json["projects"][absolute_repo_path]["mcpServers"]`. Workspace source config, skills, and agents are propagated into repo-local generated paths for OpenCode, Cursor, Codex, and Claude; user-created project-local skill folders remain unmanaged until project-scoped installs are supported.
231
245
 
232
246
  Cursor propagation intentionally stays to repo-local MCP, skills, and agents; it does not copy the shared workspace `AGENTS.md` into child repos.
233
247
 
@@ -291,12 +305,12 @@ The compiler migration is documented in:
291
305
  - [x] MCP add/remove/list commands
292
306
  - [x] Rules system with YAML frontmatter and per-editor compilation
293
307
  - [x] Cross-compilation for skills and agents
308
+ - [x] Planner integration for cross-compiled skills and agents
294
309
  - [x] Per-workspace git-exclude customization
295
310
  - [x] Interactive TUI for import selection
296
311
  - [x] Claude Code support
297
312
  - [ ] Project-scoped skill installs and sync
298
313
  - [ ] `rules add` / `skills add` / `agents add` commands (open `$EDITOR` with template)
299
- - [ ] Planner integration for cross-compiled skills and agents
300
314
  - [ ] Shell auto-complete
301
315
  - [ ] Full TUI mode (command palette + menus)
302
316
 
@@ -1,3 +1,3 @@
1
1
  __all__ = ["__version__"]
2
2
 
3
- __version__ = "0.3.11"
3
+ __version__ = "0.3.13"
@@ -10,6 +10,7 @@ from code_agnostic.cli.commands.explain_lossiness import explain_lossiness
10
10
  from code_agnostic.cli.commands.import_ import import_group
11
11
  from code_agnostic.cli.commands.mcp import mcp
12
12
  from code_agnostic.cli.commands.plan import plan
13
+ from code_agnostic.cli.commands.projects import projects
13
14
  from code_agnostic.cli.commands.restore import restore
14
15
  from code_agnostic.cli.commands.rules import rules
15
16
  from code_agnostic.cli.commands.skills import skills
@@ -25,7 +26,7 @@ from code_agnostic.errors import SyncAppError
25
26
  )
26
27
  @click.pass_context
27
28
  def cli(ctx: click.Context) -> None:
28
- """App-based config sync."""
29
+ """Manage one source of truth for AI coding-tool config."""
29
30
  ctx.obj = {}
30
31
 
31
32
 
@@ -40,6 +41,7 @@ cli.add_command(explain_lossiness)
40
41
  # Register command groups
41
42
  cli.add_command(apps)
42
43
  cli.add_command(workspaces)
44
+ cli.add_command(projects)
43
45
  cli.add_command(rules)
44
46
  cli.add_command(skills)
45
47
  cli.add_command(agents_group)
@@ -7,14 +7,19 @@ from typing import Any
7
7
  import yaml
8
8
 
9
9
  from code_agnostic.agents.models import Agent
10
+ from code_agnostic.errors import InvalidConfigSchemaError
10
11
 
11
12
 
12
13
  def serialize_opencode_agent(agent: Agent) -> str:
13
14
  fm: dict[str, Any] = {}
14
15
  if agent.metadata.name:
15
16
  fm["name"] = agent.metadata.name
16
- if agent.metadata.description:
17
- fm["description"] = agent.metadata.description
17
+ if not agent.metadata.description:
18
+ raise InvalidConfigSchemaError(
19
+ agent.source_path,
20
+ "OpenCode agents require a description",
21
+ )
22
+ fm["description"] = agent.metadata.description
18
23
  model = agent.metadata.effective_value("opencode", "model")
19
24
  if model:
20
25
  fm["model"] = model
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from pathlib import Path
2
3
  from typing import Any
3
4
 
@@ -21,7 +22,8 @@ from code_agnostic.errors import InvalidConfigSchemaError, InvalidJsonFormatErro
21
22
 
22
23
  class CodexConfigRepository(IAppConfigRepository):
23
24
  def __init__(self, root: Path | None = None) -> None:
24
- self._root = root or (Path.home() / CODEX_PROJECT_DIRNAME)
25
+ self._root = root or _default_codex_root()
26
+ self._skills_dir = _default_codex_skills_dir(root)
25
27
 
26
28
  @property
27
29
  def root(self) -> Path:
@@ -33,7 +35,7 @@ class CodexConfigRepository(IAppConfigRepository):
33
35
 
34
36
  @property
35
37
  def skills_dir(self) -> Path:
36
- return self.root.parent / AGENTS_PROJECT_DIRNAME / SKILLS_DIRNAME
38
+ return self._skills_dir
37
39
 
38
40
  @property
39
41
  def agents_dir(self) -> Path:
@@ -81,3 +83,16 @@ class CodexConfigRepository(IAppConfigRepository):
81
83
  config = self.load_config()
82
84
  config["agents"] = payload
83
85
  self.save_config(config)
86
+
87
+
88
+ def _default_codex_root() -> Path:
89
+ codex_home = os.environ.get("CODEX_HOME")
90
+ if codex_home:
91
+ return Path(codex_home).expanduser()
92
+ return Path.home() / CODEX_PROJECT_DIRNAME
93
+
94
+
95
+ def _default_codex_skills_dir(root: Path | None) -> Path:
96
+ if root is not None:
97
+ return root.parent / AGENTS_PROJECT_DIRNAME / SKILLS_DIRNAME
98
+ return Path.home() / AGENTS_PROJECT_DIRNAME / SKILLS_DIRNAME
@@ -226,18 +226,6 @@
226
226
  },
227
227
  "type": "object"
228
228
  },
229
- "AppsMcpPathOverrideConfigToml": {
230
- "additionalProperties": false,
231
- "properties": {
232
- "enabled": {
233
- "type": "boolean"
234
- },
235
- "path": {
236
- "type": "string"
237
- }
238
- },
239
- "type": "object"
240
- },
241
229
  "AskForApproval": {
242
230
  "description": "Determines the conditions under which the user is consulted to approve running the command proposed by Codex.",
243
231
  "oneOf": [
@@ -408,7 +396,23 @@
408
396
  "type": "boolean"
409
397
  },
410
398
  "apps_mcp_path_override": {
411
- "$ref": "#/definitions/FeatureToml_for_AppsMcpPathOverrideConfigToml"
399
+ "anyOf": [
400
+ {
401
+ "type": "boolean"
402
+ },
403
+ {
404
+ "additionalProperties": false,
405
+ "properties": {
406
+ "enabled": {
407
+ "type": "boolean"
408
+ },
409
+ "path": {
410
+ "type": "string"
411
+ }
412
+ },
413
+ "type": "object"
414
+ }
415
+ ]
412
416
  },
413
417
  "auth_elicitation": {
414
418
  "type": "boolean"
@@ -836,16 +840,6 @@
836
840
  },
837
841
  "type": "object"
838
842
  },
839
- "FeatureToml_for_AppsMcpPathOverrideConfigToml": {
840
- "anyOf": [
841
- {
842
- "type": "boolean"
843
- },
844
- {
845
- "$ref": "#/definitions/AppsMcpPathOverrideConfigToml"
846
- }
847
- ]
848
- },
849
843
  "FeatureToml_for_CodeModeConfigToml": {
850
844
  "anyOf": [
851
845
  {
@@ -4534,7 +4528,23 @@
4534
4528
  "type": "boolean"
4535
4529
  },
4536
4530
  "apps_mcp_path_override": {
4537
- "$ref": "#/definitions/FeatureToml_for_AppsMcpPathOverrideConfigToml"
4531
+ "anyOf": [
4532
+ {
4533
+ "type": "boolean"
4534
+ },
4535
+ {
4536
+ "additionalProperties": false,
4537
+ "properties": {
4538
+ "enabled": {
4539
+ "type": "boolean"
4540
+ },
4541
+ "path": {
4542
+ "type": "string"
4543
+ }
4544
+ },
4545
+ "type": "object"
4546
+ }
4547
+ ]
4538
4548
  },
4539
4549
  "auth_elicitation": {
4540
4550
  "type": "boolean"
@@ -13,8 +13,15 @@ from code_agnostic.utils import merge_dict_overlay, read_json_safe, write_json
13
13
 
14
14
 
15
15
  class OpenCodeConfigRepository(IAppConfigRepository):
16
- def __init__(self, root: Path | None = None) -> None:
16
+ def __init__(
17
+ self,
18
+ root: Path | None = None,
19
+ config_path: Path | None = None,
20
+ legacy_config_path: Path | None = None,
21
+ ) -> None:
17
22
  self._root = root or (Path.home() / ".config" / "opencode")
23
+ self._config_path = config_path
24
+ self._legacy_config_path = legacy_config_path
18
25
 
19
26
  @property
20
27
  def root(self) -> Path:
@@ -22,7 +29,7 @@ class OpenCodeConfigRepository(IAppConfigRepository):
22
29
 
23
30
  @property
24
31
  def config_path(self) -> Path:
25
- return self.root / OPENCODE_CONFIG_FILENAME
32
+ return self._config_path or self.root / OPENCODE_CONFIG_FILENAME
26
33
 
27
34
  @property
28
35
  def skills_dir(self) -> Path:
@@ -39,13 +46,14 @@ class OpenCodeConfigRepository(IAppConfigRepository):
39
46
  return plural
40
47
 
41
48
  def load_config(self) -> dict[str, Any]:
42
- payload, error = read_json_safe(self.config_path)
49
+ config_path = self._read_config_path()
50
+ payload, error = read_json_safe(config_path)
43
51
  if error is not None:
44
- raise InvalidJsonFormatError(self.config_path, error)
52
+ raise InvalidJsonFormatError(config_path, error)
45
53
  if payload is None:
46
54
  return {}
47
55
  if not isinstance(payload, dict):
48
- raise InvalidConfigSchemaError(self.config_path, "must be a JSON object")
56
+ raise InvalidConfigSchemaError(config_path, "must be a JSON object")
49
57
  return payload
50
58
 
51
59
  def save_config(self, payload: dict[str, Any]) -> None:
@@ -105,3 +113,8 @@ class OpenCodeConfigRepository(IAppConfigRepository):
105
113
 
106
114
  if tools:
107
115
  merged["tools"] = tools
116
+
117
+ def _read_config_path(self) -> Path:
118
+ if self.config_path.exists() or self._legacy_config_path is None:
119
+ return self.config_path
120
+ return self._legacy_config_path
@@ -43,48 +43,44 @@
43
43
  },
44
44
  "additionalProperties": false
45
45
  },
46
- "ReferenceConfigEntry": {
47
- "anyOf": [
48
- {
46
+ "ConfigV2.Reference.Git": {
47
+ "type": "object",
48
+ "properties": {
49
+ "repository": {
49
50
  "type": "string"
50
51
  },
51
- {
52
- "type": "object",
53
- "properties": {
54
- "repository": {
55
- "type": "string",
56
- "description": "Git repository URL, host/path reference, or GitHub owner/repo shorthand"
57
- },
58
- "branch": {
59
- "type": "string",
60
- "description": "Branch or ref to clone and inspect"
61
- }
62
- },
63
- "required": [
64
- "repository"
65
- ],
66
- "additionalProperties": false
52
+ "branch": {
53
+ "type": "string"
67
54
  },
68
- {
69
- "type": "object",
70
- "properties": {
71
- "path": {
72
- "type": "string",
73
- "description": "Absolute path, ~/ path, or workspace-relative path to a local reference directory"
74
- }
75
- },
76
- "required": [
77
- "path"
78
- ],
79
- "additionalProperties": false
55
+ "description": {
56
+ "type": "string"
57
+ },
58
+ "hidden": {
59
+ "type": "boolean"
80
60
  }
81
- ]
61
+ },
62
+ "required": [
63
+ "repository"
64
+ ],
65
+ "additionalProperties": false
82
66
  },
83
- "ReferenceConfig": {
67
+ "ConfigV2.Reference.Local": {
84
68
  "type": "object",
85
- "additionalProperties": {
86
- "$ref": "#/$defs/ReferenceConfigEntry"
87
- }
69
+ "properties": {
70
+ "path": {
71
+ "type": "string"
72
+ },
73
+ "description": {
74
+ "type": "string"
75
+ },
76
+ "hidden": {
77
+ "type": "boolean"
78
+ }
79
+ },
80
+ "required": [
81
+ "path"
82
+ ],
83
+ "additionalProperties": false
88
84
  },
89
85
  "PermissionActionConfig": {
90
86
  "type": "string",
@@ -390,6 +386,7 @@
390
386
  "field": {
391
387
  "type": "string",
392
388
  "enum": [
389
+ "reasoning",
393
390
  "reasoning_content",
394
391
  "reasoning_details"
395
392
  ]
@@ -826,9 +823,39 @@
826
823
  "additionalProperties": false,
827
824
  "description": "Additional skill folder paths"
828
825
  },
826
+ "references": {
827
+ "type": "object",
828
+ "additionalProperties": {
829
+ "anyOf": [
830
+ {
831
+ "type": "string"
832
+ },
833
+ {
834
+ "$ref": "#/$defs/ConfigV2.Reference.Git"
835
+ },
836
+ {
837
+ "$ref": "#/$defs/ConfigV2.Reference.Local"
838
+ }
839
+ ]
840
+ },
841
+ "description": "Named git or local directory references"
842
+ },
829
843
  "reference": {
830
- "$ref": "#/$defs/ReferenceConfig",
831
- "description": "Named git or local directory references that can be mentioned as @alias or @alias/path"
844
+ "type": "object",
845
+ "additionalProperties": {
846
+ "anyOf": [
847
+ {
848
+ "type": "string"
849
+ },
850
+ {
851
+ "$ref": "#/$defs/ConfigV2.Reference.Git"
852
+ },
853
+ {
854
+ "$ref": "#/$defs/ConfigV2.Reference.Local"
855
+ }
856
+ ]
857
+ },
858
+ "description": "@deprecated Use 'references' field instead. Named git or local directory references"
832
859
  },
833
860
  "watcher": {
834
861
  "type": "object",
@@ -5,7 +5,7 @@ import shutil
5
5
  import click
6
6
  from rich.console import Console
7
7
 
8
- from code_agnostic.cli.helpers import workspace_config_root
8
+ from code_agnostic.cli.helpers import validate_resource_name, workspace_config_root
9
9
  from code_agnostic.cli.options import workspace_option
10
10
  from code_agnostic.core.repository import CoreRepository
11
11
  from code_agnostic.tui import SyncConsoleUI
@@ -33,6 +33,7 @@ def agents_list(obj: dict[str, str], workspace: str | None) -> None:
33
33
  @workspace_option()
34
34
  @click.pass_obj
35
35
  def agents_remove(obj: dict[str, str], name: str, workspace: str | None) -> None:
36
+ validate_resource_name(name, "agent")
36
37
  core = CoreRepository()
37
38
  root = workspace_config_root(core, workspace)
38
39
  agent_dir = root / "agents" / name
@@ -30,8 +30,10 @@ def apps_enable(obj: dict[str, str], app: str) -> None:
30
30
  ui = SyncConsoleUI(Console())
31
31
  core = CoreRepository()
32
32
  service = AppsService(core)
33
- service.enable(app.lower())
33
+ app = app.lower()
34
+ service.enable(app)
34
35
  ui.render_apps(service.list_status_rows())
36
+ ui.render_app_enabled_next_steps(app)
35
37
 
36
38
 
37
39
  @apps.command("disable", help="Disable app sync target.")