agentleFS
rainearcherrainearcher/quiver/skills/loom/SKILL.md

loom

Skill0 starsChanged 59 days agoMITView on GitHub

Read and manage Loom videos from the shell via the `loom` CLI, which ships inside this skill (nothing to install). Use whenever the user pastes a loom.com URL or mentions a Loom recording — "summarize this loom", "what did they say in this loom", "pull the transcript of this Loom video", "get the captions/chapters/key takeaways", "what are the action items from this recording", "extract to-dos from my last 10 looms", "list my Loom videos", "search my Looms for X", "who commented on this loom", "download this Loom video", "what's the download URL", "turn this Loom into meeting notes", "rename/archive/move/pin this video", "add a comment at 2:30". Handles transcripts, WebVTT captions, AI summaries, chapter markers, key takeaways, descriptions, comments and threaded replies, AI-extracted tasks, emoji reactions, backlinks, MP4 download URLs, plus library management across videos, folders, spaces, Watch Later and tags. Human-readable text by default, `--json` for parsing, `-o PATH` for long transcripts, `--dry-run` on every write. Requires LOOM_COOKIE (a browser `connect.sid` session cookie) — Loom has no official API key.

  • Reads credentials
  • Installs packages

8 other projects use a version of this.

Adopted by

Most recently taken up by

  • Other versions8 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 8

    1. epicsagas/Velith★ 40same name
    2. Yassimba/loom★ 9same name
    3. Wondermonger-daydreaming/claude-skills-library★ 7same name
    4. jsuppe/loom★ 4same name
    5. loom-fun/loom-skills★ 4same name
    6. Maxwell-FreeFOV/loom★ 4same name
    7. fontezbrooks/loomDaddy★ 1same name
    8. loombeading/loom★ 0same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repositoryOne other file it gives its agents.

The file

We split this skill into the rules it gives an agent

8 rules. 0 are common, 2 are distinctive, and 6 are very specific to this project.

  • 0

    Common

    Most of the 5 edited versions we read keep these.

  • 2

    Distinctive

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Verify everything once, on first use in a project:

    line 33
  2. Very specific:

    Always go through scripts/loom.sh, the wrapper that ships beside this file.

    line 43
  3. Very specific:

    Every command takes the bare hex ID, not a URL.

    line 76
  4. Very specific:

    If the summary is null (Loom never generated one) or the user wants specifics — a quote, a decision, who said what — fall back to the …

    line 221
  5. Very specific:

    When the user wants a real briefing rather than a one-liner, video details fetches metadata, transcript, chapters, summary, tasks and …

    line 227
  6. Very specific:

    Search matches video metadata, not transcript bodies.

    line 255
  7. Very specific:

    If it prints null, the MP4 has not been rendered yet.

    line 271
  8. Distinctive:

    Always check the exit code.

    line 324

“Common” is measured: kept by at least 6 in 10 of the 5 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Loom CLI

loom is a command-line client for Loom's internal GraphQL API. It reads videos, transcripts, captions, AI summaries, chapters, key takeaways, comments and action items, and manages your library — all from the shell, with --json on every command so output composes with jq.

There is no MCP server and nothing to configure in .mcp.json. You call the CLI with Bash.

Prerequisites

  • uv on PATH (provides uvx), or loom already installed on PATH
  • LOOM_COOKIE — your Loom browser session cookie

The CLI itself is vendored into this skill at vendor/, so there is nothing to install and nothing is fetched from PyPI. uvx builds that local copy the first time and caches it.

Loom has no official API key, so the tool talks to Loom as you, using your browser session cookie. Getting one:

  1. Open loom.com in a browser and sign in
  2. DevTools (F12) → Application → Cookies → https://www.loom.com
  3. Copy the value of the connect.sid cookie (it starts with s%3A)
  4. export LOOM_COOKIE='s%3A...'

