OpenCut/AGENTS.md

7.7 KiB
Raw Blame History

AGENTS.md

Overview

Privacy-first video editor, with a focus on simplicity and ease of use.

Lib vs Utils

  • lib/ - domain logic (specific to this app)
  • utils/ - small helper utils (generic, could be copy-pasted into any other app)

Core Editor System

The editor uses a singleton EditorCore that manages all editor state through specialized managers.

Architecture

EditorCore (singleton)
├── playback: PlaybackManager
├── timeline: TimelineManager
├── scene: SceneManager
├── project: ProjectManager
├── media: MediaManager
└── renderer: RendererManager

When to Use What

In React Components

Always use the useEditor() hook:

import { useEditor } from '@/hooks/use-editor';

function MyComponent() {
  const editor = useEditor();
  const tracks = editor.timeline.getTracks();

  // Call methods
  editor.timeline.addTrack({ type: 'media' });

  // Display data (auto re-renders on changes)
  return <div>{tracks.length} tracks</div>;
}

The hook:

  • Returns the singleton instance
  • Subscribes to all manager changes
  • Automatically re-renders when state changes

Outside React Components

Use EditorCore.getInstance() directly:

// In utilities, event handlers, or non-React code
import { EditorCore } from "@/core";

const editor = EditorCore.getInstance();
await editor.export({ format: "mp4", quality: "high" });

Actions System

Actions are the trigger layer for user-initiated operations. The single source of truth is @/lib/actions/definitions.ts.

To add a new action:

  1. Add it to ACTIONS in @/lib/actions/definitions.ts:
export const ACTIONS = {
  "my-action": {
    description: "What the action does",
    category: "editing",
    defaultShortcuts: ["ctrl+m"],
  },
  // ...
};
  1. Add handler in @/hooks/use-editor-actions.ts:
useActionHandler(
  "my-action",
  () => {
    // implementation
  },
  undefined,
);

In components, use invokeAction() for user-triggered operations:

import { invokeAction } from '@/lib/actions';

// Good - uses action system
const handleSplit = () => invokeAction("split-selected");

// Avoid - bypasses UX layer (toasts, validation feedback)
const handleSplit = () => editor.timeline.splitElements({ ... });

Direct editor.xxx() calls are for internal use (commands, tests, complex multi-step operations).

Commands System

Commands handle undo/redo. They live in @/lib/commands/ organized by domain (timeline, media, scene).

Each command extends Command from @/lib/commands/base-command and implements:

  • execute() - saves current state, then does the mutation
  • undo() - restores the saved state

Actions and commands work together: actions are "what triggered this", commands are "how to do it (and undo it)".

Frontend Agent Guide (React + Clean UI)

This repository uses test-first development and clean UI/code principles. AI agents must follow these rules when planning, coding, and refactoring.


1) Core Principles

Test-first is mandatory

Follow Red → Green → Refactor where practical:

  1. Red: Write a failing test that captures the behavior.
  2. Green: Implement the simplest code to pass.
  3. Refactor: Improve structure/readability with tests green.

UI work that is purely presentational may start with a minimal component and then tests, but behavior changes must be test-first.

Clean code and clean UI always

  • Prefer clarity over cleverness.
  • Use small components, meaningful names, single responsibility.
  • Keep UI structure simple; avoid deeply nested layouts.
  • Avoid over-engineering; introduce abstractions only when pressure appears.

Minimal scope

  • Implement only whats needed for the current task/tests.
  • No premature “future-proofing.”

Never use any

  • Do not use any as a type.
  • Prefer precise types or generics.

2) Workflow Rules (How the agent works)

Before coding

  • Identify the smallest behavior to add.
  • Decide where it belongs (component, hook, util, store).
  • Write/adjust tests first for behavior changes.

While coding

  • Keep changes small and incremental.
  • Run tests frequently and keep them green.

After coding

  • Refactor for readability and structure.
  • Ensure linting/formatting pass.
  • Update docs only if behavior/usage changed.

3) Project Architecture Expectations (React)

Component structure

  • UI components: presentational, no side effects.
  • Feature components: orchestrate UI + hooks/state.
  • Hooks: encapsulate shared logic.
  • Utilities: pure functions.

Dependency direction

  • Features can use shared UI/components/utils.
  • Shared UI must not depend on feature-specific logic.

State

  • Prefer local state where possible.
  • Use a shared store only when state must be shared across major areas.

4) Testing Strategy (React)

Preferred test types

  1. Unit tests: pure utils, hooks (default).
  2. Component tests: React Testing Library for behavior.
  3. E2E tests: only for high-level flows.

What to test

  • Behavior and user interactions, not implementation details.
  • Edge cases and failure paths.

Testing rules

  • Every new behavior must include tests.
  • Tests must be deterministic.
  • Avoid snapshot tests for logic-heavy components.

5) Clean Code Rules (Non-negotiable)

Naming

  • Use intention-revealing names.
  • Avoid ambiguous abbreviations.

Functions & components

  • Keep functions small.
  • Keep components focused.
  • Avoid prop drilling if a context or store is more appropriate.

Error handling

  • Fail fast; show user-friendly messages where needed.
  • No silent failures.

Comments

  • Use comments sparingly, only for why, not what.

Formatting

  • Follow repo lint/format rules.
  • No unused variables or dead code.

6) React Conventions

Props & types

  • Use typed props and shared types in types/ or local types.ts.
  • Avoid widening types; keep them as narrow as possible.

Accessibility

  • Use semantic HTML.
  • Ensure keyboard navigability for interactive elements.

Styling

  • Follow repo styling approach consistently.
  • Keep styles co-located with components when possible.

7) Implementation Guidelines

When adding new UI behavior

  1. Write a test describing the interaction.
  2. Implement the smallest change to pass.
  3. Refactor for clarity and reusability.

When fixing a bug

  1. Add a failing test.
  2. Fix with minimal change.
  3. Refactor if needed.

8) Agent Output Expectations

When producing changes, the agent should:

  • Include tests with each behavior change.
  • Keep patches focused and minimal.
  • Summarize what changed and why.

9) Quality Gate Checklist (must pass)

  • All tests pass (unit, component, e2e as applicable)
  • Lint/format checks pass
  • No flaky or time-dependent tests
  • No new unused exports or dead code
  • Accessibility reviewed for interactive changes

10) Default Commands (adjust if repo differs)

Prefer these commands if they exist:

  • npm test / pnpm test
  • npm run test:watch
  • npm run test:e2e
  • npm run lint
  • npm run format

Follow package.json scripts if different.


11) Anti-Patterns to Avoid

  • Writing behavior before tests (unless purely presentational).
  • Mixing unrelated refactors with feature work.
  • Over-mocking your own code.
  • Snapshot tests for logic-heavy UI.
  • Large shared “utils” dumping grounds.

12) When uncertain

  • Choose the simplest interpretation.
  • Write tests that document the behavior.
  • Keep changes minimal and reversible.

13) Commit message

  • Follow commit message convention standard