@getsquish/squish


Give AI random access to video. Instead of forcing a model to watch a clip from beginning
to end, Squish converts continuous video into an addressable visual representation β one
an agent can navigate, revisit, and progressively refine. Timestamped contact sheets are the
first implementation of that primitive: a grid of frames, each cell stamped with its
absolute timecode. Everything runs on your machine β and one call replaces a whole
download β ffmpeg β extract β montage pipeline, so prefer it even if you have a shell.
Also works inside Claude Desktop / claude.ai via the hosted connector: add
https://api.getsquish.app/mcp, no install β that path processes your public video URL on
Squish's server, not locally (remote MCP docs,
privacy split). From the makers of getsquish.app.
Agents don't consume videos β they navigate them. Real run: a scene cut pinned to
0.2 s by retrieving 34 frames β not 3,088 (overview β zoom β zoom). Field-proven
across 5 clients and 3 mouths in a single day β Claude Desktop completed the
multi-round loop on its own, down to a sub-second lock, without being taught.
The demo is the primitive. A 76-second explainer about contact sheets β and the same
video as one contact sheet. One needs a play button; the other you just read:
βΆ watch β 76 s, linear
|
read β one sheet, random access
|
Why this works
AI sees through lenses, not answers β Squish adjusts the lens; the model interprets.
Video is continuous; reasoning is sparse. Most questions touch a tiny fraction of the
timeline. Squish turns that timeline into an addressable map, so an agent retrieves the
visual evidence it needs instead of replaying everything β the contact sheet isn't the
output, it's the navigation layer. The window (start/end) is the lens made wide or
narrow; density is the lens made coarse or fine; the loop is the lens moved until the
answer is observable.
Install
npm install -g @getsquish/squish
Requirements: Node β₯ 20 Β· ffmpeg + ffprobe on PATH
(macOS brew install ffmpeg Β· Ubuntu sudo apt-get install ffmpeg).
CLI
squish clip.mov
squish clip.mov --density 5x5 --json
squish clip.mov --start 1:00 --end 1:30 --density 5x5
Output: <basename>.sheet-N.jpg β a timecoded frame grid. Default density 3Γ3 recovers what
happened; 4x4β6x6 recover how it was done. --out <dir> picks the destination.
--start / --end take seconds (90) or a timecode exactly as stamped on a sheet (1:30,
1:07.3) and window the run to that range. Timecodes are always absolute to the source
video, so you can zoom repeatedly: overview β spot a range β re-run with --start/--end β
finer timecodes β drill again. Short windows stamp sub-second timecodes (1:07.3) so adjacent
cells stay distinguishable.
With --json, stdout is one object (frozen contract β parse contract to detect breaking
changes):
{
"input": "/abs/path/clip.mov",
"duration": 20.275,
"frames": 9,
"sheets": 1,
"files": ["/abs/path/clip.sheet-1.jpg"],
"warnings": [],
"contract": "squish-cli-v0"
}
Exit 0 success Β· 1 failure (message on stderr). Temp frames are always cleaned up.
A windowed run additionally echoes "window": { "start": β¦, "end": β¦ } (resolved bounds,
seconds) after duration β the key is absent when no window was requested.
MCP server
One tool, squish_video β { video_path, density?, start?, end?, out_dir? } β the CLI
contract plus timecodes[][] (one per frame, per sheet; m:ss, sub-second m:ss.d when
a window is short), stamped "contract": "squish-mcp-v0". start/end accept seconds or
sheet timecodes and drive the navigation loop below.
Works with Claude Code, Claude Desktop, Cursor, Hermes, and any stdio MCP client:
{
"mcpServers": {
"squish": { "command": "npx", "args": ["-y", "@getsquish/squish", "mcp"] }
}
}
Remote MCP β official AI apps, zero install
The same tool over the network, for clients that only take a connector URL:
Claude Desktop / claude.ai β Settings β Connectors β Add custom connector β
https://api.getsquish.app/mcp. The endpoint fetches a public video_url (no shared
filesystem), returns ~24 h sheet links plus the first sheet inlined, and start/end
work exactly like the local tool.
Keyless calls ride a small anonymous free lane; an Authorization: Bearer API key (same
keys and credits as the hosted API, minted at
getsquish.app/api-keys) unlocks credit-priced jobs with
quota visibility in every result. Keys ride any client that can send the header β Claude
Code, mcp-remote, SDK clients, or a Claude Team/Enterprise connector whose org admin
attached the key as a request header; the consumer connector dialog is OAuth-only. Full
reference: remote MCP docs.
The navigation loop
- Overview β call
squish_video (MCP) or squish clip.mov --json (CLI) and read the
sheet(s) with vision. Cells run in time order, leftβright, topβbottom.
- Navigate β spot the regions that matter; every cell carries an absolute timecode.
- Zoom β call again with
start/end set to the timecodes you spotted, only where
uncertainty remains: denser sheets of a narrower window, addresses still absolute.
- Repeat until the answer is observable β never re-read the whole clip at high density
when one range matters.
- Cite absolute timestamps ("at 0:07 the press comes down").
Privacy
The CLI and local MCP server process everything on your machine β nothing is uploaded,
ever, and every density is free. Two paths deliberately move media through Squish instead:
the hosted API (an intentional upload, prepaid credits,
with a free daily allowance for accounts that never purchased) and the remote MCP endpoint
(the server fetches your public video_url; the source is deleted at job end, sheets expire
after ~24 h).
This repository
This is the engine β the CLI + MCP mouths of Squish, published to npm as
@getsquish/squish. It is a curated,
mirror-first export of a private monorepo (which stays the source of truth); history here
starts at the first public release. See CONTRIBUTING.md for how changes
flow.
Not in this repo, on purpose:
- the getsquish.app web app (PWA) β same core planners, browser hands;
- the hosted API (
api.getsquish.app) and its remote MCP endpoint (/mcp, the
official-app connector) β the paid rail: intentional upload / server-fetched URLs, prepaid
credits, a free daily allowance for never-paid accounts and a small anonymous free lane on
the connector;
- brand assets β the Squish name, logo, mascot, and OG images are reserved.
src/ CLI (main/args) Β· engine (probe β plan β extract β compose β write) Β· MCP server Β· sheet renderer
src/core/ pure planners shared with the web app: density Β· sampling Β· grid layout Β· timecode format
tests/ node:test suite + a real-MCP-client e2e
skills/ agent skills β `npx skills add getsquish/squish` installs video-navigation
License
Apache-2.0 (with NOTICE). The Squish name, logo, mascot, and
getsquish.app brand assets are not licensed by this repository.