The connect.sid= prefix is added automatically, so either s%3A... or connect.sid=s%3A... works. Make it permanent by adding the export to ~/.zshrc / ~/.bashrc or ~/.claude/.env, then restarting the CLI. The cookie lasts roughly 30 days; when it expires every command exits 3.

Alternatives: --cookie VALUE passes a cookie inline, and LOOM_AUTH_FILE / --auth-file PATH accepts a Playwright storage-state JSON file.

Verify everything once, on first use in a project:

bash ./scripts/check-setup.sh

It prints ✓/✗ per requirement, makes one live read-only call to prove the session works, and exits 0 when ready. If it fails, surface its output to the user and stop — do not start guessing at commands.

Invocation contract

Always go through scripts/loom.sh, the wrapper that ships beside this file. It locates the vendored CLI relative to its own path, so it works from any working directory — do not try to cd anywhere first, and do not invoke uvx yourself.

This skill is installed to a different path depending on how it was obtained, and CLAUDE_PLUGIN_ROOT is not set for plain Bash calls. So resolve the wrapper once per session, then reuse $LOOM for every call:

# Plugin installs land in ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/;
# pick the highest version if several are present.
cached=$(ls -d ~/.claude/plugins/cache/*/loom/*/skills/loom 2>/dev/null | sort -V | tail -1)

for d in \
  "${CLAUDE_PLUGIN_ROOT:-/nonexistent}/skills/loom" \
  "$cached" \
  ~/.claude/skills/loom \
  .claude/skills/loom \
  ./skills/loom
do
  [ -n "$d" ] && [ -f "$d/scripts/loom.sh" ] && LOOM="bash $d/scripts/loom.sh" && break
done

if [ -z "${LOOM:-}" ]; then
  # Last resort: search the Claude config dir wherever the skill ended up.
  found=$(find ~/.claude -path '*/skills/loom/scripts/loom.sh' -print -quit 2>/dev/null)
  [ -n "$found" ] && LOOM="bash $found"
fi

[ -z "${LOOM:-}" ] && { echo "loom skill not found on disk" >&2; exit 1; }
$LOOM --version

The first call builds the vendored package (well under a second); every later call in the session is ~0.1s. If the user already has loom on PATH and prefers it, LOOM_BIN=loom makes the wrapper defer to it.

Turning a pasted URL into a VIDEO_ID

Every command takes the bare hex ID, not a URL. Passing a URL fails with exit 2 (invalid ID), because IDs are restricted to [A-Za-z0-9_.-]. Strip it first:

loom_id() { printf '%s' "$1" | sed -E 's#.*loom\.com/(share|embed)/##; s#[?/#].*##'; }

VIDEO_ID=$(loom_id "https://www.loom.com/share/1a2b3c4d5e6f7890abcdef1234567890?sid=abc")
# -> 1a2b3c4d5e6f7890abcdef1234567890

This handles /share/ and /embed/ links and drops any ?sid= tracking query.

Global options

These work on every command and may be given before or after the subcommand — loom --json video list and loom video list --json are identical.

FlagEffect
--jsonPrint the raw payload as JSON instead of the human rendering
-o PATH, --output PATHWrite the payload to PATH (- means stdout)
--save-dir DIRSave video assets under DIR/<video_id>/ (video commands only)
-q, --quietSuppress notes and [Saved to ...] lines on stderr
--cookie VALUELoom session cookie, overriding $LOOM_COOKIE
--auth-file PATHPlaywright storage-state file, overriding $LOOM_AUTH_FILE
--timeout SECONDSHTTP timeout in seconds (default 30)
--dry-runOn write commands: print the resolved operation and exit without calling Loom
--versionPrint the version

Text output goes to stdout; notes, [Saved to ...] lines and errors go to stderr, so piping stdout stays clean.

Command reference

60 commands across 9 groups. R = read, W = write (honours --dry-run). Every level has help: loom --help, loom video --help, loom video transcript --help. --content and --description accept - to read all of stdin. --name does not — passing --name - sets the name to the literal string -.

