code-agnostic 0.3.11__tar.gz → 0.3.12__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.
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/PKG-INFO +18 -12
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/README.md +17 -11
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/__init__.py +1 -1
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/__main__.py +1 -1
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/agents/opencode.py +7 -2
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/codex/config_repository.py +17 -2
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/codex/schema.json +34 -24
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/opencode/config_repository.py +18 -5
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/opencode/schema.json +65 -38
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/commands/agents.py +2 -1
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/commands/apps.py +3 -1
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/commands/rules.py +2 -1
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/commands/skills.py +12 -5
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/helpers.py +13 -1
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/imports/service.py +70 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/mcp_service.py +10 -3
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/planner.py +19 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/skills/compilers.py +8 -1
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/tui/renderers.py +44 -2
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/workspace_artifacts.py +1 -1
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic.egg-info/PKG-INFO +18 -12
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/pyproject.toml +1 -1
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_agents.py +15 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_apply_target.py +4 -4
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_apps.py +2 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_mcp.py +33 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_module_organization.py +1 -1
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_rules.py +15 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_skills.py +37 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_status.py +13 -1
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_workspaces.py +3 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_planner_executor.py +17 -9
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_workspace_config_sync.py +58 -4
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/LICENSE +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/agents/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/agents/claude.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/agents/codex.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/agents/compilers.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/agents/models.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/agents/parser.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/app_id.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/apps_service.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/claude/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/claude/config_repository.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/claude/mapper.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/claude/service.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/codex/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/codex/mapper.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/codex/schema_repository.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/codex/service.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/common/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/common/compiled_planning.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/common/framework.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/common/interfaces/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/common/interfaces/mapper.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/common/interfaces/repositories.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/common/interfaces/service.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/common/loader.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/common/models.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/common/schema.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/common/symlink_planning.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/common/utils.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/cursor/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/cursor/config_repository.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/cursor/mapper.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/cursor/schema.json +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/cursor/schema_repository.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/cursor/service.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/opencode/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/opencode/mapper.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/opencode/schema_repository.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/opencode/service.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/aliases.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/commands/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/commands/apply.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/commands/explain_lossiness.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/commands/import_.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/commands/mcp.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/commands/plan.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/commands/restore.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/commands/status.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/commands/validate.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/commands/workspaces.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/cli/options.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/constants.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/core/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/core/repository.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/core/workspace_repository.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/errors.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/executor.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/generated_artifacts.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/git_exclude_service.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/imports/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/imports/adapters.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/imports/filesystem.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/imports/models.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/lossiness.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/models.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/rules/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/rules/compilers.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/rules/models.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/rules/parser.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/rules/repository.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/skills/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/skills/models.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/skills/parser.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/spec/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/spec/loaders.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/spec/schemas/agent.v1.schema.json +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/spec/schemas/mcp.base.schema.json +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/spec/schemas/mcp.v1.schema.json +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/spec/schemas/rule.v1.schema.json +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/spec/schemas/skill.v1.schema.json +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/status.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/tui/__init__.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/tui/enums.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/tui/import_selector.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/tui/sections.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/tui/tables.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/utils.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/validation.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/workspaces.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic.egg-info/SOURCES.txt +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic.egg-info/dependency_links.txt +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic.egg-info/entry_points.txt +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic.egg-info/requires.txt +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic.egg-info/top_level.txt +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/setup.cfg +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_aliases.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_apply_apps.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_apply_codex.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_apply_cursor.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_explain_lossiness.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_flags.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_git_exclude.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_import.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_import_interactive.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_plan.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_restore.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_validate.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_cli_workspace_resolution.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_common_mcp_to_dto.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_common_repository.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_compiled_planning.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_dto_to_common_mcp.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_git_exclude_service.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_mcp_service.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_planner_rules.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_symlink_planning.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_sync_plan_model.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_transactional_executor.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_utils.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_version.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/tests/test_workspace_repo_status.py +0 -0
- {code_agnostic-0.3.11 → code_agnostic-0.3.12}/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.
|
|
3
|
+
Version: 0.3.12
|
|
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
|
|
|
@@ -73,11 +73,12 @@ Today the implementation is still mixed: some assets are compiled and some are s
|
|
|
73
73
|
- workspace source config under `~/.config/code-agnostic/workspaces/<name>/`,
|
|
74
74
|
propagated into repos inside a registered workspace.
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
Workspace sync may generate repo-local outputs, but those outputs are not
|
|
77
|
+
source. Project-local skill folders that users create directly inside a repo,
|
|
78
|
+
such as `.agents/skills` or `.opencode/skills`, are app-native inputs but are
|
|
79
|
+
not managed as source by `code-agnostic` yet. First-class project-scoped
|
|
80
|
+
installs are planned so a single registered project can have managed local
|
|
81
|
+
source config without bypassing the hub.
|
|
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
|
|
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
|
|
|
@@ -238,7 +239,10 @@ code-agnostic plan
|
|
|
238
239
|
code-agnostic apply
|
|
239
240
|
```
|
|
240
241
|
|
|
241
|
-
|
|
242
|
+
There is no `skills install` command yet; copy skills into managed source first,
|
|
243
|
+
then use the normal `plan` / `apply` workflow.
|
|
244
|
+
|
|
245
|
+
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_HOME` when set, defaulting to `~/.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`.
|
|
242
246
|
|
|
243
247
|
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
248
|
|
|
@@ -249,10 +253,12 @@ code-agnostic skills install ./my-skill --apply
|
|
|
249
253
|
```
|
|
250
254
|
|
|
251
255
|
That command should copy the skill into the source of truth and then run the normal compiler/apply flow.
|
|
256
|
+
See [docs/project-scoped-skills.md](docs/project-scoped-skills.md) for the
|
|
257
|
+
first implementation slice.
|
|
252
258
|
|
|
253
259
|
### Workspaces
|
|
254
260
|
|
|
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.
|
|
261
|
+
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
262
|
|
|
257
263
|
Cursor propagation intentionally stays to repo-local MCP, skills, and agents; it does not copy the shared workspace `AGENTS.md` into child repos.
|
|
258
264
|
|
|
@@ -316,12 +322,12 @@ The compiler migration is documented in:
|
|
|
316
322
|
- [x] MCP add/remove/list commands
|
|
317
323
|
- [x] Rules system with YAML frontmatter and per-editor compilation
|
|
318
324
|
- [x] Cross-compilation for skills and agents
|
|
325
|
+
- [x] Planner integration for cross-compiled skills and agents
|
|
319
326
|
- [x] Per-workspace git-exclude customization
|
|
320
327
|
- [x] Interactive TUI for import selection
|
|
321
328
|
- [x] Claude Code support
|
|
322
329
|
- [ ] Project-scoped skill installs and sync
|
|
323
330
|
- [ ] `rules add` / `skills add` / `agents add` commands (open `$EDITOR` with template)
|
|
324
|
-
- [ ] Planner integration for cross-compiled skills and agents
|
|
325
331
|
- [ ] Shell auto-complete
|
|
326
332
|
- [ ] Full TUI mode (command palette + menus)
|
|
327
333
|
|
|
@@ -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
|
|
|
@@ -48,11 +48,12 @@ Today the implementation is still mixed: some assets are compiled and some are s
|
|
|
48
48
|
- workspace source config under `~/.config/code-agnostic/workspaces/<name>/`,
|
|
49
49
|
propagated into repos inside a registered workspace.
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
Workspace sync may generate repo-local outputs, but those outputs are not
|
|
52
|
+
source. Project-local skill folders that users create directly inside a repo,
|
|
53
|
+
such as `.agents/skills` or `.opencode/skills`, are app-native inputs but are
|
|
54
|
+
not managed as source by `code-agnostic` yet. First-class project-scoped
|
|
55
|
+
installs are planned so a single registered project can have managed local
|
|
56
|
+
source config without bypassing the hub.
|
|
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
|
|
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
|
|
|
@@ -213,7 +214,10 @@ code-agnostic plan
|
|
|
213
214
|
code-agnostic apply
|
|
214
215
|
```
|
|
215
216
|
|
|
216
|
-
|
|
217
|
+
There is no `skills install` command yet; copy skills into managed source first,
|
|
218
|
+
then use the normal `plan` / `apply` workflow.
|
|
219
|
+
|
|
220
|
+
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_HOME` when set, defaulting to `~/.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`.
|
|
217
221
|
|
|
218
222
|
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
223
|
|
|
@@ -224,10 +228,12 @@ code-agnostic skills install ./my-skill --apply
|
|
|
224
228
|
```
|
|
225
229
|
|
|
226
230
|
That command should copy the skill into the source of truth and then run the normal compiler/apply flow.
|
|
231
|
+
See [docs/project-scoped-skills.md](docs/project-scoped-skills.md) for the
|
|
232
|
+
first implementation slice.
|
|
227
233
|
|
|
228
234
|
### Workspaces
|
|
229
235
|
|
|
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.
|
|
236
|
+
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
237
|
|
|
232
238
|
Cursor propagation intentionally stays to repo-local MCP, skills, and agents; it does not copy the shared workspace `AGENTS.md` into child repos.
|
|
233
239
|
|
|
@@ -291,12 +297,12 @@ The compiler migration is documented in:
|
|
|
291
297
|
- [x] MCP add/remove/list commands
|
|
292
298
|
- [x] Rules system with YAML frontmatter and per-editor compilation
|
|
293
299
|
- [x] Cross-compilation for skills and agents
|
|
300
|
+
- [x] Planner integration for cross-compiled skills and agents
|
|
294
301
|
- [x] Per-workspace git-exclude customization
|
|
295
302
|
- [x] Interactive TUI for import selection
|
|
296
303
|
- [x] Claude Code support
|
|
297
304
|
- [ ] Project-scoped skill installs and sync
|
|
298
305
|
- [ ] `rules add` / `skills add` / `agents add` commands (open `$EDITOR` with template)
|
|
299
|
-
- [ ] Planner integration for cross-compiled skills and agents
|
|
300
306
|
- [ ] Shell auto-complete
|
|
301
307
|
- [ ] Full TUI mode (command palette + menus)
|
|
302
308
|
|
|
@@ -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
|
-
|
|
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 (
|
|
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.
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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"
|
{code_agnostic-0.3.11 → code_agnostic-0.3.12}/code_agnostic/apps/opencode/config_repository.py
RENAMED
|
@@ -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__(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
-
"
|
|
47
|
-
"
|
|
48
|
-
|
|
46
|
+
"ConfigV2.Reference.Git": {
|
|
47
|
+
"type": "object",
|
|
48
|
+
"properties": {
|
|
49
|
+
"repository": {
|
|
49
50
|
"type": "string"
|
|
50
51
|
},
|
|
51
|
-
{
|
|
52
|
-
"type": "
|
|
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": "
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
"
|
|
67
|
+
"ConfigV2.Reference.Local": {
|
|
84
68
|
"type": "object",
|
|
85
|
-
"
|
|
86
|
-
"
|
|
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
|
-
"
|
|
831
|
-
"
|
|
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
|
-
|
|
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.")
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import click
|
|
4
4
|
from rich.console import Console
|
|
5
5
|
|
|
6
|
-
from code_agnostic.cli.helpers import workspace_config_root
|
|
6
|
+
from code_agnostic.cli.helpers import validate_resource_name, workspace_config_root
|
|
7
7
|
from code_agnostic.cli.options import workspace_option
|
|
8
8
|
from code_agnostic.core.repository import CoreRepository
|
|
9
9
|
from code_agnostic.rules.repository import RulesRepository
|
|
@@ -37,6 +37,7 @@ def rules_list(obj: dict[str, str], workspace: str | None) -> None:
|
|
|
37
37
|
@workspace_option()
|
|
38
38
|
@click.pass_obj
|
|
39
39
|
def rules_remove(obj: dict[str, str], name: str, workspace: str | None) -> None:
|
|
40
|
+
validate_resource_name(name, "rule")
|
|
40
41
|
core = CoreRepository()
|
|
41
42
|
root = workspace_config_root(core, workspace)
|
|
42
43
|
|
|
@@ -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
|
|
@@ -41,11 +41,17 @@ def skills_list(obj: dict[str, str], workspace: str | None) -> None:
|
|
|
41
41
|
]
|
|
42
42
|
for source in skill_sources
|
|
43
43
|
]
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
f"
|
|
44
|
+
skill_dir = compact_home_path(root / "skills")
|
|
45
|
+
scope_message = (
|
|
46
|
+
f"No workspace skills configured for {workspace}"
|
|
47
47
|
if workspace
|
|
48
|
-
else
|
|
48
|
+
else "No global skills configured"
|
|
49
|
+
)
|
|
50
|
+
empty_message = (
|
|
51
|
+
f"{scope_message} in {skill_dir}.\n"
|
|
52
|
+
f"- Copy a skill into {skill_dir}/<name>\n"
|
|
53
|
+
"- code-agnostic plan\n"
|
|
54
|
+
"- code-agnostic apply"
|
|
49
55
|
)
|
|
50
56
|
ui.render_list(
|
|
51
57
|
"skills",
|
|
@@ -60,6 +66,7 @@ def skills_list(obj: dict[str, str], workspace: str | None) -> None:
|
|
|
60
66
|
@workspace_option()
|
|
61
67
|
@click.pass_obj
|
|
62
68
|
def skills_remove(obj: dict[str, str], name: str, workspace: str | None) -> None:
|
|
69
|
+
validate_resource_name(name, "skill")
|
|
63
70
|
core = CoreRepository()
|
|
64
71
|
root = workspace_config_root(core, workspace)
|
|
65
72
|
skill_dir = root / "skills" / name
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Shared helper functions for CLI commands."""
|
|
2
2
|
|
|
3
|
-
from pathlib import Path
|
|
3
|
+
from pathlib import Path, PureWindowsPath
|
|
4
4
|
|
|
5
5
|
import click
|
|
6
6
|
|
|
@@ -31,6 +31,18 @@ def workspace_config_root(core: CoreRepository, workspace: str | None) -> Path:
|
|
|
31
31
|
return core.workspace_config_dir(workspace)
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
def validate_resource_name(name: str, resource_type: str) -> None:
|
|
35
|
+
if (
|
|
36
|
+
not name.strip()
|
|
37
|
+
or name in {".", ".."}
|
|
38
|
+
or "/" in name
|
|
39
|
+
or "\\" in name
|
|
40
|
+
or Path(name).is_absolute()
|
|
41
|
+
or PureWindowsPath(name).drive
|
|
42
|
+
):
|
|
43
|
+
raise click.ClickException(f"Invalid {resource_type} name: {name}")
|
|
44
|
+
|
|
45
|
+
|
|
34
46
|
def status_row_for_app(app_name: str, plan, apps: AppsService) -> EditorStatusRow:
|
|
35
47
|
if not apps.is_enabled(app_name):
|
|
36
48
|
return EditorStatusRow(
|