LCR-85: Add multi-harness skill system with --tools flags#76
Conversation
Extract Claude-Code-specific skill installation into a harness-agnostic system. New harness registry maps tool IDs (Claude Code, Codex, Cursor, GitHub Copilot, OpenCode) to per-tool install paths. Skills, agents, and guides are copied to all selected harnesses; hooks and settings remain Claude Code only. - Add src/lightcone/cli/harness.py (registry module) - Add --tools flag to lc init and lc update --sync - Refactor _install_harnesses to loop over selected harnesses - Add _display_install_summary with post-install output - Add tests/test_harness.py (unit tests for registry) - Add tests/test_harness_install.py (CLI integration tests) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LCR-85 Reformat the skill system to support multiple harnesses (Claude Code, Codex, Cursor, ...)
Today the skill system is Claude-Code-specific: Current stateThe CLI ships these skills today (see
Plus the All of these are copied into each target project by Design direction — OpenSpec-style per-tool deliveryOpenSpec solves the same problem by keeping a single canonical skill set and mapping it to each tool's native format at install time:
It's a directory-structure lookup table, not transpilation — the skill content stays identical; only the file location and filename convention changes per harness. Proposed scope for the
|
✅ Eval Results
Graders✅ spec_valid (1.00) Full output |
Update TestSyncProjectPlugins to reflect that sync only copies skills, agents, and guides. Hooks and scripts are init-time only. - test_sync_copies_plugin_dirs: assert agents synced, hooks/scripts not - test_sync_scripts_executable: renamed to test_sync_no_scripts - _make_plugin_source fixture: add agents/ dir Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@claude please review this PR |
|
Claude finished @aboucaud's task in 2m 3s —— View job PR Review: LCR-85 Multi-Harness Skill SystemTasks
Overall this is a clean, well-structured refactor. The registry abstraction is the right call and the test coverage is solid. A few issues to address before merging: Bugs / Correctness1. Type annotation bug in
# current (wrong)
global_notices: list[str] = []
...
global_notices.append((h.tool_name, gpath)) # tuple, not str
# fix
global_notices: list[tuple[str, str]] = []2.
# _install_harnesses should mirror _sync_project_plugins's guards:
if h.has_skills:
_copy_dir(plugin_source / "skills", prefix / "skills")
if h.has_agents:
_copy_dir(plugin_source / "agents", prefix / "agents")
...
if h.has_guides:
_copy_dir(plugin_source / "guides", prefix / "guides")3.
# current
for tid in tool_ids:
harness = HARNESS_REGISTRY[tid] # KeyError on unknown id
# fix: reuse existing validator
for harness in resolve_harnesses(tool_ids):
...Design Issues4.
# commands.py — both @click.option("--tools") decorators
type=click.Choice(list(ALL_TOOL_IDS)),5.
6. Duplicate tool IDs silently double-install
ids = list(dict.fromkeys(tool_ids)) if tool_ids else ["claude"]Minor Issues7. The summary (line 1076) only shows 8. Wrong ADR in this PR
TestsThe test structure is clean and covers the important cases well. A few notes:
Summary: Four issues worth fixing before merge — the type annotation bug (#1), the |
- Add harness.py to repository structure - Add harness registration to extending table Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@claude please fix the reported issues |
|
Claude finished @aboucaud's task in 5m 46s —— View job Fixed all reported issuesTasks
|
- Fix type annotation: global_notices list[str] -> list[tuple[str,str]] - Add has_skills/has_agents/has_guides guards to _install_harnesses to match the same guards already present in _sync_project_plugins - Replace raw HARNESS_REGISTRY[tid] lookups with resolve_harnesses() in _sync_project_plugins and _prompt_sync_projects for consistent validation - Replace hardcoded click.Choice tool lists with ALL_TOOL_IDS so adding a new harness requires only one change in the registry - Add agents/guides entries to _display_install_summary output - Replace print() in ensure_dir with warnings.warn() (leaf module) - De-duplicate tool IDs in resolve_harnesses() using dict.fromkeys - Remove misplaced docs/adr/0001-adopt-dagster-slurm.md (Prism/SLURM ADR unrelated to this multi-harness PR) Co-authored-by: Alexandre Boucaud <aboucaud@users.noreply.github.com>
|
@claude please fix the test errors you created |
|
Claude finished @aboucaud's task in 2m 9s —— View job Tasks
Both failures were in |
…warn - test_duplicate_tools_preserved → test_duplicate_tools_deduplicated: update assertion to len==1 after fix #6 introduced dict.fromkeys de-duplication - test_warns_on_permission_error: replace capsys stdout check with pytest.warns(UserWarning) after fix #5 changed print() to warnings.warn() Co-authored-by: Alexandre Boucaud <aboucaud@users.noreply.github.com>
1. CLAUDE.md: update Plugin system section to reflect multi-harness install/sync behaviour; add convention to keep CLAUDE.md current during PRs. 2. harness.py: add comments clarifying that has_hooks/has_settings are Claude Code-specific flags (no other tool has per-project agent automation hooks or settings files). 3. commands.py: make pip upgrade failure non-fatal in lc update — warn and continue to sync instead of raising SystemExit(1), so lc update --tools X works from inside a project venv. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Still missing
|
- docs/architecture.md: rename plugin section to "Agent harness plugin"; show per-harness vs Claude-only content; list harness registry - docs/cli/init.md: add --tools option; update modes and internal helpers - docs/cli/update.md: add --tools option; clarify what is/isn't synced; note non-fatal pip upgrade; update examples - docs/skills/index.md: update install paths; add multi-harness table Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The plugin source directory was named after Claude Code. Now that skills, agents, and guides are distributed to all harnesses, rename to plugin/ to reflect its actual purpose. - git mv claude/ plugin/ (history preserved) - pyproject.toml: update force-include and sdist include paths - src/lightcone/cli/plugin.py: update bundled + dev path constants - CLAUDE.md, docs/: replace all claude/lightcone and lightcone/cli/claude/lightcone path references Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AGENTS.md is the harness-agnostic convention read by Codex and other agent tools. CLAUDE.md is retained as a one-line pointer for Claude Code session compatibility. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
src/lightcone/cli/harness.pyregistry maps tool IDs to per-tool install paths--toolsflag tolc initandlc update --syncTest plan
uv run pytest tests/test_harness.py tests/test_harness_install.py -v— 32/32 passeduv run ruff check src/ tests/— cleanuv run mypy src/— no new errorslc init --tools claude --tools codex .and verify both.claude/and.codex/populatedlc update --tools codexand verify only.codex/affected🤖 Generated with Claude Code