Skip to content

Commit c41ceaf

Browse files
committed
feat: skills for every agent, sixteen vision providers, 1.2.0
Three things were holding the project back, and none of them were the engine. Skills reached one agent ------------------------ The ten skills are the layer that decides *when* an agent should look at video — the part that makes the rest get used. They lived under `adapters/claude-skill/skills/`, where only Claude Code could find them. The open skills ecosystem reads a top-level `skills/` directory and installs into 27+ agents from it, so that is where they are now: npx skills add oxbshw/watch-skill -g The Claude Code plugin moved to the repository root rather than keeping a mirrored copy, so one set of files serves both ecosystems and cannot drift. `skills.sh.json` declares the package. Six vision providers became sixteen ----------------------------------- Added Groq, Together, Fireworks, DeepSeek, xAI, Mistral, Moonshot, Z.ai, and Qwen, plus `custom` for any OpenAI-compatible server — vLLM, LM Studio, llama.cpp, LiteLLM, Azure, a company gateway. Two contributors asked for that last one before it existed. They are table entries, not code. Every one speaks OpenAI's `/chat/completions`, so the request builder is generated from the registry and adding a vendor touches no request logic. `--base-url` and a `WATCHSKILL_<PROVIDER>_BASE_URL` per vendor point the same entry at a regional host or a self-hosted server; passing it to a provider with its own wire format is a clear error rather than a flag that does nothing. `WATCHSKILL_GROQ_API_KEY` had existed for releases with no Groq provider behind it — read, reported by `doctor`, impossible to use. Three more agents ----------------- Zed, whose key is `context_servers` rather than `mcpServers`, so a config copied from any other client in the matrix silently fails. Roo Code, with the project-scoped `.roo/mcp.json` a team can commit. Continue, one file per server. Each config comes from that project's own documentation and is marked documentation-verified, not machine-tested. Adding an agent no longer needs someone to draw it first. The test required a hand-made avatar for every page, which contradicted the twenty-minute contribution path CONTRIBUTING advertises. A page without art belongs in the matrix and joins the README gallery when art lands; art that exists must still be shown, and no page may be orphaned. Supply chain and platform ------------------------- - PyPI uploads carry PEP 740 attestations: publishing moved to the official action, which signs distributions with this workflow's identity, so a wheel can be verified as built here. - The container image builds for linux/arm64 as well as amd64 — Apple Silicon was running ffmpeg under emulation — with an SBOM and a signed build-provenance attestation on the pushed digest. - Dependabot watches Actions, Python dependencies, and the base image. A compromised action is the shortest path into a pipeline that can publish to PyPI. - AGENTS.md at the root, the convention Codex, Cursor, and Copilot read. A project whose users are agents did not have one. Offline suite 644 green, up from 559.
1 parent 054fb19 commit c41ceaf

43 files changed

