code-agnostic 0.3.4__tar.gz → 0.3.5__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.4 → code_agnostic-0.3.5}/PKG-INFO +57 -14
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/README.md +56 -13
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/__init__.py +1 -1
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/__main__.py +3 -1
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/agents/opencode.py +36 -12
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/app_id.py +1 -1
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/apps_service.py +3 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/codex/config_repository.py +2 -1
- code_agnostic-0.3.5/code_agnostic/apps/codex/schema.json +5188 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/codex/service.py +8 -1
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/common/compiled_planning.py +7 -3
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/common/interfaces/service.py +1 -0
- code_agnostic-0.3.5/code_agnostic/apps/opencode/schema.json +1252 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/opencode/service.py +14 -4
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/commands/skills.py +23 -2
- code_agnostic-0.3.5/code_agnostic/cli/commands/status.py +64 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/helpers.py +6 -7
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/options.py +0 -12
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/constants.py +1 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/core/repository.py +1 -1
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/executor.py +71 -23
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/git_exclude_service.py +5 -1
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/planner.py +50 -33
- code_agnostic-0.3.5/code_agnostic/skills/compilers.py +75 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/skills/models.py +2 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/skills/parser.py +11 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/spec/loaders.py +11 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/status.py +4 -2
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/tui/renderers.py +55 -8
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic.egg-info/PKG-INFO +57 -14
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic.egg-info/SOURCES.txt +1 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/pyproject.toml +1 -1
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_apply_apps.py +246 -11
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_import.py +1 -1
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_plan.py +19 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_skills.py +7 -1
- code_agnostic-0.3.5/tests/test_cli_status.py +155 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_workspaces.py +5 -2
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_common_repository.py +4 -5
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_git_exclude_service.py +4 -2
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_planner_executor.py +64 -15
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_transactional_executor.py +274 -0
- code_agnostic-0.3.5/tests/test_version.py +11 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_workspace_config_sync.py +112 -30
- code_agnostic-0.3.4/code_agnostic/apps/codex/schema.json +0 -114
- code_agnostic-0.3.4/code_agnostic/apps/opencode/schema.json +0 -7675
- code_agnostic-0.3.4/code_agnostic/cli/commands/status.py +0 -52
- code_agnostic-0.3.4/code_agnostic/skills/compilers.py +0 -39
- code_agnostic-0.3.4/tests/test_cli_status.py +0 -64
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/LICENSE +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/agents/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/agents/codex.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/agents/compilers.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/agents/models.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/agents/parser.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/codex/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/codex/mapper.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/codex/schema_repository.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/common/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/common/framework.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/common/interfaces/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/common/interfaces/mapper.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/common/interfaces/repositories.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/common/loader.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/common/models.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/common/schema.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/common/symlink_planning.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/common/utils.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/cursor/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/cursor/config_repository.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/cursor/mapper.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/cursor/schema.json +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/cursor/schema_repository.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/cursor/service.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/opencode/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/opencode/config_repository.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/opencode/mapper.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/apps/opencode/schema_repository.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/aliases.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/commands/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/commands/agents.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/commands/apply.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/commands/apps.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/commands/explain_lossiness.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/commands/import_.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/commands/mcp.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/commands/plan.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/commands/restore.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/commands/rules.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/commands/validate.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/cli/commands/workspaces.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/core/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/core/workspace_repository.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/errors.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/imports/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/imports/adapters.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/imports/filesystem.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/imports/models.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/imports/service.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/lossiness.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/mcp_service.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/models.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/rules/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/rules/compilers.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/rules/models.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/rules/parser.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/rules/repository.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/skills/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/spec/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/spec/schemas/agent.v1.schema.json +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/spec/schemas/mcp.base.schema.json +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/spec/schemas/mcp.v1.schema.json +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/spec/schemas/rule.v1.schema.json +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/spec/schemas/skill.v1.schema.json +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/tui/__init__.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/tui/enums.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/tui/import_selector.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/tui/sections.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/tui/tables.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/utils.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/validation.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic/workspaces.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic.egg-info/dependency_links.txt +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic.egg-info/entry_points.txt +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic.egg-info/requires.txt +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/code_agnostic.egg-info/top_level.txt +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/setup.cfg +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_agents.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_aliases.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_apply_codex.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_apply_cursor.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_apply_target.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_apps.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_explain_lossiness.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_flags.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_git_exclude.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_import_interactive.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_mcp.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_module_organization.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_restore.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_rules.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_validate.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_cli_workspace_resolution.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_common_mcp_to_dto.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_compiled_planning.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_dto_to_common_mcp.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_mcp_service.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_planner_rules.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_symlink_planning.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_sync_plan_model.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_utils.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/tests/test_workspace_repo_status.py +0 -0
- {code_agnostic-0.3.4 → code_agnostic-0.3.5}/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.5
|
|
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
|
|
@@ -36,11 +36,17 @@ AI coding tools each want config in a different place and format. When you use m
|
|
|
36
36
|
├── config/
|
|
37
37
|
│ └── mcp.base.json MCP servers (editor-agnostic)
|
|
38
38
|
├── rules/
|
|
39
|
-
│ └── python-style
|
|
39
|
+
│ └── python-style/
|
|
40
|
+
│ ├── meta.yaml Rule metadata
|
|
41
|
+
│ └── prompt.md Rule instructions
|
|
40
42
|
├── skills/
|
|
41
|
-
│ └── code-reviewer/
|
|
43
|
+
│ └── code-reviewer/
|
|
44
|
+
│ ├── meta.yaml Skill metadata
|
|
45
|
+
│ └── prompt.md Skill instructions
|
|
42
46
|
└── agents/
|
|
43
|
-
└── architect
|
|
47
|
+
└── architect/
|
|
48
|
+
├── meta.yaml Agent metadata
|
|
49
|
+
└── prompt.md Agent instructions
|
|
44
50
|
|
|
45
51
|
↓ plan / apply ↓
|
|
46
52
|
|
|
@@ -51,6 +57,8 @@ AI coding tools each want config in a different place and format. When you use m
|
|
|
51
57
|
|
|
52
58
|
Each resource is cross-compiled to the target editor's native format. Rules become `.mdc` files for Cursor, `AGENTS.md` sections for OpenCode/Codex, etc.
|
|
53
59
|
|
|
60
|
+
Legacy single-file rules, `skills/<name>/SKILL.md`, and markdown agents are still supported for migration, but bundle directories are the preferred source format for new config.
|
|
61
|
+
|
|
54
62
|
Today the implementation is still mixed: some assets are compiled and some are symlinked. The active migration plan is to move to generated outputs everywhere with a strict compiler contract instead of implicit per-app behavior.
|
|
55
63
|
|
|
56
64
|
## Install
|
|
@@ -88,6 +96,7 @@ code-agnostic apps enable -a cursor
|
|
|
88
96
|
code-agnostic apps enable -a opencode
|
|
89
97
|
|
|
90
98
|
# Preview and apply
|
|
99
|
+
code-agnostic validate
|
|
91
100
|
code-agnostic plan
|
|
92
101
|
code-agnostic apply
|
|
93
102
|
```
|
|
@@ -103,7 +112,7 @@ code-agnostic apply
|
|
|
103
112
|
| Workspace root `AGENTS.md` link | yes | yes | yes |
|
|
104
113
|
| Native repo config include for workspace `AGENTS.md` | yes | -- | -- |
|
|
105
114
|
| Repo/subdir gets shared workspace `AGENTS.md` today | yes | -- | yes |
|
|
106
|
-
|
|
|
115
|
+
| Nested `AGENTS.md` discovery | -- | yes | yes |
|
|
107
116
|
| Workspace propagation | yes | -- | yes |
|
|
108
117
|
| Import from | yes | yes | yes |
|
|
109
118
|
| Interactive import (TUI) | yes | yes | yes |
|
|
@@ -112,7 +121,7 @@ Cursor workspace propagation is intentionally disabled to avoid duplicate MCP in
|
|
|
112
121
|
|
|
113
122
|
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`.
|
|
114
123
|
|
|
115
|
-
Cursor documents `AGENTS.md`
|
|
124
|
+
Cursor documents `AGENTS.md` support in project roots and subdirectories. `code-agnostic` still disables Cursor workspace propagation, so it 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.
|
|
116
125
|
|
|
117
126
|
## Features
|
|
118
127
|
|
|
@@ -121,12 +130,20 @@ Cursor documents `AGENTS.md` as a root-level project file. Codex documents `AGEN
|
|
|
121
130
|
Plan-then-apply workflow. Preview every change before it touches disk.
|
|
122
131
|
|
|
123
132
|
```bash
|
|
133
|
+
code-agnostic validate # check canonical source files
|
|
124
134
|
code-agnostic plan -a cursor # dry-run for one editor
|
|
125
135
|
code-agnostic plan # dry-run for all
|
|
126
136
|
code-agnostic apply # apply changes
|
|
127
137
|
code-agnostic status # check drift
|
|
128
138
|
```
|
|
129
139
|
|
|
140
|
+
If managed outputs need repair after an apply, restore the active synced revision:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
code-agnostic restore
|
|
144
|
+
code-agnostic restore -w myproject
|
|
145
|
+
```
|
|
146
|
+
|
|
130
147
|
### MCP management
|
|
131
148
|
|
|
132
149
|
Add, remove, and list MCP servers without editing JSON by hand.
|
|
@@ -162,13 +179,32 @@ code-agnostic rules remove --name python-style
|
|
|
162
179
|
|
|
163
180
|
### Skills and agents
|
|
164
181
|
|
|
165
|
-
Canonical YAML frontmatter format, cross-compiled per editor.
|
|
182
|
+
Canonical YAML frontmatter format, cross-compiled per editor. Install or edit skills in the `code-agnostic` source of truth, then run `plan` / `apply`; do not hand-copy generated skills into `.codex`, `.cursor`, or OpenCode directories.
|
|
166
183
|
|
|
167
184
|
```bash
|
|
168
185
|
code-agnostic skills list
|
|
169
186
|
code-agnostic agents list
|
|
170
187
|
```
|
|
171
188
|
|
|
189
|
+
Manual skill install today:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
mkdir -p ~/.config/code-agnostic/skills
|
|
193
|
+
cp -R ./my-skill ~/.config/code-agnostic/skills/my-skill
|
|
194
|
+
code-agnostic plan
|
|
195
|
+
code-agnostic apply
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
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`.
|
|
199
|
+
|
|
200
|
+
Planned convenience command:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
code-agnostic skills install ./my-skill --apply
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
That command should copy the skill into the source of truth and then run the normal compiler/apply flow.
|
|
207
|
+
|
|
172
208
|
### Workspaces
|
|
173
209
|
|
|
174
210
|
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`. Repo-local app config, skills, and agents are propagated for OpenCode and Codex.
|
|
@@ -210,13 +246,12 @@ All commands use named flags (`-a`, `-w`, `-v`). Singular aliases work too: `app
|
|
|
210
246
|
|
|
211
247
|
The compiler migration is documented in:
|
|
212
248
|
|
|
213
|
-
- [
|
|
214
|
-
- [docs/compiler/
|
|
215
|
-
- [docs/compiler/
|
|
216
|
-
- [docs/compiler/
|
|
217
|
-
- [docs/compiler/
|
|
218
|
-
- [docs/compiler/
|
|
219
|
-
- [docs/compiler/lossiness.md](/Users/alexeyartishevsky/PycharmProjects/llm-sync/docs/compiler/lossiness.md)
|
|
249
|
+
- [docs/compiler/overview.md](docs/compiler/overview.md)
|
|
250
|
+
- [docs/compiler/skills.md](docs/compiler/skills.md)
|
|
251
|
+
- [docs/compiler/agents.md](docs/compiler/agents.md)
|
|
252
|
+
- [docs/compiler/rules.md](docs/compiler/rules.md)
|
|
253
|
+
- [docs/compiler/mcp.md](docs/compiler/mcp.md)
|
|
254
|
+
- [docs/compiler/lossiness.md](docs/compiler/lossiness.md)
|
|
220
255
|
|
|
221
256
|
## Roadmap
|
|
222
257
|
|
|
@@ -243,3 +278,11 @@ The compiler migration is documented in:
|
|
|
243
278
|
uv sync --dev
|
|
244
279
|
uv run pytest
|
|
245
280
|
```
|
|
281
|
+
|
|
282
|
+
Real app-ingestion E2E is gated because it requires installed target CLIs and
|
|
283
|
+
uses each tool's own introspection surface:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
CODE_AGNOSTIC_REAL_APP_E2E=1 uv run pytest tests/e2e/test_real_app_ingestion_e2e.py -q
|
|
287
|
+
CODE_AGNOSTIC_REAL_APP_E2E=1 CODE_AGNOSTIC_REAL_APP_TARGETS=codex,opencode uv run pytest tests/e2e/test_real_app_ingestion_e2e.py -q
|
|
288
|
+
```
|
|
@@ -13,11 +13,17 @@ AI coding tools each want config in a different place and format. When you use m
|
|
|
13
13
|
├── config/
|
|
14
14
|
│ └── mcp.base.json MCP servers (editor-agnostic)
|
|
15
15
|
├── rules/
|
|
16
|
-
│ └── python-style
|
|
16
|
+
│ └── python-style/
|
|
17
|
+
│ ├── meta.yaml Rule metadata
|
|
18
|
+
│ └── prompt.md Rule instructions
|
|
17
19
|
├── skills/
|
|
18
|
-
│ └── code-reviewer/
|
|
20
|
+
│ └── code-reviewer/
|
|
21
|
+
│ ├── meta.yaml Skill metadata
|
|
22
|
+
│ └── prompt.md Skill instructions
|
|
19
23
|
└── agents/
|
|
20
|
-
└── architect
|
|
24
|
+
└── architect/
|
|
25
|
+
├── meta.yaml Agent metadata
|
|
26
|
+
└── prompt.md Agent instructions
|
|
21
27
|
|
|
22
28
|
↓ plan / apply ↓
|
|
23
29
|
|
|
@@ -28,6 +34,8 @@ AI coding tools each want config in a different place and format. When you use m
|
|
|
28
34
|
|
|
29
35
|
Each resource is cross-compiled to the target editor's native format. Rules become `.mdc` files for Cursor, `AGENTS.md` sections for OpenCode/Codex, etc.
|
|
30
36
|
|
|
37
|
+
Legacy single-file rules, `skills/<name>/SKILL.md`, and markdown agents are still supported for migration, but bundle directories are the preferred source format for new config.
|
|
38
|
+
|
|
31
39
|
Today the implementation is still mixed: some assets are compiled and some are symlinked. The active migration plan is to move to generated outputs everywhere with a strict compiler contract instead of implicit per-app behavior.
|
|
32
40
|
|
|
33
41
|
## Install
|
|
@@ -65,6 +73,7 @@ code-agnostic apps enable -a cursor
|
|
|
65
73
|
code-agnostic apps enable -a opencode
|
|
66
74
|
|
|
67
75
|
# Preview and apply
|
|
76
|
+
code-agnostic validate
|
|
68
77
|
code-agnostic plan
|
|
69
78
|
code-agnostic apply
|
|
70
79
|
```
|
|
@@ -80,7 +89,7 @@ code-agnostic apply
|
|
|
80
89
|
| Workspace root `AGENTS.md` link | yes | yes | yes |
|
|
81
90
|
| Native repo config include for workspace `AGENTS.md` | yes | -- | -- |
|
|
82
91
|
| Repo/subdir gets shared workspace `AGENTS.md` today | yes | -- | yes |
|
|
83
|
-
|
|
|
92
|
+
| Nested `AGENTS.md` discovery | -- | yes | yes |
|
|
84
93
|
| Workspace propagation | yes | -- | yes |
|
|
85
94
|
| Import from | yes | yes | yes |
|
|
86
95
|
| Interactive import (TUI) | yes | yes | yes |
|
|
@@ -89,7 +98,7 @@ Cursor workspace propagation is intentionally disabled to avoid duplicate MCP in
|
|
|
89
98
|
|
|
90
99
|
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`.
|
|
91
100
|
|
|
92
|
-
Cursor documents `AGENTS.md`
|
|
101
|
+
Cursor documents `AGENTS.md` support in project roots and subdirectories. `code-agnostic` still disables Cursor workspace propagation, so it 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.
|
|
93
102
|
|
|
94
103
|
## Features
|
|
95
104
|
|
|
@@ -98,12 +107,20 @@ Cursor documents `AGENTS.md` as a root-level project file. Codex documents `AGEN
|
|
|
98
107
|
Plan-then-apply workflow. Preview every change before it touches disk.
|
|
99
108
|
|
|
100
109
|
```bash
|
|
110
|
+
code-agnostic validate # check canonical source files
|
|
101
111
|
code-agnostic plan -a cursor # dry-run for one editor
|
|
102
112
|
code-agnostic plan # dry-run for all
|
|
103
113
|
code-agnostic apply # apply changes
|
|
104
114
|
code-agnostic status # check drift
|
|
105
115
|
```
|
|
106
116
|
|
|
117
|
+
If managed outputs need repair after an apply, restore the active synced revision:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
code-agnostic restore
|
|
121
|
+
code-agnostic restore -w myproject
|
|
122
|
+
```
|
|
123
|
+
|
|
107
124
|
### MCP management
|
|
108
125
|
|
|
109
126
|
Add, remove, and list MCP servers without editing JSON by hand.
|
|
@@ -139,13 +156,32 @@ code-agnostic rules remove --name python-style
|
|
|
139
156
|
|
|
140
157
|
### Skills and agents
|
|
141
158
|
|
|
142
|
-
Canonical YAML frontmatter format, cross-compiled per editor.
|
|
159
|
+
Canonical YAML frontmatter format, cross-compiled per editor. Install or edit skills in the `code-agnostic` source of truth, then run `plan` / `apply`; do not hand-copy generated skills into `.codex`, `.cursor`, or OpenCode directories.
|
|
143
160
|
|
|
144
161
|
```bash
|
|
145
162
|
code-agnostic skills list
|
|
146
163
|
code-agnostic agents list
|
|
147
164
|
```
|
|
148
165
|
|
|
166
|
+
Manual skill install today:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
mkdir -p ~/.config/code-agnostic/skills
|
|
170
|
+
cp -R ./my-skill ~/.config/code-agnostic/skills/my-skill
|
|
171
|
+
code-agnostic plan
|
|
172
|
+
code-agnostic apply
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
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`.
|
|
176
|
+
|
|
177
|
+
Planned convenience command:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
code-agnostic skills install ./my-skill --apply
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
That command should copy the skill into the source of truth and then run the normal compiler/apply flow.
|
|
184
|
+
|
|
149
185
|
### Workspaces
|
|
150
186
|
|
|
151
187
|
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`. Repo-local app config, skills, and agents are propagated for OpenCode and Codex.
|
|
@@ -187,13 +223,12 @@ All commands use named flags (`-a`, `-w`, `-v`). Singular aliases work too: `app
|
|
|
187
223
|
|
|
188
224
|
The compiler migration is documented in:
|
|
189
225
|
|
|
190
|
-
- [
|
|
191
|
-
- [docs/compiler/
|
|
192
|
-
- [docs/compiler/
|
|
193
|
-
- [docs/compiler/
|
|
194
|
-
- [docs/compiler/
|
|
195
|
-
- [docs/compiler/
|
|
196
|
-
- [docs/compiler/lossiness.md](/Users/alexeyartishevsky/PycharmProjects/llm-sync/docs/compiler/lossiness.md)
|
|
226
|
+
- [docs/compiler/overview.md](docs/compiler/overview.md)
|
|
227
|
+
- [docs/compiler/skills.md](docs/compiler/skills.md)
|
|
228
|
+
- [docs/compiler/agents.md](docs/compiler/agents.md)
|
|
229
|
+
- [docs/compiler/rules.md](docs/compiler/rules.md)
|
|
230
|
+
- [docs/compiler/mcp.md](docs/compiler/mcp.md)
|
|
231
|
+
- [docs/compiler/lossiness.md](docs/compiler/lossiness.md)
|
|
197
232
|
|
|
198
233
|
## Roadmap
|
|
199
234
|
|
|
@@ -220,3 +255,11 @@ The compiler migration is documented in:
|
|
|
220
255
|
uv sync --dev
|
|
221
256
|
uv run pytest
|
|
222
257
|
```
|
|
258
|
+
|
|
259
|
+
Real app-ingestion E2E is gated because it requires installed target CLIs and
|
|
260
|
+
uses each tool's own introspection surface:
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
CODE_AGNOSTIC_REAL_APP_E2E=1 uv run pytest tests/e2e/test_real_app_ingestion_e2e.py -q
|
|
264
|
+
CODE_AGNOSTIC_REAL_APP_E2E=1 CODE_AGNOSTIC_REAL_APP_TARGETS=codex,opencode uv run pytest tests/e2e/test_real_app_ingestion_e2e.py -q
|
|
265
|
+
```
|
|
@@ -48,13 +48,15 @@ cli.add_command(import_group)
|
|
|
48
48
|
|
|
49
49
|
def main() -> int:
|
|
50
50
|
try:
|
|
51
|
-
cli(standalone_mode=False)
|
|
51
|
+
result = cli(standalone_mode=False)
|
|
52
52
|
except click.exceptions.Exit as exc:
|
|
53
53
|
code = exc.exit_code
|
|
54
54
|
return code if isinstance(code, int) else 1
|
|
55
55
|
except click.ClickException as exc:
|
|
56
56
|
exc.show()
|
|
57
57
|
return 2
|
|
58
|
+
if isinstance(result, int):
|
|
59
|
+
return result
|
|
58
60
|
return 0
|
|
59
61
|
|
|
60
62
|
|
|
@@ -22,25 +22,25 @@ def serialize_opencode_agent(agent: Agent) -> str:
|
|
|
22
22
|
if reasoning_effort:
|
|
23
23
|
fm["reasoningEffort"] = reasoning_effort
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
if agent.metadata.tools.read is not True:
|
|
27
|
-
tools["read"] = agent.metadata.tools.read
|
|
28
|
-
if agent.metadata.tools.write is not True:
|
|
29
|
-
tools["write"] = agent.metadata.tools.write
|
|
30
|
-
if agent.metadata.tools.mcp:
|
|
31
|
-
tools["mcp"] = agent.metadata.tools.mcp
|
|
32
|
-
if tools:
|
|
33
|
-
fm["tools"] = tools
|
|
34
|
-
|
|
35
|
-
for key, value in agent.metadata.app_passthrough(
|
|
25
|
+
passthrough = agent.metadata.app_passthrough(
|
|
36
26
|
"opencode",
|
|
37
27
|
consumed_keys={
|
|
38
28
|
"model",
|
|
39
29
|
"reasoning_effort",
|
|
40
30
|
"sandbox_mode",
|
|
41
31
|
"nickname_candidates",
|
|
32
|
+
"permission",
|
|
42
33
|
},
|
|
43
|
-
)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
permission = _merge_permission(
|
|
37
|
+
_compile_permission(agent),
|
|
38
|
+
agent.metadata.app_overrides.get("opencode", {}).get("permission"),
|
|
39
|
+
)
|
|
40
|
+
if permission:
|
|
41
|
+
fm["permission"] = permission
|
|
42
|
+
|
|
43
|
+
for key, value in passthrough.items():
|
|
44
44
|
if key in fm:
|
|
45
45
|
continue
|
|
46
46
|
fm[key] = value
|
|
@@ -54,3 +54,27 @@ def serialize_opencode_agent(agent: Agent) -> str:
|
|
|
54
54
|
|
|
55
55
|
parts.append(agent.content)
|
|
56
56
|
return "\n".join(parts)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _compile_permission(agent: Agent) -> dict[str, Any]:
|
|
60
|
+
permission: dict[str, Any] = {}
|
|
61
|
+
permission["read"] = "allow" if agent.metadata.tools.read else "deny"
|
|
62
|
+
permission["edit"] = "allow" if agent.metadata.tools.write else "deny"
|
|
63
|
+
for item in agent.metadata.tools.mcp:
|
|
64
|
+
server = item.get("server")
|
|
65
|
+
if not server:
|
|
66
|
+
continue
|
|
67
|
+
tool = item.get("tool")
|
|
68
|
+
key = f"{server}_{tool}" if tool else f"{server}_*"
|
|
69
|
+
permission[key] = "allow"
|
|
70
|
+
return permission
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _merge_permission(
|
|
74
|
+
generated: dict[str, Any], override: Any | None
|
|
75
|
+
) -> dict[str, Any] | Any:
|
|
76
|
+
if override is None:
|
|
77
|
+
return generated
|
|
78
|
+
if isinstance(override, dict):
|
|
79
|
+
return {**generated, **override}
|
|
80
|
+
return override
|
|
@@ -60,7 +60,7 @@ APP_CATALOG: dict[AppId, AppMetadata] = {
|
|
|
60
60
|
toggleable=True,
|
|
61
61
|
importable=True,
|
|
62
62
|
supports_import_agents=True,
|
|
63
|
-
supports_workspace_propagation=
|
|
63
|
+
supports_workspace_propagation=False,
|
|
64
64
|
project_dir_name=CURSOR_PROJECT_DIRNAME,
|
|
65
65
|
config_filename=CURSOR_CONFIG_FILENAME,
|
|
66
66
|
),
|
|
@@ -86,6 +86,9 @@ class AppsService:
|
|
|
86
86
|
|
|
87
87
|
def plan_for_target(self, target: str) -> SyncPlan:
|
|
88
88
|
normalized = target.lower()
|
|
89
|
+
if normalized != "all" and not self.is_enabled(normalized):
|
|
90
|
+
return SyncPlan([], [], [f"{normalized} is disabled for sync."])
|
|
91
|
+
|
|
89
92
|
app_services = self._resolve_services_for_target(normalized)
|
|
90
93
|
plan = SyncPlanner(
|
|
91
94
|
core=self.core_repository,
|
|
@@ -11,6 +11,7 @@ import tomlkit
|
|
|
11
11
|
from code_agnostic.apps.common.interfaces.repositories import IAppConfigRepository
|
|
12
12
|
from code_agnostic.constants import (
|
|
13
13
|
AGENTS_DIRNAME,
|
|
14
|
+
AGENTS_PROJECT_DIRNAME,
|
|
14
15
|
CODEX_CONFIG_FILENAME,
|
|
15
16
|
CODEX_PROJECT_DIRNAME,
|
|
16
17
|
SKILLS_DIRNAME,
|
|
@@ -32,7 +33,7 @@ class CodexConfigRepository(IAppConfigRepository):
|
|
|
32
33
|
|
|
33
34
|
@property
|
|
34
35
|
def skills_dir(self) -> Path:
|
|
35
|
-
return self.root / SKILLS_DIRNAME
|
|
36
|
+
return self.root.parent / AGENTS_PROJECT_DIRNAME / SKILLS_DIRNAME
|
|
36
37
|
|
|
37
38
|
@property
|
|
38
39
|
def agents_dir(self) -> Path:
|