standardnguyen/rolandcode

OpenCode with all telemetry removed. Clean builds, no phone-home.

TypeScript

106

9,885 commits

updated May 23, 2026

See the code

README

Rolandcode

Status: maintenance mode (2026-05-22). This fork is pinned to upstream v1.4.6 and is not getting active syncs. The correction further down is most of the reason: of the endpoints originally cited, only two (models.dev startup fetch, app.opencode.ai web-UI fallback proxy) are actually default-on in upstream's CLI. That's a thin enough strip surface that maintaining a parallel TypeScript codebase across upstream's restructures isn't justified by the threat-model delta. As of v1.4.14 upstream consolidated packages/server + packages/util into packages/shared, which would break 84 of this fork's imports on its own; the v1.4 → v1.15 path past that compounds the cost further.

If you want strip-equivalent protection on a newer upstream: run upstream opencode and either (a) set OPENCODE_MODELS_URL to a local snapshot, or (b) blackhole models.dev and app.opencode.ai at your DNS / firewall layer. That's the no-fork equivalent of what this codebase does mechanically, and it works against future endpoints the same way.

The existing v1.4.6 binary still works and isn't being deprecated. Security-relevant fixes from upstream can be cherry-picked manually into a v1.4.6 patch line if needed — open an issue.

Personal context for anyone wondering: most of my AI-coding work runs through Claude Code now. Rolandcode exists for the local-tier sovereignty case (a local LLM on hardware I control, no calls leaving the network), and at that scope v1.4.6 is plenty — it's already a capable TUI against a local llama.cpp endpoint. I don't need it to keep up with upstream's frontier features, because the frontier work happens through API on a different surface. So this fork has stopped being a tracking effort and become a frozen artifact, which is the honest version of what it always was.


A fork of OpenCode that bakes the model catalog into the binary at build time, removes the web-UI fallback proxy, and strips references to the vendor's hosted sharing/search/proxy endpoints from the source tree.

Most of what upstream calls out to is opt-in (session sharing, GitHub integration, the Zen hosted provider) or gated behind a permission prompt (Exa web search) — setting the right config does the job for those. Rolandcode removes the code paths anyway, belt-and-suspenders, and runs scripts/verify-clean.sh on every build so new references can't silently reappear on a sync.

The name is from Browning's Childe Roland to the Dark Tower Came.

Correction (2026-04-17): An earlier version of this README claimed OpenCode "silently transmits data" via PostHog, Honeycomb, and a list of other endpoints. That was overstated. After this r/LocalLLaMA comment from u/Spotty_Weldah — the author of the original source-code audit, who walked back their own framing after going deeper — I went back through the source myself: PostHog lives in a GitHub Actions download-stats cron, Honeycomb lives in the cloud-console Lambda, and most of the remaining endpoints are opt-in or permission-gated in upstream. The genuinely default-on, in-CLI calls are the models.dev startup fetch and the app.opencode.ai web-UI fallback proxy — those are the real reason the fork exists. Sorry for the overclaim, and thanks to Spotty_Weldah for the correction.


What's stripped, and what it actually does in upstream

EndpointUpstream behaviorCategory
models.devFetched on startup to populate the model catalog. Redirectable via OPENCODE_MODELS_URL.Default-on — baked from snapshot at build time instead
app.opencode.aiFallback proxy in the web-UI route (src/server/ui/index.ts) when embedded UI assets are absentDefault-on for web-UI users — proxy code removed
opncd.ai / api.opencode.aiSession sharing. Only fires after /share, share: auto in config, or OPENCODE_AUTO_SHARE=1Opt-in upstream; code path removed
opencode.ai/zen/v1Hosted provider ("Zen"/"Go"). Only if the user signs up at opencode.ai/zen and configures the providerOpt-in upstream; code path removed
mcp.exa.aiWeb search. Invoked by the websearch tool after the user approves a permission promptPermission-gated upstream; code path removed
us.i.posthog.comDownload-stats cron in script/stats.ts + .github/workflows/stats.yml. Not built into the CLI.Not in upstream CLI; source kept clean as a guard
api.honeycomb.ioCloud-console Lambda log processor in packages/console/. Not built into the CLI.Not in upstream CLI; source kept clean as a guard

At this point, those first two rows are the real reasons the fork exists. That and inertia. The rest is defense-in-depth — config drift, a future regression, or a silent upstream change can't put them back.

