Lightweight, extensible CLI for the-loop — quality-of-life commands the the-loop plugin can use (e.g. a GitHub webhook receiver).
Project description
the-loop CLI
A lightweight, extensible command-line companion to the the-loop plugin, written in Python (stdlib-only core — zero runtime dependencies). Python is intentional: it leaves room to add self-learning / ML capabilities later (mostly exposed as Python SDKs).
Install
From PyPI (published as the-loopy-one — the base name the-loop was taken; the
import package and CLI keep the natural the_loop/the-loop):
pip install the-loopy-one # or: uv pip install the-loopy-one
pip install "the-loopy-one[config]" # + PyYAML, for reading .the-loop/config.yaml defaults
the-loop --help
For local development the-loop uses uv (its declared Python package manager). From the repo root:
uv sync # installs the workspace (this CLI + dev tooling) from uv.lock
uv run the-loop --help # run the CLI
Or install this package on its own with any PEP 517 installer:
uv pip install -e . # or: pip install -e .
uv pip install -e ".[config]" # PyYAML, for reading .the-loop/config.yaml defaults
uv pip install -e ".[dev]" # pytest + commitizen
This exposes the primary CLI: the-loop. Releases are automatic: on merge to main,
.github/workflows/release.yml runs cz bump to derive the next version from the
Conventional Commits / PR titles since the last tag (feat → minor, fix → patch,
BREAKING CHANGE → major), tags it, and publishes to PyPI via Trusted Publishing (OIDC —
no stored token). Merges with no feat/fix/breaking change publish nothing. See
docs/decisions/decision-019.md.
Commands
gh-webhook — GitHub webhook receiver
the-loop gh-webhook start [--host 127.0.0.1] [--port 8787] [--path /gh-webhook] \
[--pidfile .the-loop/gh-webhook.pid] \
[--secret-env THE_LOOP_GH_WEBHOOK_SECRET] \
[--route | --no-route]
the-loop gh-webhook stop [--pidfile .the-loop/gh-webhook.pid]
- Verifies the GitHub
X-Hub-Signature-256HMAC when the secret env var is set (exportTHE_LOOP_GH_WEBHOOK_SECRET=...). The secret is read from the environment, never a flag, so it doesn't leak into process listings. GET /healthreturns200 ok.- Defaults can come from
.the-loop/config.yaml(webhooks.ghWebhook) when PyYAML is installed; flags always override. --route(default fromwebhooks.ghWebhook.routing.enabled) routes each verified event to the registered harness session working that item: the router extracts the work item(s) from the payload (issue/PR number, PR head-branchissue-<n>convention, closing keywords,workflow_run/check_*PRs), deduplicates onX-GitHub-Delivery, and the dispatcher resumes the matched session via its official CLI (claude -p … --resume <session-id>/cursor-agent -p … --resume <chat-id>), one event at a time per session, in parallel across sessions. Unmatched events followrouting.spawnOnUnmatched(neverdrops;alwaysspawns + registers a session). Design:docs/specs/issue-15/design.md,docs/decisions/decision-016.md.
sessions — link work items to harness sessions (webhook routing)
the-loop sessions register --work-item github:OWNER/REPO#N --harness claude \
--harness-session-id "$CLAUDE_SESSION_ID" [--cwd .] [--force]
the-loop sessions list [--status active|closed] [--format table|json]
the-loop sessions close --work-item github:OWNER/REPO#N
- The registry lives in
webhooks.ghWebhook.routing.registryDir(default.the-loop/sessions/, git-ignored) as one human-inspectable JSON file per session; writes are atomic, so concurrent sessions on the same machine are safe. - One work item ↔ one active session;
--forcereplaces a stale registration. - Claude Code sessions register with
$CLAUDE_SESSION_ID; Cursor sessions register with the chat id they were launched with (non-interactivecursor-agent lsis unreliable for id discovery, so the id is captured at registration time). - When a work item's PR is merged or closed, the receiver auto-closes the session
(on the
pull_requestclosedevent) — no manualsessions closeneeded.
Label-gated auto-execution (spawnOnUnmatched: labeled): give an issue/PR the
configurable routing.autoExecuteLabel (default the-loop: auto-execute) and the
receiver spawns a session and starts /the-loop:work-on on it — then routes that item's
later activity (comments, reviews, CI, its linked PR) to the same session, and
auto-closes on PR merge. Label presence is read straight from the webhook payload (no
extra API call). A new issue without the label is received and ignored.
scenarios — query the Gherkin scenarios integration tests cover
the-loop scenarios [--root .] [--glob PATTERN ...] [--format table|markdown|json]
- Scans integration-test files for the Gherkin-syntax docstrings the-loop requires
(
Feature:/Scenario:/ Given-When-Then, plus an optionalRequirement:link to arequirements.md) and presents them as a table — so a coding-agent harness can answer "what scenarios are tested?" without running anything. - Language-agnostic: Python docstrings, JS/TS block comments and Go comments all work.
- Globs come from
--glob(repeatable), elsetesting.integrationTestGlobsin.the-loop/config.yaml(when PyYAML is installed), else built-in defaults covering common layouts. --format markdownemits a GitHub-flavoured table (for PR briefings);--format jsonis machine-readable (includes each scenario's steps andfile:line).
Adding a command (extensibility)
- Create
the_loop/commands/<your_command>.py. - Subclass
Command, setname/help, implementadd_argumentsandrun, and decorate the class with@register. - Import the module in
the_loop/commands/__init__.py.
The CLI discovers registered commands automatically.
Test
pytest # from this directory
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file the_loopy_one-0.2.1.tar.gz.
File metadata
- Download URL: the_loopy_one-0.2.1.tar.gz
- Upload date:
- Size: 36.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31bdc89ab295742a47eac73340dd4314e504dd383b0e3022a67e4cdc4035efcc
|
|
| MD5 |
a08941aa09a17022b9afb89ee6243297
|
|
| BLAKE2b-256 |
fd4a90a3963a183704e00406ed391e49102e9e6e0b2501adbc098d223c3a9294
|
Provenance
The following attestation bundles were made for the_loopy_one-0.2.1.tar.gz:
Publisher:
release.yml on MadaraUchiha-314/the-loop
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
the_loopy_one-0.2.1.tar.gz -
Subject digest:
31bdc89ab295742a47eac73340dd4314e504dd383b0e3022a67e4cdc4035efcc - Sigstore transparency entry: 2083383183
- Sigstore integration time:
-
Permalink:
MadaraUchiha-314/the-loop@29b30232b696eb91389d81949fe4bc58c610d548 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/MadaraUchiha-314
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@29b30232b696eb91389d81949fe4bc58c610d548 -
Trigger Event:
push
-
Statement type:
File details
Details for the file the_loopy_one-0.2.1-py3-none-any.whl.
File metadata
- Download URL: the_loopy_one-0.2.1-py3-none-any.whl
- Upload date:
- Size: 32.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e6e687d0e0084b4c40a8159856b960d9fb38cbf9a40da88c1c5f09d25e9a1f2f
|
|
| MD5 |
c655bb69f785939eb949e8d07350cdaf
|
|
| BLAKE2b-256 |
26d9f19d7cdeca64457feec0be91695358adf8754c34ca86aa5b1435e1ba1a8f
|
Provenance
The following attestation bundles were made for the_loopy_one-0.2.1-py3-none-any.whl:
Publisher:
release.yml on MadaraUchiha-314/the-loop
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
the_loopy_one-0.2.1-py3-none-any.whl -
Subject digest:
e6e687d0e0084b4c40a8159856b960d9fb38cbf9a40da88c1c5f09d25e9a1f2f - Sigstore transparency entry: 2083383199
- Sigstore integration time:
-
Permalink:
MadaraUchiha-314/the-loop@29b30232b696eb91389d81949fe4bc58c610d548 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/MadaraUchiha-314
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@29b30232b696eb91389d81949fe4bc58c610d548 -
Trigger Event:
push
-
Statement type: