Skip to content

[strategy] Fork maintenance strategy - decouple, contribute, minimize #157

@randomm

Description

@randomm

Strategic Analysis: Fork Maintenance

Our fork (randomm/opencode) has diverged from upstream (anomalyco/opencode) with 93 files changed (56 new, 33 modified, 4 deleted, +6,597/-1,222 lines). This issue documents findings and recommended strategy to reduce maintenance burden while preserving our key differentiators.


Our Three Differentiators

1. Non-blocking Async Task Tool (HIGH maintenance burden)

What: Tasks run asynchronously and return immediately. Parent agent continues working while tasks execute in background. Includes slot-based concurrency (max 5), check_task polling tool, and auto-wakeup on completion.

Scope:

  • tool/task.ts — 238 lines changed (+158 insertions)
  • session/index.ts — 603 lines changed (+592 insertions) ← main conflict zone
  • session/prompt.ts — 356 lines refactored
  • tool/check_task.ts — 164 lines NEW
  • session/tools.ts — 221 lines NEW (extracted from prompt.ts)
  • util/tasks.ts — 68 lines NEW

Invasiveness: HIGHLY INVASIVE — deep session lifecycle changes in session/index.ts and session/prompt.ts, exactly the files upstream actively develops.

Upstream PR viability: Medium — requires architectural buy-in. Would need backward compatibility (blocking mode as option).

2. Lightweight TUI — oclite (LOW maintenance burden)

What: Separate minimal TUI. Currently implemented in two forms:

  • Raw ANSI (cli/lite/) — 527 lines, 6 files
  • React/Ink (cli/ink/) — ~1,840 lines, 35 files

Invasiveness: 100% ADDITIVE — all new files, zero modifications to upstream code.

Can be fully decoupled as standalone thin client:

  • Infrastructure already exists: opencode serve command, SDK --attach flag
  • Replace createInProcessFetch() with real HTTP fetch → ~2-3MB client binary
  • Architecture: opencode serve --port 4096 + oclite connects via SDK over HTTP
  • Eliminates all TUI files from fork diff

Upstream PR viability: Easy — fully isolated, no conflicts.

3. rg Tool — Unified Search (LOW maintenance burden)

What: Replaces separate grep + glob tools with unified rg tool using ripgrep. Two modes: content search (default) and file listing (files_only=true).

Scope:

  • tool/rg.ts — 222 lines NEW
  • tool/rg.txt — 13 lines NEW
  • tool/registry.ts — 8 lines changed
  • Deleted: glob.ts, glob.txt, grep.ts, grep.txt

Invasiveness: LOW — clean replacement, only 8-line registry edit.

Upstream PR viability: High — clear improvement, simpler API, better performance.


Recommended Strategy: Decouple + Contribute + Minimize Fork

Step 1: Decouple oclite as standalone thin client

  • Connect to vanilla opencode serve via HTTP SDK
  • ~2-3MB binary, zero backend dependencies
  • Eliminates all 35+ TUI files from fork diff

Step 2: Contribute rg tool upstream as PR

  • Clean improvement, easy to pitch
  • Only 2 new files + 8-line registry edit
  • Eliminates 6 files from fork diff

Step 3: Keep async task tool as focused fork

  • This is the real differentiator worth maintaining
  • Reduces fork surface from 93 files to ~10-15 files
  • Use shuvcode-style automated sync for everything else
  • Only conflict zone: session/index.ts and session/prompt.ts

Net Result

Fork surface drops from 93 files to ~10-15 files. Upstream sync becomes manageable. Vanilla opencode improvements flow automatically for everything except the task system.


Alternative Strategies Considered

A: Upstream everything (eliminate fork)

  • PR all three features upstream
  • Pro: Zero maintenance burden
  • Con: Async tasks require architectural buy-in, may be rejected or delayed
  • Con: Loss of control over direction

B: Stay forked with automated sync (shuvcode approach)

  • GitHub Actions workflow monitors upstream releases
  • Auto-merge with conflict resolution rules
  • Fork-specific files tracked in manifest
  • Pro: Full control, automated 80% of syncs
  • Con: Still 93 files to maintain, conflicts in session/* files

C: Plugin-based approach

  • Async task tool as plugin
  • Pro: Zero fork needed
  • Con: Plugin hooks don't support core tool replacement or session lifecycle changes
  • Con: rg tool and TUI can't be plugins

Active Fork Ecosystem (for reference)

Fork Stars Relevance
Clouder0/overcode 24 Most similar — async agents, parallel workers, inter-agent messaging
Latitudes-Dev/shuvcode 66 Community QA layer — cherry-picks upstream PRs, automated sync
OneOfLzx/opencode-sentinel 21 Enterprise/air-gapped deployment

Key upstream PRs to watch:


Action Items

  • Decouple oclite: Replace createInProcessFetch() with HTTP SDK client
  • Test oclite connecting to opencode serve
  • Prepare rg tool upstream PR (with deprecation path for grep/glob)
  • Set up shuvcode-style automated sync for non-conflicting files
  • Document async task tool architecture for potential upstream PR
  • Evaluate Clouder0/overcode for collaboration opportunities

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions