Skip to main content
Glama
netsuflow-review

netsuflow-review

Official
by NetsumaInfo
README.md
<div align="center">
  <h1>NetsuFlow Review</h1>

[![CI](https://github.com/NetsumaInfo/NetsuFlow-Review/actions/workflows/ci.yml/badge.svg)](https://github.com/NetsumaInfo/NetsuFlow-Review/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/github/license/NetsumaInfo/NetsuFlow-Review)](LICENSE)

</div>

NetsuFlow Review is a local web page where you watch the videos an AI agent made and tell it what to fix, frame by frame. The agent publishes a render through MCP; you stop on a frame, a passage or a whole shot and leave a comment with words, a drawing on the picture and reference files; the agent reads it, sees the frame with your drawing, publishes the next version and answers under each comment.

<img src="docs/images/review.png" alt="The Comment mode: the picture with a red arrow drawn on it, the film strip of the frames around the playhead, the timeline with its waveform and comment marks, and on the right the comment being written and two open comments tagged Important and Minor">

> [!NOTE]
> First milestone. It was made for renders of [NetsuFlow](https://github.com/NetsumaInfo) driven by Claude Code, and works with any agent that speaks MCP over HTTP. Everything runs on your computer: there is no account and no cloud.

## Install

You need Git, Node.js 22 or later, pnpm and FFmpeg (with FFprobe). The scripts install what is missing, download the project into `NetsuFlow-Review` in your home folder, and install its packages. At the end they offer to connect Claude Code and to add the agent skill.

Windows (PowerShell, uses winget):

```powershell
irm https://raw.githubusercontent.com/NetsumaInfo/NetsuFlow-Review/main/scripts/install.ps1 | iex
```

macOS or Linux (Homebrew, apt, dnf or pacman):

```bash
curl -fsSL https://raw.githubusercontent.com/NetsumaInfo/NetsuFlow-Review/main/scripts/install.sh | bash
```

On Linux without Homebrew, install Node.js 22 yourself first: the script stops and says so.

By hand:

```bash
git clone https://github.com/NetsumaInfo/NetsuFlow-Review.git
cd NetsuFlow-Review
pnpm install
```

## Start

```bash
pnpm start
```

The page is built and served on `http://localhost:6220`. The server listens on `127.0.0.1` and refuses any request that does not come from this computer.

| Command | What it runs |
|---|---|
| `pnpm start` | The built page and the server, one process, port 6220 |
| `pnpm phone` | The same, also on your local network, for a phone (see [On a phone](#on-a-phone)) |
| `pnpm dev` | The page with live reload on `http://localhost:1450`, and the server |

## Connect the agent

The install script offers this. By hand, for Claude Code:

```bash
claude mcp add --transport http netsuflow-review http://127.0.0.1:6220/mcp
```

Inside this folder, Claude Code already finds the server in `.mcp.json`. Any agent that speaks MCP over streamable HTTP connects to the same address. The server tells the agent how a review works when it connects; the [`netsu-review`](skills/netsu-review/SKILL.md) skill adds how to turn comments into the next version. Copy it into `~/.claude/skills/` to use it in Claude Code.

Then, from the project where the agent makes the video:

- "publish the render for review";
- "read my comments on the clip and fix them";
- "compare v3 with the reference I added, around the drop".

## How it works

```mermaid
flowchart LR
  agent[Agent] -- "publish_version" --> server[NetsuFlow Review server]
  server -- writes --> files[(reviews/name/)]
  server -- tells --> page[Page]
  you([You]) -- "comments, drawings, references" --> page
  page -- saves --> server
  agent -- "get_review, look_comment" --> server
  agent -- "settle_comments" --> server
```

A review is a folder: `review.json` (versions, comments, replies, reference videos), the versions `v1.mp4`, `v2.mp4`…, the files you attach under `refs/`, and the pictures of frames under `thumbs/`. The page follows changes to the folder, so a version the agent publishes, or its reply, shows up without reloading.

## Three ways to look at a version

| Mode | What it is for |
|---|---|
| Comment | A frame or a passage: words, a drawing, references, a cut to move |
| Shots | The version cut into shots, each with its picture; a press takes the whole shot for a comment |
| Compare | Two versions side by side or with a wipe, at the same frame, with the older version's comments placed on the newer timeline. Or a reference video next to the render |

<img src="docs/images/compare.png" alt="The Compare mode: a reference video of colour bars on the left, version 2 on the right, the bar that aligns the reference on the render, and the comments of version 2">

A **reference video** is a clip that shows what you want. Add one from the Compare mode (or the agent adds it), then align it on the render: "Starts here" puts its first frame at the playhead, and the buttons, or `,` and `;`, move it by one or ten frames. The ear button picks which video you hear.

## Being precise

| Tool | Key | What it does |
|---|---|---|
| Frames | ← → ↑ ↓ | The page shows the frame the video actually decoded, and FFmpeg gives the agent the same one: both were checked against the frame counter of a test pattern at 24 and 23.976 fps. |
| Timeline | wheel, `+`, `−`, `0` | The mouse wheel zooms it down to single frames, with a time ruler, the waveform of the sound, the cuts, each comment, your markers and the loop. Hovering shows the frame under the pointer. Its handle sets its height. |
| Film strip | `B` | The frames around the playhead side by side, with a line where a cut falls. |
| Picture zoom | `Z`, Ctrl and the wheel, or two fingers | Up to 8×, pixels kept sharp from 4×. |
| Playback | `J` `K` `L`, `S`, `R`, `G` | As in an editor (backwards included), speeds from ¼ to 2, a loop on the passage, the comment or the shot, and `G` to type a frame number or a timecode. |
| Markers | `M` | Drop them while it plays, come back with `N` and `P`, comment them later. They stay in your browser; the agent does not see them. |
| Move a cut | `X` | Take the nearest cut, go where it should fall, set it. The agent gets both frames and the gap in frames. |
| Topics and priority | `!` | Timing, colour, motion, sound, text, effect; important, normal, minor. The agent reads important comments first, and the list filters by topic. |
| Guides | `H` | Thirds, centre, safe areas, and 9:16, 4:5 and 1:1 frames with the outside dimmed. |
| Links | | Copy the link of a frame (`…/#/<review>/v<n>?f=<frame>`) or of a comment (`?c=<id>`). A timecode the agent writes in a reply is a button that goes there. |
| Save the frame | | A PNG at the video's own size. |

The layout is yours: handles size the review list, the comments panel, the comment being written, the film strip and the timeline; the panel icons of the header tuck the side panels away, and the comment being written, its topics and the drawing tools fold. It is kept in the browser, and a button puts the first layout back.

## On a phone

```bash
pnpm phone
```

The server then also listens on your local network. On the computer, the phone button at the top of the review list shows a QR code to scan from a phone on the same Wi-Fi. The link holds a secret key, kept in `reviews/.key`: it becomes a cookie on the phone and leaves the address. A phone never reaches the agent's endpoint. To change the key, delete that file and restart. The first time, Windows may ask to let Node through its firewall.

<img src="docs/images/phone.png" width="300" alt="The page on a phone: the picture with a drawn shape, the transport buttons, the timeline, and the comment being written">

On a phone, the list is a page of its own, everything is a size bigger for a finger, two fingers zoom into the picture, and the drawing tools start folded.

## The agent's tools

| Tool | What it does |
|---|---|
| `publish_version` | Hands a render over: creates the review the first time, then adds the next version. Takes the agent's shots, or finds the cuts with FFmpeg |
| `list_reviews` | Every review, with its versions and open comments |
| `get_review` | The versions, reference videos and comments (open, done or all), important ones first |
| `look_comment` | The frame of a comment with the drawing laid over it, then each reference file |
| `settle_comments` | Answers comments that were handled, and marks them done |
| `reply_comment` | Answers without marking done: a question, or why it was not done |
| `set_shots` | Fixes how a version is cut into shots |
| `add_reference_video` | Adds a reference video, and where it starts on the render |
| `align_reference` | Changes where a reference video starts |
| `compare_reference` | Shows a version and a reference at the same instants, in pairs of pictures |

Every tool can be called from a terminal, without an agent: `pnpm mcp` lists them, `pnpm mcp <tool> '<json>'` calls one.

## Shortcuts

`?` shows them all in the page. Every one of them also has a button, for a phone.

<details>
<summary>The full list</summary>

| Key | Effect |
|---|---|
| Space | Play, stop |
| `L`, `J`, `K` | Play forwards, backwards, stop; `L` or `J` again plays faster |
| `S` | Speed: ¼, ½, 1, 2 |
| `R` | Loop the passage, else the comment, else the shot |
| `V` | Mute |
| ← → | One frame (Shift: ten) |
| ↑ ↓ | Previous, next cut |
| `N`, `P` | Next, previous comment or marker |
| Home, End | Start, end of the video |
| `G` | Go to a frame or a timecode |
| `Z`, Ctrl + wheel | Zoom the picture |
| Wheel on the timeline, `+`, `−` | Zoom the timeline (Shift + wheel scrolls it) |
| `0` | The whole timeline |
| `B` | Film strip |
| `F` | Full screen |
| `H` | Guides |
| `,` and `;` | In Compare, the reference one frame earlier, later |
| `C` | Write a comment |
| `I`, `O` | Start, end of a passage |
| `X` | Move the nearest cut; `X` again sets where it falls |
| `!` | Important or not |
| `M` | Drop a marker; Shift + `M` clears them |
| `D`, `A` | Line, arrow |
| Esc | Leave the tool, then the cut, then the comment |
| Ctrl + Enter | Send the comment |

On a French keyboard `[` and `]` need AltGr, which the page ignores: comments are walked with `N` and `P`.

</details>

## Where the files are

`reviews/` in the project folder, ignored by git. Set `NETSUREVIEW_DIR` for another folder and `NETSUREVIEW_PORT` for another port.

## Limits

- The page plays what your browser can play, and nothing else.
- Cuts are found by FFmpeg's scene detection (threshold 0.3, on a copy 240 px wide); two cuts less than half a second apart count as one. An agent that knows its edit gives its shots instead.
- A phone works on the same local network only, not over the internet.
- What was tried and what was not, measured on one machine, is in [`docs/STATUS.md`](docs/STATUS.md). Among what was not: a real phone with a finger, and videos of several tens of minutes.

## Contributing

Issues and pull requests are welcome; for a large change, open an issue first. [`CONTRIBUTING.md`](CONTRIBUTING.md) explains the setup and the checks, [`AGENTS.md`](AGENTS.md) the structure and the rules of the code, [`DESIGN.md`](DESIGN.md) the words and the look of the page. Security flaws go through [`SECURITY.md`](SECURITY.md), never a public issue. Everyone follows the [Code of Conduct](CODE_OF_CONDUCT.md).

## Support

If NetsuFlow Review saves you time, you can [sponsor its author on GitHub](https://github.com/sponsors/NetsumaInfo).

## License

[MIT](LICENSE). The dependencies are under MIT, ISC, BSD, Apache-2.0, MPL-2.0 (`@resvg/resvg-js`, used unmodified) and, for the Inter typeface, the SIL Open Font License. FFmpeg is not shipped: the page calls the one installed on your computer.