Files
opencode/packages/opencode/BUN_SHELL_MIGRATION_PLAN.md
Dax Raad 3c6c74457d sync
2026-02-25 01:48:10 -05:00

3.6 KiB

Bun shell migration plan

Practical phased replacement of Bun $ calls.

Goal

Replace runtime Bun shell template-tag usage in packages/opencode/src with a unified Process API in util/process.ts.

Keep behavior stable while improving safety, testability, and observability.

Current baseline from audit:

  • 143 runtime command invocations across 17 files
  • 84 are git commands
  • Largest hotspots:
    • src/cli/cmd/github.ts (33)
    • src/worktree/index.ts (22)
    • src/lsp/server.ts (21)
    • src/installation/index.ts (20)
    • src/snapshot/index.ts (18)

Decisions

  • Extend src/util/process.ts (do not create a separate exec module).
  • Proceed with phased migration for both git and non-git paths.
  • Keep plugin $ compatibility in 1.x and remove in 2.0.

Non-goals

  • Do not remove plugin $ compatibility in this effort.
  • Do not redesign command semantics beyond what is needed to preserve behavior.

Constraints

  • Keep migration phased, not big-bang.
  • Minimize behavioral drift.
  • Keep these explicit shell-only exceptions:
    • src/session/prompt.ts raw command execution
    • worktree start scripts in src/worktree/index.ts

Process API proposal (src/util/process.ts)

Add higher-level wrappers on top of current spawn support.

Core methods:

  • Process.run(cmd, opts)
  • Process.text(cmd, opts)
  • Process.lines(cmd, opts)
  • Process.status(cmd, opts)
  • Process.shell(command, opts) for intentional shell execution

Git helpers:

  • Process.git(args, opts)
  • Process.gitText(args, opts)

Shared options:

  • cwd, env, stdin, stdout, stderr, abort, timeout, kill
  • allowFailure / non-throw mode
  • optional redaction + trace metadata

Standard result shape:

  • code, stdout, stderr, duration_ms, cmd
  • helpers like text() and arrayBuffer() where useful

Phased rollout

Phase 0: Foundation

  • Implement Process wrappers in src/util/process.ts.
  • Refactor src/util/git.ts to use Process only.
  • Add tests for exit handling, timeout, abort, and output capture.

Phase 1: High-impact hotspots

Migrate these first:

  • src/cli/cmd/github.ts
  • src/worktree/index.ts
  • src/lsp/server.ts
  • src/installation/index.ts
  • src/snapshot/index.ts

Within each file, migrate git paths first where applicable.

Phase 2: Remaining git-heavy files

Migrate git-centric call sites to Process.git* helpers:

  • src/file/index.ts
  • src/project/vcs.ts
  • src/file/watcher.ts
  • src/storage/storage.ts
  • src/cli/cmd/pr.ts

Phase 3: Remaining non-git files

Migrate residual non-git usages:

  • src/cli/cmd/tui/util/clipboard.ts
  • src/util/archive.ts
  • src/file/ripgrep.ts
  • src/tool/bash.ts
  • src/cli/cmd/uninstall.ts

Phase 4: Stabilize

  • Remove dead wrappers and one-off patterns.
  • Keep plugin $ compatibility isolated and documented as temporary.
  • Create linked 2.0 task for plugin $ removal.

Validation strategy

  • Unit tests for new Process methods and options.
  • Integration tests on hotspot modules.
  • Smoke tests for install, snapshot, worktree, and GitHub flows.
  • Regression checks for output parsing behavior.

Risk mitigation

  • File-by-file PRs with small diffs.
  • Preserve behavior first, simplify second.
  • Keep shell-only exceptions explicit and documented.
  • Add consistent error shaping and logging at Process layer.

Definition of done

  • Runtime Bun $ usage in packages/opencode/src is removed except:
    • approved shell-only exceptions
    • temporary plugin compatibility path (1.x)
  • Git paths use Process.git* consistently.
  • CI and targeted smoke tests pass.
  • 2.0 issue exists for plugin $ removal.