This document is the file-system map of the @cortexkit/antigravity-auth* monorepo at the v2.0 parity refactor. It is written from the tracked source tree — every listed file is the actual path shipped on main (c362269); directories such as dist/, node_modules/, packages/opencode/src/tui-compiled/, and per-agent working roots are tracked as .gitignored but called out where relevant.
The stack has one business purpose (talk to the Google Antigravity agy CLI from non-Google harnesses) and three runtime surfaces (OpenCode server plugin, OpenTUI sidebar, Pi extension). These paragraphs are the only thing you have to read to navigate the tree:
- Account, rotation, quota, transport, OAuth, and persistence live in
packages/core. That package has zero host-runtime imports — it only knowsfetch,node:fs,node:net, and afetchAccountQuotacallback — and it owns the durableaccount-storage.tsengine and theaccount-manager.tsselection/rotation logic. The OpenCode side owns a thin adapter that wraps it (path resolution +.gitignoresync) and a fetch interceptor that drives it. packages/opencode/src/plugin/index.tsis the only composition root the host calls. Its default factories are aliased frompackages/opencode/index.tsas{AntigravityCLIOAuthPlugin, GoogleOAuthPlugin}. Everything else underpackages/opencode/src/plugin/is a subsystem wired by that root.packages/opencode/src/tui.tsxand thepackages/opencode/src/tui-compiled/twin are the OpenTUI sidebar. They are read-only consumers of the on-disksidebar-state.jsonand the loopback HTTP RPC. They never import frompackages/opencode/src/plugin/storage.ts,accounts.ts, or any OAuth code; that boundary is enforced by the import graph documented inARCHITECTURE.md.
antigravity-auth/
├── AGENTS.MD # operator-facing agent manual
├── ARCHITECTURE.md # system-of-record architecture doc
├── STRUCTURE.md # this file — file-system map
├── README.md # project landing page
├── biome.json # Biome formatter + linter config
├── bunfig.toml # Bun test preload (test/setup.ts + OpenTUI preload)
├── bun.lock # Bun lockfile (committed)
├── lefthook.yml # pre-commit Biome check
├── mise.toml # Bun 1.3 + Node 24 toolchain pin
├── tsconfig.scripts.json # tsconfig for scripts/, test/, e2e-tests
├── package.json # root monorepo (npm workspaces: packages/*)
├── models # JSON snapshot of upstream Antigravity model list
├── .github/ # GitHub config: workflows, issue templates, FUNDING
├── scripts/ # root build/dev/release/version-sync tooling
├── test/ # repo-root test preload + cross-package sanity tests
├── test-fixtures/ # frozen Antigravity CLI JSON fixtures used by tests
└── packages/
├── core/ # @cortexkit/antigravity-auth-core — harness-agnostic
├── opencode/ # @cortexkit/opencode-antigravity-auth — server + tui
├── pi/ # @cortexkit/pi-antigravity-auth — Pi extension
└── e2e-tests/ # private deterministic e2e workspace
The models blob at the repo root is a tracked JSON snapshot of the upstream Antigravity model inventory; the e2e tests assert it stays in sync with the metadata fixtures. Treat the packages/opencode/src/tui-compiled/ directory as a build artifact: it is gitignored and regenerated by packages/opencode/scripts/build-tui.ts. Files are listed under Generated and ignored artifacts below.
| Workspace | Runtime responsibility | Imports from |
|---|---|---|
packages/core |
All harness-agnostic logic: OAuth PKCE, transport, account pool, rotation, quota, persistence. | Node built-ins only. |
packages/opencode |
OpenCode server plugin (fetch interceptor, account runtime, slash commands, RPC) and the OpenTUI sidebar. | @cortexkit/antigravity-auth-core, @opencode-ai/plugin, @opentui/*, solid-js. |
packages/pi |
Pi extension — a custom OAuth provider that bridges Pi's pi.registerProvider API to the core transport + transforms. |
@cortexkit/antigravity-auth-core, @earendil-works/pi-* (peer). |
packages/e2e-tests |
Private black-box flows against a mock Antigravity loopback server (@cortexkit/antigravity-auth-e2e, private: true). |
packages/opencode, packages/core. |
scripts/ |
Workspace-level tooling: dev symlink lifecycle, version sync, release script. | Node built-ins + child process. |
test/ |
Preload + global types + a small handful of repo-root sanity tests (environment.test.ts, dev.test.ts). |
Bun test harness. |
test-fixtures/ |
Frozen JSON snapshots of captured agy CLI metadata and streaming requests, through version 1.1.6. |
None. |
.github/ |
Workflows (CI, release, issue triage), issue templates, FUNDING. | GitHub Actions. |
The harness-agnostic core. Every export under packages/core/src/index.ts:1-30 is grouped by concern; the test files live next to the production code (*.test.ts co-location). The package ships to npm as @cortexkit/antigravity-auth-core@2.0.0 and is the only dependency packages/opencode and packages/pi are allowed to take against internal code.
packages/core/bunfig.toml—preload = ["../../test/setup.ts"]. Test isolation root.packages/core/package.json— declaresmain/exportson./dist/, lists peer deps (@openauthjs/openauth,xdg-basedir,zod).packages/core/tsconfig.json— library tsconfig (extends@tsconfig/bun).packages/core/tsconfig.build.json— emit + declaration tsconfig used bybun run build(tsc -p tsconfig.build.json).packages/core/LICENSE,packages/core/README.md— MIT + repo readme.
packages/core/src/account-manager.ts—AccountManager: per-account selection, rate-limit state, fingerprint, soft-quota, health score. Hosts callgetCurrentOrNextForFamily,markAccountCoolingDown,markRateLimitedWithReason.packages/core/src/account-storage.ts— durable JSON shapeAccountStorageV4withaccounts[],activeIndex,activeIndexByFamily; migration v1→v4; lock-held read-modify-write via the fenced file lock.packages/core/src/account-types.ts— pure types (ManagedAccount,AccountSessionIdentity,RateLimitReason,CooldownReason,AccountStorageV4).packages/core/src/agy-request-metadata.ts—buildAgyRequestMetadata(the labels block —last_step_index,model_enum,trajectory_id,used_claude*,used_non_gemini_model) and the per-workspaceAgyRequestSessionStoreregistry.packages/core/src/agy-transport.ts— bounded TLS socket pool, chunked + gzip body decode, idle-timeout watchdog. Hosts pass aconnectTlsWithAbortfactory through the dependency seam.packages/core/src/antigravity/oauth.ts—authorizeAntigravity,exchangeAntigravity,refreshAntigravityToken. Owns PKCE pack/unpack, the51121callback URL constant, and the client metadata header.packages/core/src/auth.ts—parseRefreshParts,formatRefreshParts,accessTokenExpired(60s buffer), refresh-token validity.packages/core/src/auth-types.ts— packed/refresh token wire types.packages/core/src/constants.ts— endpoints (ANTIGRAVITY_ENDPOINT_FALLBACKS = [DAILY, PROD]), scopes, request headers, sentinel values (SKIP_THOUGHT_SIGNATURE),CLAUDE_TOOL_SYSTEM_INSTRUCTION, OAuth prompt copy.packages/core/src/fetch-timeout.ts—fetchWithActiveTimeout(15s header abort, stream-safe: the abort listener is removed once the body streams).packages/core/src/file-lock.ts— renovating fenced file lock (acquireFencedFileLock+releaseFencedFileLock), eviction marker withpid/createdAt(MARKER_TTL_MS = 30_000) for stale-claim reclamation,assertOwnedownership check,whenLost()/hasLost()ownership-loss signals, idempotent terminal release, and TOCTOU-safe renewal that stages a temp file beforerename(2).packages/core/src/fingerprint.ts— per-account device fingerprint + fingerprint history persistence helpers.packages/core/src/logger.ts—createLogger('module-name')thin wrapper used by every other module.packages/core/src/model-registry.ts— canonical model definitions, quota groups, header-style per-model metadata (mirrored topackages/opencode/src/plugin/model-registry.tswhich adds harness-specific overrides).packages/core/src/model-types.ts—QuotaGroupSummary, family enum, header style enum, model specification types.packages/core/src/project.ts—loadCodeAssist,ensureProjectContext. Provisions the AntigravityprojectIdfor an account.packages/core/src/quota-manager.ts—QuotaManager: per-account quota cache, exponential backoff, in-flight dedupe (refreshAccountreturns the existing promise), disposal honoursAbortSignal.packages/core/src/quota-types.ts— quota result shapes (AccountQuotaResult).packages/core/src/rotation.ts—HealthScoreTracker,TokenBucketTracker,selectHybridAccount(the hybrid scoring formula used byaccount-manager.getCurrentOrNextForFamily),calculateBackoffMs,computeSoftQuotaCacheTtlMs.packages/core/src/atomic-write.ts— temp-file +renamewriter (mode0o600, no copy fallback); rawnode:fsonly.packages/core/src/version.ts— exportedVERSIONconstant; the build pipeline uses it for cache busting.
packages/core/src/transform/index.ts— barrel re-export of all transforms and types.packages/core/src/transform/types.ts—TransformContext,TransformResult,ModelFamily,ThinkingTier,ResolvedModel,GoogleSearchConfig,ThinkingConfig,TransformDebugInfo.packages/core/src/transform/claude.ts—applyClaudeTransforms,appendClaudeThinkingHint,buildClaudeThinkingConfig,computeClaudeMaxOutputTokens,ensureClaudeMaxOutputTokens,isClaudeModel,isClaudeThinkingModel,normalizeClaudeTools,configureClaudeToolConfig.packages/core/src/transform/gemini.ts—applyGeminiTransforms,buildGemini3ThinkingConfig,buildGemini25ThinkingConfig,buildImageGenerationConfig,isGemini3Model,isGemini25Model,isGeminiModel,isImageGenerationModel,normalizeGeminiTools,toGeminiSchema.packages/core/src/transform/cross-model-sanitizer.ts— payload cleanup before family switch (sanitizeCrossModelPayload,sanitizeCrossModelPayloadInPlace,stripClaudeThinkingFields,stripGeminiThinkingMetadata,getModelFamily).packages/core/src/transform/model-resolver.ts—resolveModelWithTier,resolveModelWithVariant,resolveModelForHeaderStyle,MODEL_ALIASES,GEMINI_3_THINKING_LEVELS,THINKING_TIER_BUDGETS.
Every production file has a corresponding *.test.ts sibling. The dense transform families (Claude, Gemini, cross-model sanitizer, model resolver) and the storage/rotation files each have a focused test file. Standalone tests: account-manager.test.ts, account-storage.test.ts, agy-request-metadata.test.ts, agy-transport.test.ts, antigravity/oauth.test.ts, atomic-write.test.ts, fetch-timeout.test.ts, file-lock.test.ts, fingerprint.test.ts, model-registry.test.ts, project.test.ts, quota-manager.test.ts, rotation.test.ts, plus all transforms: transform/claude.test.ts, transform/gemini.test.ts, transform/cross-model-sanitizer.test.ts, transform/cross-model-integration.test.ts, transform/model-resolver.test.ts. Run via bun run --cwd packages/core test (which delegates to bun test --isolate ./src).
@cortexkit/opencode-antigravity-auth. Exposes two exports subpaths ("." and "./tui") and pins the supported host range through engines.opencode (>=1.17.13 <2); the host installer (opencode plugin) reads the subpaths and writes a server entry to opencode.json and a TUI entry to tui.json. Production layout:
packages/opencode/
├── index.ts # barrel: re-exports AntigravityCLIOAuthPlugin + GoogleOAuthPlugin
├── assets/antigravity.schema.json # generated JSON schema for the plugin config (built by script/build-schema.ts)
├── bunfig.toml # test preload
├── package.json # peerDependencies on @opencode-ai/plugin + @opentui/*
├── tsconfig.json / tsconfig.build.json # library + build tsconfigs
├── docs/ # ANTIGRAVITY_API_SPEC, ARCHITECTURE, CONFIGURATION, MODEL-VARIANTS, MULTI-ACCOUNT, TROUBLESHOOTING
├── script/ # one-off CLI tests + the schema builder (see Root tooling and CI below)
├── scripts/ # build-tui.ts, build-tui.test.ts, smoke-tui-pack-install.ts
├── src/ # all TypeScript source (see OpenCode TUI and RPC inventory below)
└── dist/ # build output (gitignored)
The src/tui-compiled/ directory lives under src/ but is gitignored — see Generated and ignored artifacts.
packages/opencode/src/index.ts— top-level barrel re-exportingAntigravityCLIOAuthPluginandGoogleOAuthPluginfromplugin/index.ts.packages/opencode/src/cli.ts— standalone CLI binary entry (thebinfield ofpackage.json); the build step bundles it todist/cli.js.packages/opencode/src/antigravity/oauth.ts— host-thin re-export / extension shim aroundcore/antigravity/oauth.ts(used by the CLI'sOAuthLoginRequest).packages/opencode/src/constants.ts— plugin-level constants: command names (ANTIGRAVITY_*_COMMAND_NAME), modal command constants,MODAL_COMMANDS.packages/opencode/src/shims.d.ts— ambient type shims for host globals.packages/opencode/src/sidebar-state.ts—SidebarStateV1snapshot schema,setSidebarMachineStatewriter,mergeMachineState,upsertSidebarActiveRouting,drainSidebarWrites, fenced-lock + atomic-write chain. The single source of truth both the server and the TUI read.packages/opencode/src/rpc/— the loopback HTTP RPC; see OpenCode TUI and RPC inventory below.
packages/opencode/src/plugin/index.ts—createAntigravityPlugin(providerId, options)factory. The single composition root.packages/opencode/src/plugin/types.ts—PluginInput,PluginContext,PluginResult,GetAuth, host types.packages/opencode/src/plugin/dependencies.ts—PluginDependencyOverrides(the seam the e2e workspace uses to swapfetchImpl,agyTransport,filesystemRoots,oauth,clock) +resolvePluginDependenciesdefault-resolver.packages/opencode/src/plugin/lifecycle.ts—createPluginLifecycle— the disposal root that coordinatesdisposeAccountRuntime,shutdownDiskSignatureCache,sessionRegistry.clear(),clearFetchState,drainSidebarWrites, and the registered disposables (RPC server, file logger, auto-update checker). Disposables are registered with aLifecyclePhaseof'producer'or'consumer'; producers (e.g. the auth loader's fetch-interceptor runtime) are disposed before the sidebar drain, consumers after.packages/opencode/src/plugin/auth-loader.ts—createAuthLoader— the function the host invokes on everyauth.loader(...)call. Detects auth drift, rebuilds theAccountManager, and returns a freshfetchclosure bound to a new fetch interceptor.packages/opencode/src/plugin/auth.ts— token validation helpers used by the loader (refresh-parts checks, expiry buffer).packages/opencode/src/plugin/auth-doctor.ts— self-healing diagnostics for an unrecoverable auth store.packages/opencode/src/plugin/auth-drift.ts—detectAuthStorageDrift: compares the host'sgetAuth()result against the on-disk pool and surfaces arestorablepath.packages/opencode/src/plugin/accounts.ts— host-sideAccountManagerfactory. Stores pool viaplugins/opencode/storage.ts, exportsgetCurrentOrNextForFamily,markAccountCoolingDown,markRateLimitedWithReason.packages/opencode/src/plugin/account-access.ts— CLI-facing account prompts (promptAccountIndexForVerification,promptOpenVerificationUrl,createAccountAccessService).packages/opencode/src/plugin/storage.ts— host-path adapter: resolvesOPENCODE_CONFIG_DIR, handles%APPDATA%on Windows, syncs the on-disk.gitignore. Delegates all data operations tocore/account-storage.ts.packages/opencode/src/plugin/persist-account-pool.ts— lock-held append-and-rewrite ofantigravity-accounts.jsonused after a fresh OAuth login.packages/opencode/src/plugin/fetch-interceptor.ts—createFetchInterceptor— the largest file in the tree. Outer loop picks an account, inner loop walksANTIGRAVITY_ENDPOINT_FALLBACKS, retry/quota/routing pipeline, soft-quota + killswitch gates (killswitch evaluation is model-aware: agemini-prorequest checks ONLY thegemini-proquota group via a precomputedeligibleIndexesSet that is reused after core selection and after the quota-fallback re-selection), sidelinesetSidebarMachineStatewrites,transformAntigravityResponsereverse-transform.packages/opencode/src/plugin/fetch/retry-state.ts— per-interceptorRetryState(rate-limit toast debounce, retry counts).packages/opencode/src/plugin/fetch/warmup.ts—WarmupState(probe accounts under load to detect soft-quota cliffs before they surprise the dispatcher).packages/opencode/src/plugin/fetch-routing.ts—resolveHeaderRoutingDecision,resolveQuotaFallbackHeaderStyle,getCurrentRoutingDecision(live override from operator settings).packages/opencode/src/plugin/request.ts— outbound transform pipeline (sanitize → resolve → inject metadata → order payload → harden).packages/opencode/src/plugin/request-helpers.ts—cleanGenerativeLanguageRequest, thinking-block filtering, tool-id orphan recovery glue.packages/opencode/src/plugin/agy-request-metadata.ts— host-side adapter aroundcore/agy-request-metadata.tswith the session registry host binding.packages/opencode/src/plugin/agy-transport.ts— host-side adapter aroundcore/agy-transport.ts; thin wrapper for the dependency-injected transport.packages/opencode/src/plugin/transform/cross-model-sanitizer.ts— host-side re-export of the core sanitizer (kept separate so a future OpenCode-specific override can fork without touching core).packages/opencode/src/plugin/transform/model-resolver.ts— host-side re-export.packages/opencode/src/plugin/transform/types.ts— host-side re-export.packages/opencode/src/plugin/transform/index.ts— host-side barrel.packages/opencode/src/plugin/quota.ts—createOpenCodeQuotaManager(the host wrapper overcore/quota-manager.ts). Hands agetAccountsForSidebarclosure to the core manager so quota refreshes push redacted sidebar snapshots.packages/opencode/src/plugin/refresh-queue.ts—createProactiveRefreshQueue— background timer that refreshes tokens before the access token expires.packages/opencode/src/plugin/rotation.ts— host thin wrapper aroundcore/rotation.ts; pushesinitHealthTrackerandinitTokenTrackerper the user config.packages/opencode/src/plugin/token.ts—refreshAccessToken— called by the fetch interceptor when a token is within the 60s expiry buffer.packages/opencode/src/plugin/oauth-methods.ts— interactive OAuth menu (Add another,Refresh,Check quotas,Verify accounts,Doctor,Manage,Cancel); also drivesauthorizeAntigravityandexchangeAntigravityfrom core.packages/opencode/src/plugin/oauth-login.ts—performOAuthLogin: orchestrates thestartOAuthListener+exchangeAntigravityflow for the CLI path.packages/opencode/src/plugin/server.ts—startOAuthListener(bindshttp://localhost:51121for the redirect, falls back to manual paste for headless / WSL2).packages/opencode/src/plugin/catalog.ts—applyAntigravityProviderCatalog+registerAntigravityCommands— handlesconfig.provider.*andconfig.command.*injection.packages/opencode/src/plugin/commands.ts—applyCommand(RPCapplycallback),createCommandExecuteBefore,createSidebarRefresher. The single wiring point for/antigravity-*slash commands.packages/opencode/src/plugin/cli.ts— small terminal prompts (promptProjectId,promptAddAnotherAccount) used by the OAuth method flow.packages/opencode/src/plugin/ui/auth-menu.ts— full-screen interactive auth menu renderer (showAuthMenu,showAccountDetails,showFingerprintHistory).packages/opencode/src/plugin/ui/model-status.ts— per-model quota status rendering helpers.packages/opencode/src/plugin/ui/quota-status.ts— quota summary rendering helpers.packages/opencode/src/plugin/ui/select.ts— primitive select-with-description list (kept free of the host'shide-propertyso invalid options stay visible).packages/opencode/src/plugin/ui/confirm.ts— primitive confirm dialog.packages/opencode/src/plugin/ui/ansi.ts— ANSI helpers shared by the UI primitives.packages/opencode/src/plugin/event-handler.ts—createEventHandler— host event hook (session.created / session.idle etc.).packages/opencode/src/plugin/recovery.ts—createSessionRecoveryHook— auto-recovers sessions fromtool_result_missingerrors.packages/opencode/src/plugin/recovery/index.ts— recovery subsystem barrel.packages/opencode/src/plugin/recovery/types.ts— recovery state types.packages/opencode/src/plugin/recovery/constants.ts— recovery limits (max attempts, retry delays).packages/opencode/src/plugin/recovery/storage.ts— durable on-disk state for in-flight recovery attempts.packages/opencode/src/plugin/thinking-recovery.ts— recovery for thinking-block signature mismatches (Geminiskip_thought_signature_validatorpath).packages/opencode/src/plugin/killswitch.ts—evaluateKillswitchForAccount,throwIfAllKilled— operator-tuned per-family/minimum-remaining-percent gate. Evaluation is model-aware via themodel/quotaModeloption: agemini-prorequest checks ONLY thegemini-proquota group, not the max of pro+flash.packages/opencode/src/plugin/operator-settings.ts—createOperatorSettingsController: the runtime-mutable settings store (routing flags, killswitch, log level). Persists through the fenced-lock writer.packages/opencode/src/plugin/config/schema.ts— Zod schema forantigravity.json(the public config schema). Schema description source forscript/build-schema.ts.packages/opencode/src/plugin/config/loader.ts—loadConfig(directory),loadConfigFile. Computes the legacy Windows migration fallback. Swallows malformed JSON.packages/opencode/src/plugin/config/writer.ts— fenced-lock writer for the user config (used by the operator settings controller).packages/opencode/src/plugin/config/updater.ts—updateOpencodeConfig— generic writer helper for the host's opencode.json.packages/opencode/src/plugin/config/models.ts—OPENCODE_MODEL_DEFINITIONSliteral copy + the hostModeladapter.packages/opencode/src/plugin/config/operator-settings-schema.ts— Zod schema for theoperator.*subtree.packages/opencode/src/plugin/config/index.ts— barrel for the config subtree; also callsloadConfig+initRuntimeConfig.packages/opencode/src/plugin/cache/index.ts— barrel for the cache subtree.packages/opencode/src/plugin/cache.ts— backwards-compatible thin re-export ofcache/index.ts(kept for legacy callers).packages/opencode/src/plugin/cache/signature-cache.ts— disk-backed cache for thinking-block signatures.packages/opencode/src/plugin/stores/signature-store.ts—SignatureStorepersistence interface + memory-backed default.packages/opencode/src/plugin/core/streaming/index.ts— barrel for the streaming subsubsystem.packages/opencode/src/plugin/core/streaming/transformer.ts— the SSE reverse-transform: strips Antigravity envelope, splicesthoughtSignature, aggregatesusageMetadata, produces aReadableStream<Uint8Array>.packages/opencode/src/plugin/core/streaming/types.ts—SignatureStore,StreamingCallbacks,StreamingOptions,StreamingUsageMetadata,ThoughtBuffer.packages/opencode/src/plugin/debug.ts— debug file logger for the server plugin (writes to the user-configuredlog_dir). Project IDs and fingerprint-form User-Agents are masked viaredactSensitivebefore emission, and the logged request-body preview is field-redacted viaredactBodyForLogso a project ID embedded in the body never leaks verbatim.packages/opencode/src/plugin/errors.ts— domain error classes (AntigravityKillswitchError,AntigravityTokenRefreshError,LiveNetworkDeniedError, etc.).packages/opencode/src/plugin/fingerprint.ts— host thin wrapper that pins theFingerprintVersionfor an account.packages/opencode/src/plugin/gemini-dump.ts—/gemini-dumpmodal command — saves raw payload/response to disk for debugging. Session IDs and project IDs are masked viamaskIdentifier; header User-Agents are redacted byredactForDump; the request body written to disk is field-redacted viaredactJsonBodyStringso project IDs embedded in the body are masked.packages/opencode/src/plugin/google-search-tool.ts— server-sidegoogle_searchtool implementation.packages/opencode/src/plugin/image-saver.ts— writes Gemini image-generation output to disk and returns the file path back to the caller.packages/opencode/src/plugin/logger.ts— structured logger (createLogger,initLogger,setRuntimeLogLevel).packages/opencode/src/plugin/logging-utils.ts— small ANSI/console helpers plusredactSensitive/redactSensitiveFields(case-insensitive walk overtoken|refresh|access|project|fingerprint|deviceId|sessionId|sessionToken|secret|password|apiKey|clientSecretkeys —projectcatches bareproject/managedProjectIdbody fields), andredactJsonBodyString/redactBodyForLogwhich field-redact a serialized JSON request body before it reaches a debug log or dump file.packages/opencode/src/plugin/model-registry.ts— host overlay oncore/model-registry.ts(OpenCodeModelshape +providerOptionsdefaults).packages/opencode/src/plugin/project.ts— host thin wrapper aroundcore/project.ts.packages/opencode/src/plugin/prompt-context.ts— extracts the active prompt context (workspace + system prompt) for cross-model sanitizer decisions.packages/opencode/src/plugin/search.ts—executeSearchGoogle Search grounding tool implementation.packages/opencode/src/plugin/session-context.ts—AgySessionRegistry, per-sessionAgyRequestSessionStoreregistration.packages/opencode/src/plugin/version.ts— runs once at plugin boot to publish the installed plugin version (used by the auto-update checker).packages/opencode/src/plugin/host-api-compatibility.test.ts— pins the opencode host SDK to a stable property subset (so a host bump that moves a name does not break us silently).
packages/opencode/src/hooks/auto-update-checker/ — a self-contained module that runs in the background of the host:
packages/opencode/src/hooks/auto-update-checker/index.ts— barrel;createAutoUpdateCheckerHookis the host-side hook entry point.packages/opencode/src/hooks/auto-update-checker/checker.ts— the actual update check:npm view @cortexkit/opencode-antigravity-auth version+ auto-pin routine.packages/opencode/src/hooks/auto-update-checker/cache.ts— on-disk cache of the last known good version.packages/opencode/src/hooks/auto-update-checker/constants.ts— check interval, npm registry URL.packages/opencode/src/hooks/auto-update-checker/logging.ts— internal logger.packages/opencode/src/hooks/auto-update-checker/types.ts— types for the hook's report.
The plugin directory mirrors the source tree with *.test.ts siblings for nearly every file: account-access, account-ineligibility.persistence, account-ineligibility, accounts, agy-transport, antigravity-first-fallback, auth-doctor, auth-drift, auth-loader, auth, cache, catalog, commands, core/streaming/transformer, debug, errors, event-handler, fetch-interceptor, fetch/retry-state, fetch-routing, fetch/warmup, gemini-dump, google-search-tool, host-api-compatibility, image-saver, killswitch, lifecycle, logger, logging-utils, model-specific-quota, oauth-methods, operator-settings, persist-account-pool, quota-fallback, quota, recovery, reexports, refresh-queue, request-helpers, request, rotation, search, session-context, storage, stores/signature-store, thinking-recovery, token, plus the UI subtree (ui/ansi, ui/auth-menu.actions, ui/auth-menu, ui/model-status, ui/quota-status), version, and the host-SDK pins.
Top-level co-located tests under packages/opencode/src/: cli.test.ts, constants.test.ts, plugin-entry.test.ts, sidebar-state.test.ts, rpc/notifications.test.ts, rpc/port-file.test.ts, rpc/rpc-client.test.ts, rpc/rpc-server.test.ts, and the TUI tests tui/command-dialogs.test.tsx, tui/file-logger.test.ts, tui.test.tsx. Run via bun run --cwd packages/opencode test (delegates to bun test --isolate ./src).
The TUI is a thin Solid sidebar that polls a redacted snapshot file and a loopback HTTP RPC. Two halves of the contract: the read seam (sidebar file) and the bidirectional seam (RPC + bearer token).
packages/opencode/src/sidebar-state.ts—SidebarStateV1schema,getSidebarStateFile(),setSidebarMachineState,mergeMachineState,upsertSidebarActiveRouting,buildSidebarMachineStateFromAccounts,drainSidebarWrites. Header (lines 1-38) documents the split between server-side reads/writes and TUI-side reads.
packages/opencode/src/rpc/protocol.ts— wire types:CommandModalName(six modal commands),OpenDialogPayload,RpcNotification,ApplyRequest,ApplyResult.packages/opencode/src/rpc/rpc-server.ts—startRpcServer({ dir, apply, drain }). Binds127.0.0.1:0, mints a 32-byte hex bearer token, writes the port file, servesPOST /rpc/apply(server timeout 120s) andPOST /rpc/pending-notifications(request timeout 2s). UsestimingSafeEqualfor the bearer check.packages/opencode/src/rpc/rpc-client.ts—createRpcClient(dir, expectedPid)— discovers the port file, posts JSON withAuthorization: Bearer <token>, enforces a 2s default viafetchWithActiveTimeout.packages/opencode/src/rpc/port-file.ts—writePortFile/discoverPortFile.<dir>/port-<pid>.jsonwith{ pid, port, token }, mode0o600, atomic viarenameSyncfrom a.tmpsibling.packages/opencode/src/rpc/rpc-dir.ts—getRpcDir:ANTIGRAVITY_AUTH_RPC_DIRenv wins, else<XDG_STATE_HOME>/cortexkit/antigravity-auth/rpc/<sha256(directory)[:16]>.packages/opencode/src/rpc/notifications.ts— bounded queue (max 100 entries),pushNotification,drainNotifications(lastReceivedId, sessionId?).isTuiConnectedreflects whether the TUI polled withinCONNECTION_TTL_MS = 5000.- Tests:
notifications.test.ts,port-file.test.ts,rpc-client.test.ts,rpc-server.test.ts.
packages/opencode/src/tui.tsx—@jsxImportSource @opentui/solid. TheTuiPlugindefault export registers theslots.sidebar_contentslot. Hard rules for the file are documented in its module header (lines 1-22).packages/opencode/src/tui/entry.mjs— host-aware loader. Probesopentui:runtime-module:<encodeURIComponent('@opentui/solid')>; falls back to the rawtui.tsxif the host has no runtime module resolver.packages/opencode/src/tui/command-dialogs.tsx—DialogSelect/DialogConfirm/DialogPrompttrees mounted from RPC notifications. EveryMODAL_COMMANDSoption has a stablekeyand an explanatorydescription.packages/opencode/src/tui/file-logger.ts— write-only file logger under<xdg-state>/cortexkit/antigravity-auth/tui.log(mode0o600, 1 MB tail-truncated). Parent dir is forced to0o700after every write and existing log files are re-chmod-ed to0o600to repair any leaked permissions. Never writes to stdout/stderr.packages/opencode/src/tui/ansi.ts— small ANSI helpers used by the dialog tree.- Tests:
tui.test.tsx,tui/command-dialogs.test.tsx,tui/file-logger.test.ts.
@cortexkit/pi-antigravity-auth. A small extension that bridges the Pi runtime's registerProvider API to the core transport. Layout:
packages/pi/bunfig.toml—preload = ["../../test/setup.ts", "@opentui/solid/preload"]. (OpenTUI preload is harmless here; the Pi extension itself does not use@opentui/solid.)packages/pi/package.json— declaresmainon./dist/index.js,peerDependencieson@earendil-works/pi-*, runtime dependency only on@cortexkit/antigravity-auth-core.packages/pi/tsconfig.json,packages/pi/tsconfig.build.json— library + build configs.packages/pi/LICENSE,packages/pi/README.md— MIT + readme.
packages/pi/src/index.ts— package entry.providerId = 'google-antigravity'; registers the provider withpi.registerProvider; defines the OAuth login + refresh flows againstcore/antigravity/oauth.ts.packages/pi/src/stream.ts—streamCortexKitAntigravity: streams throughcore/agy-transport.ts, preserves signed thinking/tool events, and maintains session-scoped native AGY execution metadata.packages/pi/src/convert.ts— Pi Context-to-Gemini conversion with native AGY tool-call IDs, signature replay, cross-model sanitization, and same-target function-response roles.packages/pi/src/credential-cache.ts— stashes the packedrefreshToken|projectId|managedProjectIdtriple so the stream can rejoin project context after the access token is stripped.packages/pi/src/paths.ts— resolves thePI_AGENT_DIRandPI_ANTIGRAVITY_AUTH_FILEpaths on every platform (%APPDATA%on Windows,~/.pi/agent/elsewhere).packages/pi/src/index.test.ts,convert.test.ts,credential-cache.test.ts,stream.test.ts— co-located tests.
@cortexkit/antigravity-auth-e2e — private: true, not published. Houses deterministic black-box flows against a mock Antigravity loopback server.
packages/e2e-tests/bunfig.toml—preload = ["./src/setup.ts"],root = "./src"so the e2e-runner only loads this workspace's tests.packages/e2e-tests/tsconfig.json— extends@tsconfig/bun.packages/e2e-tests/package.json—private, depends onworkspace:*core + opencode packages.
packages/e2e-tests/src/setup.ts— per-test temp root + env reset (HOME,XDG_*,APPDATA,LOCALAPPDATA,OPENCODE_CONFIG_DIR,PI_AGENT_DIR,PI_ANTIGRAVITY_AUTH_FILE,OPENCODE_ANTIGRAVITY_GEMINI_DUMP_DIR,ANTIGRAVITY_AUTH_RPC_DIR,ANTIGRAVITY_AUTH_SIDEBAR_STATE_FILE), plus a loopback-onlyglobalThis.fetchguard (installFetchGuard/restoreFetchGuard, line 51-84) that throwsLiveNetworkDeniedErrorfor any non-loopback URL. The guard is installed inbeforeEachand restored inafterEachso a stray live URL surfaces as a real exception that points at the offending call site. Each isolated test file's finalafterAlldisposes harnesses scoped to its roots before deleting them; a post-deleteexistsSynccheck throws if a root survives. The opt-in orphan sweep (AGY_E2E_SWEEP_ORPHANS=1) only removesagy-e2e-*entries older than 24h by mtime.packages/e2e-tests/src/harness.ts—E2eHarness: builds a mock loopback server, aPluginDependencyOverridesbag that points the production plugin at127.0.0.1, andcreatePlugin()/runCli()helpers. The single seam every e2e test uses to talk to the plugin under test.packages/e2e-tests/src/fetch-router.ts—installFetchRouter— routesglobalThis.fetchthrough the mock when the URL targets the loopback server.packages/e2e-tests/src/mock-antigravity-server.ts—startMockAntigravityServer+MockServerHandle. Configurable routes, scripted responses, request recorder.packages/e2e-tests/src/process-runner.ts—process-runner: spawns theantigravity-authCLI binary in a temp dir and pins stdout/stderr for assertions.packages/e2e-tests/src/cli-flow.e2e.test.ts— CLI flows (login, refresh, quota check) against the mock.packages/e2e-tests/src/plugin-flow.e2e.test.ts— full plugin instance lifecycle against the mock.packages/e2e-tests/src/rpc-tui-flow.e2e.test.ts— RPC server boot + notification drain end-to-end.packages/e2e-tests/src/fetch-guard.test.ts— pins the loopback-onlyglobalThis.fetchguard: loopback URLs pass through, non-loopback URLs throwLiveNetworkDeniedError, the guard is restored inafterEach.- Unit tests under this workspace:
mock-antigravity-server.test.ts,process-runner.test.ts. - Run via
bun run test:e2eat the repo root (delegates tobun test --isolate ./packages/e2e-tests/src/plugin-flow.e2e.test.ts ./packages/e2e-tests/src/cli-flow.e2e.test.ts ./packages/e2e-tests/src/rpc-tui-flow.e2e.test.ts ./packages/e2e-tests/src/fetch-guard.test.ts).
scripts/dev.ts—bun scripts/dev.ts. Resolves dev paths, symlinkspackages/opencode/dist/index.jsinto.opencode/plugins/antigravity-auth.js, then runstsc --watchon core andesbuild --watchon opencode in parallel until SIGINT/SIGTERM.--checkvalidates the symlink and exits.scripts/dev-clean.ts— inverse ofdev.ts; removes the development symlink.scripts/version-sync.mjs— synchronized version bump forpackages/{core,opencode,pi}/package.json(and the@cortexkit/antigravity-auth-corepin in dependents). Supports--dry-runand--from-tag(driven byGITHUB_REF_NAMEin CI).scripts/release.sh— semver validate + dry-run flag, pre-flightbun run typecheck/bun run test/bun run build, sync versions, commit, tagv$X.Y.Z, push to origin. GitHub Actions then runs the publish matrix.
test/setup.ts— installsmkdtempSynctest root + env overrides on every package workspace, definesglobalThis.stubbed/unstubAllGlobals/freshImport, and patchesjest.setSystemTime/jest.useRealTimersto also spy onDate.now().test/global.d.ts— type declarations for the helperstest/setup.tsinstalls.test/environment.test.ts— pins the env-isolation contract (HOME,XDG_*,APPDATA,OPENCODE_CONFIG_DIR,PI_AGENT_DIR, etc.).test/dev.test.ts— pinsscripts/dev.ts'sresolveDevPaths/createDevSymlink/removeDevSymlinkso a symlink-layout regression fails before the next release.test-fixtures/agy-cli-1.1.3-model-metadata.jsonandtest-fixtures/agy-cli-1.1.3-stream-request.json— frozen snapshots of the upstreamagyCLI for comparator tests.test-fixtures/agy-cli-1.1.5-*andtest-fixtures/agy-cli-1.1.6-*— versioned frozen wire snapshots.
Project-wide tsconfig used by bun run typecheck (root script typecheck) for scripts/**/*.ts, test/**/*.ts, and packages/e2e-tests/src/**/*.ts.
package.json— root monorepo (@cortexkit/antigravity-auth,private: true,workspaces: [packages/*]). Exposesbuild,typecheck,test,test:e2e,test:e2e:models,test:e2e:regression,dev,dev:clean,format,format:check,lint,pack:core:dry,pack:opencode-dry,pack:pi-dry.biome.json— formatter + linter config (indent: 2 spaces,semicolons: asNeeded,quoteStyle: single). Test files (**/*.test.ts) andpackages/opencode/src/plugin/ui/select.tscarry override files that disable a small set of rules where the test naturally needs them.bunfig.toml— root:preload = ["./test/setup.ts", "@opentui/solid/preload"].lefthook.yml— pre-commit:biome check --staged --no-errors-on-unmatchedon*.{ts,tsx,js,mjs,json,jsonc,yml,yaml}.mise.toml— pinsbun = "1.3"andnode = "24".bun.lock— committed; CI usesbun install --frozen-lockfile.models— tracked JSON snapshot of the upstream model inventory (referenced by the e2e tests for drift assertions).
.github/workflows/ci.yml— push/PR tomain: Setup Node 24 + Bun 1.3,bun install --frozen-lockfile,bun run typecheck,bun run build,bun run --cwd packages/opencode smoke:tui,bun test,bun run test:e2e,bun run format:check,bun run lint..github/workflows/release.yml— onv*tag push + workflow_dispatch: runs the same checks (test/build/e2e/format/lint) before publishing via OIDC trusted publishing.publish-npmis a matrix job that publishes core, then opencode, then pi, each from a fresh job so npm obtains a per-package OIDC token. Closes with asoftprops/action-gh-releaseGitHub Release..github/workflows/issue-triage.yml— self-hosted Opencode Triage agent: parses label output, appliesbug/enhancement/documentation/question/invalid+area/auth/area/models/area/config/area/compat, posts an automated reply, and closes duplicates..github/FUNDING.yml,.github/ISSUE_TEMPLATE/bug_report.yml,.github/ISSUE_TEMPLATE/feature_request.yml,.github/ISSUE_TEMPLATE/config.yml.
| Package | File | Symbol | Purpose |
|---|---|---|---|
@cortexkit/antigravity-auth-core |
packages/core/src/index.ts |
(barrel) | All harness-agnostic exports — re-exported per file. |
@cortexkit/opencode-antigravity-auth (server) |
packages/opencode/index.ts |
AntigravityCLIOAuthPlugin, GoogleOAuthPlugin |
Host plugin registrations (bound factory with ANTIGRAVITY_PROVIDER_ID = 'google'). |
@cortexkit/opencode-antigravity-auth (server — raw) |
packages/opencode/src/plugin/index.ts |
createAntigravityPlugin, PluginResult |
Direct composition root for tests + non-host callers. |
@cortexkit/opencode-antigravity-auth (server — CLI) |
packages/opencode/src/cli.ts |
default export | Standalone antigravity-auth CLI entry. Build emits dist/cli.js. |
@cortexkit/opencode-antigravity-auth (tui) |
packages/opencode/src/tui/entry.mjs |
{ id: 'cortexkit.antigravity-auth', tui } |
OpenTUI sidebar entry. Resolves through dist/src/tui.d.ts (types) + src/tui/entry.mjs (loader). |
@cortexkit/opencode-antigravity-auth (server — fallback) |
packages/opencode/src/plugin-entry.test.ts |
test entry | Verifies the public barrel exports the two stable plugin names. |
@cortexkit/pi-antigravity-auth |
packages/pi/src/index.ts |
default function |
Pi extension. Resolves as pi.extensions: ['./dist/index.js'] per packages/pi/package.json:34-38. |
The exports map at packages/opencode/package.json declares both . (the bundled server root) and ./tui (the OpenTUI loader). The host's opencode plugin installer reads the subpaths and writes a server entry to opencode.json plus a TUI entry to tui.json; the host then resolves them as two independent plugin registrations.
These directories exist at build time but are gitignored (see .gitignore). They are not part of the source tree:
node_modules/— Bun-installed dependencies, workspace-wide. Ignored.dist/—packages/core/dist/,packages/opencode/dist/,packages/pi/dist/. Per-packagetsc --build+ esbuild output. Ignored. The publishedfilesallowlist (packages/opencode/package.json:46-61, etc.) packagesdist/explicitly so the build output is what ships on npm.*.tgz—bun pm pack --dry-runoutput staging. Ignored.coverage/,*.lcov,logs/,*.log,_.log,antigravity-debug-*.log— coverage + log output. Ignored.*.tsbuildinfo— TypeScript incremental compile cache. Ignored..opencode/— IDE + local OpenCode plugin dir. The root.gitignoreignores it;scripts/dev.tsmakes.opencode/plugins/antigravity-auth.jsa symlink during dev.- Agent working directories:
.hive/,.omo/,.opencode/,.sisyphus/,.alfonso/— session state, historian dumps, run continuation, council runs. All ignored. test-file.ts— temporary scratch file used by the dev loop. Ignored.package-lock.json— npm optional-dep native-binary workaround. Ignored.
packages/opencode/src/tui-compiled/ is the only directory in the tree that ships in the npm tarball but is gitignored at the source level. It is rebuilt from source every release.
- Source manifest:
packages/opencode/scripts/build-tui.ts—buildTui({ packageRoot })walks the relative static import graph rooted atsrc/tui.tsx, transforms each.tsxthrough@opentui/solid/scripts/solid-transform(rewriting virtual runtime modules toopentui:runtime-module:<encoded>), and copies non-TSX sibling files as-is. - Shipped source allowlist:
packages/opencode/scripts/build-tui.ts:91-102(SHIPPED_SOURCE_FILES) is the canonical allowlist that ships —src/tui.tsx,src/tui/entry.mjs,src/tui/ansi.ts,src/tui/command-dialogs.tsx,src/tui/file-logger.ts,src/sidebar-state.ts,src/rpc/rpc-client.ts,src/rpc/rpc-dir.ts,src/rpc/port-file.ts,src/rpc/protocol.ts. - Behavior: the loader
src/tui/entry.mjsprobesopentui:runtime-module:<encodeURIComponent('@opentui/solid')>; if that succeeds it loads../tui-compiled/tui.tsx(the host has a runtime-module resolver), otherwise it loads the dev fallback../tui.tsxvia@opentui/solid/preload.src/tui/entry.mjsis intentionally NOT copied into the compiled tree — it ships via thesrc/tui/directory entry inpackage.jsonfiles. - Test:
packages/opencode/scripts/build-tui.test.tspins the SHIPPED_SOURCE_FILES list, the import-graph traversal, the transformed output, and the TUI's import graph against the credential-module allowlist (account-manager,account-storage,oauth,quota-manager,rotation— the latter viaFORBIDDEN_PATTERNS). - Pack smoke test:
packages/opencode/scripts/smoke-tui-pack-install.tspacks core + opencode viabun pm pack, installs them into a real consumer workspace withbun install --no-save, then resolves@cortexkit/opencode-antigravity-auth/.and@cortexkit/opencode-antigravity-auth/tuithrough the export map and asserts the file shipped by the tarball lines up with the path the loader expects. Run viabun run --cwd packages/opencode smoke:tui. - Schema JSON:
packages/opencode/assets/antigravity.schema.jsonis also a generated artifact, produced bypackages/opencode/script/build-schema.tsfrompackages/opencode/src/plugin/config/schema.ts(the Zod schema). Run viabun run --cwd packages/opencode build:schema.
- Files / directories:
kebab-case.ts—account-manager.ts,fetch-interceptor.ts,auto-update-checker/,core/streaming/. No exceptions in tracked source. - Test files: co-located
*.test.tssiblings (e.g.account-storage.ts↔account-storage.test.ts). The single exception is the e2e workspace, which uses*.e2e.test.tsfor the three black-box flows so the rootbun testandbun test:e2eselectors can target them precisely. - Types / interfaces:
PascalCase—AccountManager,AntigravityConfig,SidebarStateV1,PluginResult. - Functions / variables:
camelCase—getCurrentOrNextForFamily,resolveModelWithTier,setSidebarMachineState. - Constants:
UPPER_SNAKE_CASE—ANTIGRAVITY_PROVIDER_ID,CLAUDE_TOOL_SYSTEM_INSTRUCTION,SKIP_THOUGHT_SIGNATURE,DEFAULT_AGY_RESPONSE_HEADER_TIMEOUT_MS. - Test framework: Bun's bundled test runner (
bun test); tests can spell helpers asbun:test(describe,it,expect,beforeEach,afterEach,jestnamespace).bunfig.tomlin every workspace preloads./test/setup.tsfor env isolation. - Assertion style:
expect(actual).toBe(...),.toEqual(...),.toMatchObject(...); no third-party assertion library. - Test isolation env vars:
ANTIGRAVITY_TEST_ROOT,HOME,USERPROFILE,XDG_CONFIG_HOME,XDG_CACHE_HOME,XDG_DATA_HOME,XDG_STATE_HOME,APPDATA,LOCALAPPDATA,OPENCODE_CONFIG_DIR,OPENCODE_ANTIGRAVITY_GEMINI_DUMP_DIR,PI_AGENT_DIR,PI_ANTIGRAVITY_AUTH_FILE,ANTIGRAVITY_AUTH_RPC_DIR,ANTIGRAVITY_AUTH_SIDEBAR_STATE_FILE. Set automatically bytest/setup.ts. - Formatting: Biome 2.5.3, two-space indent, semicolons omitted, single quotes, trailing commas. The root runner is
bun run format:checkandbun run lint.
┌─────────────────┐
│ packages/core │ ← harness-agnostic. Node built-ins only.
│ │ Owns: OAuth, transport, account pool,
│ │ rotation, quota, persistence, transforms.
└────────▲────────┘
│
┌─────────────────┴─────────────────┐
│ │
┌────┴─────────┐ ┌────────┴────────┐
│ packages/ │ │ packages/pi │ ← depends only on core.
│ opencode │ │ Pi runtime via │
│ server │ │ peerDeps only. │
│ plugin │ └─────────────────┘
│ │ │
│ ├──────┴──┐ TUI split is via file + RPC, not imports.
│ │ sidebar │
│ │ state │
│ │ + │
│ │ RPC │
│ ▼ ▼
│ ┌────────┐ ┌──────────┐
│ │ rpc/ │ │ tui.tsx │
│ │ (server)│ │ (TUI) │
│ └────────┘ └──────────┘
└─────────────────────────┘
▲
│ (e2e workspace consumes server plugin under test)
┌──────┴───────┐
│ packages/ │ ← private, depends on core + opencode.
│ e2e-tests │
└──────────────┘
Holds:
coremust not import fromopencode,pi, ore2e-tests. It only knowsfetch,node:fs,node:net, and afetchAccountQuotacallback — it must not import@opencode-ai/pluginor@earendil-works/pi-ai. The corollary: every host-runtime call is injected throughPluginDependencyOverrides(packages/opencode/src/plugin/dependencies.ts).pidepends only oncoreand Pi's peer deps. It never reaches intoopencode. The Pi extension has no concept of an account pool —core/auth.tstreats the refresh token as opaque so both Pi and OpenCode can reuse it.opencodeserver → OpenTUI communication is async and out-of-process. The TUI imports nothing frompackages/opencode/src/plugin/{storage,accounts,fetch-interceptor,oauth-*}— onlysrc/sidebar-state.ts,src/rpc/protocol.ts,src/rpc/rpc-client.ts,src/rpc/rpc-dir.ts, and the localsrc/tui/folder. The compiler would let it, so the contract is enforced by the import-graph review atpackages/opencode/src/tui.tsx:1-22, the import-graph gate inpackages/opencode/scripts/build-tui.test.ts, and the e2e fixture inpackages/e2e-tests/src/rpc-tui-flow.e2e.test.ts.e2e-testsdoes not take a peer on the host. It loads the plugin source as an internal import so the production factory is exercised as-is.
Pick the path that lines up with the smallest possible blast radius. The list below is in the same shape as the verification gates.
- New core primitive (transport rule, persistence primitive, OAuth step): add or edit a file under
packages/core/src/. Public surface changes go throughpackages/core/src/index.ts; co-locate a*.test.tsnext to it. Type additions live in the matching*-types.tsfile (e.g.account-types.ts,auth-types.ts,model-types.ts,quota-types.ts). - New model transform or sanitization rule:
packages/core/src/transform/. Add a focused export totransform/index.ts(or re-exporttransform/types.tsfor the type). Update the focused test sibling; if the change touches model resolution, also updatetransform/model-resolver.tsand itsmodel-resolver.test.ts. - New provider endpoint or sentinel value:
packages/core/src/constants.ts. If the value is per-account (overridable via config), the override goes inpackages/opencode/src/plugin/config/schema.tsinstead, and the fallback hard-codes the constant. - New OpenCode hook (host lifecycle — e.g. tool registration, event hook): add a module under
packages/opencode/src/plugin/, wire it frompackages/opencode/src/plugin/index.ts's factory, register it as a disposable inpackages/opencode/src/plugin/lifecycle.ts, and co-locate a*.test.ts. Examples:event-handler.ts,recovery/recovery.ts,hooks/auto-update-checker/index.ts,google-search-tool.ts. - New modal command (slash command that opens a dialog):
- Add the constant to
packages/opencode/src/constants.ts(ANTIGRAVITY_*_COMMAND_NAME). - Add the entry to
MODAL_COMMANDSinpackages/opencode/src/plugin/commands.ts. - Register the canonical and (where applicable) alias names in
packages/opencode/src/plugin/catalog.ts'sregisterAntigravityCommandsandapplyAntigravityProviderCatalog. - Add the modal name to
packages/opencode/src/rpc/protocol.ts'sCommandModalNameunion. - Build the dialog in
packages/opencode/src/tui/command-dialogs.tsx(andtui/command-dialogs.test.tsx). The three-wirings invariant is pinned by a dedicated test inpackages/opencode/src/plugin/commands.test.ts.
- Add the constant to
- New sidebar field: extend
SidebarStateV1inpackages/opencode/src/sidebar-state.ts(the schema) and thebuildSidebarMachineStateFromAccounts+mergeMachineStatewriters; render the new field inpackages/opencode/src/tui.tsx(andpackages/opencode/src/tui.test.tsx). Remember that sidebar state is public — it lands in<xdg-state>/cortexkit/antigravity-auth/sidebar-state.jsonand must contain no tokens or project IDs. - New RPC method or notification shape:
packages/opencode/src/rpc/protocol.ts(wire types) +packages/opencode/src/rpc/rpc-server.ts(server handler) +packages/opencode/src/rpc/rpc-client.ts(TUI caller). Bump the bearer check if you add an unauthenticated path. Add a sibling*.test.tsper file. - New CLI command:
packages/opencode/src/cli.ts(the bundled CLI binary). Updatescripts/dev.tsonly if the new command affects the dev symlink lifecycle, which it should not. Co-locate a CLI-level test underpackages/e2e-tests/src/cli-flow.e2e.test.ts. - New Pi behavior (provider shape change, new path resolver, conversion rule): live under
packages/pi/src/. The package surface issrc/index.ts; stream adapters live insrc/stream.ts; request/response converters live insrc/convert.ts; path resolvers live insrc/paths.ts. Co-locate a*.test.tsnext to each. - New E2E fixture:
packages/e2e-tests/src/mock-antigravity-server.tsfor the server side, then a scenario in one of the three*.e2e.test.tsfiles. The harness contract isE2eHarnessfrompackages/e2e-tests/src/harness.ts. - New config field: add the Zod field in
packages/opencode/src/plugin/config/schema.ts(and the operator runtime override inconfig/operator-settings-schema.tsif the field is mutable from/antigravity-*). Re-runbun run --cwd packages/opencode build:schemasoassets/antigravity.schema.jsonstays in sync. The loader tolerates a missing field —loadConfigFileinconfig/loader.tsswallows malformed JSON and falls back to defaults.
These are the file clusters where one logical change needs to touch more than one path. A coordinated change should land in the same PR.
| Change | Files that must move |
|---|---|
| Rename or change a core export | packages/core/src/index.ts + the source file + the per-file test + the re-exporter in packages/opencode/src/plugin/transform/{index.ts,...} (if it's a transform) + every .test.ts that imports the old name. |
Add a new @cortexkit/antigravity-auth-core dependency in packages/opencode or packages/pi |
Bump the published version, then re-run scripts/version-sync.mjs so dependents pick up the new pin. |
| Add a modal command | constants.ts (ANTIGRAVITY_*_COMMAND_NAME), plugin/commands.ts (MODAL_COMMANDS, applyCommand), plugin/catalog.ts (registerAntigravityCommands, applyAntigravityProviderCatalog), rpc/protocol.ts (CommandModalName), tui/command-dialogs.tsx (dialog payload builder) + the matching *.test.ts siblings. The pinning test in plugin/commands.test.ts will fail if any one drifts. |
Change SidebarStateV1 schema |
packages/opencode/src/sidebar-state.ts (schema + writers + merge), packages/opencode/src/tui.tsx (render), packages/opencode/src/tui.test.tsx (render assertions). The TUI is a polling consumer — version bumps are additive, not breaking. |
| Change a session-shape contract | packages/core/src/agy-request-metadata.ts (storage, buildAgyRequestMetadata), packages/opencode/src/plugin/agy-request-metadata.ts (host adapter), packages/opencode/src/plugin/session-context.ts (registry), every *.test.ts that pins trajectory / labels. |
| Change an OAuth step | packages/core/src/antigravity/oauth.ts (the truth), packages/opencode/src/antigravity/oauth.ts (host re-export), packages/opencode/src/plugin/server.ts (callback listener), packages/opencode/src/plugin/oauth-methods.ts (UI flow), packages/pi/src/index.ts (Pi adapter — uses authorizeAntigravity + exchangeAntigravity directly). |
| Change the refresh queue cadence | packages/core/src/auth.ts (buffer), packages/core/src/rotation.ts (backoff), packages/opencode/src/plugin/refresh-queue.ts (cadence), the operator settings override in config/operator-settings-schema.ts, the dialog in packages/opencode/src/plugin/commands.ts. |
| Bump a published package | scripts/release.sh (one command) + scripts/version-sync.mjs (writes the new version + cross-package pin). GitHub Actions re-tests, then publishes via OIDC. |
| Change the loopback RPC contract | packages/opencode/src/rpc/protocol.ts + rpc-server.ts + rpc-client.ts + rpc/notifications.ts + rpc/port-file.ts. The TUI's entry.mjs loader does not change. |
| Add a TUI-rendered sidebar field | sidebar-state.ts (schema + writer), tui.tsx (renderer). The TUI uses Bun's OpenTUI preload during dev (bunfig.toml), so no separate rebuild for dev iteration — only the scripts/build-tui.ts step for shipping. |