Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions .github/workflows/skills-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: Skills CI/CD

on:
push:
branches: [master]
paths:
- "skills/**"
- "scripts/skills/**"
- ".github/workflows/skills-ci.yml"
pull_request:
paths:
- "skills/**"
- "scripts/skills/**"
- ".github/workflows/skills-ci.yml"

jobs:
validate-and-build:
name: Validate & Build Skills
runs-on: ubuntu-latest
permissions:
contents: write # needed to commit dist/smithery/ back to repo

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Install project dependencies
run: npm install --legacy-peer-deps

- name: Install skills-ref CLI
run: |
if npm install -g skills-ref 2>/dev/null; then
echo "SKILLS_REF_AVAILABLE=true" >> $GITHUB_ENV
else
echo "SKILLS_REF_AVAILABLE=false" >> $GITHUB_ENV
echo "⚠️ skills-ref not found on npm — validation steps will be skipped"
fi

# ── Step 1: Validate source SKILL.md (ClawHub format) ────────────────
# Source may have ClawHub extensions that fail strict spec validation — non-blocking.
- name: "[Source] Validate against agentskills.io spec"
id: validate-source
run: |
if [ "$SKILLS_REF_AVAILABLE" = "true" ]; then
echo "### Source SKILL.md Validation" >> $GITHUB_STEP_SUMMARY
skills-ref validate ./skills/pullthatupjamie 2>&1 | tee -a $GITHUB_STEP_SUMMARY \
&& echo "✅ Source: valid" \
|| echo "⚠️ Source has spec issues (expected — ClawHub extensions present)"
else
echo "⚠️ Skipping source validation (skills-ref unavailable)"
fi
continue-on-error: true

# ── Step 2: Build Smithery-compliant dist ─────────────────────────────
- name: "[Smithery] Build dist from source"
run: node scripts/skills/build-smithery.js

# ── Step 3: Validate Smithery dist (strict — blocks CI on failure) ────
- name: "[Smithery] Validate dist against agentskills.io spec"
run: |
if [ "$SKILLS_REF_AVAILABLE" = "true" ]; then
echo "### Smithery dist/ Validation" >> $GITHUB_STEP_SUMMARY
skills-ref validate ./dist/smithery/pullthatupjamie 2>&1 | tee -a $GITHUB_STEP_SUMMARY
else
echo "⚠️ Skipping dist validation (skills-ref unavailable)"
fi

# ── Step 4: Build ClawHub zip ─────────────────────────────────────────
- name: "[ClawHub] Build zip"
run: node scripts/skills/build-clawhub-zip.js

# ── Step 5: Upload artifacts ──────────────────────────────────────────
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: skill-builds-${{ github.sha }}
path: dist/
retention-days: 30

# ── Step 6: Commit dist/smithery/ back to repo (master push only) ─────
# Smithery's gitUrl points to this committed path.
# Uses [skip ci] to prevent an infinite workflow loop.
- name: Commit dist/smithery/ to repo
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add dist/smithery/
if git diff --cached --quiet; then
echo "No changes to dist/smithery/ — skipping commit"
else
git commit -m "ci: update dist/smithery from build [skip ci]"
git push
fi

# ── Step 7: Print submission URLs ─────────────────────────────────────
- name: Print submission URLs
run: |
VERSION=$(node -e "const m=require('./skills/pullthatupjamie/_meta.json'); console.log(m.version)")
REPO="uncleJim21/pullthatupjamie-backend"
BRANCH="master"
GIT_URL="https://github.com/${REPO}/tree/${BRANCH}/dist/smithery/pullthatupjamie"

cat >> $GITHUB_STEP_SUMMARY << EOF

---

## Skill Build: v${VERSION}

### Smithery

Submit once (or on each new version) using your Smithery API key:

