trackmcp
Back to directory
wisechef-ai

loopskill-api

View on GitHub

Open-core 'Spotify for AI agents' — a self-hostable registry of runnable agent artifacts: skills, bundles, loops, and personalities. docker compose up → working registry in 60s, zero signup. MCP-native, MPL-2.0.

2 stars PythonOthers Updated Sep 4, 2026
agent-toolsai-agentsclaudedeveloper-toolsllmmcpopen-coreself-hostedskill-registry

Documentation

LoopSkill

**A local CLI for skills you already have, plus a self-hostable registry to

pull more from.** Start with the CLI — it needs no account and makes no

network call for `import`/`diff`.


60 seconds: see skill drift, reproducibly

This is a literal, self-contained transcript. Paste every command below

into a clean shell — it fabricates two fake "skill" installs, edits one

and deletes the other to simulate drift, then diffs. You will get

*exactly* this output; nothing here depends on skills you already have

installed.

sh
git clone https://github.com/wisechef-ai/loopskill-api && cd loopskill-api
python3 -m venv .venv && ./.venv/bin/pip install ./cli
alias loopskill=./.venv/bin/loopskill   # or add ./.venv/bin to PATH
loopskill --version

# --- fabricate a "machine" with two skills, take a snapshot ---
mkdir -p /tmp/loopskill-demo/home/.claude/skills/agent-reach
mkdir -p /tmp/loopskill-demo/home/.claude/skills/recipes
cat > /tmp/loopskill-demo/home/.claude/skills/agent-reach/SKILL.md  /tmp/loopskill-demo/home/.claude/skills/recipes/SKILL.md  /tmp/loopskill-demo/home/.claude/skills/agent-reach/SKILL.md 

[claude] DRIFT DETECTED
  - only in /tmp/loopskill-demo/machine-a.lock.json: recipes
  ~ changed:          agent-reach
[codex] in sync (0 skill(s))
[cursor] in sync (0 skill(s))
[hermes] in sync (0 skill(s))

DRIFT FOUND

Exit code is `1` — drift found, script- and CI-friendly. Run `loopskill

diff` again with nothing changed and exit code is `0`. That's the whole

pitch: two snapshots, one command, drift visible in the time it took to

read this paragraph — on the skills you actually have, not a demo, once

you drop `--home`.

`import` and `diff` make zero network calls — this isn't a promise in

a docstring, it's a structural guarantee: the network-capable code lives

in exactly one module (`loopskill.pull`) that `import`/`diff` never

import, and

`cli/tests/test_loopskill_cli.py::test_import_and_diff_make_zero_network_calls`

proves it by breaking `socket.socket` for the duration of those commands.

Full CLI reference, lockfile format, and `pull`/`apply` (the two commands

that DO touch the network, opt-in): **cli/README.md**.


What this repo actually is

Two things, and the CLI is the one to start with:

1. `cli/` — a local, offline-by-construction tool for the skills you

already have on disk. No account, no server, no LoopSkill dependency

for `import`/`diff`. Point it at any registry that serves the same

well-known bundle-index shape for `pull`/`apply`, or never call those

commands at all.

2. `app/` — a self-hostable FastAPI registry (this repo) that the CLI's

`pull`/`apply` can optionally talk to, and that also serves a browsable

catalog at loopskill.io. The registry is not

the reason to start here — the CLI working on your own machine, before

you've made an account, is.

Loops: two limits stated up front

The registry also serves 10 vetted loops (`scripts/seed_starter_catalog.py`).

`POST /api/loops/{slug}/run` is synchronous and works anywhere. Putting a loop on

a *fleet member* so it fires on a schedule is a second path with two constraints

worth knowing before you build on it:

1. A loop reports nothing unless its own prompt says to. Telemetry exists

only because the loop's prompt calls `scripts/loopskill-emit-run.sh`. Nothing

else observes a fire — not the scheduler, not the server. Omit that line and

the loop runs forever while every dashboard shows zero. This is the reason

`loop_runs` sat at 1 for a year.

2. Cron materialization is Hermes-only. `app/loop_apply.py` writes the Hermes

scheduler's `~/.hermes/cron/jobs.json`, and nothing else speaks that format

yet. On Codex, Claude or OpenCode hosts `scripts/install-loop-apply.sh`

refuses rather than installing a cron that can never converge. The skill path

is cross-vendor; the scheduled-loop path is not.

Both are covered end to end in docs/SELF_HOST.md.

Self-host the registry (optional, for `pull`/`apply` against your own instance)

sh
git clone https://github.com/wisechef-ai/loopskill-api
cd loopskill-api && docker compose up

Zero-config: SQLite, auto-generated dev secrets, a seeded starter catalog.

Your dev API key is printed on first boot. Full guide, including the

Postgres/production path: **docs/SELF_HOST.md**.

Then run a loop — the runner is live (no LLM needed for verify-mode):

