Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ site/

# Plans (local only)
plan/
docs/superpowers/

# Environment and logs
.env*
Expand Down
84 changes: 76 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ lola uninstall my-module --scope user
- `src/lola/market/manager.py` - MarketplaceRegistry class for marketplace operations
- `src/lola/market/search.py` - Search functionality across marketplace caches
- `src/lola/config.py` - Global paths (LOLA_HOME, MODULES_DIR, INSTALLED_FILE, MARKET_DIR, CACHE_DIR)
- `src/lola/targets.py` - Assistant definitions and file generators (ASSISTANTS dict, generate_* functions)
- `src/lola/targets/` - Assistant target package:
- `__init__.py` - TARGETS registry, `get_target()` lookup
- `base.py` - `AssistantTarget` ABC, `BaseAssistantTarget` defaults, shared helpers (`_generate_agent_with_frontmatter`, `_generate_passthrough_command`, `_get_content_path`)
- `install.py` - Install/uninstall orchestration (`install_to_assistant`, `_install_module_tree`, `_uninstall_module_tree`, `_install_skills/commands/agents/mcps/instructions`)
- `claude_code.py`, `cursor.py`, `gemini.py`, `openclaw.py`, `opencode.py` - Per-target implementations
- `src/lola/parsers.py` - Source fetching (SourceHandler classes) and skill/command parsing
- `src/lola/frontmatter.py` - YAML frontmatter parsing

Expand All @@ -102,9 +106,19 @@ my-module/
SKILL.md # Required: skill definition with frontmatter
scripts/ # Optional: supporting files
commands/ # Slash commands (*.md files)
review.md # A command
review/ # Optional: co-named sidecar dir of supporting files
phase.md # for a multi-file command (copied with review.md)
agents/ # Subagents (*.md files)
```

A command can be a single `*.md` file or a *multi-file command*: an entry file
`commands/<cmd>.md` plus a co-named sidecar directory `commands/<cmd>/` holding
supporting files the entry reads at runtime (e.g. via a path relative to its own
location). The sidecar directory is copied verbatim alongside the entry file for
file-based targets (Claude Code, Cursor, OpenCode) and removed on uninstall. The
sidecar's files are not registered as separate commands.

### Marketplace Structure

Marketplaces are YAML files with module catalogs:
Expand Down Expand Up @@ -136,19 +150,65 @@ modules:

Defined in `targets.py` TARGETS dict. Each assistant has different output formats:

| Assistant | Skills | Commands | Agents |
|-----------|--------|----------|--------|
| claude-code | `.claude/skills/<skill>/SKILL.md` | `.claude/commands/<cmd>.md` | `.claude/agents/<agent>.md` |
| cursor | `.cursor/skills/<skill>/SKILL.md` | `.cursor/commands/<cmd>.md` | `.cursor/agents/<agent>.md` |
| gemini-cli | `GEMINI.md` (managed section) | `.gemini/commands/<cmd>.toml` | N/A |
| openclaw | `~/.openclaw/workspace/skills/<skill>/SKILL.md` | N/A | N/A |
| opencode | `AGENTS.md` (managed section) | `.opencode/commands/<cmd>.md` | `.opencode/agents/<agent>.md` |
| Assistant | Skills | Commands | Agents | Modules |
|-----------|--------|----------|--------|---------|
| claude-code | `.claude/skills/<skill>/SKILL.md` | `.claude/commands/<cmd>.md` | `.claude/agents/<agent>.md` | `.claude/modules/<name>/` |
| cursor | `.cursor/skills/<skill>/SKILL.md` | `.cursor/commands/<cmd>.md` | `.cursor/agents/<agent>.md` | `.cursor/modules/<name>/` |
| gemini-cli | `GEMINI.md` (managed section) | `.gemini/commands/<cmd>.toml` | N/A | `.gemini/modules/<name>/` |
| openclaw | `~/.openclaw/workspace/skills/<skill>/SKILL.md` | N/A | N/A | `modules/<name>/` |
| opencode | `AGENTS.md` (managed section) | `.opencode/commands/<cmd>.md` | `.opencode/agents/<agent>.md` | `.opencode/modules/<name>/` |

Agent frontmatter is modified during generation:
- Claude Code: `name` (agent name) and `model: inherit` are added
- Cursor: `name` (agent name) and `model: inherit` are added
- OpenCode: `mode: subagent` is added

**Module tree:** During installation, the entire module content tree is copied to
the target's `modules/<name>/` directory. This preserves internal relative paths
between module files (e.g. a `packs/` directory that agents reference at
runtime). Skills, commands, and agents all receive a module-dir preamble block
between frontmatter and body, pointing to the installed module tree. Assets can
use this path to locate module-relative resources like convention packs,
reference files, or other shared content that falls outside the standard
skills/commands/agents directories.

The preamble is plain text inlined between frontmatter and body:

```markdown
Module root: .claude/modules/review-council
This is the installed root of the module. Resolve all relative file references in this document against the path above.
Example: packs/foo.md -> .claude/modules/review-council/packs/foo.md
```

**Exceptions:** Gemini CLI commands use TOML format and do not receive the
preamble. The Gemini `ManagedSectionTarget` emits
`**Module root:** \`<path>\`` with an example resolution line in the skills
batch section instead.

Example generated agent file with preamble:
```markdown
---
name: divisor-guard-code
model: inherit
---
Module root: .claude/modules/review-council
This is the installed root of the module. Resolve all relative file references in this document against the path above.
Example: packs/foo.md -> .claude/modules/review-council/packs/foo.md

# Guard - Code Review
...
```

User-scope module tree paths:

| Target | User Scope Module Dir |
|--------|----------------------|
| claude-code | `~/.claude/modules/<name>/` |
| cursor | `~/.cursor/modules/<name>/` |
| gemini-cli | `~/.gemini/modules/<name>/` |
| openclaw | `~/.openclaw/workspace/modules/<name>/` |
| opencode | `~/.config/opencode/modules/<name>/` |

**Backwards compatibility:** Uninstall also checks for old prefixed filenames
(`<module>.<cmd>.md`, `<module>.<agent>.md`) so installs made before prefix
removal are cleaned up correctly.
Expand All @@ -171,6 +231,14 @@ Tests use Click's `CliRunner` for CLI testing. Key fixtures in `tests/conftest.p
- `marketplace_with_modules` - creates marketplace with test modules
- `marketplace_disabled` - creates disabled marketplace for testing

**Unused parameters in ABC overrides (ruff ARG002 vs ty):**
When test stubs or `BaseAssistantTarget` override an ABC method without using
every parameter, ruff raises `ARG002` (unused method argument). Do **not**
prefix the parameter with `_` — `ty` enforces the Liskov Substitution Principle
and rejects parameter name changes in overrides. Instead, annotate each unused
parameter with an inline `# noqa: ARG002` comment. This matches the existing
pattern in `src/lola/targets/base.py` (e.g. `BaseAssistantTarget` stubs).

**Marketplace testing patterns:**
- HTTP requests are mocked using `unittest.mock.patch` with `urllib.request.urlopen`
- Marketplace YAML validation uses actual `Marketplace` model validation
Expand Down
25 changes: 15 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ Lola is a universal AI Package Manager. If an agent's skills were an RPM, Lola i

## Supported AI Assistants

| Assistant | Skills | Commands | Agents |
| ----------- | ------ | -------- | ------ |
| Claude Code | Yes | Yes | Yes |
| Cursor | Yes | Yes | Yes |
| Gemini CLI | Yes | Yes | N/A |
| OpenCode | Yes | Yes | Yes |
| Assistant | Skills | Commands | Agents | Modules |
| --------- | ------ | -------- | ------ | ------- |
| Claude Code | Yes | Yes | Yes | Yes |
| Cursor | Yes | Yes | Yes | Yes |
| Gemini CLI | Yes | Yes | N/A | Yes |
| OpenCode | Yes | Yes | Yes | Yes |

## Installation

Expand Down Expand Up @@ -358,12 +358,16 @@ my-module/
templates/ # Optional: templates
commands/ # Optional: slash commands
review-pr.md
review-pr/ # Optional: sidecar directory for multi-file commands
phase-1.md
quick-commit.md
agents/ # Optional: subagents
my-agent.md
packs/ # Optional: any extra directories are preserved
conventions.md
```

> **Note:** Modules use auto-discovery. Skills are discovered from `skills/<name>/SKILL.md`, commands from `commands/*.md`, and agents from `agents/*.md`. No manifest file is required.
> **Note:** Modules use auto-discovery. Skills are discovered from `skills/<name>/SKILL.md`, commands from `commands/*.md`, and agents from `agents/*.md`. No manifest file is required. Any additional directories (e.g., `packs/`, `templates/`, `reference/`) are copied to the target assistant's `modules/<name>/` directory during installation, preserving internal relative paths.

### SKILL.md

Expand Down Expand Up @@ -408,12 +412,13 @@ Commands are automatically converted to each assistant's format:
1. **Marketplaces**: Register catalogs at `~/.lola/market/` with cached data at `~/.lola/market/cache/`
2. **Discovery**: Search across enabled marketplace caches to find modules
3. **Registry**: Modules are stored in `~/.lola/modules/`
4. **Installation**: Skills and commands are converted to each assistant's native format
4. **Installation**: Skills and commands are converted to each assistant's native format. The full module content tree is also copied to the target's `modules/<name>/` directory, preserving all internal paths so agents can locate shared resources (convention packs, reference files, etc.)
5. **Prefixing**: Skills and commands are prefixed with module name to avoid conflicts (e.g., `mymodule-skill`)
6. **Scopes**:
6. **Module tree**: Generated skill, command, and agent files receive a plain-text preamble block pointing to the installed module tree, allowing agents to discover module-relative resources at runtime
7. **Scopes**:
- **Project scope** (default): Copies modules to `.lola/modules/` within the project
- **User scope**: Installs globally to platform-appropriate user config directories
7. **Updates**: `lola mod update` re-fetches from original source; `lola update` regenerates files; `lola market update` refreshes marketplace caches
8. **Updates**: `lola mod update` re-fetches from original source; `lola update` regenerates files; `lola market update` refreshes marketplace caches

## Code of Conduct

Expand Down
12 changes: 12 additions & 0 deletions docs/dev-guide/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@ When a module is added (via `lola mod add` or through a market install), it gets

When installed into a project, Lola copies the module from the cache and generates assistant-specific files. Each project has independent copies and generated files.

The installation pipeline runs in this order:

1. **Module copy** -- module cached to `.lola/modules/<name>/`
2. **Pre-install hook** -- optional script from `lola.yaml`
3. **Module tree** -- full content tree copied to the target's `modules/<name>/` directory (e.g., `.claude/modules/<name>/`), preserving all internal paths for agent-accessible shared resources
4. **Skills** -- skill directories copied or registered per target format
5. **Commands** -- command files copied; file-based targets (Claude Code, Cursor, OpenCode) also copy co-named sidecar directories
6. **Agents** -- agent files generated with target-specific frontmatter and a plain-text preamble pointing to the installed module tree
7. **MCPs** -- MCP server configs merged into target config files
8. **Instructions** -- module instructions written to managed sections
9. **Post-install hook** -- optional script from `lola.yaml`

## Source Handlers

Lola uses a strategy pattern for fetching modules from different sources:
Expand Down
43 changes: 43 additions & 0 deletions docs/guides/creating-modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ my-module/
mcps.json # MCP settings
```

You can add any additional directories alongside the standard ones (e.g., `packs/`, `templates/`, `reference/`). During installation, the entire module content tree is copied to the target assistant's `modules/<name>/` directory, preserving all internal relative paths.

!!! note
`lola mod init` currently creates only the AI Context Module pattern. Standalone Agent Skill initialization (`lola skill init`) is planned for a future release.

Expand Down Expand Up @@ -79,6 +81,47 @@ Review PR #$ARGUMENTS and provide feedback.

Use `$ARGUMENTS` for all args or `$1`, `$2` for positional. Lola automatically converts commands to each assistant's native format (markdown for Claude Code and Cursor, TOML for Gemini CLI).

## Add shared resources for agents

Modules often include shared resources that agents need at runtime -- convention packs, reference documents, templates, or protocol files. Place these in any directory at the module content root:

```text
my-module/
module/
agents/
reviewer.md
packs/ # Shared resources for agents
conventions.md
severity.md
skills/
my-skill/
SKILL.md
```

During installation, the full content tree is copied to the target's modules directory (e.g., `.claude/modules/my-module/`). Generated skill, command, and agent files receive a plain-text module directory preamble between the frontmatter and body, pointing to the installed module tree (Gemini CLI commands use TOML format and do not receive the preamble). Agents can read this path to locate module-relative resources:

```markdown
---
name: reviewer
model: inherit
---
Module root: .claude/modules/my-module
This is the installed root of the module. Resolve all relative file references in this document against the path above.
Example: packs/foo.md -> .claude/modules/my-module/packs/foo.md

Read `conventions.md` from the packs directory.
```

The module tree is installed per-target at:

| Target | Project Scope | User Scope |
|-------------|-----------------------------|-----------------------------------------|
| Claude Code | `.claude/modules/<name>/` | `~/.claude/modules/<name>/` |
| Cursor | `.cursor/modules/<name>/` | `~/.cursor/modules/<name>/` |
| Gemini CLI | `.gemini/modules/<name>/` | `~/.gemini/modules/<name>/` |
| OpenClaw | `modules/<name>/` | `~/.openclaw/workspace/modules/<name>/` |
| OpenCode | `.opencode/modules/<name>/` | `~/.config/opencode/modules/<name>/` |

## Register and install

```bash
Expand Down
6 changes: 6 additions & 0 deletions docs/guides/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,16 @@ my-module/
scripts/
commands/
review.md
review/ # Optional: sidecar directory for multi-file commands
phase-1.md
agents/
helper.md
packs/ # Optional: any extra directories are preserved
conventions.md
```

Any directories beyond the standard `skills/`, `commands/`, and `agents/` are preserved during installation. The entire module content tree is copied to the target assistant's `modules/<name>/` directory (e.g., `.claude/modules/my-module/`), maintaining all internal relative paths. This allows agents to reference shared resources like convention packs, templates, or protocol files at runtime.

## Appending Context References

When an AI Context Module has files that reference each other, for example an `AGENTS.md` that says:
Expand Down
2 changes: 2 additions & 0 deletions mk/dev.mk
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ lint: ## - run ruff (check + format check) and mypy on src
@uv run ruff format --check src tests
@echo "Running mypy..."
@uv run mypy src
@echo "Running ty check..."
@uv run ty check

# Subtrees clean must never descend into: virtualenv, lola state, git internals.
# -prune (not -not -path) is required to skip the subtree entirely — otherwise
Expand Down
Loading
Loading