Installation

Download a binary from the releases page, or run with Docker:

docker run --rm -it -v "$PWD:/workspace" -w /workspace ghcr.io/standardnguyen/rolandcode

Building from source

git clone https://github.com/standardnguyen/rolandcode.git
cd rolandcode
bun install

# Download a model catalog snapshot
curl -fsSL -o models-api.json https://models.dev/api.json

# Build
MODELS_DEV_API_JSON=$PWD/models-api.json bun run --cwd packages/opencode build --single

The binary is at packages/opencode/dist/opencode-linux-x64/bin/rolandcode (or the equivalent for your platform).

Building from a fresh Debian container

If you're starting from a bare Debian 12 install (container, VM, or cloud instance):

# Prerequisites
apt-get update && apt-get install -y git curl unzip

# Install Bun
curl -fsSL https://bun.sh/install | bash
source ~/.bashrc

# Build from source
git clone https://github.com/standardnguyen/rolandcode.git
cd rolandcode
bun install
curl -fsSL -o models-api.json https://models.dev/api.json
MODELS_DEV_API_JSON=$PWD/models-api.json bun run --cwd packages/opencode build --single

# Verify it's clean
bash scripts/verify-clean.sh

# Run it
./packages/opencode/dist/opencode-linux-x64/bin/rolandcode

Or build with Docker (no Bun required):

git clone https://github.com/standardnguyen/rolandcode.git
cd rolandcode
docker build -t rolandcode .
docker run --rm -it -v "$PWD:/workspace" -w /workspace rolandcode

Verification

Every build can be verified clean:

bash scripts/verify-clean.sh

This greps the entire source tree for the known domains and SDK packages. If any reference remains, the build fails. Mechanical, not clever — but it catches regressions on upstream syncs.

How it works

Rolandcode maintains a small patch set on top of upstream. Each strip commit targets one concern:

  • strip-models-dev — runtime model-list fetch; replaced with a build-time snapshot
  • strip-app-proxyapp.opencode.ai web-UI fallback proxy
  • strip-share-sync — automatic session sharing
  • strip-opencode-apiapi.opencode.ai / opncd.ai endpoints
  • strip-zen-gateway — Zen hosted-provider routing
  • strip-examcp.exa.ai web search
  • strip-posthog — removes script/stats.ts references so the domain can't drift into the CLI
  • strip-honeycomb — same for packages/console Honeycomb references

Small, isolated commits rebase cleanly when upstream moves.

Testing

# Full suite (runs permission tests in Docker when running as root)
bash scripts/test.sh

# Just the main suite
cd packages/opencode && bun test --timeout 30000

# Just the permission tests (must be non-root, or use Docker)
docker run --rm -v $(pwd):/app:ro -w /app/packages/opencode -u 1000:1000 --tmpfs /tmp:exec oven/bun:1.3.10 \
  bun test test/tool/write.test.ts test/config/tui.test.ts --timeout 30000

Known test issues

TestStatusWhy
session.llm.stream (2 of 10)FlakyMock HTTP server state leaks between parallel tests. Passes 10/10 when run in isolation (bun test test/session/llm.test.ts). Upstream test isolation bug — not a code defect.
tool.write > throws error when OS denies write accessFails as rootRoot bypasses chmod 0o444. Passes in Docker as non-root. scripts/test.sh handles this automatically.
tui config > continues loading when legacy source cannot be strippedFails as rootSame root-vs-chmod issue. Passes in Docker as non-root.
fsmonitor (2 tests)SkippedWindows-only (process.platform === "win32").
worktree-remove (1 test)SkippedWindows-only.
unicode filenames modification and restoreSkippedUpstream explicitly skipped — known bug they haven't fixed.

Upstream

This is a fork of anomalyco/opencode (MIT license). All original code is theirs. The full upstream commit history is preserved — you can see exactly what was changed and why.

OpenCode is a capable AI coding agent with a great TUI, LSP support, and multi-provider flexibility. I use it because it's good software. The strips exist because I'd rather not keep OPENCODE_MODELS_URL and a careful config review in my head on every invocation.

License

MIT — same as upstream. See LICENSE.

Contributors

(top 30 of 450)

thdxr

1,992 commits

adamdotdevin

1,859 commits

rekram1-node

1,117 commits

actions-user

981 commits

standardnguyen/rolandcode