sh
# the zero-config Docker Compose stack always boots with this dev key
# (override via WR_API_KEY in production) — same value the boot banner prints
curl -X POST localhost:8200/api/loops/hello-world-loop/run \
  -H "x-api-key: rec_dev_wiserecipes_local_testing_key"
# → {"passed": true, "confinement": "bounded", "duration_seconds": 0.03, ...}

A fresh registry that doesn't just *list* a loop — it *executes* the

loop's success check under enforced bounds and hands you a verdict.


What's actually in this codebase (and the honest answer to "why so big")

314 app Python files, 77,341 lines of app code, 115 Alembic migrations,

442 test files (clean-checkout counts; the local tree carries one untracked

junk migration + test that CI never sees), 2 GitHub stars, 0 forks (measured 2026-08-21 via `gh

repo view wisechef-ai/loopskill-api --json stargazerCount,forkCount`).

That ratio is real and it isn't a good one. [Issue

#68](https://github.com/wisechef-ai/loopskill-api/issues/68) asked about

it; the honest answer — including why the codebase grew from a working

recipe-search product's battle-tested auth/Stripe/sandbox stack rather

than from a blank registry, and the concrete cuts committed as a result —

is in

docs/decisions/2026-08-11-bundles0811-p4-issue-68-codebase-size.md.

Every number above is checked against a live filesystem measurement by

`tests/test_readme_claims.py` on every run — it fails the build if this

paragraph drifts from reality the way #68's original numbers did.


Core API surface (self-hosted registry)

MethodPathDescription
`GET``/api/healthz`DB health check
`GET``/api/skills/search`Full-text + vector hybrid skill search
`GET``/api/skills/{slug}`Skill detail + versions
`GET``/api/bundles/discover`Browse public bundles
`GET``/api/loops`List loops (with their safety contracts)
`GET``/api/loops/{slug}`Loop detail — contract, run count, rating
`POST``/api/loops`Publish a loop (validates the contract)
`POST``/api/loops/{slug}/run`Run the loop's verification → objective pass/fail
`POST``/api/loops/{slug}/rate`Rate a loop 1–5 (social-proof signal)
`GET``/api/personalities`List deployable personalities

MCP-native: agents (Claude Code, Cursor, anything speaking MCP) discover

and install over the protocol. There's also a signed-URL tarball path for

direct fetch.

Architecture

FastAPI + SQLAlchemy. The same alembic migration chain runs on SQLite

(self-host) and Postgres (hosted) — no `create_all` drift; the SQLite boot

replays the real migrations, so what you self-host is what production

runs. Full module layout: **AGENTS.md**.

Auth flow

code
APIKeyMiddleware.dispatch()
  └─ validate_key(db, x-api-key)
       └─ request.state.auth_ctx = AuthContext(scope, user_id, tier, …)
            └─ REST routes / MCP tools / runner call authz.can_*() predicates

API keys are `rec_`-prefixed and passed in the `x-api-key` header. Most

read endpoints (search, detail, discover) are unauthenticated. Free-tier

skills install anonymously with no key (200 + tarball); installing a

paid-tier skill, publishing, running, and rating all require a key.


Develop

bash
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
pre-commit install                       # ruff, bandit, mypy --strict, actionlint, yamllint

pytest -q                                # fast run
pytest -n auto --cov=app --cov-fail-under=80   # the CI gate

alembic upgrade head                     # apply migrations before first start (non-SQLite)
uvicorn app.main:app --reload --port 8201

> Sandbox (Linux only): the kernel sandbox (`app/sandbox/`) needs

> firejail or bubblewrap.

> Where neither is functional (macOS, hardened containers), the loop runner falls back to bounded

> mode — POSIX rlimits + scrubbed env + isolated workspace — so loops still run; the response declares

> which `confinement` level it achieved. Multi-tenant fleet owners set `WR_LOOP_RUN_REQUIRE_SANDBOX=true`

> to refuse bounded-mode execution and require a real kernel sandbox.

Contributor guide for AI agents: AGENTS.md.


Why open-core

The whole registry is the OSS product (MPL-2.0). Self-host it anywhere —

`docker compose up` is the complete experience, not a teaser, and nothing

phones home. The hosted plan is "don't run it yourself," never a feature

gate. Same posture as n8n / PostHog / Supabase.

License

MPL-2.0 — see LICENSE. The whole registry is open source; we only charge for hosting it.

Frequently asked questions

What is loopskill-api?

loopskill-api is Open-core 'Spotify for AI agents' — a self-hostable registry of runnable agent artifacts: skills, bundles, loops, and personalities. docker compose up → working registry in 60s, zero signup. MCP-native, MPL-2.0.

How do I install loopskill-api?

Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.

Is loopskill-api open source?

Yes — it is hosted on GitHub at https://github.com/wisechef-ai/loopskill-api and has 2 stars.

Related MCP tools

Run your own MCP server? See who uses it and what to fix.

Measure it with TrackMCP