# Plan: Load skills from `.agents/skills/` directory

## Background

There's an emerging common standard for agents to store skills in `.agents/skills/`. Swival currently only looks in `.swival/skills/`. We should support both, with `.agents/skills/` as an additional discovery location.

## Current behavior

In `swival/skills.py:discover_skills()` (line 255):

1. Scans `<base_dir>/.swival/skills/` for project-local skills (flat, one level)
2. Scans each `--skills-dir` extra directory (recursive up to 3 levels via `_scan_skills_dir`)
3. First-seen name wins (project-local takes precedence over extra dirs)

## Proposed changes

### 1. Add `.agents/skills/` as a second local skills directory

In `discover_skills()`, after scanning `.swival/skills/`, also scan `<base_dir>/.agents/skills/`. Both are project-local discovery sources (locality of individual skills still depends on resolved path — see Design Decisions). Precedence order:

1. `.swival/skills/` (highest — existing Swival-specific location)
2. `.agents/skills/` (new — common agent standard)
3. `--skills-dir` extra directories (lowest)

This means if the same skill name exists in both `.swival/skills/` and `.agents/skills/`, the `.swival/skills/` version wins. This is the least-surprise behavior for existing users.

### 2. Code changes in `skills.py`

Move the `scanned` set initialization **above** both local scans (currently at line 284, move to right after `catalog` is created). Then insert the `.agents/skills/` block after `.swival/skills/`:

```python
    catalog: dict[str, SkillInfo] = {}
    base_resolved = Path(base_dir).resolve()

    # Initialize scanned set early — both local dirs and --skills-dir use it
    scanned: set[Path] = set()

    # Scan project-local skills first (.swival/skills/)
    local_skills = base_resolved / ".swival" / "skills"
    if local_skills.is_dir():
        try:
            entries = sorted(local_skills.iterdir())
        except OSError:
            entries = []
        for entry in entries:
            if entry.is_dir():
                _try_load_skill(entry, base_resolved, catalog, verbose)
        scanned.add(local_skills.resolve())

    # Scan .agents/skills/ (common agent standard, lower precedence than .swival/skills/)
    agents_skills = base_resolved / ".agents" / "skills"
    if agents_skills.is_dir():
        try:
            entries = sorted(agents_skills.iterdir())
        except OSError:
            entries = []
        for entry in entries:
            if entry.is_dir():
                _try_load_skill(entry, base_resolved, catalog, verbose)
        scanned.add(agents_skills.resolve())

    # Process each --skills-dir path
    ...
```

Note: locality (`is_local`) is determined by `_try_load_skill` via `resolved_path.is_relative_to(base_resolved)`. This means if `.agents` is a symlink pointing outside the repo, those skills will correctly be treated as external (`is_local=False`). This is intentional — symlinks outside the project boundary should not get implicit local trust.

### 3. Update documentation

- `docs.md/skills.md` (line ~36): update the skill discovery description to mention both `.swival/skills/` and `.agents/skills/`, with precedence order
- `CLAUDE.md` architecture section: mention `.agents/skills/` alongside `.swival/skills/`
- Run `make website` to rebuild `docs/pages/` HTML from the updated markdown

### 4. Tests to add

Add tests in `tests/test_skills.py`:

- `test_discover_from_agents_skills_dir` — skills in `.agents/skills/` are discovered
- `test_agents_skills_are_local` — skills from `.agents/skills/` have `is_local=True`
- `test_agents_skills_symlinked_outside` — `.agents` symlinked outside repo, skills get `is_local=False`
- `test_swival_skills_take_precedence` — same skill name in both dirs, `.swival/skills/` wins
- `test_both_dirs_combined` — different skills from both dirs are all discovered
- `test_agents_skills_dir_missing` — no error when `.agents/skills/` doesn't exist
- `test_agents_skills_take_precedence_over_extra` — same skill name in `.agents/skills/` and a distinct `--skills-dir`, `.agents/skills/` wins
- `test_agents_skills_not_rescanned_via_extra_dirs` — passing `.agents/skills/` as `extra_dirs` doesn't duplicate-load or produce shadow warnings

### 5. No config changes needed

This is automatic discovery, same as `.swival/skills/`. No new CLI flags or config keys required.

## Design decisions

- **Symlink behavior**: `is_local` is determined by whether the resolved skill path is inside `base_dir`. If `.agents` is a symlink pointing outside the repo, skills under it will be `is_local=False` (external). This is intentional — symlinks outside the project boundary should not get implicit local trust.
- **Precedence**: `.swival/skills/` > `.agents/skills/` > `--skills-dir`. Fits the existing first-seen-wins model. Swival-specific config always takes priority over the cross-agent standard.

## Estimated scope

- ~20 lines of changed code in `skills.py` (restructure `scanned` init + new scan block)
- ~80 lines of new tests (8 test cases)
- Doc updates in `docs.md/skills.md` + `make website` rebuild
