I wrote this post with Claude Code and posted it myself. The project was built with Claude Code too.

I play in an adult rec basketball league. Nobody coaches us and nobody watches film. What we do have is a lot of phone video that nobody opens again.

Claude Code can look at images, so I tried giving it frames from my own shooting drill and asking what it saw. On one session it pointed out that my set shots went 9 of 11, my jump shots 7 of 19, and the 8 jump shots in the last ten minutes all missed. I hadn't noticed that at all.

The annoying part was everything around the review: pulling frames, cutting clips, making something my teammates would actually open on a phone, adding audio so they don't have to read. So I wrote a CLI for that part and called it sports-video-coach (MIT).

A real run on my own shooting drill: video in, the agent's film review, the coaching page out

Video goes in, you get a coaching page with clips and narration, and a video with freeze frames, rings and subtitles.

The CLI doesn't call any model

The agent is already sitting in my terminal, so I didn't want the tool to need its own API key. The CLI does ffmpeg, rendering and bookkeeping. When it needs someone to watch or write, it stops and hands over to the agent.

It also worked with Codex.

How the handover works

You tell your agent to run it on a video:

$ sports-video-coach run drill.mp4 --sport basketball frames: 4 sheets (0.5 s per tile) in .../run/frames [run] waiting for the agent: review ... # exit 3 

Exit code 3 means "your turn". The agent opens the contact sheets, writes review.json (the guide is sports-video-coach guide review), and runs the same command again. Exit 1 means a step failed and names its log, 0 means done.

I've had better results giving the agent a file path and an exit code than a long instruction.

Rejecting thin reviews

I spent a while rewording the guides when the reviews came back thin. What fixed it was a check. If the review is too short, the run refuses to build a page and says why:

review.json: needs a `moments` list with at least 3 entries 

The agent fixes that and goes again. It can still misread a play, but a review with fewer than three moments never becomes a page.

A rerun skips the steps that are already done. If I go back and edit the review, the next run tells me which later steps are now out of date. I either redo them or keep them with --accept.

What's still rough

The review is only as good as what the agent can see in frame sheets, and it can be wrong.

Basketball is the sport I built it for. It has player tracking and pulls the league box score, but tracking needs a GPU. Any other sport goes through generic: no tracking, just the agent looking at frame sheets. You can write a plugin for your sport with sports-video-coach new-plugin <name>.

Try it

The demo page shows the output with nothing to install. It's a synthetic drill, not my footage.

To build every output locally (about a minute, needs ffmpeg, no agent):

uv tool install git+https://github.com/mariusDing/sports-video-coach sports-video-coach demo 

In Claude Code: /plugin marketplace add mariusDing/sports-video-coach.

Repo: https://github.com/mariusDing/sports-video-coach

I mostly use it for basketball. If you play something else, I'd like to hear what it gets wrong.