How the code is organised
A map of the repository, how the renderer talks to the main process, where each feature lives, and the conventions to follow.
This is the map to read before you change anything. It names the folders, shows how a request travels from a button to the disk, and points at where to read more. It describes the public repository at github.com/kwebby/cutscript, which holds the app only. The cutscript.dev website and these docs are not in it.
The top level
src/ the app: main process, preload script, renderer, shared code, design runtime
native/ Swift helpers: capture, cutout, track
resources/ files that ship with the app: ffmpeg, cursor styles, icons, skills, Design pack
scripts/ build, packaging, licence, changelog and skill-check scripts
tests/ end-to-end scripts, fixtures and the skill conformance tests
build/ icons, entitlements and installer files
docs/ only record-motion/ffmpeg-lgpl: the build scripts and notes for the bundled ffmpegOther files at the top level that you will meet: README.md, LICENSE (the GNU AGPL-3.0-only text), NOTICE (the additional permission for linking with Remotion), THIRD-PARTY-NOTICES.md, package.json, electron.vite.config.ts, electron-builder.yml, eslint.config.mjs, the TypeScript configs and CHANGELOG.md. The changelog file only points to cutscript.dev/changelog, where the release notes are published.
Inside src/
| Folder | What lives there |
|---|---|
src/main | The Electron main process. index.ts starts the app. ipc/ registers the typed handlers. services/ holds the work: projects, settings, ffmpeg, export, transcription, recording, the AI director, One AI, design, tracking, voice enhance and link download. windows/ and platform/ hold the windows, menus and operating-system details. jobs.ts runs background jobs with progress and cancellation. |
src/preload | The preload script that exposes window.api to the renderer. |
src/renderer/src | The React interface. features/ has a folder for each area (dashboard, editor, script, timeline, preview, properties, captions, export, settings, recorder, director, oneAi and more). components/ui is the shared kit. stores/ holds the zustand stores. styles/ holds the design tokens. |
src/shared | Code both processes use: the types, the IPC contract in api.ts, the defaults, the edit engine in edit.ts, the time model and the pure logic for motion, scenes, the director and One AI. |
src/design-runtime | The kit and the host that render AI-designed and Design pack graphics frame by frame. scripts/build-design-kit.mjs and scripts/build-design-host.mjs build them into resources/design-kit. |
The main process has three entry points, set in electron.vite.config.ts: the app, a worker that reads attachments for the AI director, and a worker for the tracking blur.
How a request travels
- A component calls a method on
window.api, such aswindow.api.director.estimate(...). - The preload script sends it as an IPC call named
<namespace>:<method>. - A typed handler receives it and calls a service in
src/main/services. Most handlers are registered insrc/main/ipc/index.ts. The larger areas, such as the director and One AI, register their own. - The service does the work. For long work it starts a job in
jobs.ts, which streams progress back as events.
The contract between the two sides is one file, src/shared/api.ts. It lists every method and event channel. Add a method there first, and the compiler then tells you what else needs changing.
The edit model
The transcript is never modified. An edit is a small record: which words are deleted, ignored or hidden, which words you corrected, which pauses you shortened, and the extra cuts. src/shared/edit.ts turns that record into a list of kept ranges of the source file. The preview plays the original file and skips the cut ranges. A plain export renders the kept ranges with ffmpeg. A project with motion effects is drawn frame by frame by the same scene code the preview uses, so the preview and the file match.
That is why the filler, pause and repetition finders are pure functions in edit.ts, with their tests beside them.
Where to look for a feature
| You want to change | Start in |
|---|---|
| Filler, pause and repeat detection | src/shared/edit.ts, src/shared/defaults.ts, src/renderer/src/features/ai |
| Export options and formats | src/renderer/src/features/export, src/main/services/export |
| Transcription providers and models | src/main/services/stt, src/shared/aiCapabilities.ts, src/shared/aiModelFacts.ts |
| Recording | src/main/services/recording, src/renderer/src/features/recorder, native/capture |
| Tracking blur | src/shared/tracking, src/main/services/tracking, native/track |
| Captions | src/renderer/src/features/captions, src/shared/captionFit.ts, src/shared/defaults.ts |
| The AI director and One AI | src/main/services/director, src/main/services/oneAi, src/shared/oneAi |
| Graphics and the Design pack | src/main/services/designDirector, src/shared/design, resources/design-exemplars |
| Skills | resources/director-skills, src/shared/director/skillbook |
| Release notes | scripts/changelog-notes.mjs |
| The bundled ffmpeg | docs/record-motion/ffmpeg-lgpl |
Notes in the code
The repository has no per-area design notes. Many source files open with a comment that says what the file owns and the rules it keeps, so read that comment before you change the file. The one folder under docs/ is docs/record-motion/ffmpeg-lgpl, which holds the build scripts, build notes and checksums for the bundled ffmpeg.
Conventions
- Format. Prettier with single quotes, no semicolons, a line width of 100 and no trailing commas. Two spaces, LF line endings. Run
npm run format. - Types. ESLint asks for explicit return types on functions. Run
npm run lintandnpm run typecheck. - Tests beside the code. A file
foo.tshasfoo.test.tsnext to it. Several modules say in their header that they use relative imports so Vitest can load them, and you should follow that note where you see it. - Pure logic goes in
src/sharedwhen both processes or the tests need it. - Generated files stay generated.
CHANGELOG.mdonly points to the website, and release notes are written inscripts/changelog-notes.mjs.resources/design-exemplars/index.jsoncomes fromnode scripts/check-design-guidance.mjs --write-index.resources/nativeis a build output.
Where your data lives
A running Cutscript keeps its data in ~/Library/Application Support/Cutscript. Projects are in projects/<id>/, with project.json, generated audio in assets/ and derived files in cache/. Settings are in settings.json, and API keys are in secrets.json, encrypted with the macOS keychain. Imported media is referenced where it is, not copied.
Related
Was this page helpful?
Comments
Longer questions go better in the forum.
No comments yet. Ask a question or add what you found.
Sign in with GitHub or Google to comment.
Sign in to comment