Dashboard › opencode › Distillation
ff5de108-e374-491c-85f5-16f746c5c6a1["lore_tm_v1_F1bYADzsscyq1mE1ui_tVqj3M31W-xslsKPj2c8BTso","lore_tm_v1_TdEVoSz2p5HuoZ1leFs78UI1uFi-Bk-gNtDZNnNM3Q4","lore_tm_v1_gpZbwta9IyJ92d_EH8DyQOTsSHxbPNecsEPi7FvpC_g","lore_tm_v1_Oho5jJuU2v77Xax-3gqyXTt8u9-6dzRWQWLwVxLNq9s","lore_tm_v1_iUvyxWd5XPgyp0-2C29HsaxxTsXOZ58YeqfAmR2d6-w","lore_tm_v1_cI77fOTDGOHQAIvHPJ_e5z6v5gCh1rdPigX6jiLvylk","lore_tm_v1_7pNIsI0XhTVJQssHhaSffwk7ZnOxOrnAv417TtWURt4"]
--local flag always disables remote mode: opts.local === true sets config.remoteGateway = false and config.remoteGatewayAutoDetected = false./home/byk/Code/opencode-lore-v2/packages/gateway/src/cli/start.ts, startGateway(opts, ioOverrides) executes startGatewayLocked() under withLifecycleLock("gateway-start", ...); CLI values override loaded configuration for port, hosts, debug, and allowRemoteManagement.opts.local sets config.hostedMode = !opts.local; absent opts.local and absent LORE_HOSTED_MODE defaults lore start to hosted mode; otherwise loadConfig()’s environment-derived value remains. In-process OpenCode plugin and Pi extension callers, plus lore run and lore import, must pass local: true because hosted mode is process-wide and disables filesystem operations including getGitRemote(), .lore.md import, config loading, and file watching.LORE_REMOTE_GATEWAY or LORE_HOSTED_MODE settings and bind-address auto-detection. For lore start with opts.local === undefined and neither environment variable present, it defaults to remote mode by setting config.remoteGateway = true and config.remoteGatewayCommandDefault = true if remote mode was not already enabled.assertGatewayAccessConfigured(config) runs only after CLI/environment/default hosted- and remote-mode precedence is fully applied, allowing --local to opt out before validation./home/byk/Code/opencode-lore-v2/packages/gateway/src/cli/start.ts uses only [config.port] for an explicit port; otherwise it tries 3207 → 5673 → 0, where 0 requests an OS-assigned random port. Each start generates a 32-byte base64url controlToken; process identity is currentProcessIdentity() or the explicit fallback unverified:${controlToken} for platforms such as Windows without a race-free Node creation-time query.startGatewayLocked() first checks the persisted process record and authenticates it via io.authenticate(record). On success it reuses the recorded port and authenticated host, returning owned: false, managementToken: record.token, and a no-op shutdown."127.0.0.1", config.hosts, and matching-record hosts. A reachable unauthenticated occupant causes an explicit-port error directing the user to --port / LORE_LISTEN_PORT, or advances a default-port attempt to the next port with a notification.log.warn; non-quiet lore start callers receive [lore] messages through console.error, preventing stdout/stderr writes from corrupting an OpenCode or Pi full-screen TUI.io.removePort(actualPort, controlToken) and removes the process record only when its pid, token, and processIdentity still match the current process. Database-close failures produce a warning because SQLite recovery handles failed best-effort checkpoints; an earlier shutdownError is still rethrown.opts.processBoundary is true, gateway startup creates processShutdown with io.createProcessShutdownController(shutdown). Remote shutdown invokes processShutdown(0) when present; otherwise it calls shutdown(), reports Remote shutdown failed: ... on failure, and sets process.exitCode = 1.await server.stop(). Errors not matching /port\b.*\bin use/i or /EADDRINUSE/i are immediately rethrown. After a conflict it re-reads and authenticates the exact persisted owner; an authenticated record is reused, while an unauthenticated explicit-port conflict throws and a default-port conflict advances to the next candidate.0 always succeeds or throws a non-EADDRINUSE error, making the final throw new Error("Failed to bind to any port.") unreachable.commandStart(opts) delegates background mode to startDaemon(opts); foreground mode calls startGateway({ ...opts, processBoundary: true }). If it does not own the returned gateway, it reports the existing addresses and dashboard, notes that hosted-mode state belongs to the running instance, and exits successfully.packages/core/src/plugin/module.ts as directories; the local-file branch exists for legacy auto-discovery of standalone server sources.packages/core/src/plugin/module.ts exports PluginModule.make, which obtains Watcher.Service, an Effect scope, a FiberSet runtime promise, an unbounded PubSub<void>, and a deduplicating Set<string> of watched paths. watchTarget(file) recursively walks to the nearest existing ancestor and classifies it as "directory" or "file", allowing creation of missing dependency path segments to trigger recovery.PluginModule.make acquires createPluginSources((file) => runPromise(watch(file))) and disposes it on release. Its API provides load(operation, options?) and a changes() stream backed by the PubSub; each watcher subscription publishes changes and uses a Deferred<void> to signal readiness.id plus either an effect function or a setup function. Invalid modules become PluginModule.LoadError with message Plugin must export a default definition with an id and an effect or setup function.; promise-style setup definitions are adapted through PluginPromise.fromPromise(value).PluginModule.load() classifies operation.target as local when path.isAbsolute(operation.target). Package targets use npm.resolve(operation.target) when options?.install === false, otherwise npm.add(operation.target). Local standalone files become { server: pathToFileURL(operation.target).href }; directories and installed packages use Host.resolve(installed ?? { directory: operation.target }).options?.install === false, absence of a server entrypoint returns { pending: true }; otherwise an absent entrypoint raises PluginModule.LoadError with Plugin entrypoint not found: ${operation.target}. Local entrypoints load through sources.read(entrypoint), while package entrypoints use Host.load(entrypoint) and preserve installed?.revision.id, optional features.tui and features.rpc, revision: JSON.stringify([operation, loaded.version]), and an effect that injects operation.options. Its source is { type: "local", path: fileURLToPath(entrypoint) } for absolute targets or { type: "package", target, version? } for installed packages.packages/core/src/plugin/promise.ts re-exports fromPromise from @opencode/plugin/promise/adapter.