Summary
Commands can be multi-file: an entry file commands/<cmd>.md plus a co-named sidecar directory commands/<cmd>/ holding procedure files the entry reads at runtime (e.g. via ${COMMAND_DIR}/<cmd>/phase.md). lola treated every command as a single .md file and emitted only the entry. The sidecar directory was dropped, so the entry's runtime references broke and the command installed incompletely. Exit code 0, no warning.
Root cause
_generate_passthrough_command (src/lola/targets/base.py) copied the single entry file and never looked for a co-named sidecar directory beside it. Skills already get whole-directory handling for their supporting files; commands didn't.
Fix
Copy the sidecar directory alongside the entry file for file-based targets (claude-code, cursor, opencode) through the shared passthrough helper, and remove it on uninstall so removal stays symmetric. This mirrors the directory handling skills already get. gemini-cli (TOML commands) and openclaw (no commands) are unaffected.
Affected files (in the fix)
src/lola/targets/base.py: copy the co-named sidecar directory in the passthrough helper; remove it on uninstall.
tests/test_targets.py: cover sidecar copy for claude-code and opencode, plus the no-sidecar case (no spurious directory created).
AGENTS.md: document the multi-file command shape.
Steps to Reproduce
- Register a module with a multi-file command, e.g. review-council ships
commands/review-council.md plus commands/review-council/ (prepare.md, delegate.md, verify.md, report.md, quality-gates.md).
lola install review-council -a claude-code.
- Inspect
.claude/commands/.
Expected
The entry file and its co-named sidecar directory are both installed:
.claude/commands/review-council.md
.claude/commands/review-council/prepare.md
.claude/commands/review-council/delegate.md
Actual
Only .claude/commands/review-council.md is written. The review-council/ sidecar is missing, so the entry's ${COMMAND_DIR}/review-council/*.md reads resolve to nothing and the command can't run its phases. Install still reports success.
Summary
Commands can be multi-file: an entry file
commands/<cmd>.mdplus a co-named sidecar directorycommands/<cmd>/holding procedure files the entry reads at runtime (e.g. via${COMMAND_DIR}/<cmd>/phase.md). lola treated every command as a single.mdfile and emitted only the entry. The sidecar directory was dropped, so the entry's runtime references broke and the command installed incompletely. Exit code 0, no warning.Root cause
_generate_passthrough_command(src/lola/targets/base.py) copied the single entry file and never looked for a co-named sidecar directory beside it. Skills already get whole-directory handling for their supporting files; commands didn't.Fix
Copy the sidecar directory alongside the entry file for file-based targets (claude-code, cursor, opencode) through the shared passthrough helper, and remove it on uninstall so removal stays symmetric. This mirrors the directory handling skills already get. gemini-cli (TOML commands) and openclaw (no commands) are unaffected.
Affected files (in the fix)
src/lola/targets/base.py: copy the co-named sidecar directory in the passthrough helper; remove it on uninstall.tests/test_targets.py: cover sidecar copy for claude-code and opencode, plus the no-sidecar case (no spurious directory created).AGENTS.md: document the multi-file command shape.Steps to Reproduce
commands/review-council.mdpluscommands/review-council/(prepare.md, delegate.md, verify.md, report.md, quality-gates.md).lola install review-council -a claude-code..claude/commands/.Expected
The entry file and its co-named sidecar directory are both installed:
Actual
Only
.claude/commands/review-council.mdis written. Thereview-council/sidecar is missing, so the entry's${COMMAND_DIR}/review-council/*.mdreads resolve to nothing and the command can't run its phases. Install still reports success.