Every change to a file that exists upstream at the pinned commit is listed
here. New files under packages/android, script/android and docs/android
are not upstream modifications and are not listed.
- Reason: add an Android build target so the unmodified server can be
compiled with
bun build --compile. - Why new-file-only was impossible: the target list, target selection and compile defines are defined exclusively in this file; there is no configuration hook.
- Behavior before:
--target=flag did not exist; targets were either the full cross-platform matrix or the host platform via--single; noandroidABI;OPENCODE_LIBCwasglibc/muslonly. - Behavior after:
- new
--target=<os>-<arch>[-<abi>]flag filtersallTargets; linux-arm64-androidandlinux-x64-androidtargets added;OPENCODE_LIBCis'bionic'for android targets, and theprocess.env.OPENTUI_LIBCdefine is skipped for android (no OpenTUI Android shared library exists);- generated
package.jsonusesos: ["android"]and omitslibcfor android; - exits with an error when a
--target=value matches nothing.
- new
- Reason: on Android there is no
@ff-labs/fff-bin-*package, soFileFinder.isAvailable()throws during capability detection instead of returningfalse. - Why new-file-only was impossible: the capability check is inside the fff
implementation itself, selected through the
#fffimport condition. - Behavior before:
available()propagated the native lookup error. - Behavior after:
available()returnsfalseon unsupported platforms; search transparently falls back to the ripgrep layer (filesystem/search.tsalready selectsripgrepLayerwhen fff is unavailable).
- Reason: on
process.platform === "android"the backend selector had no branch, so the watcher service logged an error and disabled itself even if a binding were available. - Why new-file-only was impossible: backend choice is a local function in this file.
- Behavior before:
getBackend()returnedundefinedon Android. - Behavior after: Android maps to the
inotifybackend (same mechanism as Linux). If the native binding is missing the service still degrades gracefully; this patch only removes the platform gap.
- Reason: Bun on Android can return
undefinedentries fromreaddir(..., { withFileTypes: true })for directories it cannot stat, which crashedreadDirectoryEntrieswith a null dereference. - Why new-file-only was impossible: the mapping loop is inside the filesystem service implementation.
- Behavior before: any
undefinedentry threwTypeError. - Behavior after: malformed entries are skipped; directory listings for otherwise readable directories succeed.
- Reason:
filesystem.tsimportsFileSystemSearchandsearch.tsimported theFileSystemnamespace back fromfilesystem.ts, forming a runtime import cycle. In the Android bundle the cycle resolved such thatFileSystem.nodewasundefinedwhileplugin/internal.tswas evaluated, which crashed every request that built the location services (Undefined layer node in group > plugin-internal > @opencode/v2/FileSystem). - Why new-file-only was impossible: the cycle lives in the two existing modules; the smallest safe fix is to remove the runtime edge.
- Behavior before:
search.tsusedFileSystem.Entry/FindInput/Matchvalues andFileSystem.GlobInput/GrepInputtypes from the cycle. - Behavior after: value classes are imported from their source
(
@opencode-ai/schema/filesystem, whichfilesystem.tsre-exports) and the two input types use a type-only import, so no runtime cycle remains. Behavior is unchanged; the same classes are used.
This was verified by reproducing the crash on device and re-testing
/file, /find/file and the system prompt after the fix.
packages/app/**- the frontend is frozen (see final report /git diff).packages/desktop/**- Electron host studied but not copied to Android.packages/core/src/process.ts,cross-spawn-spawner.ts- the existing process abstraction is used unchanged; Bun provides the Android implementation underneath it.Server.listenand all server routes - started through the existing CLI entrypoint.
The prior experimental branch android-app-snapshot contained additional
patches (Termux CLI tweaks, native Compose client, open-url shim). They were
not carried over; the Android host in packages/android is new code and
does not require them.