OpenCode with all telemetry removed. Clean builds, no phone-home.

TypeScript

106

9,885 commits

updated May 23, 2026

See the code

README

Rolandcode

Status: maintenance mode (2026-05-22). This fork is pinned to upstream v1.4.6 and is not getting active syncs. The correction further down is most of the reason: of the endpoints originally cited, only two (models.dev startup fetch, app.opencode.ai web-UI fallback proxy) are actually default-on in upstream's CLI. That's a thin enough strip surface that maintaining a parallel TypeScript codebase across upstream's restructures isn't justified by the threat-model delta. As of v1.4.14 upstream consolidated packages/server + packages/util into packages/shared, which would break 84 of this fork's imports on its own; the v1.4 → v1.15 path past that compounds the cost further.

If you want strip-equivalent protection on a newer upstream: run upstream opencode and either (a) set OPENCODE_MODELS_URL to a local snapshot, or (b) blackhole models.dev and app.opencode.ai at your DNS / firewall layer. That's the no-fork equivalent of what this codebase does mechanically, and it works against future endpoints the same way.

The existing v1.4.6 binary still works and isn't being deprecated. Security-relevant fixes from upstream can be cherry-picked manually into a v1.4.6 patch line if needed — open an issue.

Personal context for anyone wondering: most of my AI-coding work runs through Claude Code now. Rolandcode exists for the local-tier sovereignty case (a local LLM on hardware I control, no calls leaving the network), and at that scope v1.4.6 is plenty — it's already a capable TUI against a local llama.cpp endpoint. I don't need it to keep up with upstream's frontier features, because the frontier work happens through API on a different surface. So this fork has stopped being a tracking effort and become a frozen artifact, which is the honest version of what it always was.


A fork of OpenCode that bakes the model catalog into the binary at build time, removes the web-UI fallback proxy, and strips references to the vendor's hosted sharing/search/proxy endpoints from the source tree.

Most of what upstream calls out to is opt-in (session sharing, GitHub integration, the Zen hosted provider) or gated behind a permission prompt (Exa web search) — setting the right config does the job for those. Rolandcode removes the code paths anyway, belt-and-suspenders, and runs scripts/verify-clean.sh on every build so new references can't silently reappear on a sync.

The name is from Browning's Childe Roland to the Dark Tower Came.

Correction (2026-04-17): An earlier version of this README claimed OpenCode "silently transmits data" via PostHog, Honeycomb, and a list of other endpoints. That was overstated. After this r/LocalLLaMA comment from u/Spotty_Weldah — the author of the original source-code audit, who walked back their own framing after going deeper — I went back through the source myself: PostHog lives in a GitHub Actions download-stats cron, Honeycomb lives in the cloud-console Lambda, and most of the remaining endpoints are opt-in or permission-gated in upstream. The genuinely default-on, in-CLI calls are the models.dev startup fetch and the app.opencode.ai web-UI fallback proxy — those are the real reason the fork exists. Sorry for the overclaim, and thanks to Spotty_Weldah for the correction.


What's stripped, and what it actually does in upstream

EndpointUpstream behaviorCategory
models.devFetched on startup to populate the model catalog. Redirectable via OPENCODE_MODELS_URL.Default-on — baked from snapshot at build time instead
app.opencode.aiFallback proxy in the web-UI route (src/server/ui/index.ts) when embedded UI assets are absentDefault-on for web-UI users — proxy code removed
opncd.ai / api.opencode.aiSession sharing. Only fires after /share, share: auto in config, or OPENCODE_AUTO_SHARE=1Opt-in upstream; code path removed
opencode.ai/zen/v1Hosted provider ("Zen"/"Go"). Only if the user signs up at opencode.ai/zen and configures the providerOpt-in upstream; code path removed
mcp.exa.aiWeb search. Invoked by the websearch tool after the user approves a permission promptPermission-gated upstream; code path removed
us.i.posthog.comDownload-stats cron in script/stats.ts + .github/workflows/stats.yml. Not built into the CLI.Not in upstream CLI; source kept clean as a guard
api.honeycomb.ioCloud-console Lambda log processor in packages/console/. Not built into the CLI.Not in upstream CLI; source kept clean as a guard

At this point, those first two rows are the real reasons the fork exists. That and inertia. The rest is defense-in-depth — config drift, a future regression, or a silent upstream change can't put them back.

Installation

Download a binary from the releases page, or run with Docker:

docker run --rm -it -v "$PWD:/workspace" -w /workspace ghcr.io/standardnguyen/rolandcode

Building from source

git clone https://github.com/standardnguyen/rolandcode.git
cd rolandcode
bun install

# Download a model catalog snapshot
curl -fsSL -o models-api.json https://models.dev/api.json

# Build
MODELS_DEV_API_JSON=$PWD/models-api.json bun run --cwd packages/opencode build --single

The binary is at packages/opencode/dist/opencode-linux-x64/bin/rolandcode (or the equivalent for your platform).

Building from a fresh Debian container

If you're starting from a bare Debian 12 install (container, VM, or cloud instance):

# Prerequisites
apt-get update && apt-get install -y git curl unzip

# Install Bun
curl -fsSL https://bun.sh/install | bash
source ~/.bashrc

# Build from source
git clone https://github.com/standardnguyen/rolandcode.git
cd rolandcode
bun install
curl -fsSL -o models-api.json https://models.dev/api.json
MODELS_DEV_API_JSON=$PWD/models-api.json bun run --cwd packages/opencode build --single

# Verify it's clean
bash scripts/verify-clean.sh

# Run it
./packages/opencode/dist/opencode-linux-x64/bin/rolandcode

Or build with Docker (no Bun required):

git clone https://github.com/standardnguyen/rolandcode.git
cd rolandcode
docker build -t rolandcode .
docker run --rm -it -v "$PWD:/workspace" -w /workspace rolandcode

Verification

Every build can be verified clean:

bash scripts/verify-clean.sh

This greps the entire source tree for the known domains and SDK packages. If any reference remains, the build fails. Mechanical, not clever — but it catches regressions on upstream syncs.

How it works

Rolandcode maintains a small patch set on top of upstream. Each strip commit targets one concern:

  • strip-models-dev — runtime model-list fetch; replaced with a build-time snapshot
  • strip-app-proxyapp.opencode.ai web-UI fallback proxy
  • strip-share-sync — automatic session sharing
  • strip-opencode-apiapi.opencode.ai / opncd.ai endpoints
  • strip-zen-gateway — Zen hosted-provider routing
  • strip-examcp.exa.ai web search
  • strip-posthog — removes script/stats.ts references so the domain can't drift into the CLI
  • strip-honeycomb — same for packages/console Honeycomb references

Small, isolated commits rebase cleanly when upstream moves.

Testing

# Full suite (runs permission tests in Docker when running as root)
bash scripts/test.sh

# Just the main suite
cd packages/opencode && bun test --timeout 30000

# Just the permission tests (must be non-root, or use Docker)
docker run --rm -v $(pwd):/app:ro -w /app/packages/opencode -u 1000:1000 --tmpfs /tmp:exec oven/bun:1.3.10 \
  bun test test/tool/write.test.ts test/config/tui.test.ts --timeout 30000

Known test issues

TestStatusWhy
session.llm.stream (2 of 10)FlakyMock HTTP server state leaks between parallel tests. Passes 10/10 when run in isolation (bun test test/session/llm.test.ts). Upstream test isolation bug — not a code defect.
tool.write > throws error when OS denies write accessFails as rootRoot bypasses chmod 0o444. Passes in Docker as non-root. scripts/test.sh handles this automatically.
tui config > continues loading when legacy source cannot be strippedFails as rootSame root-vs-chmod issue. Passes in Docker as non-root.
fsmonitor (2 tests)SkippedWindows-only (process.platform === "win32").
worktree-remove (1 test)SkippedWindows-only.
unicode filenames modification and restoreSkippedUpstream explicitly skipped — known bug they haven't fixed.

Upstream

This is a fork of anomalyco/opencode (MIT license). All original code is theirs. The full upstream commit history is preserved — you can see exactly what was changed and why.

OpenCode is a capable AI coding agent with a great TUI, LSP support, and multi-provider flexibility. I use it because it's good software. The strips exist because I'd rather not keep OPENCODE_MODELS_URL and a careful config review in my head on every invocation.

License

MIT — same as upstream. See LICENSE.

Contributors

(top 30 of 450)

thdxr

1,992 commits

adamdotdevin

1,859 commits

rekram1-node

1,117 commits

actions-user

981 commits

Languages

TypeScript

57.4%

MDX

38.3%

CSS

3.0%