<div align="center">
<img src="logo/skill_ex.svg" alt="SkillEx Logo" width="200"/>
</div>
# SkillEx – Claude Skill Aggregator
[](https://hex.pm/packages/skill_ex)
[](https://hexdocs.pm/skill_ex)
[](https://github.com/nshkrdotcom/supertester/blob/main/skill_ex/LICENSE)
SkillEx is our hub for collecting `.claude/skills` directories from every Elixir repo, validating them, and packaging a single `skills-pack-<date>.zip` that Claude can load in one go. Each application owns the content of its skill, while SkillEx keeps the packs fresh and consistent.
---
## Why SkillEx Exists
- **One-stop distribution** – No more hunting through repos; the pack contains every published skill.
- **Consistent validation** – Every skill runs through the same packaging/validation script before inclusion.
- **Repeatable automation** – The CLI emits JSON so CI pipelines can publish artifacts or fail fast on issues.
- **Change tracking** – The manifest captures checksums and timestamps so we know what shipped and when.
---
## Quick Start
```bash
# Install deps and run the test suite
mix deps.get
mix test
# Review or edit the manifest
cat manifest.json
# Run a sync using the script (dry run shown)
elixir scripts/sync_skills.exs \
--manifest manifest.json \
--target skills \
--dry-run
```
The script reports a JSON summary and (when not in dry-run) copies every discovered skill into `skills/<repo>/<skill-name>/`, runs validation, updates `manifest.json`, and emits a packaged zip under `dist/`.
---
## Repository Layout
```
skill_ex/
├── lib/
│ ├── skill_ex/aggregator.ex # Sync, validation, packaging logic
│ └── skill_ex/manifest.ex # Manifest load/save helpers
├── scripts/sync_skills.exs # CLI that drives the aggregator
├── skills/ # Output directory populated by sync
├── dist/ # Final zipped packs (created on demand)
├── manifest.json # Declares upstream repos and tracks sync metadata
├── docs/ # Extended documentation (workflow, manifest, CI)
├── test/ # ExUnit suites & helpers (pure TDD coverage)
└── logo/skill_ex.svg # Project badge for docs/dashboards
```
---
## Core Components
| Component | Responsibility |
| --- | --- |
| `SkillEx.Manifest` | Load/save JSON manifest, manage `skills` entries, timestamp updates. |
| `SkillEx.Aggregator` | Copy skills out of repos, call validators, compute checksums, package archives, and refresh the manifest. |
| `scripts/sync_skills.exs` | Thin CLI wrapper. Parses flags, loads repos from the manifest, invokes the aggregator, prints JSON for CI usage. |
| `test/support/test_helpers.exs` | Fixture helpers (temp dirs, fake repos, stub validators) used across tests. |
Implementation details and extension ideas live in the docs directory—start with [`docs/WORKFLOW.md`](docs/WORKFLOW.md).
---
## Running the Sync Script
```
elixir scripts/sync_skills.exs \
--manifest path/to/manifest.json \
--target path/to/output/skills \
--package-script path/to/scripts/package_skill.py \
[--dry-run] \
[--clock 2025-10-08T12:00:00Z] \
[--version 2025.10.08]
```
### Flags
| Flag | Required | Description |
| --- | --- | --- |
| `--manifest` | ✅ | Manifest file to read/write. Determines which repos export skills. |
| `--target` | ✅ | Directory that should contain synced skills. Created if missing. |
| `--package-script` | ✅ (unless validator provided) | External validator/packager (typically `scripts/package_skill.py`). |
| `--dry-run` | Optional | Reports what *would* happen without copying or packaging. |
| `--clock` | Optional | ISO8601 timestamp used for deterministic runs/tests. Defaults to `DateTime.utc_now/0`. |
| `--version` | Optional | Overrides the archive suffix (`skills-pack-<version>.zip`). Useful in CI. |
The script exits with `0` for success and `1` when sync/validation encounters errors. Output is always JSON so downstream steps can parse it reliably.
---
## Manifest Overview
The manifest ties everything together. It tracks **which repos export skills** and stores **metadata about the last successful sync**.
```json
{
"version": 1,
"generated_at": "2025-10-08T12:00:00Z",
"repositories": [
{
"name": "supertester",
"path": "../supertester",
"skills_dir": ".claude/skills"
}
],
"skills": [
{
"name": "supertester-otp-testing",
"source_repo": "supertester",
"target_path": "supertester/supertester-otp-testing",
"checksum": "01ab...ff",
"packaged_at": "2025-10-08T12:00:00Z"
}
]
}
```
Every field is documented in [`docs/MANIFEST_REFERENCE.md`](docs/MANIFEST_REFERENCE.md), including optional keys and gotchas (network paths, symlinks, etc.).
---
## Typical Workflow
1. **Prepare source repos**
- Each repo houses its skill under `.claude/skills/<repo-skill>/SKILL.md`.
- Ensure the repo’s own validator (usually `scripts/package_skill.py`) succeeds locally.
2. **Update `manifest.json`**
- Add repo entries (absolute or relative paths).
- Commit the manifest change back to SkillEx.
3. **Run the CLI**
- Dry-run first to audit the operations (`planned` count).
- Run without `--dry-run` to copy, validate, and write the bundle.
4. **Inspect outputs**
- Check `skills/<repo>/<skill>/` to confirm the expected files.
- Review the JSON summary and updated manifest for checksum/timestamp changes.
- Find the zipped artifact under `dist/skills-pack-<date>.zip`.
5. **Automate**
- CI can invoke the script, parse JSON, and upload the archive as a build artifact.
- See [`docs/CI_PLAYBOOK.md`](docs/CI_PLAYBOOK.md) for ideas.
The ExUnit suite mirrors this flow with deterministic temp repos so regressions are caught quickly.
---
## Development & Testing
| Task | Command |
| --- | --- |
| Run entire test suite | `mix test` |
| Format stubs or generated manifests | `mix format` |
| Execute only aggregator tests | `mix test test/skill_ex/aggregator_test.exs` |
| Run script tests (integration style) | `mix test test/scripts/sync_skills_script_test.exs` |
All tests are written first (true TDD). When expanding the system:
- **Add tests before implementation** for new behaviours (new validator modes, multi-root targets, etc.).
- **Use test helpers** to keep fixtures tidy.
- **Prefer pure functions** (clock injection, custom validator) to keep tests deterministic.
---
## Roadmap & Ideas
- Surface git metadata (repo SHA, branch) in manifest skill entries.
- Allow repo-specific validator overrides instead of one global `--package-script`.
- Support incremental packaging (skip unchanged skills based on checksum).
- Publish checksum diff reports to highlight what changed between packs.
- Add optional `references/` ingestion to capture documentation bundles.
If you explore any of these, drop a note in the docs so future developers know the plan.
---
## Learn More
- [`docs/WORKFLOW.md`](docs/WORKFLOW.md) – Deep dive into onboarding repos and daily operation.
- [`docs/MANIFEST_REFERENCE.md`](docs/MANIFEST_REFERENCE.md) – Field-by-field schema with pitfalls and examples.
- [`docs/CI_PLAYBOOK.md`](docs/CI_PLAYBOOK.md) – Suggestions for wiring SkillEx into GitHub Actions, Buildkite, or GitLab.
## 📄 License
This project is licensed under the MIT License – see the [LICENSE](https://github.com/nshkrdotcom/supertester/blob/main/skill_ex/LICENSE) file for details.
Questions? Share findings or improvements in the repo so the next engineer has an even smoother ride.