This repository has no description
1

Configure Feed

Select the types of activity you want to include in your feed.

at main 116 lines 5.0 kB View raw View rendered
1# 🔎 loup 2 3**Turn user session recordings into cited pull requests & issues — on [Tangled](https://tangled.org), over the AT Protocol.** 4 5loup is a webhook harness you drop into your repo. Point your session-recording 6provider at it; when a recording comes in, loup finds where the user struggled, 7locates it in your code, and opens a **PR** (with a fix) or an **issue** (for the 8fuzzy stuff) on Tangled — each citing the **exact moment of confusion** as a 9screenshot that deep-links into the recording. 10 11Every artifact it creates — the PR, the issue, the screenshot citations — is a 12real AT Protocol record. No bespoke backend; the protocol carries the state. 13 14``` 15 recording (mp4/mov) + session context 16 17 ▼ ffmpeg cuts citation frames at the hotspots 18 findings ──► localize in your repo ──► PR (fix) | gzipped patch in a round 19 │ └► issue | flag for humans 20 21 open on Tangled with inline, video-deep-linked screenshot citations 22``` 23 24## Install 25 26```bash 27npm install -g loup-cli # installs the `loup` command 28``` 29 30## Setup 31 32Run **`loup init`** inside the repo you want loup to operate on. It scaffolds two 33files (and adds the secret one to `.gitignore`): 34 35**`loup.config.json`** — non-secret, safe to commit: 36 37```jsonc 38{ 39 "service": "https://tngl.sh", 40 "targetRepo": "your-handle.tngl.sh/your-repo", // repo to open PRs/issues on 41 "targetRepoDid": "did:plc:…", // that repo's DID 42 "targetBranch": "main", 43 "port": 4319 44} 45``` 46 47**`.env`** — secrets, never committed: 48 49```bash 50TANGLED_HANDLE=your-handle.tngl.sh 51TANGLED_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx # tngl.sh → Settings → App passwords 52# ANTHROPIC_API_KEY=sk-ant-... # optional — turns on the vision pass 53``` 54 55> **No SSH key needed.** loup posts over the AT Protocol (it writes pull/issue 56> *records* to your PDS), not via `git push`. The only credential it needs is a 57> Tangled **app password** — generate one at **tngl.sh → Settings → App 58> passwords** and paste it into `.env`. Use an app password, not your account 59> password. 60 61## Use 62 63```bash 64loup serve # the real pipeline — analyzes & posts to Tangled 65loup serve --demo # offline replay of known-good PRs (no LLM, no network) 66 67# from another terminal, send a recording (a link is optional, for deep-link citations): 68loup send recording.mov --url https://youtu.be/VIDEO 69``` 70 71`loup serve` **posts for real** as soon as `.env` has your Tangled credentials — 72it prints the live PR/issue URLs. If those credentials are missing it runs a safe 73**dry-run** (analyzes + drafts, posts nothing) instead of erroring. 74 75`loup serve --demo` replays a fixed set of real, already-open PRs/issue offline — 76handy for a guaranteed demo with no network or API key. 77 78The webhook also accepts a raw POST (`multipart/form-data`: `video`, optional 79`video_url`, optional `text`) — exactly the shape a recording provider would send. 80 81## How it works 82 83When a recording arrives: 84 851. **ffmpeg** cuts it into **one screenshot per second**, each with its timestamp 86 burned in. 872. loup hands those frames **+ your app's source code** (`sourcePaths`) to a 88 Claude model (**`claude-opus-4-8`** by default) under a **single system prompt**. 893. The model watches the session frame by frame, finds every place the user hit a 90 bug or got confused, cross-references the source for the root cause, and — for 91 things it can fix — returns the **corrected file**. 924. loup turns that corrected file into a patch with `git diff` (so it **always 93 applies**), then opens a **PR** with it, or files an **issue** for the fuzzy 94 stuff — each citing the exact frame, deep-linked back into the recording. 95 96Pass optional `--text` notes alongside the recording (a provider's session events, 97your own annotations) to nudge the model — but it works from the recording alone. 98 99## Why Tangled / AT Protocol 100 101A pull request is a `sh.tangled.repo.pull` record (patch as a gzipped blob in a 102round); an issue is `sh.tangled.repo.issue`; a citation is a `sh.tangled.feed.comment` 103whose markdown body embeds the screenshot blob. loup just writes records to its 104own PDS — no clone, no push, no server to run for state. Because contribution is 105federated, it can open PRs/issues on **any** repo, not just its own. 106 107## Config 108 109| File | What | 110|---|---| 111| `loup.config.json` | target repo (`targetRepo`, `targetRepoDid`, `targetBranch`), `repoRoot` (defaults to CWD), **`sourcePaths`** (files/dirs to feed the model), `port`, `model` | 112| `.env` | `TANGLED_HANDLE`, `TANGLED_APP_PASSWORD`, `ANTHROPIC_API_KEY` (the vision pass), optional `LOUP_MODEL` (never commit) | 113 114`sourcePaths` points loup at your UI source (templates, components, pages) so the 115model can locate issues and write fixes. `loup serve` posts for real once `.env` 116has `TANGLED_HANDLE` + `TANGLED_APP_PASSWORD`; without them it dry-runs.