\`\`\`bash
curl -X PUT "https://api.smithery.ai/skills/\${SMITHERY_NAMESPACE}/pullthatupjamie" \\
-H "Authorization: Bearer \${SMITHERY_API_KEY}" \\
-H "Content-Type: application/json" \\
-d '{"gitUrl": "${GIT_URL}"}'
\`\`\`

**Skill URL after registration:**
\`https://smithery.ai/skills/\${SMITHERY_NAMESPACE}/pullthatupjamie\`

**gitUrl (what you pass to Smithery):**
\`${GIT_URL}\`

---

### ClawHub

Download the \`skill-builds\` artifact from this run and upload the zip:
- File: \`dist/clawhub/pullthatupjamie-v${VERSION}.zip\`
- Upload at: https://clawhub.ai/publish

EOF
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ scripts/seedPodcastFeeds.js
/dev-helper-scripts
test/cost-baseline-100.sh
.l402-creds

# Skills build artifacts — ClawHub zips are CI artifacts, not committed
dist/clawhub/
Binary file added dist/.DS_Store
Binary file not shown.
180 changes: 180 additions & 0 deletions dist/smithery/pullthatupjamie/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
---
name: pullthatupjamie
description: 'PullThatUpJamie — Podcast Intelligence. Semantically indexed corpus: 109+ feeds, ~7K episodes, ~1.9M paragraphs. Use when agents need to: (1) find what experts said across major podcasts (Rogan, Huberman, Bloomberg, TFTC, Lex Fridman, etc.), (2) build interactive research sessions with timestamped playable audio clips, (3) generate shareable MP4 clips with burned-in subtitles, (4) discover people/orgs and podcast appearances, (5) ingest new feeds on demand. Smart search (smartMode): LLM triage for vague queries — entity extraction, corpus metadata resolution, query rewriting. Three-tier strategy: title → chapter → semantic. Free tier: no credentials needed. Paid tier via L402 Lightning: 500 sats (~$0.33) covers 150+ searches. lnget compatible.'
metadata:
clawdbot:
emoji: 🎙️
homepage: https://pullthatupjamie.ai
openclaw:
homepage: https://pullthatupjamie.ai
requires:
env: []
credentials:
- name: NWC_CONNECTION_STRING
description: Nostr Wallet Connect URI for paying Lightning invoices. Only needed for paid tier (free tier works without credentials).
required: false
- name: JAMIE_L402_CREDENTIAL
description: 'L402 credential returned after paying a credit invoice. Format: L402 <base64_macaroon>:<hex_preimage>. Used as the Authorization header for all paid requests.'
required: false
externalServices:
- url: https://www.pullthatupjamie.ai
description: Jamie API — podcast search, research sessions, corpus browsing, RSS feed ingestion, clip generation (all endpoints proxied for security)
externalTools:
- name: Lightning wallet (any)
description: 'For paid tier only: Any Lightning wallet (Zeus, BlueWallet, Phoenix, Alby extension, etc.) to pay BOLT-11 invoices. NO CLI tools are required or auto-executed by this skill.'
required: false
version: 1.6.0
homepage: https://pullthatupjamie.ai
license: Proprietary
compatibility: Requires internet access to https://www.pullthatupjamie.ai. Free tier works immediately with no credentials. Paid tier requires a Lightning-compatible wallet (Zeus, BlueWallet, Phoenix, Alby, etc.) for L402 payments. lnget handles payment flow automatically.
---

# PullThatUpJamie — Podcast Intelligence

Powered by [Pull That Up Jamie](https://pullthatupjamie.ai).

## Why Use This

Jamie is a **retrieval/vector DB as a service for podcasts**. Instead of:
- Transcribing hours of audio yourself (expensive, slow)
- Stuffing full transcripts into context (thousands of tokens wasted)
- Web searching and getting SEO spam, listicles, and low-quality summaries
- Multiple search iterations across unreliable sources

You run a single semantic search ($0.002, returns in under 2s) and get the **exact clip** with timestamp, audio deeplink, and transcript. Every result is timestamped to the second — you're not handing users a 2-hour episode and saying "it's in there somewhere." You're linking them to the exact 30-second moment where the expert makes the point. 500 sats ($0.33) covers an entire deep research session of 150+ searches.

**Don't see the podcast you need?** Use `POST /api/discover-podcasts` ($0.005) to search the full Podcast Index catalog, then submit episodes for transcription via `POST /api/on-demand/submitOnDemandRun` ($0.45). Once processed, episodes get timestamped chaptering and become searchable at paragraph level.

**Your output is not a text wall.** Research sessions are interactive web experiences where users play audio clips inline, browse visually, and share with others. Every clip deeplinks to the exact moment in the source audio. The session link IS the deliverable.

## Corpus Coverage (as of Feb 2026)

109 feeds · ~7K episodes · ~1.9M indexed paragraphs · ~11.5K identified people/orgs. Growing.

| Category | Notable Feeds | Feeds | Episodes |
|---|---|---|---|
| **Bitcoin/Crypto** | TFTC, Bitcoin Audible, Simply Bitcoin, Peter McCormack, What is Money, Once Bitten, Ungovernable Misfits | 41 | ~11,700 |
| **Finance/Markets** | Bloomberg Intelligence, Bloomberg Surveillance, Prof G Markets, Tim Ferriss, Diary of a CEO | 11 | ~5,700 |
| **Health/Wellness** | Huberman Lab, Peter Attia Drive, Meat Mafia, FoundMyFitness, Modern Wisdom | 7 | ~3,000 |
| **Politics/Culture** | Ron Paul Liberty Report, No Agenda, Tucker Carlson, Breaking Points, Pod Save America | 8+ | ~2,800 |
| **Tech/General** | Joe Rogan Experience, Lex Fridman, How I Built This, Kill Tony, Sean Carroll's Mindscape | 40+ | ~17,000 |

**If a feed isn't indexed yet, you can ingest it on demand** from any RSS feed. See the Ingestion section in [references/podcast-rra.md](references/podcast-rra.md).

**Free corpus browsing** (no auth required for reads): `GET /api/corpus/feeds`, `/api/corpus/stats`, `/api/corpus/people`. Check before you search.

## Auth Flow (L402 Protocol)

**Free tier available.** Corpus browsing (no auth needed) and IP-based search quota are available. To use the free tier on paid endpoints, add the header `X-Free-Tier: true` to your requests. Without this header, paid endpoints return an immediate 402 L402 challenge. The free tier has per-endpoint quotas (e.g., 50 searches/week) — once exhausted, you'll need to pay via L402 to continue.

Jamie uses the [L402 protocol](https://docs.lightning.engineering/the-lightning-network/l402) for paid access. Compatible with [lnget](https://github.com/lightninglabs/lnget) and any L402-aware client.

### How Paid Access Works

Every paid request goes through the same L402 flow: hit an endpoint, receive a 402 with a Lightning invoice, pay the invoice, retry with `Authorization: L402 <macaroon>:<preimage>`. Each payment gives you credits on pullthatupjamie.ai. Each API call deducts its cost from your balance.

**You choose how to use it.** Pay per query if you want — that's just a credit you use once. Or deposit more upfront and reuse the same credential across all endpoints until the balance is depleted. The 402 response includes the full pricing table (`creditInfo.pricingMicroUsd`) so you can decide.

**Key points:**
- **Credential works across all endpoints:** The same `macaroon:preimage` works on `/search-quotes`, `/search-chapters`, `/make-clip`, `/jamie-assist`, etc. until the balance is depleted.
- **Response headers on every paid request:** `X-Credits-Remaining-USD` and `X-Credits-Cost-USD` tell you your balance and what the call cost.
- **Custom amount:** The default invoice is 500 sats (~$0.33). To request a different amount, add `?amountSats=N` to any request (min 10, max 500,000 sats). The 402 response will contain an invoice for that amount.
- **Balance endpoint:** `GET /api/agent/balance` with your L402 credential returns your full balance breakdown.
- **When credits run out:** The next request returns a fresh 402 challenge. Pay it to continue. If using lnget, this is automatic.

### Automatic Flow (lnget)

If using [lnget](https://github.com/lightninglabs/lnget), everything happens automatically:
```bash
lnget "https://www.pullthatupjamie.ai/api/search-quotes" \
-d '{"query": "bitcoin energy consumption"}'
```
lnget handles the 402 challenge, pays the invoice, caches the credential per-domain, and retries. Subsequent requests to any pullthatupjamie.ai endpoint reuse the cached credential with no additional payment.

### Manual Flow

#### 1. Hit any protected endpoint
```bash
curl -s -D- -X POST -H "Content-Type: application/json" \
-d '{"query": "bitcoin energy consumption"}' \
"https://www.pullthatupjamie.ai/api/search-quotes"
```
Returns `HTTP 402` with:
- `WWW-Authenticate` header: contains `macaroon` and `invoice` (BOLT-11)
- JSON body: contains `creditInfo` with pricing table, min/max deposit amounts, and balance endpoint

#### 2. Pay the Invoice
**Pay using ANY Lightning wallet** (Zeus, BlueWallet, Phoenix, Alby browser extension, etc.). Save the **preimage** returned by your wallet — you need it for the credential.

**NWC (programmatic):** If using [Alby CLI](https://github.com/getAlby/alby-cli) or any NWC-compatible wallet:
```bash
npx @getalby/cli pay-invoice -c "NWC_CONNECTION_STRING" -i "BOLT11_INVOICE"
```
Returns `preimage`.

#### 3. Retry with L402 credential
```bash
curl -s -X POST \
-H "Authorization: L402 MACAROON:PREIMAGE" \
-H "Content-Type: application/json" \
-d '{"query": "bitcoin energy consumption"}' \
"https://www.pullthatupjamie.ai/api/search-quotes"
```
Credits are auto-activated on first use. **Reuse this same credential on all subsequent requests** to any pullthatupjamie.ai endpoint until depleted.

#### Custom Credit Amount
To deposit more (or less) than the default 500 sats, add `?amountSats=N` to any request:
```bash
curl -s -D- -X POST -H "Content-Type: application/json" \
-d '{"query": "bitcoin energy consumption"}' \
"https://www.pullthatupjamie.ai/api/search-quotes?amountSats=5000"
```
Returns a 402 challenge with a 5,000-sat invoice instead of the default. Min: 10 sats, Max: 500,000 sats.

### Check Balance
```bash
curl -s -H "Authorization: L402 MACAROON:PREIMAGE" \
"https://www.pullthatupjamie.ai/api/agent/balance"
```

## Modules

### Available Now
- **Podcast RRA (Retrieve, Research, Analyze):** See [references/podcast-rra.md](references/podcast-rra.md) — search the corpus, build interactive research sessions, discover people/orgs, ingest new feeds. Now with **Smart Search** (`smartMode`) for handling vague or descriptive queries.
- **Podcast Discovery:** `POST /api/discover-podcasts` — LLM-assisted search across the full Podcast Index catalog. Returns matching podcasts with `transcriptAvailable` flags and actionable next-step endpoints. Use this to find podcasts not yet in the corpus, then submit them for transcription via on-demand processing.
- **Create:** See [references/create.md](references/create.md) — generate shareable MP4 clips with burned-in subtitles from any search result. Full pipeline: Search → Create clip → Share.

### Coming Soon
- **Publish:** Cross-post to Twitter, Nostr, and more. Research a topic → generate a post → publish everywhere.

## Credits Running Low
Check `X-Credits-Remaining-USD` in response headers during workflows, or call `GET /api/agent/balance`. If the balance is too low for the next call, that request will return a fresh 402 challenge with a new invoice. Pay it to continue. If using lnget, this top-up happens automatically.

## Security & Trust

**No Command Execution:** This skill does NOT execute arbitrary shell commands, install packages, or modify system state. All operations are HTTP API calls to `pullthatupjamie.ai`. The skill documentation references an optional CLI tool (`@getalby/cli`) for paying Lightning invoices, but this is:
- **Never auto-executed** — requires explicit operator approval
- **Completely optional** — operators can use any Lightning wallet instead
- **Not installed by this skill** — operators must manually install if desired

**Free tier:** Corpus browsing (`/api/corpus/*`) works without any headers. For paid endpoints, add `X-Free-Tier: true` to get an IP-based quota allowance (e.g., 50 searches/week). Without this header, paid endpoints return a 402 immediately. You can evaluate the service before providing any payment info.

**Paid tier credentials:** The L402 credential (macaroon + preimage) is a sensitive bearer token. It should be:
- Stored securely (env vars or encrypted config, not in plaintext logs)
- Never shared with untrusted agents or services
- Backed by a wallet with limited funds (e.g., 500-1000 sats)

**All API calls proxied:** All operations route through `https://www.pullthatupjamie.ai`. RSS feed parsing, search, and ingestion are handled server-side. No direct external URL fetching by the agent.

**No persistence or privilege escalation:** This skill has no install hooks, no `always: true`, and does not modify other skills or system config.

## Gotchas
- API base: `https://www.pullthatupjamie.ai` (must include `www.` — bare domain redirects and breaks API calls)
- **Free tier requires `X-Free-Tier: true` header.** Without it, paid endpoints return 402 immediately. Corpus endpoints work without any headers.
- **Credit reuse is optional.** You can pay per query (each 402 = one credit used once) or deposit more and reuse the same `L402 macaroon:preimage` credential across all endpoints. Either way works.
- Custom amount: append `?amountSats=N` to any request (min 10, max 500,000). No separate purchase endpoint.
- Alby CLI: `pay-invoice` with `-i` flag (not `pay`)
- 500 sats gets ~150+ searches. Start there.
- Monitor balance via `X-Credits-Remaining-USD` response header or `GET /api/agent/balance`.
- Research session creation takes 30-45 seconds. Be patient.
- Clip creation takes 30-120 seconds. Poll `/api/clip-status/:lookupHash` every 5 seconds.
Loading
Loading