Turns your Loom recordings into reviewed action plans in Notion, with an optional markdown copy
(plan plus raw transcript) in Google Drive. Installed as a Claude Code plugin it runs on your
Claude subscription: no LLM API keys, and no .env for the common case.
Loom has no public API; this uses an authenticated-session approach scoped to your personal account. Treat the stored session as a credential, and read "Known limits" before installing.
/plugin marketplace add fontezbrooks/loomDaddy
/plugin install loom-daddy@loomDaddy
One required step: sign in to Loom.
/loom-daddy:loom-auth
This opens a real browser. Complete Google SSO by hand (Google blocks automated sign-in); the
script detects the signed-in session and saves it automatically, no terminal input needed. Re-run
it whenever the session expires (override the wait with LOGIN_TIMEOUT_MS).
Optionally confirm everything is wired up:
/loom-daddy:setup # doctor: session + Notion MCP + (optional) Drive
Nothing else is needed for the common case:
- Analysis runs on your Claude subscription (no LLM API key).
- Notion publishing uses your connected Notion MCP (no Notion token). You name the target database once on your first publish and it is remembered.
- State (session, seen-recordings ledger, cached Notion destination) lives in
~/.loom-daddy(override withLOOM_DADDY_DATA_DIR) and survives plugin upgrades.
/loom-daddy:list # recent recordings
/loom-daddy:analyze <id> # transcript -> action plan
/loom-daddy:render <id> # action plan -> markdown
/loom-daddy:publish <id> [--to notion|drive|both] # push the plan out
/loom-daddy:process # full pipeline over all new recordings
/loom-daddy:status # session and pipeline state
Natural language works too ("analyze my standup loom and put it in Notion") via the
model-invocable loom skill.
Each plan contains a summary, decisions, action items with inferred owners, priorities and timeframes, timestamped source links back to the recording, and open questions.
Drive upload (a transcript plus action-plan markdown copy per recording) is optional: when
DRIVE_FOLDER_ID / GOOGLE_APPLICATION_CREDENTIALS are unset, the Drive step skips itself with a
notice and Notion publishing still works.
To enable it with your own Google account (verified flow, OAuth via the Google Workspace CLI):
- Install and configure the gcloud CLI for basic auth: https://cloud.google.com/sdk/docs/install
- Install and configure the Google Workspace CLI (
gws), making sure to select Google Drive when it asks which services to grant: https://github.com/googleworkspace/cli#interactive-local-desktop - Export the credential:
This writes an
gws auth export --unmasked > credentials.jsonauthorized_userOAuth credential (client id/secret + refresh token). It is a real credential: keep it out of git and out of shared folders. - Set
GOOGLE_APPLICATION_CREDENTIALSto that file's absolute path. - Open the target Drive folder in a browser and copy the id from the URL
(
https://drive.google.com/drive/folders/<DRIVE_FOLDER_ID>); setDRIVE_FOLDER_ID.
As a plugin, set both variables in a .env file in the installed plugin directory
(/loom-daddy:setup tells you where and verifies the result: it should report
[OK] Drive configured (optional)). For the standalone daemon, set them in the repo .env.
A service-account key JSON with Drive scope also works for GOOGLE_APPLICATION_CREDENTIALS if you
prefer machine credentials over a personal OAuth grant.
/loom-daddy:schedule install [--interval N] # default: every 45 minutes
/loom-daddy:schedule status # installed? loaded? auth reachable? log path
/loom-daddy:schedule remove
Installs a per-user macOS LaunchAgent that runs /loom-daddy:process --commit on a schedule,
on your Claude subscription. Preview the generated plist with install --dry-run. Stay logged in
for the first run so the subscription credential is reachable (keychain access only exists in the
logged-in session).
It is local-only by design: the authenticated Loom session lives on your machine, so a hosted/remote agent cannot drive it.
- First diagnostic for anything:
/loom-daddy:setup. It checks the session, data dir, Notion MCP, and optional Drive config, and says what to fix. - Loom session expired (list/analyze/process start failing auth):
/loom-daddy:loom-authagain. Sessions need one periodic manual refresh; there is no way around the interactive SSO. - Notion publish has no destination: you name the target database on your first
/loom-daddy:publish(for example "publish to my Meeting Notes database"); it is then remembered in~/.loom-daddy. - After updating the plugin: updates install into a new versioned plugin directory, and two
things do not follow automatically. (1) The scheduler's LaunchAgent has the old directory baked
in, so re-run
/loom-daddy:schedule installafter an update. (2) A plugin-directory.env(Drive config) does not carry over; re-create it, then re-run/loom-daddy:setupto verify. Everything in~/.loom-daddy(session, ledger, Notion destination) does survive updates. - Doc or behavior changes not showing up: installed plugins are pinned to the version they were
installed at; update the plugin from
/pluginto pull a newer release.
The pipeline also runs outside Claude Code as a plain Node daemon: API-key based, with a pluggable LLM provider, publishing to Notion via the API instead of MCP. Use this for a headless runner or if you do not use Claude Code.
npm install
npx playwright install chromium # only needed on the runner host
Environment (required): NOTION_TOKEN, NOTION_PARENT_DATABASE_ID, DRIVE_FOLDER_ID,
GOOGLE_APPLICATION_CREDENTIALS (see "Google Drive copy" above), plus the selected LLM
provider's credentials (below).
Optional: LOOM_LOOKBACK_DAYS, POLL_OVERLAP_MINUTES, POLL_CRON, STORAGE_STATE_PATH,
STATE_PATH, LOOM_BASE_URL.
LLM_PROVIDER selects the model adapter (default anthropic). Only the selected provider's
credentials are required, so you can keep several configured and switch by flipping one var.
anthropic(default):ANTHROPIC_API_KEY, optionalANTHROPIC_MODEL.gemini: AI StudioGEMINI_API_KEY, or Vertex viaGEMINI_PROJECT_NAME(+ optionalGEMINI_LOCATION, defaultglobal). OptionalGEMINI_MODEL(defaultgemini-3-flash-preview). Requires the optional dep:npm i @google/genai.ollama(local):OLLAMA_MODEL, optionalOLLAMA_HOST(defaulthttp://localhost:11434). No API key; runs against a local Ollama daemon.
Per-run override on analyze/run-once: --provider <name> and --model <name>. Example:
tsx scripts/analyze.ts <id> --provider gemini --model gemini-3-pro-preview.
npm run login # same interactive Google SSO as the plugin login
npm start # runs one cycle immediately, then on POLL_CRON
Each workflow stage runs in isolation via tsx scripts/<stage>.ts, chaining through a
gitignored artifacts/ dir (<id>.transcript.json, <id>.meta.json, <id>.plan.json,
<id>.action-plan.md). Most scripts accept a bare video id (resolved against artifacts/)
or an explicit file path. Stages that write to Drive/Notion are dry-run by default; pass
--commit to perform real writes.
tsx scripts/list.ts [--days N] [--limit N] [--json] # find a recording id (session)
tsx scripts/session-check.ts # is the stored session still valid?
tsx scripts/resolve-url.ts <id> # print the signed transcript URL (parser debug)
tsx scripts/download.ts <id> [--days N] # Loom -> <id>.transcript.json + <id>.meta.json
tsx scripts/analyze.ts <id|file> [--meta f] [--provider p] [--model m] # transcript -> <id>.plan.json
tsx scripts/render.ts <id|file> # plan -> <id>.action-plan.md (no network)
tsx scripts/save.ts <id|file> [--commit] # transcript -> Drive
tsx scripts/publish.ts <id|file> [--transcript f] [--commit] # plan -> Notion + Drive
tsx scripts/record-publish.ts <id> --url <pageUrl> # record a Notion publish done via MCP
tsx scripts/mark.ts <id> [--force] # ledger the id (needs a Notion receipt)
tsx scripts/run-once.ts <id> [--days N] [--provider p] [--model m] [--commit] # full chain for one id
tsx scripts/clean.ts # wipe the artifacts dir
analyze and render need no Loom session, so they run offline against fixtures (e.g. the
HAR-derived transcript) for prompt and formatting iteration. ARTIFACTS_DIR overrides the
artifacts location.
- Two GraphQL queries list recordings in a poll window:
recentUserVideos(your own recordings) andGetCalendarMeetings(recorded meetings on your synced calendar, regardless of who recorded them; recorder attribution is published to Notion). - Fully-processed + unseen recordings are selected (idempotency ledger); the two sources are merged by video id. If one source errors the other still processes.
- Each recording's share page yields a short-lived signed CDN transcript URL.
- The transcript JSON (
phrases: [{ts, value, speakerName}]) is fetched immediately. - Claude returns a schema-validated action plan (summary, decisions, action items with inferred owners/priorities/timeframes, timestamp source links, open questions).
- The plan is published to Notion and written, with the raw transcript, to Google Drive.
The trigger is a poll (no Loom webhook exists), so it is near-real-time.
npm test # vitest, core logic against real fixtures from the HAR
npm run typecheck # tsc --noEmit
Architecture keeps all network and SDK access behind injectable interfaces
(HttpClient, StructuredModel, NotionApi, DriveApi), so the core (loom/,
transcript/, analyze/, publish/, state/, runner.ts) is unit-tested without
network. Heavy SDKs (Playwright, Anthropic, Notion, googleapis) are loaded via dynamic
import in session/ and integrations/ and are optional dependencies.
- ToS-gray: automated credentialed access to Loom. Scoped to a personal account, internal/low-risk content; treat the stored session as a credential.
- Fragile points:
loom/sharePage.tsandloom/queries.tsride undocumented endpoints. - One periodic manual session refresh (
/loom-daddy:loom-authornpm run login) when the session expires. - Meetings recorded by a teammate whose sharing settings restrict access warn-and-retry each cycle until that recorder grants workspace viewing access.
- When upgrading to the meetings-aware build (0.3.0) with forward-only intent, write the
current ISO timestamp into
state/watermark.jsonfirst; an absent watermark backfillslookbackDaysof teammates' meetings. - Design, research, and requirements notes are maintained separately (internal).