Lines changed: 906 additions & 82 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude-plugin/marketplace.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
},
77
"metadata": {
88
"description": "Give any AI agent the ability to actually watch video.",
9-
"version": "1.1.0"
9+
"version": "1.2.0"
1010
},
1111
"plugins": [
1212
{
1313
"name": "watch-skill",
14-
"source": "./adapters/claude-skill",
14+
"source": ".",
1515
"description": "Watch, index, ask, and iterate on video (THE LOOP). Persistent index, self-healing answers, and a local lessons store — Windows/Linux/macOS.",
16-
"version": "1.1.0",
16+
"version": "1.2.0",
1717
"author": {
1818
"name": "Watch Skill contributors",
1919
"url": "https://github.com/oxbshw/watch-skill"

adapters/claude-skill/.claude-plugin/plugin.json renamed to .claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
33
"name": "watch-skill",
44
"displayName": "Watch Skill",
5-
"version": "1.1.0",
5+
"version": "1.2.0",
66
"description": "Give the agent a video input via Watch Skill: watch, index, ask, and iterate (THE LOOP).",
77
"author": {
88
"name": "Watch Skill contributors",

.github/dependabot.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
version: 2
2+
updates:
3+
# Actions pinned by major tag still move underneath you; a compromised or
4+
# abandoned action is the shortest path into a release pipeline that can
5+
# publish to PyPI.
6+
- package-ecosystem: github-actions
7+
directory: "/"
8+
schedule:
9+
interval: weekly
10+
day: monday
11+
commit-message:
12+
prefix: "chore(ci)"
13+
groups:
14+
actions:
15+
patterns: ["*"]
16+
17+
- package-ecosystem: pip
18+
directory: "/"
19+
schedule:
20+
interval: weekly
21+
day: monday
22+
commit-message:
23+
prefix: "chore(deps)"
24+
# One PR per week for the routine bumps; anything that breaks an API gets
25+
# its own so the failure is readable.
26+
groups:
27+
minor-and-patch:
28+
patterns: ["*"]
29+
update-types: ["minor", "patch"]
30+
ignore:
31+
# Pinned deliberately in pyproject with a reason next to each bound.
32+
- dependency-name: rich
33+
update-types: ["version-update:semver-major"]
34+
35+
- package-ecosystem: docker
36+
directory: "/"
37+
schedule:
38+
interval: weekly
39+
day: monday
40+
commit-message:
41+
prefix: "chore(docker)"

.github/workflows/docker.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ jobs:
2929
permissions:
3030
contents: read
3131
packages: write
32+
id-token: write # OIDC identity the provenance attestation is signed with
33+
attestations: write
3234
steps:
3335
- uses: actions/checkout@v4
3436

@@ -72,13 +74,33 @@ jobs:
7274
cat doctor.json
7375
docker run --rm "${{ env.IMAGE }}:ci" --help > /dev/null
7476
77+
# arm64 matters: Apple Silicon is most of the macOS install base, and
78+
# running an amd64 image under emulation makes ffmpeg work crawl.
79+
- name: Set up QEMU for the arm64 build
80+
if: github.event_name != 'pull_request'
81+
uses: docker/setup-qemu-action@v3
82+
7583
- name: Push
7684
if: github.event_name != 'pull_request'
85+
id: push
7786
uses: docker/build-push-action@v6
7887
with:
7988
context: .
8089
push: true
90+
platforms: linux/amd64,linux/arm64
8191
tags: ${{ steps.meta.outputs.tags }}
8292
labels: ${{ steps.meta.outputs.labels }}
8393
cache-from: type=gha
8494
cache-to: type=gha,mode=max
95+
provenance: mode=max
96+
sbom: true
97+
98+
# Signs the pushed digest with the workflow's own identity, so anyone
99+
# can verify the image came from this repository and no other.
100+
- name: Attest the build provenance
101+
if: github.event_name != 'pull_request'
102+
uses: actions/attest-build-provenance@v2
103+
with:
104+
subject-name: ${{ env.IMAGE }}
105+
subject-digest: ${{ steps.push.outputs.digest }}
106+
push-to-registry: true

.github/workflows/release.yml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
uv run python - <<'EOF'
3232
import zipfile
3333
from pathlib import Path
34-
root = Path("adapters/claude-skill/skills/watch")
34+
root = Path("skills/watch")
3535
Path("dist").mkdir(exist_ok=True)
3636
with zipfile.ZipFile("dist/watch-skill.skill", "w", zipfile.ZIP_DEFLATED) as z:
3737
for f in root.rglob("*"):
@@ -70,9 +70,15 @@ jobs:
7070
with:
7171
name: dist
7272
path: dist
73-
- uses: astral-sh/setup-uv@v5
74-
# No token: PyPI verifies the workflow's OIDC identity instead.
75-
# Configure the publisher once at
73+
# No token: PyPI verifies this workflow's OIDC identity. The publisher
74+
# is configured once at
7675
# https://pypi.org/manage/project/watch-skill/settings/publishing/
76+
#
77+
# The official action rather than `uv publish` because it also signs
78+
# PEP 740 attestations, so an installer can verify a wheel was built
79+
# by this workflow in this repository and not swapped en route.
7780
- name: Publish to PyPI
78-
run: uv publish --trusted-publishing always
81+
uses: pypa/gh-action-pypi-publish@release/v1
82+
with:
83+
attestations: true
84+
print-hash: true

AGENTS.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Working on Watch Skill
2+
3+
Read this before changing anything. It is the short version of
4+
[CONTRIBUTING.md](CONTRIBUTING.md) and the rules in
5+
[docs/DECISIONS.md](docs/DECISIONS.md).
6+
7+
## What this project is
8+
9+
A local-first video layer for AI agents. It turns video into a persistent,
10+
searchable index with timestamped evidence, and closes a capture → critique →
11+
fix → proof loop over an agent's own work. Python 3.11+, MIT.
12+
13+
## Layout
14+
15+
| Path | What lives there |
16+
|---|---|
17+
| `src/watch_skill/` | The engine. All logic. |
18+
| `src/watch_skill/surfaces/` | MCP, CLI, REST. Thin wrappers only. |
19+
| `skills/` | The ten agent skills. Canonical location — the skills CLI reads it. |
20+
| `commands/` | Slash commands for the Claude Code plugin. |
21+
| `adapters/` | Framework and harness adapters. No engine logic. |
22+
| `tests/` | Mirrors the `src/` layout. |
23+
| `docs/agents/` | One page per supported agent, each with an honest status. |
24+
25+
## Commands
26+
27+
```bash
28+
uv sync --extra all # full dev environment
29+
uv run pytest -m "not network" # the offline suite — must be green
30+
uv run ruff check . # lint
31+
uv run watch-skill doctor # check the binaries the engine needs
32+
```
33+
34+
Tests marked `network` hit the real internet and are excluded from the merge
35+
gate. Do not add network calls to the offline suite.
36+
37+
## Rules that are not negotiable
38+
39+
- **The engine is agent-agnostic.** No harness-specific branching in
40+
`src/watch_skill/`. That belongs in `adapters/` or a skill.
41+
- **Surfaces stay thin.** MCP, CLI, and REST wrap the same functions. A
42+
behaviour that exists in one and not the others is a bug.
43+
- **Every bug fix ships a regression test**, and the test must fail against
44+
the old code. Verify that; do not assume it.
45+
- **Index changes are forward migrations.** Never rewrite history in the
46+
schema; add a migration.
47+
- **MCP tool names are a contract.** Renaming one breaks every configured
48+
agent. Add, don't rename.
49+
- **Privacy invariants are tested** in `tests/test_privacy.py` and listed in
50+
[SECURITY.md](SECURITY.md). The video never leaves the machine; no cookies
51+
or logins; cloud speech-to-text is opt-in. Breaking one is a security bug.
52+
- **Errors carry a `fix`.** Every raised `WatchSkillError` needs a code and a
53+
sentence telling the reader what to do. `tests/test_error_fix_audit.py`
54+
enforces it.
55+
- **Claims are checked.** Prices live in a dated `prices.json`; benchmark
56+
numbers come from a recorded run; an agent page says whether it was
57+
machine-tested or only doc-verified. Do not write a claim you have not
58+
verified, and do not upgrade a status you did not earn.
59+
60+
## Adding things
61+
62+
- **A vision provider**: an entry in `src/watch_skill/vision/registry.py`.
63+
If it speaks OpenAI's `/chat/completions`, use `_openai_compatible(...)` and
64+
write no request code. Add the model defaults to
65+
`health/vision_setup.py` and a price to `vision/prices.json` — moving that
66+
file's `as_of` date is part of the edit.
67+
- **An agent**: start from `templates/agent-adapter/`. One config block, one
68+
page in `docs/agents/`, one validation run.
69+
- **A skill**: a directory under `skills/` with a `SKILL.md`. The
70+
`description` is a trigger surface — write the phrasings a user would
71+
actually type, not a summary.
72+
73+
## Style
74+
75+
Match the file you are editing. Comments explain *why*, never *what*. If a
76+
line needs a comment to say what it does, rewrite the line.

CHANGELOG.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,65 @@
11
# Changelog
22

3+
## v1.2.0 — 2026-08-08
4+
5+
### Skills reach every agent, not just Claude Code
6+
- The ten skills moved from `adapters/claude-skill/skills/` to a top-level
7+
`skills/` directory, which is where the open skills ecosystem looks. They
8+
now install into any of its 27+ supported agents:
9+
`npx skills add oxbshw/watch-skill -g`. Buried where they were, only
10+
Claude Code could see them — the agent-facing layer that decides *when* to
11+
watch video was the least distributed part of the project.
12+
- The Claude Code plugin is rooted at the repository instead of a
13+
subdirectory, so one copy of each skill serves both ecosystems rather than
14+
a mirror that can drift. `skills.sh.json` declares the package.
15+
16+
### Sixteen vision providers, from six
17+
- Added Groq, Together AI, Fireworks, DeepSeek, xAI, Mistral, Moonshot,
18+
Z.ai, and Qwen (DashScope) — plus `custom` for any OpenAI-compatible
19+
server: vLLM, LM Studio, llama.cpp, LiteLLM, Azure OpenAI, a company
20+
gateway. Two contributors asked for the last one before it existed.
21+
- These are registry entries, not code. Every one of them speaks OpenAI's
22+
`/chat/completions`, so a single builder is generated from the table and
23+
adding a vendor touches no request logic.
24+
- `--base-url` on `setup-vision`, and a `WATCHSKILL_<PROVIDER>_BASE_URL` for
25+
each, so one entry reaches a regional endpoint, a proxy, or a self-hosted
26+
server. Passing it to a provider with its own wire format is a clear error
27+
rather than a silently ignored flag.
28+
- **`WATCHSKILL_GROQ_API_KEY` existed with no Groq provider behind it.** The
29+
setting was read, reported by `doctor`, and impossible to use.
30+
31+
### Three more agents
32+
- [Zed](docs/agents/zed.md), whose key is `context_servers` rather than
33+
`mcpServers` — a config copied from any other client here does not work.
34+
- [Roo Code](docs/agents/roo-code.md), with the project-scoped `.roo/mcp.json`
35+
a team can commit.
36+
- [Continue](docs/agents/continue.md), which reads one file per server from
37+
`.continue/mcpServers/`.
38+
39+
### Supply chain and platform
40+
- **PyPI uploads carry PEP 740 attestations.** Publishing moved from
41+
`uv publish` to the official PyPI action, which signs the distributions
42+
with this workflow's identity — an installer can verify a wheel was built
43+
here and not swapped in transit.
44+
- **The container image is multi-arch.** `linux/arm64` alongside `amd64`, so
45+
Apple Silicon and ARM servers stop running ffmpeg under emulation. The
46+
pushed digest also gets a signed build-provenance attestation, and the
47+
build emits an SBOM.
48+
- **Dependabot** watches Actions, Python dependencies, and the base image
49+
weekly. A compromised action is the shortest path into a pipeline that can
50+
publish to PyPI.
51+
- **`AGENTS.md` at the repository root** — the cross-agent convention that
52+
Codex, Cursor, Copilot, and others read. For a project whose users are
53+
agents, not having one was an odd gap.
54+
55+
### Changed
56+
- **An agent page no longer requires hand-drawn art to exist.** The test
57+
demanded an avatar for every page, so adding an agent was blocked on
58+
someone illustrating it — which contradicted the twenty-minute
59+
contribution path in CONTRIBUTING. A page without art belongs in the
60+
matrix; it joins the README gallery when the art lands. Art that *does*
61+
exist must still be shown, and no page may be orphaned from the matrix.
62+
363
## v1.1.0 — 2026-08-08
464

565
Distribution work. v1.0 was installable only by cloning the repository,

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,6 @@ in `health/doctor.py` so self-healing covers them.
9292

9393
## Releasing
9494

95-
1. Bump `version` in `pyproject.toml` and `adapters/claude-skill/**` manifests.
95+
1. Bump `version` in `pyproject.toml` and `**` manifests.
9696
2. `uv build` and check the wheel installs into a clean venv.
9797
3. Tag `vX.Y.Z`.

README.md

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,20 @@ watch-skill search "pricing decision" # search every indexed video
115115
watch-skill serve # MCP over stdio
116116
```
117117

118-
Transcription, OCR, and search can run locally without an API key. For visual Q&A, use
119-
Gemini, Anthropic, OpenAI, OpenRouter, or a local Ollama model. See
120-
[Getting started](docs/getting-started.md) for manual installation and
118+
Transcription, OCR, and search run locally and need no API key. Visual question
119+
answering uses whichever provider you already pay for — Anthropic, OpenAI, Gemini,
120+
OpenRouter, Groq, Together, Fireworks, DeepSeek, xAI, Mistral, MiniMax, Moonshot,
121+
Z.ai, or Qwen — or nothing at all with a local Ollama model. Anything else that
122+
speaks the OpenAI format (vLLM, LM Studio, llama.cpp, LiteLLM, Azure OpenAI, a
123+
company gateway) works through the `custom` provider:
124+
125+
```bash
126+
watch-skill setup-vision --provider groq # or any of the above
127+
watch-skill setup-vision --provider custom \
128+
--base-url http://127.0.0.1:8000/v1 # your own server
129+
```
130+
131+
See [Getting started](docs/getting-started.md) for manual installation and
121132
[Configuration](docs/configuration.md) for provider and privacy settings.
122133

123134
## Why use it
@@ -165,12 +176,27 @@ Native tools are also available for [LangChain/LangGraph, CrewAI, OpenAI Agents
165176
LlamaIndex, and AutoGen](docs/agents/frameworks.md); any other framework can use REST or
166177
MCP.
167178

168-
| Connection | Supported agents and frameworks |
179+
### Skills, in any agent
180+
181+
The ten skills are the agent-facing layer: they decide *when* to reach for video,
182+
so an agent uses Watch Skill without being told to. They live in a top-level
183+
`skills/` directory, which is what the open skills ecosystem reads — so they
184+
install into any of its 27+ supported agents with one command, not just Claude Code:
185+
186+
```bash
187+
npx skills add oxbshw/watch-skill -g
188+
```
189+
190+
| Connection | How it reaches the agent |
169191
|---|---|
170-
| Plugin and skills | [Claude Code](docs/agents/claude-code.md), [OpenClaw](docs/agents/openclaw.md), [Pi](docs/agents/pi.md), [Hermes-style agents](docs/agents/hermes.md) |
171-
| MCP | [Claude Desktop](docs/agents/claude-desktop.md), [Cursor](docs/agents/cursor.md), [Codex CLI](docs/agents/codex-cli.md), [Cline](docs/agents/cline.md), [Windsurf](docs/agents/windsurf.md), [Gemini CLI](docs/agents/gemini-cli.md), [VS Code](docs/agents/vscode.md), [GitHub Copilot CLI](docs/agents/github-copilot-cli.md), [Kimi Code](docs/agents/kimi-code.md), [Qwen Code](docs/agents/qwen-code.md), [OpenCode](docs/agents/opencode.md), [Goose](docs/agents/goose.md), [OpenHands](docs/agents/openhands.md), [Kilo Code](docs/agents/kilocode.md), [Qodo](docs/agents/qodo.md), [Agent Zero](docs/agents/agent-zero.md) |
172-
| Native Python tools | [LangChain/LangGraph, CrewAI, OpenAI Agents SDK, LlamaIndex, and AutoGen](docs/agents/frameworks.md) |
173-
| HTTP | Vercel AI SDK, n8n, and any client that can call REST/OpenAPI |
192+
| **Skills** | Every agent the [skills CLI](https://skills.sh) supports — Claude Code, Codex CLI, Cursor, GitHub Copilot, Gemini CLI, VS Code, and the rest — plus [OpenClaw](docs/agents/openclaw.md), [Pi](docs/agents/pi.md), and [Hermes-style agents](docs/agents/hermes.md) |
193+
| **MCP** | [Claude Desktop](docs/agents/claude-desktop.md), [Cursor](docs/agents/cursor.md), [Codex CLI](docs/agents/codex-cli.md), [Cline](docs/agents/cline.md), [Windsurf](docs/agents/windsurf.md), [Gemini CLI](docs/agents/gemini-cli.md), [VS Code](docs/agents/vscode.md), [GitHub Copilot CLI](docs/agents/github-copilot-cli.md), [Zed](docs/agents/zed.md), [Roo Code](docs/agents/roo-code.md), [Continue](docs/agents/continue.md), [Kimi Code](docs/agents/kimi-code.md), [Qwen Code](docs/agents/qwen-code.md), [OpenCode](docs/agents/opencode.md), [Goose](docs/agents/goose.md), [OpenHands](docs/agents/openhands.md), [Kilo Code](docs/agents/kilocode.md), [Qodo](docs/agents/qodo.md), [Agent Zero](docs/agents/agent-zero.md) |
194+
| **Native Python tools** | [LangChain/LangGraph, CrewAI, OpenAI Agents SDK, LlamaIndex, and AutoGen](docs/agents/frameworks.md) |
195+
| **HTTP** | Vercel AI SDK, n8n, and any client that can call REST/OpenAPI |
196+
197+
Skills and MCP complement each other: skills carry the judgement about when video
198+
is worth watching, MCP carries the 23 tools. Installing both is the full setup, and
199+
`watch-skill setup` does it.
174200

175201
The [full compatibility matrix](docs/agents/README.md) separates machine-tested,
176202
machine-configured, and documentation-verified integrations. If your agent is missing,

0 commit comments

Comments
 (0)