loom video — read

CommandReturns--save-dir file
video list [--limit N] [--all]Your videos, most recent first
video search QUERY [--limit N] [--all]Videos matching a keyword
video get VIDEO_IDMetadata: name, duration, owner, views, created datemetadata.json
video details VIDEO_IDMetadata + transcript + chapters + summary + tasks + comments, concurrently, as markdowndetails.md, metadata.json, transcript.txt, chapters.txt, summary.txt, tasks.txt, comments.txt
video transcript VIDEO_IDFull transcript with timestamps and speakerstranscript.txt
video captions VIDEO_IDWebVTT captions with start+end times per cuecaptions.vtt
video summary VIDEO_IDAI-generated summarysummary.txt
video chapters VIDEO_IDAI-generated chapter markerschapters.txt
video takeaways VIDEO_IDAI-generated key takeawaystakeaways.txt
video description VIDEO_IDAI description with timestamped sectionsdescription.txt
video tags VIDEO_IDTags on the videotags.txt
video comments VIDEO_IDComments and threaded repliescomments.txt
video tasks VIDEO_IDAI-extracted action itemstasks.txt
video reactions VIDEO_IDEmoji reactions, with who and whenreactions.txt
video backlinks VIDEO_IDWhere the video is shared or embeddedbacklinks.txt
video confluence VIDEO_IDLinked Confluence pages
video meeting-notes VIDEO_IDConfluence meeting notes URL
video download-url VIDEO_IDSigned MP4 download URL
video watch-time VIDEO_IDLast timestamp where you stopped watching

--limit N takes 1–200 and defaults to 50. --all drains every page instead and ignores --limit.

loom video — write

CommandEffect
video rename VIDEO_ID --name TEXTRename a video
video set-description VIDEO_ID --description TEXT|-Overwrite the description
video settings VIDEO_ID --set KEY=VALUEUpdate settings; repeatable, VALUE is JSON-decoded when possible
video delete VIDEO_IDPermanently delete a video — cannot be undone
video archive VIDEO_ID... [--archive|--no-archive]Archive (default) or unarchive videos
video recover VIDEO_IDRecover a deleted video from the trash
video duplicate VIDEO_IDDuplicate a video
video pin VIDEO_ID [--pin|--no-pin]Pin or unpin a video in your library
video follow VIDEO_ID [--follow|--no-follow]Follow or unfollow a video
video move VIDEO_ID... --to FOLDER_IDMove videos into a folder
video share VIDEO_ID... --space SPACE_IDShare to one or more spaces (repeat --space)
video regenerate-mp4 VIDEO_IDTrigger MP4 regeneration

loom comment

CommandR/WEffect
comment reactions COMMENT_ID [--type COMMENT|REPLY]REmoji reactions on a comment
comment add VIDEO_ID --content TEXT|- [--timestamp N]WPost a comment, optionally at a timestamp (seconds)
comment edit COMMENT_ID --video VIDEO_ID --content TEXT|-WOverwrite a comment's text
comment delete COMMENT_ID [--type COMMENT|REPLY]WDelete a comment — cannot be undone
comment react COMMENT_ID --reaction EMOJI [--type COMMENT|REPLY]WReact to a comment

loom task — AI-extracted action items

CommandR/WEffect
task add VIDEO_ID --content TEXT|- [--timestamp N]WCreate an action item
task update TASK_ID --content TEXT|-WUpdate an action item's text
task delete TASK_IDWDelete an action item — cannot be undone
task approve TASK_IDWMark an action item approved
task respond TASK_ID [--responded|--no-responded]WMark an action item responded (or not)

Reading tasks is loom video tasks VIDEO_ID — the task group is writes only.

loom reaction

