Skip to content

Instantly share code, notes, and snippets.

@johnlindquist
Created February 7, 2026 17:53
Show Gist options
  • Select an option

  • Save johnlindquist/7980fe5796995112af2c7058225e024f to your computer and use it in GitHub Desktop.

Select an option

Save johnlindquist/7980fe5796995112af2c7058225e024f to your computer and use it in GitHub Desktop.

The Great Split: 197 Rust Files Under 500 Lines

TL;DR

We enforced a strict 500-line maximum on every .rs file in the Script Kit GPUI codebase — a 328,000-line Rust project — using a swarm of 25 autonomous Codex agents working in parallel.


The Numbers

Metric Value
Files over 500 lines (before) 197
Files over 500 lines (after) 0*
Total commits 8
Files changed 1,186
New files created 991
Files deleted 39
Files renamed 28
Lines added 272,380
Lines removed 250,079
Net change +22,301 lines (module boilerplate)

*A handful of subdirectory files still being cleaned up by a final worker


The Worst Offenders (Before)

File Lines
src/ai/window.rs 8,736
src/app_impl.rs 7,425
src/scripts_tests.rs 5,275
src/notes/window.rs 5,097
src/render_builtins.rs 4,678
src/main.rs 3,974
src/prompts/chat.rs 3,569
src/platform.rs 3,480
src/stories/run_button_exploration.rs 3,122
src/scriptlet_tests.rs 2,921
src/ai/providers.rs 2,914
src/protocol/message.rs 2,909
src/app_actions.rs 2,848
src/watcher.rs 2,830
src/scripts/search.rs 2,690
src/logging.rs 2,563
src/actions/builders.rs 2,524

And 180 more files between 500–2,500 lines each.


How We Did It: The Codex Swarm

Phase 1: The Split (20 parallel agents)

We decomposed the 197 oversized files into 20 scoped tasks and spawned a Codex agent for each:

Agent Scope Files Split
codex-app-impl src/app_impl* 7,425-line monolith → modules
codex-ai-window src/ai/* 8,736-line window.rs → submodules
codex-main-rs src/main.rs 3,974-line main → entry modules
codex-notes-window src/notes/* 5,097-line window → submodules
codex-render-builtins src/render_builtins* 4,678 lines → per-builtin files
codex-platform src/platform* 3,480 lines → platform modules
codex-prompts src/prompts/* chat.rs + 5 others
codex-actions-dialog src/actions/dialog* 19 dialog test files (~2K each)
codex-actions-builders src/actions/* builders.rs + non-dialog files
codex-protocol src/protocol/* message.rs + types.rs
codex-app-star src/app_*.rs 6 app_ files
codex-tests src/*_tests.rs 3 large test files → chunks
codex-stories src/stories/* story files
codex-scripts src/scripts/* search.rs + others
codex-config-theme src/config/*, src/theme/* config + theme modules
codex-designs src/designs/* design system files
codex-components src/components/* 7 component files
codex-terminal src/terminal/* 5 terminal files
codex-render-prompts src/render_prompts/* arg.rs + form.rs
codex-toplevel-misc src/*.rs 55+ remaining top-level files

Phase 2: The Fix-Up (6 parallel agents)

With 20 agents editing the same Rust codebase simultaneously, we ended up with 499 compile errors from broken imports, lost serde derives, and visibility issues. We spawned 6 more agents to fix them:

Agent Task Result
codex-fix-protocol-types Fix serde imports in protocol/ ✅ Done in ~2 min
codex-fix-actions Fix builder imports in actions/ ✅ Done
codex-fix-prompts Fix visibility in prompts/ ✅ Done
codex-fix-components Fix module paths in components/ ✅ Done
codex-fix-remaining Fix everything else (broadest scope) ✅ 499→0 errors
codex-fix-clippy-tests Fix clippy + test compilation 🔄 Running

The Error Cascade

The most interesting challenge was the error cascade from parallel agents:

  1. Agent A splits protocol/types.rs into submodules
  2. Agent B splits actions/builders.rs which imports from protocol/types
  3. Agent C splits prompts/ which imports from both
  4. All three commit independently → import paths break across module boundaries

The fix-up phase had to resolve these cross-cutting concerns — primarily:

  • 155 missing #[serde] attributes (derive macros lose scope in include!() files)
  • 42 missing Serialize/Deserialize derives
  • Visibility downgrades (types that were pub within a file become private when moved to submodules)

Split Strategy

Each agent used one of two approaches:

1. Module Directory (mod.rs + subfiles)

For files with clear logical sections:

src/platform.rs (3,480 lines)
→ src/platform/
    mod.rs          (re-exports)
    accessibility.rs (340 lines)
    window_ops.rs    (290 lines)
    display.rs       (380 lines)
    ...

2. Include Wrapper (include!() + part files)

For tightly-coupled code that can't easily separate imports:

src/app_impl.rs (7,425 lines)
→ src/app_impl.rs     (include! wrapper)
  src/app_impl/
    mod.rs
    startup.rs      (480 lines)
    handlers.rs     (450 lines)
    lifecycle.rs    (390 lines)
    ...

Lessons Learned

  1. Parallel agents + shared codebase = merge hell. The split phase went fast but the fix-up phase was essential. Budget 30% of time for cross-agent conflict resolution.

  2. Serde derives are the #1 casualty of file splits. When you include!() a file, it doesn't get its own use imports — they come from the parent. But when you make it a proper module, every file needs its own imports.

  3. The biggest agent always finishes last. codex-toplevel-misc had 55 files and took 3x longer than any other agent. Better to split into 3-4 agents from the start.

  4. File claim locks prevent duplicate work but become stale when agents die. We had to manually release claims from a killed agent to unblock others.

  5. cargo check passing ≠ cargo clippy --all-targets passing. Test targets have additional import requirements that only surface with --all-targets.


The Commit Chain

f650654 refactor: split all .rs files to be under 500 lines
37fc9d0 fix(components): repair split module imports in component renders  
53fec3f refactor(stories): split oversized story modules into submodules
ddd673f refactor(ai-window): split window.rs into focused modules
e2a47d1 refactor(render_builtins): split builtin renderers into module files
5af3a86 test(app_impl): update source-audit paths after module split
4937a03 refactor(app_impl): split ScriptListApp impl into modules
c3ef366 feat: add module docs, agent tooling, and streamlined AGENTS.md

Generated from the Script Kit GPUI codebase — a Rust (GPUI) + TypeScript (Bun) desktop application framework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment