editor
AGENTS.md7 starsChanged 4 days agoMITView on GitHub
Development guide for AI agents and human contributors working on MakeMyClip Editor — a Claude Code skill, clip CLI, MCP server and local browser UI that wrap FFmpeg for AI-driven video editing. For contribution policy, commit format, and PR process, see CONTRIBUTING.md. The MCP server (src/mcp/server.ts, started with clip mcp) exposes the timeline tools over stdio to Claude Desktop and other MCP clients, alongside the skill + CLI path.
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,843 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
The file
We split this AGENTS.md into the rules it gives an agent
10 rules. About 0 are common, 4 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 60
Prefer interface over type for object shapes.
- Distinctive: line 61
Use Zod for any boundary (MCP tool inputs, file I/O, network).
- Distinctive: line 63
No classes for stateless logic — use functions and modules.
- Distinctive: line 79
Add JSDoc only for exported public APIs (MCP tool descriptions, schema docs).
- Distinctive: line 80
Never reference tickets, PRs, or "added for X" in comments — those rot.
- Very specific: line 86
No defensive try/catch around code that can't fail.
- Very specific: line 105
All FFmpeg runs go through runFfmpeg in src/ffmpeg/run.ts.
- Very specific: line 107
Never embed user-provided strings into a filter graph without escaping via the helper in src/ffmpeg/escape.ts.
- Very specific: line 114
Run all three before committing.
- Very specific: line 123
Commit: Conventional Commits — <type>(<scope>): <description>.
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
AGENTS.md
Development guide for AI agents and human contributors working on MakeMyClip Editor — a Claude Code skill, clip CLI, MCP server and local browser UI that wrap FFmpeg for AI-driven video editing.
For contribution policy, commit format, and PR process, see CONTRIBUTING.md.
Project shape
editor/
├── src/
│ ├── tools/ # one file per tool (trim, zoom_pan, add_text, …)
│ ├── timeline/ # composition document: schema, ops/verbs, store, export compiler
│ ├── ffmpeg/ # safe FFmpeg arg builders + subprocess runner
│ ├── mcp/ # `clip mcp` server: timeline tools over stdio for MCP clients
│ ├── ui/ # `clip ui` browser editor: Hono server + Vite web app
│ ├── session/ # session.json op log of tool invocations (audit + undo)
│ ├── storage/ # revisioned JSON store with serialized, CAS-checked writes
│ ├── workspace.ts # workspace root + path confinement (non-negotiable #3)
│ ├── cli.ts # `clip` CLI entry
│ ├── cli-timeline.ts # `clip timeline …` subcommands
│ └── index.ts # library exports (package `main`)
├── tests/
├── SKILL.md # Claude Code skill: triggers + shell-out instructions
├── AGENTS.md
├── CONTRIBUTING.md
├── CLAUDE.md
└── package.jsonThe MCP server (src/mcp/server.ts, started with clip mcp) exposes the timeline tools over stdio to Claude Desktop and other MCP clients, alongside the skill + CLI path.
Stack
- Language: TypeScript (Node 24+)
- Package manager: pnpm (fast installs, strict resolution, content-addressable store; version pinned via
packageManagerfield inpackage.json) - Validation:
zod(timeline schema is shared with MakeMyClip.com) - Subprocess:
execa— args always as an array, never shell-string - FFmpeg:
ffmpeg-static(bundled);$MAKEMYCLIP_FFMPEG_PATHoverrides it, and the systemffmpegis the last fallback - MCP:
@modelcontextprotocol/sdk(stdio server) - UI:
hono+@hono/node-server(local API server), React 19 + Vite (web app insrc/ui/web/) - Build:
tsup(CLI + library bundle and.d.ts),vite build(UI) - Tests:
vitest - Lint/format:
@biomejs/biome(single Rust binary, replaces eslint + prettier)
Non-negotiables
- No shell interpolation. All
execa/spawncalls take args asstring[]. Noshell: true. Noexec(...)with concatenated strings. - The timeline document is the source of truth. Assembled edits mutate the composition (
src/timeline/,clip timeline …), and export compiles it to FFmpeg. The single-file tools (clip trim,clip zoom_pan, …) still render straight from their args; new assembly features go through the composition. - Workspace sandbox. Paths from
clip uiand MCP callers are confined to the workspace (resolveInWorkspaceinsrc/workspace.ts;$MAKEMYCLIP_WORKSPACE, default$TMPDIR/makemyclip-editor). CLI paths resolve against the current directory. No reads/writes outside the workspace without explicit user consent. - No network calls in the OSS core. Generation tools (voiceover, music, b-roll) will live behind a separate
@makemyclip/generationpackage (not built yet) and require explicit user opt-in. - MIT-compatible npm dependencies only. Don't pull in GPL/AGPL/BSL packages into the TypeScript dependency graph. The bundled FFmpeg binary is separately licensed (GPL) — that's fine because we invoke it as a subprocess, not link to it. See the README's License section for the full posture.
Code style
TypeScript
- Prefer
interfaceovertypefor object shapes;typefor unions/intersections. - Use Zod for any boundary (MCP tool inputs, file I/O, network).
- No
enum— use string-literal unions oras constmaps. - No classes for stateless logic — use functions and modules.
- Explicit return types on exported functions.
Naming
- Directories:
kebab-case(e.g.src/timeline-helpers/) - Files:
kebab-case.ts(e.g.zoom-pan.ts); in the React app, components arePascalCase.tsx(Timeline.tsx) and hooksuseCamelCase.ts(useTimeline.ts) - Functions/variables:
camelCase - Types/interfaces:
PascalCase - Boolean variables:
is*,has*,should* - Named exports only — no default exports, except in tool config files that require one (
vite.config.ts,tsup.config.ts,vitest.config.ts)
Comments
- Self-documenting code first; comments explain why, not what.
- No "this function does X" docstrings — the signature already does that.
- Add JSDoc only for exported public APIs (MCP tool descriptions, schema docs).
- Never reference tickets, PRs, or "added for X" in comments — those rot.
Errors
- Throw typed errors with actionable messages — they surface to the agent.
- Validate at boundaries (MCP input, file I/O); trust internal calls.
- No defensive
try/catcharound code that can't fail.
Tools
Each tool lives in src/tools/<name>.ts and exports:
- A Zod input schema (
FooInput) — validates arguments at the boundary - A handler function (
foo(input) -> Promise<FooResult>) — does the work, returns a typed result - The CLI wires tools into subcommands in
src/cli.ts(clip timeline …insrc/cli-timeline.ts); the UI exposes them throughsrc/ui/tool-registry.ts - The skill (
SKILL.md) instructs Claude Code to invoke them vianpx -y @makemyclip/editor <tool>
Rules:
- One tool per file.
- Zod schema is the single source of input truth.
- Handlers return a typed result —
{ path, ... }for tools that write a file (ingest.ts,inspect.ts,split.ts,undo.ts,delete-op.tsanddoctor.tsreturn other shapes) — never raw FFmpeg output. - Handlers must be idempotent given the same input + workspace state.
FFmpeg
- All FFmpeg runs go through
runFfmpeginsrc/ffmpeg/run.ts. The one exception issrc/ffmpeg/probe.ts, which callsexecawithreject: falseso it can parse stderr from a failed probe. - Arg builders live in
src/ffmpeg/args/— mostly one per tool (trim.ts,add-text.ts, …); a few composite tools build their args inline. The timeline export compiler (src/timeline/compile.ts) builds its own filter graphs. - Never embed user-provided strings into a filter graph without escaping via the helper in
src/ffmpeg/escape.ts.
Testing
pnpm testruns vitest.pnpm type-checkrunstsc --noEmitfor the core and again forsrc/ui/web/tsconfig.json.pnpm lintrunsbiome check.- Run all three before committing. CI also runs
pnpm build(tsup + the Vite UI build). - For tool handlers: write a unit test that asserts the built FFmpeg arg array, not the rendered output (deterministic, fast, no FFmpeg needed in CI).
- Integration tests against real FFmpeg live in
tests/integration/and run on CI only (they skip unlessCI=true).
Branch & commit rules
See CONTRIBUTING.md. Summary:
- Branch:
<type>/<short-kebab-description>— e.g.feat/zoom-pan-tool. Noclaude/*or other agent-prefixed branches. - Commit: Conventional Commits —
<type>(<scope>): <description>. - Types:
feat,fix,chore,docs,style,refactor,perf,test,build,ci,revert. - Scopes for this project:
tools,timeline,ffmpeg,cli,mcp,ui,schema,skill,deps,docs,ci.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