CommandR/WEffect
reaction frequentRYour most-used emoji reaction types
reaction add VIDEO_ID --time N --type TYPEWReact to a video at a timestamp
reaction delete REACTION_IDWDelete a reaction

loom folder

CommandR/WEffect
folder list [--limit N] [--all]RYour folders, most recent first
folder search QUERYRSearch folders by name
folder get FOLDER_IDRFolder details: name, visibility, creator
folder create --name TEXTWCreate a folder
folder rename FOLDER_ID --name TEXTWRename a folder
folder delete FOLDER_ID...WDelete folders — cannot be undone
folder move FOLDER_ID... --to FOLDER_IDWMove folders into a parent folder

loom space, watch-later, tag, user

CommandR/WEffect
space list [--all|--no-all]RSpaces you belong to; drains all pages by default
space get SPACE_IDRSpace details
watch-later countRHow many videos are in Watch Later
watch-later add VIDEO_ID [--minutes-from-utc N]WAdd a video to Watch Later
watch-later remove VIDEO_IDWRemove a video from Watch Later
tag search QUERYRSearch workspace tags
tag follow TAG [--follow|--no-follow]WFollow or unfollow a tag
user get USER_IDRA Loom user profile
user video-count USER_IDRTotal videos for a user

space list drains every page by default; --limit only takes effect together with --no-all. tag search is known to return rows containing little more than a type marker — the upstream GraphQL selection set is thin. Prefer video tags VIDEO_ID when you want the tags actually on a video.

Workflows

"Summarize this loom" / "what did they say in this loom?"

Given a pasted URL, extract the ID and read the AI summary first — it is one small call and usually answers the question.

VIDEO_ID=$(loom_id "$URL")
$LOOM video summary "$VIDEO_ID"

If the summary is null (Loom never generated one) or the user wants specifics — a quote, a decision, who said what — fall back to the transcript. Transcripts are long, so write to a file rather than flooding the conversation, then Read it:

$LOOM video transcript "$VIDEO_ID" -o /tmp/loom-$VIDEO_ID.txt

When the user wants a real briefing rather than a one-liner, video details fetches metadata, transcript, chapters, summary, tasks and comments concurrently and renders one markdown document — one call instead of six:

$LOOM video details "$VIDEO_ID" --save-dir ./notes

That writes ./notes/<VIDEO_ID>/details.md plus each fetched artifact (metadata.json, transcript.txt, chapters.txt, summary.txt, tasks.txt, comments.txt), so you can Read just the piece you need. details does not cover takeaways, captions, description, tags, reactions or backlinks — run those commands separately if you need them.

"Extract action items across my last 10 looms"

List the IDs as JSON, then pull each video's AI-extracted tasks. video tasks is list-shaped, so it prints [] (never null) and the loop is safe:

$LOOM video list --limit 10 --json | jq -r '.[].id' | while read -r id; do
  name=$($LOOM video get "$id" --json | jq -r '.name')
  echo "## $name ($id)"
  $LOOM video tasks "$id" --json | jq -r '.[] | "- \(.content)"'
done

Collect the output, then synthesize into a single grouped to-do list for the user. If a video has no AI tasks, mine video takeaways or the transcript for commitments instead of reporting nothing.

"Find the loom where we discussed X"

$LOOM video search "pricing model" --limit 20 --json | jq -r '.[] | "\(.id)\t\(.name)"'

Search matches video metadata, not transcript bodies. When the user is sure the phrase was spoken, search is the wrong tool: narrow by date with video list, then grep transcripts.

$LOOM video list --limit 25 --json | jq -r '.[].id' | while read -r id; do
  $LOOM video transcript "$id" -q | grep -qi "pricing model" && echo "hit: $id"
done

That is one API call per video — tell the user the scope before running it over a large library.

"Download this Loom"

$LOOM video download-url "$VIDEO_ID"

If it prints null, the MP4 has not been rendered yet. Trigger a render, wait, and ask again:

