From 7bf0984698e43b9aa2dd879f65951318ed410390 Mon Sep 17 00:00:00 2001
From: Maze <167211895+mazeincoding@users.noreply.github.com>
Date: Sat, 31 Jan 2026 00:20:04 +0100
Subject: codebase overhaul (#697)
---
AGENTS.md | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 121 insertions(+)
create mode 100644 AGENTS.md
(limited to 'AGENTS.md')
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 00000000..8ebac930
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,121 @@
+# 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:**
+
+```typescript
+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
{tracks.length} tracks
;
+}
+```
+
+The hook:
+
+- Returns the singleton instance
+- Subscribes to all manager changes
+- Automatically re-renders when state changes
+
+#### Outside React Components
+
+**Use `EditorCore.getInstance()` directly:**
+
+```typescript
+// 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`:
+
+```typescript
+export const ACTIONS = {
+ "my-action": {
+ description: "What the action does",
+ category: "editing",
+ defaultShortcuts: ["ctrl+m"],
+ },
+ // ...
+};
+```
+
+2. Add handler in `@/hooks/use-editor-actions.ts`:
+
+```typescript
+useActionHandler(
+ "my-action",
+ () => {
+ // implementation
+ },
+ undefined,
+);
+```
+
+**In components, use `invokeAction()` for user-triggered operations:**
+
+```typescript
+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)".
--
cgit v1.3.1