Two capabilities, and they work apart
Perception. Video, audio and screen activity become frames, transcripts and
OCR text, each carrying an absolute timestamp. Index a source once and query it
for as long as you keep it; every answer cites a moment you can open.
Verification. A frozen contract — file digests, JSON values, SQL results,
HTTP responses, DOM state — is evaluated by a separate process. The verdict is
VERIFIED, FAILED, UNVERIFIED or INCONCLUSIVE, and it does not come from
a language model.
Either is useful on its own, and the split is deliberate.
Watch Skill — the engine
Index a recording once and ask it questions for as long as you keep it. Answers
cite timestamps you can open. Verification contracts check file digests, JSON
values, SQL results, HTTP responses and DOM state, and report passed,
failed, unverified or inconclusive — four answers, because three of them
are not the same as "no".
Any agent can use it: MCP, a CLI, or a REST API.
|
DeepWatch — the workspace
Built on the official
DeepSeek Harness, with Watch
Skill composed in, installed by one command. You get an agent that
can see and prove, without wiring anything together yourself.
Every tool call leaves a receipt naming what it touched. Every path a tool
declares is checked against one workspace boundary, so a tool cannot quietly
write outside it. Results carry a Core verdict you can open, and the Library
keeps them after a restart.
Runs in your browser. Compare puts two runs of the same contract side by side
and shows where their verdicts diverged.
|
Watch Skill sees and proves. DeepWatch is the workspace it comes built into.
Start here
Three entry paths. Pick the row that describes you.
| You have | You want | Go to |
|---|
| An agent already (Claude Code, Cursor, Codex, any MCP client) | Give it eyes, ears and verification | Watch Skill |
| Nothing yet | The whole workspace, agent included | DeepWatch |
| A DeepSeek Harness you already run | Add Watch to it, keep your setup | @deepwatch/dsh-bundle |
1. Add Watch Skill to an agent you already use
pip install 'watch-skill[standard]'
watch-skill doctor
watch-skill watch <video-url-or-file>
watch-skill ask <id> "what changed at 3:12?"
Take the extra seriously. A bare pip install watch-skill gives you the
CLI, the verifier and the Bridge, and it cannot extract a frame: watch stops
at perceive.missing_dependency on the first video. [standard] is frames,
retrieval and MCP; add [ocr] to read on-screen text, [whisper] for local
transcription when a source has no captions, [loop] for the browser, or take
[all]. watch-skill doctor names the exact command for whatever is missing.
Wire it into any MCP client — [standard] includes the server:
Or install the skills into 25+ agents at once:
npx skills add oxbshw/watch-skill -g
2. The whole workspace
Prerequisites. Node ^22.19 || >=24, which is what the CLI's engines
declares. Python 3.11, 3.12 or 3.13 — the versions CI runs and the classifiers
list — and only if you want the perception and verification engine. DeepWatch
starts without it and reports every Watch capability as unavailable until it is
there.
pip install 'watch-skill[standard,ocr]'
npm install -g @deepwatch/cli
deepwatch doctor
deepwatch setup
mkdir my-project
deepwatch web --workspace ./my-project
deepwatch web prints a local URL and opens the workspace there. This is the
first thing you see:
Two numbers rather than one fraction, because "installed" and "proved" are
different facts and a single percentage would blur them. Ready now counts
what has passed a runtime gate. Needs setup counts what has not been
configured or not been tested — saved is never presented as tested. You can
open the workspace without a provider: the Library, the index and the Watch
tools all work locally.
Without a global install, the same package through npx:
npx --yes @deepwatch/cli setup
mkdir my-project
npx --yes @deepwatch/cli web --workspace ./my-project
npx is a way of running @deepwatch/cli, not a different package — there is
no unscoped deepwatch on npm.
What setup downloads. The pinned DeepSeek Harness, its exact required
peers, and the DeepWatch packages at this release's version, into a runtime
under your DeepWatch home. It prints the registry, the versions and the
destination and stops for your agreement; --yes agrees in advance and
--offline refuses outright. Nothing is installed globally except the CLI you
installed yourself. --artifacts <dir> takes the DeepWatch packages from
verified local tarballs this product hashes itself instead of from the registry,
which is what a checkout build wants. It does not make the install offline: the
pinned Harness and its generated peer closure are fetched from npm in that mode
too, and the plan setup prints says so before it fetches anything.
A model provider is not required to start. The workspace boots, the Library
works and Watch tools answer without one. You need a provider for the agent —
chat, tool use, and the critique step of THE LOOP.
Connect a model, and prove the connection
Four steps in the workspace itself, in this order. The last one is the point.
| In the app | What it does |
|---|
| Settings → Models → Add provider | Names a provider and takes a key, or leaves the field blank and reads one from the launch environment. |
| Settings → Role Bindings → Choose a model | Binds a specific provider and model to a role — Chat, or Visual perception. |
| Run provider test | Sends one real request to that exact binding and reports what came back. |
| Ready | Only now will the workspace send anything to it. |
Saved is not presented as tested. A binding with no successful provider test
behind it is blocked, and the turn says so: "…is bound but no provider test
has proved it, so nothing may be sent to it yet." Re-run the test after a host
restart — the binding persists, the proof does not.
A capability is assigned per role, not per provider. A role with nothing
assigned says so and never quietly falls back to another role's model, which is
why two of the three above read Not configured rather than inheriting Chat's.
A first task worth running
Open a workspace directory and ask for something that touches the disk:
Create notes/totals.json with the numbers 12, 30 and 18, then read it back
and tell me the sum.
You get an answer, and underneath it a row per tool call naming the exact
workspace-relative path each one touched. That is the shape everything else in
this README builds on.
Dependency readiness is not the same as a capability you have used.
deepwatch doctor reports what is installed and reachable — Node, the
Harness, the profile, Watch Core, ffmpeg. It does not claim those capabilities
have been exercised on your machine, and the workspace's own readiness panel
counts the same thing. A green row means the pieces are there; running the task
above is what tells you the pieces work together.
3. Into a DeepSeek Harness you already run
cd <your-project>
dsh plugin --profile <your-profile> add @deepwatch/dsh-bundle
dsh --profile <your-profile>
There is no web subcommand. dsh web is an alias of dsh --profile web,
so dsh --profile <your-profile> web boots your profile and then hands web
to the app as an argument — which is not what you meant and does not say so.
The Harness prints this itself under dsh --help: dsh --profile web — boot
the web profile (same as: dsh web). Name your profile once, after
--profile, and pass nothing else.
Name the same profile in both commands. dsh plugin add writes into the
profile you name; installing into one and booting another leaves you looking at
an agent with no watch_* tools and no error to explain it.
Start it from your project directory. The receipt journal is written under
the working directory the Host is launched in, so cd there first — otherwise
the Library indexes a directory you are not working in and reports empty.
To check what a profile actually composes before you start it:
dsh --profile <your-profile> --dump-config | grep watch-
Compatible Harness. This release was measured against
@deepseek-ai/dsh@0.1.1-rc.2, exactly — it is a pinned peer, not a range, so a
profile on a different Harness is a combination nobody tested. dsh --version
tells you which you have.
That is the installation. The package declares dsh.bundle.patch, so DSH
reconciles it into the profile's layer stack and applies the patch after its
own. Four narrower variants — media, browser, memory, document — are declared
alongside it for a profile that wants one capability rather than all of them.
Add the engine — with the extras, because the bundle's media capabilities are
the engine's:
pip install 'watch-skill[standard,ocr]'
[standard] is frames, retrieval and MCP; [ocr] reads on-screen text. A bare
pip install watch-skill installs a Core that cannot extract a frame, and the
Bridge would connect to it and report perceive.missing_dependency on the first
video. The Bridge finds the executable on PATH by itself.
Full guide: @deepwatch/dsh-bundle.
Requirements. The same as everywhere else here: Node ^22.19 || >=24, and
Python 3.11, 3.12 or 3.13 for the engine. Windows, macOS and Linux.
Which package is for you
Twenty-one packages ship from this repository across two registries, and only
three of them are things a person installs on purpose.
| Package | Registry | Install it if |
|---|
watch-skill | PyPI | You want perception, evidence, retrieval and verification — from a CLI, over MCP, or through REST. This is the engine. |
@deepwatch/cli | npm | You want the whole workspace. Provides the deepwatch command, which provisions and launches everything else. |
@deepwatch/dsh-bundle | npm | You already run a DeepSeek Harness and want Watch added to a profile you control. |
Everything else under @deepwatch/ is a plugin or an internal dependency —
the Harness rows the bundle composes (dsh-tools, dsh-library, dsh-live,
dsh-memory, dsh-workspace and the rest) and the packages they share
(dsh-contracts, dsh-sdk, dsh-core-bridge). They are published so the
bundle resolves and so a composition can pick one row rather than all of them.
Installing one directly is for embedding a single piece in a composition you
control; it is not a route into the product.
npx @deepwatch/cli is a way of running @deepwatch/cli rather than a
different package, and there is no unscoped deepwatch on npm.
The package map shows how the twenty compose,
and each package's own README says what it is for and what it needs.
THE LOOP: observe, act, verify
Perception is only half of it. THE LOOP is what an agent does with perception
when it is trying to fix something.
pip install 'watch-skill[standard,loop]' && playwright install chromium
watch-skill loop start http://localhost:3000/checkout \
"the total updates when quantity changes, and no NaN appears"
- Observe — a real browser records the page to video; frames are extracted
and OCR'd, each with an absolute timestamp.
- Critique — a vision model is asked whether the capture meets the criteria
you wrote. It reports issues with the timestamp each was seen at.
- Fix — you change the code.
- Verify —
watch-skill loop iterate re-captures and diffs against the
previous run, so "fixed" means the thing that was wrong is gone.
The critique step needs a vision-capable model. Without one, capture, frames,
OCR and verification still work, and the critique says it cannot judge rather
than guessing. See THE LOOP.
Corrections become lessons
When an answer is wrong, you correct it. Watch Skill classifies the correction,
stores it as a lesson in the local store, re-asks the question with the lesson
applied where the error class is mechanical, and counts what that saved.
Lessons persist between runs and stay on your machine. Nothing learns on its
own — the correction is yours to give — and nothing is uploaded.
Lessons and savings.
The DeepWatch Workspace
Everything above is the engine, and any agent can use it. DeepWatch is built on
the official DeepSeek Harness with Watch Skill already composed in, so an agent
you run there produces receipts and verdicts without you wiring anything up.
The rest of this section is one job, end to end. A checkout page charges the
wrong amount, and all you have is a screen recording of it.
Give the recording to the engine · ask it where the amount went wrong · repair
the code · prove the repair from outside the agent · come back to the record
tomorrow. Every figure and verdict below is from the run that produced this
section, on Watch Skill 1.4.3 and DeepWatch 0.1.3.
1 · Give the recording to the engine
Four seconds of somebody changing a quantity. Nothing is typed about what is
wrong with it.
watch-skill watch ./checkout-bug.webm --index
Frames come out with absolute timestamps, and the on-screen text with them:
Selection: 4 kept from 8 candidates (4 near-duplicates dropped)
t=00:00 2 × $10.00 Subtotal $20.00 Tax (10%) $2.00 Total $20.00
t=00:01 5 × $10.00 Subtotal $50.00 Tax (10%) $5.00 Total $50.00
t=00:02 3 × $10.00 Subtotal $30.00 Tax (10%) $3.00 Total $30.00
The bug is now readable: tax is computed, displayed, and left out of the total.
It is readable because those frames survived — three amounts changing in an
otherwise identical layout look like a duplicate to a frame sampler, so a
scripted capture writes down the moments it acted and the engine pins them.
2 · Ask where it happened
watch-skill ask <video-id> "what was the total when the quantity was three?"
The answer cites the timestamp it came from and the frame is on disk. When the
recording does not show an answer, that is what it says: an unanswerable
question is not a cue to guess.
3 · Repair the application
Now the agent has somewhere to start. It reads the evidence, finds orderTotal
in cart.js, and sees that the tax it computed never reaches the return value.
Every file it touches leaves a receipt naming the path, and every path a tool
declares is resolved against one workspace boundary. A write outside it is
refused and written down: the file is not touched, and the journal gains a
receipt tagged scope:outside_workspace / state:cancelled naming the attempt.
Both halves matter — a boundary that refused silently would leave you no way to
tell it had ever been tested.
Here is what it actually left behind, from the run that produced this section.
Fourteen rows went into the journal and they fold to twelve receipts, because
two were written twice — once when the tool returned, and again when Core's
verdict arrived. The four todo_write and glob rows are left out here; these
are the eight that touched something:
| Receipt | Verdict |
|---|
watch_list_sources | — |
watch_ask_source | — |
read — checkout/cart.js | — |
read — checkout/index.html | — |
watch_moment | — |
edit — checkout/cart.js | VERIFIED |
watch_verify | INCONCLUSIVE |
pwsh | — |
The model was told a customer was charged the wrong amount and that a recording
existed. It was not told what the bug was, and nothing in the workspace names
it. It listed the sources, asked the recording, pulled a moment out of it, read
two files, changed one line, and ran a verification of its own — which came
back INCONCLUSIVE, because the checks it wrote could not be evaluated. That
answer is reported as it stands rather than rounded to a pass.
4 · Prove the repair, from outside the agent
The contract was frozen before the repair and lives outside the directory the
agent can write to. Watch Core evaluates it in a separate process and returns a
verdict the agent does not author — VERIFIED, FAILED, UNVERIFIED or
INCONCLUSIVE.
The contract for the run above is
c98bd4ae3d13864869ae02be46cdba48fb97f790ec50feead6e30d17ccc007b0, and its
digest was taken before the agent started. Before the repair Core returned
fail on all three checks — expected 22, got 20, expected 33, got 30, and
#total text = '$20.00' read out of the rendered page. Afterwards, against the
same unchanged contract, all three pass and the page renders $22.00.
The card above is photographed from a different task — the totals.json one
in Start here — because it is what a VERIFIED
card looks like. It is not a picture of the checkout repair; that repair's
evidence is the contract and the receipts named above.
The contract's SHA-256 is on screen, so you can tell it is the same contract.
The verdict is the answer, and each of the four means something different.
Measured on the contract above: against the repaired workspace it is
VERIFIED; pointed at a directory that does not hold those files the checks
still run and report false, so it is FAILED; an expectation written as prose
with no executable check behind it is UNVERIFIED — honest, and not a pass;
and a check that cannot be evaluated at all comes back INCONCLUSIVE with the
check's own status left null rather than folded into a false. Given no
workspace to measure against, Core refuses the request outright
(verify.workspace_unresolved) instead of guessing a directory.
5 · Come back to it tomorrow
Restart everything — kill the process, start it again. Both records come back,
and they are two different stores worth telling apart.
Watch Core's index of sources lives in the Watch data directory. It is
there whether anything is open or not, and watch-skill list reads it with no
workspace involved. The Library's index of receipts is the Host's own: the
journal is written under the workspace at .watch/receipts, and the Library
rebuilds its index from that file on Refresh. It is derived and safe to discard.
That is why the Library follows the workspace. Run the app from the directory
you are working in; a Host started somewhere else journals somewhere else, and
a Library that reports empty after a restart is usually pointed at the wrong
directory rather than missing data.
Measured on the run above: fourteen receipts written, the process killed, and
after the restart all fourteen reopen — same record ids, same last revision,
and the two that Core had ruled on still carrying their own verdicts,
VERIFIED for the repair and INCONCLUSIVE for a check that could not run.
Compare puts the failing run and the passing run side by side and shows where
their verdicts diverged. A comparison describes a difference; it never issues a
verdict of its own.
Every image here is a photograph of a running build, and they do not all come
from the same one — saying they did would be the easiest false claim on this
page. The onboarding shot is from the current gallery, retaken against Watch
Skill 1.4.3 and DeepWatch 0.1.4 with the deterministic browser scenario
passing 42 of 42 in front of it; a gate refuses the set when the shots and the
engine they were taken against disagree. The Settings and result-card shots are
from the 1.4.3 / 0.1.4 candidate, kept because nothing in this release
changed the surface each one shows.
The screenshot page names the build
behind every image, and carries the full 57-shot gallery across three
viewports.
What "local-first" means here, precisely. Your sources, receipts, verdicts
and memory are stored on your machine, and Library search runs there. It does
not mean nothing uses the network: setup downloads the runtime from npm, some
Watch extras fetch a model the first time they run, and a hosted model provider
you configure receives what you send it. The parts that stay local are the
record and the retrieval over it.
Capture is a separate consent from any of that. Every source the workspace can
record is listed with the permission it needs and whether that permission has
been asked for — and nothing is asked for until you use it:
Holding a provider key does not permit media to leave the machine, and a cloud
engine needs its own consent even with the network open. Those are two separate
switches on purpose.
What people use it for
| |
|---|
| Ask a video a question | Index a recording once, then ask about it. Answers cite timestamps you can open. 01-watch-and-ask |
| Prove an agent's work | A deterministic contract Core runs — file digests, JSON values, SQL, HTTP, DOM. 14-browser-verification |
| Fix a UI by looking at it | Capture, critique, fix, re-verify. 04-ui-loop |
| Search across everything | One index over every source you have watched. 03-cross-video-search |
| Work offline | Local whisper and OCR, no provider, nothing leaves the machine. 15-private-offline-workflow |
| Watch something live | A stream or a browser session, bounded and cursored. 18-live-watch |
Each is a directory you can run, with its prerequisites and expected output
written next to it.
All 20 examples, by what they teach
That is all 20 examples; the index is examples/.
How it fits together
flowchart LR
subgraph W["DeepWatch workspace"]
H["DeepSeek Harness<br/>agent, tools, UI"]
P["Watch plugins<br/>tools · library · live · memory"]
H <--> P
end
P <-->|"Bridge (stdio)"| C["Watch Core<br/>Python engine"]
C --> E[("Evidence store<br/>frames · transcripts · index")]
C --> V["Verifier<br/>isolated subprocess"]
V --> R[("Verification records<br/>contract · checks · verdict")]
P --> J[("Receipt journal<br/>one per tool call")]
A["Any other agent<br/>MCP · CLI · REST"] <--> C
Watch Core is the only thing that issues a verdict. The Host may notice,
correlate, freeze a contract and ask — it may not decide the answer. That is
ADR-002, and a build gate fails if anything under
packages/ starts producing verdicts.
A receipt records what a tool call did; a verdict records what Core checked.
They are written by different processes and the Library shows them as different
columns, because an agent that ran a command successfully and an agent that did
the right thing are not the same claim.
More: architecture ·
verification ·
the 39 tools.
What works, and what it needs
| Capability | Out of the box | Needs |
|---|
| Start the app, browse, read diagnostics | ✅ | nothing |
| Verification contracts, containment, receipts | ✅ | nothing |
| Video frames and scenes | with [standard] | ffmpeg ≥ 5.1 — watch-skill doctor installs it |
| Reading on-screen text | with [ocr] | a first-use model download (~80 MB) |
| Speech to text | with [whisper] | a first-use model download; captions are used first when a source has them |
| Chat with an agent | — | a provider you add and bind |
| Visual scene description | — | a model that can see images |
| Browser capture / THE LOOP | with [loop] | playwright install chromium |
| Memory | off | enable in Settings; the store is plaintext and says so |
| Desktop app | not distributed — no installer exists | run deepwatch web |
DeepWatch starts, and stays useful, with no provider configured: verification,
containment, the Library and local perception are all local. What needs a
provider is the agent — chat, tool use, and the critique step of THE LOOP.
Three ways a capability arrives, and they are not interchangeable. A local
dependency (ffmpeg, yt-dlp, a JS runtime) runs on your machine and
watch-skill doctor will fetch and repair it. A downloaded model (OCR
weights, whisper) also runs on your machine, is a large one-time download, and
nothing about your files leaves it. A hosted provider — the agent's model,
and any vision model you bind — is somebody else's service, with their latency,
price and terms, and it sees what you send it. An OpenAI-compatible server you
run yourself (Ollama, vLLM, LM Studio, llama.cpp) is the hosted route pointed at
your own hardware: the data stays local, and whether a given model supports tool
calls or images is a property of that model, which DeepWatch reports rather than
works around.
Nothing reaches a provider until you add one, and holding a provider credential
is not permission to upload a frame or a transcript — that is a separate
consent.
What repairs itself. watch-skill doctor repairs dependencies: it
downloads yt-dlp and keeps it current, bootstraps a JS runtime, installs OCR
language data, and fetches ffmpeg where it can, reporting every repair. That
is the only thing here that acts without being asked. There is no automatic task
resumption, no autonomous learning, and no encryption at rest in this release.
Known limitations is the full list.
Measured, not asserted
Against a leading video-understanding API, same files, same scorer:
| Watch Skill | Baseline |
|---|
| Written-analysis groundedness | 89.7% | 27.9% |
| Citations per 100 words | 13.23 | 0.12 |
| Frame delivery on real footage | 96.9% | 31.2% |
| Cue starts within half a second | 100% | 25% |
Method and fixtures: benchmarks/video_backends/.
Trade-offs against the alternatives: comparison.
Documentation
| |
|---|
| Getting started | Install, first watch, first agent connection |
| Install and upgrade | Both products, optional extras, compatibility policy |
| Configuration | Settings, providers, storage locations |
| Tool reference | All 39 MCP tools and their REST/CLI counterparts |
| Verification | Contracts, the fourteen check types, assurance levels |
| Architecture | Boundaries, data flow, extension points |
| Agent matrix | Per-client setup and how far each is verified |
| Troubleshooting | Dependency repair and common runtime errors |
| Cost | What runs free, what a provider charges for |
| Known limitations | What this release does not do |
DeepWatch: workspace README ·
setup ·
the twenty packages ·
releasing ·
platform support
Three tool counts, because they answer different questions: 39 MCP tools
from watch-skill serve, 22 watch_* tools added to an agent inside
DeepWatch, 47 tools that agent is offered in total.
Coverage written by other people, and the directories that carry the project.
Described by what each one actually contains — a write-up is somebody trying
the thing and reporting back, which is not the same as an endorsement, and none
of these say anything about how many people use it.
Tutorials and write-ups
Video
Directories
| |
|---|
| Skills.sh | Lists the ten agent skills and installs them into a supported client with one command. |
| SkillsMP | A second skills directory carrying the same set. |
| MCP registry | The io.github.oxbshw/watch-skill server entry, for clients that resolve MCP servers by name. |
The full collection, kept separated into tutorials, video, integrations and
directory listings: docs/ecosystem.md. If you have
written or recorded something, open a pull request adding it there.
Contributing
Issues and pull requests welcome. CONTRIBUTING.md has the
twenty-minute path: what to install, which gate to run, and how the commit
messages are shaped. Security policy: SECURITY.md. Design
decisions and their reasons: DECISIONS.md and
ROADMAP.md.
Built on DeepSeek Harness · Powered by Watch Skill
DeepWatch and Watch Skill are independent projects and are not affiliated with
or endorsed by DeepSeek.