$LOOM video regenerate-mp4 "$VIDEO_ID"
sleep 30
$LOOM video download-url "$VIDEO_ID"

The result is a signed URL. Ask the user before actually downloading the file — hand them the URL and let them confirm, rather than pulling a large binary unprompted.

"Turn this loom into meeting notes"

$LOOM video details "$VIDEO_ID" --save-dir ./notes

Then Read ./notes/<VIDEO_ID>/details.md and write the notes yourself. Do not post anything back to Loom unless asked.

Writes and destructive commands

Everything in the W rows changes the user's Loom account, and delete on videos, comments, tasks and folders cannot be undone. Before running any write:

  1. Confirm the exact operation with the user in chat and wait for a clear yes.
  2. Dry-run it first — every write command accepts --dry-run and prints the resolved operation without calling Loom.
$LOOM video delete "$VIDEO_ID" --dry-run
$LOOM comment add "$VIDEO_ID" --content "Nice walkthrough" --timestamp 42 --dry-run

Posting a comment or a task is a message sent on the user's behalf — get explicit approval, never infer it from "handle this loom for me".

Output handling

  • Default (human text) — use for anything you are going to read and summarize. It is compact and already formatted.
  • --json — use whenever you are going to parse, loop, filter, or pipe into jq. Never regex the human rendering; it is for people.
  • -o PATH — use for long payloads (transcripts, captions, video list --all) so they land on disk instead of in the conversation. Then Read the file, or grep it, and report only what matters.
  • --save-dir DIR — use with video details (or any video read) to get a canonical, stable filename per command under DIR/<video_id>/. Repeated runs overwrite in place, so a directory of videos ends up uniformly laid out.
  • -q — silences the stderr notes and [Saved to ...] lines when you only want the payload.

Empty is not an error. List-shaped reads (comments, tasks, reactions, tags, takeaways, backlinks, confluence, search results, folder and space lists) print []; scalar reads with no value (no transcript, no summary, no download URL) print null and explain themselves on stderr. Both exit 0 — report "this video has no summary", not "the command failed".

Exit codes

CodeMeaning
0Success, including empty results
1Loom API or unexpected error
2Usage error or invalid ID
3Auth — missing or expired session
4Not found
5Network, timeout, or rate limit

Always check the exit code; the CLI writes one clean line to stderr rather than a traceback.

Troubleshooting

Exit 3 — expired or missing cookie. This is the common one. Loom session cookies last about 30 days. Tell the user to re-copy connect.sid from DevTools (loom.com → Application → Cookies) and re-export LOOM_COOKIE, then retry. Do not try to fetch or refresh the cookie yourself, and never print the cookie value back into the conversation.

Exit 2 on a video you know exists. You almost certainly passed a full loom.com URL instead of the bare ID. Run it through loom_id first.

loom.sh: vendored CLI not found. The skill is installed but vendor/ is missing, so the copy of the CLI never arrived. Reinstall the skill. If the user already has loom on PATH, LOOM_BIN=loom works around it immediately.

Exit 4. The ID is well-formed but the video, folder, comment or task does not exist, or your account cannot see it. Private videos in a workspace you are not a member of look identical to deleted ones.

Exit 5. Network trouble, a timeout, or Loom rate-limiting you. Retry once; if the video is very long, raise the ceiling with --timeout 120. Back off rather than hammering — the rate limit is on the user's own account.

video download-url prints null. The MP4 has not been rendered. Run video regenerate-mp4 VIDEO_ID, wait ~30 seconds, and retry.

tag search returns near-empty rows. Known upstream limitation — the GraphQL selection set requests almost no fields. Use video tags VIDEO_ID instead.

Neither uvx nor loom found. Install uv (https://docs.astral.sh/uv/). Do not shell out to pip install into the system Python, and do not try to install mcp-loom from PyPI — the published release there is the pre-2.0 MCP server, not this CLI.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.