Skip to content

chore: oc server related improvements#194

Merged
MihalyToth20 merged 5 commits intomainfrom
dev
Apr 28, 2026
Merged

chore: oc server related improvements#194
MihalyToth20 merged 5 commits intomainfrom
dev

Conversation

@MihalyToth20
Copy link
Copy Markdown
Collaborator

@MihalyToth20 MihalyToth20 commented Apr 28, 2026

Summary by CodeRabbit

  • New Features

    • Added --cwd and --workdir options to control OpenCode proxy working directory.
    • Added native-host status subcommand to verify native host configuration.
    • Introduced environment variables for working directory and proxy mode configuration.
  • Documentation

    • Updated OpenCode setup guide with working directory examples and new configuration options.
    • Enhanced native-host command documentation with status output details.
  • Chores

    • Added changesets for patch releases.

Unify native-host and oc serve process startup through one internal launcher so cwd/env/cors behavior stays consistent.

Also allow additional native-host extension IDs via CALY_NATIVE_HOST_EXTENSION_IDS for sideloaded installs.
Add native-host status diagnostics and tighten direct native-host dispatch so subcommands route through Commander.

Also add oc proxy workdir overrides via --cwd/--workdir with shared workspace defaults and explicit override handling.
Document native-host status command and new oc --cwd/--workdir behavior.

Clarify default shared workspace behavior and current-directory override options.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 28, 2026

🦋 Changeset detected

Latest commit: 460470f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@calycode/cli Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 28, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 22009b44-414a-4584-a6b8-82fdf220a4ef

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR introduces a new native-host status command for OpenCode, refactors OpenCode server startup into a shared launchOpencodeServer function, adds --cwd and --workdir CLI options for controlling working directory, updates routing logic for native-host detection from global to positional, and updates documentation accordingly.

Changes

Cohort / File(s) Summary
Changeset Metadata
.changeset/hot-worms-juggle.md, .changeset/yummy-trains-boil.md
Two changeset entries for patch-level releases documenting CLI improvements for native-host and working directory handling.
Documentation Updates
docs/commands/oc-native-host.md, docs/commands/oc.md, docs/guides/opencode-setup.md
Updated documentation describing native-host operations, new --cwd and --workdir options, default shared workspace behavior, and environment variables for OpenCode working directory control.
CLI Implementation
packages/cli/src/commands/opencode/implementation.ts
Added showNativeHostStatus() for reporting manifest/wrapper/registry status; introduced launchOpencodeServer() to centralize server startup logic; extended getOpencodeWorkingDir() to support explicit workdir resolution and CALY_OC_CWD flag; refactored native-host and service mode server launching to use shared helpers.
CLI Command Registration
packages/cli/src/commands/opencode/index.ts
Refactored argument parsing to extract --cwd and --workdir flags from raw arguments; added new native-host status subcommand; wired command registration to use showNativeHostStatus() and proxyOpencode() with parsed options.
CLI Routing Logic
packages/cli/src/index.ts, packages/cli/src/index-bundled.ts
Changed native-host detection from global includes-based check to positional logic verifying native-host appears immediately after the last opencode/oc token with no trailing arguments.

Sequence Diagram

sequenceDiagram
    participant Client
    participant CLI as CLI Implementation
    participant Manifest as Manifest File
    participant Wrapper as Wrapper File
    participant Registry as Windows Registry
    participant Extension as Extension Origins

    Client->>CLI: showNativeHostStatus()
    
    CLI->>Manifest: Check manifest path exists
    Manifest-->>CLI: manifest exists/missing
    
    CLI->>Wrapper: Check wrapper executable exists
    Wrapper-->>CLI: wrapper exists/missing
    
    CLI->>Registry: Query native messaging registry key
    Registry-->>CLI: registry config exists/missing
    
    CLI->>Manifest: Read manifest allowed_origins
    Manifest-->>CLI: origins list
    
    CLI->>Extension: Verify extension IDs in origins
    Extension-->>CLI: match/mismatch detected
    
    CLI->>Client: Report status + warning if mismatches
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • refactor!: rename command #188: Modifies CLI native-host routing/detection logic in the same files (packages/cli/src/index.ts and packages/cli/src/index-bundled.ts), indicating closely related changes to command routing behavior.

Poem

🐰 Hops through native-host commands with glee,
Status checks and working dirs, wild and free!
Refactored servers, routing refined,
OpenCode flows now beautifully aligned! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'chore: oc server related improvements' is partially related to the changeset. While server improvements are included, the PR also encompasses significant documentation updates, new CLI options (--cwd, --workdir), environment variable documentation, native host status checking, and command refactoring. The title focuses narrowly on server aspects and misses the broader scope of CLI enhancements and documentation updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
packages/cli/src/commands/opencode/index.ts (2)

246-252: Silent failure when --workdir has no value argument.

If a user provides --workdir as the last argument without a path, the code silently continues without setting explicitWorkdir. This could confuse users who expect the option to work.

Consider logging a warning when the value is missing:

♻️ Suggested improvement
              if (arg === '--workdir') {
                 const next = passThroughArgs[i + 1];
                 if (next) {
                    explicitWorkdir = next;
                    i++;
+                } else {
+                   log.warn('--workdir requires a path argument; ignoring.');
                 }
                 continue;
              }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/commands/opencode/index.ts` around lines 246 - 252, The
parsing branch handling the "--workdir" option silently ignores the flag when
it's the last arg (no value); update the block that checks if (arg ===
'--workdir') to detect when passThroughArgs[i + 1] is undefined and emit a clear
warning (e.g., console.warn or the CLI logger) stating that "--workdir" was
provided without a value, instead of just continuing; if desired, also consider
failing early or showing usage, but at minimum log the missing-value warning
before continuing, while keeping the existing behavior of setting
explicitWorkdir = next when next is present.

19-19: Consider adding type annotation to program parameter.

The program parameter lacks an explicit type annotation. Per coding guidelines, explicit typing is preferred over implicit any.

♻️ Suggested fix
-async function registerOpencodeCommands(program) {
+async function registerOpencodeCommands(program: import('commander').Command) {

Or import the type at the top of the file:

import type { Command } from 'commander';
// ...
async function registerOpencodeCommands(program: Command) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/commands/opencode/index.ts` at line 19, The function
registerOpencodeCommands has an untyped parameter "program"; add an explicit
type annotation (e.g., program: Command) by importing the Command type from
'commander' at the top of the file (import type { Command } from 'commander')
and update the function signature to async function
registerOpencodeCommands(program: Command) { ... }; also update any local
references or tests that call registerOpencodeCommands if they rely on the
implicit any to ensure type compatibility.
packages/cli/src/commands/opencode/implementation.ts (2)

102-212: Pre-existing concern: Process ownership verification.

Based on learnings from a previous review, killProcessOnPort() kills any process on the port without verifying ownership. The recommended solution was to persist the server's PID to a file (~/.calycode/opencode/server.pid) and only kill processes with tracked PIDs. This issue predates this PR but may be worth addressing in a follow-up to prevent accidentally killing unrelated processes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/commands/opencode/implementation.ts` around lines 102 - 212,
killProcessOnPort currently kills any process listening on the target port;
change it to read the persisted PID at ~/.calycode/opencode/server.pid (create
helper like getPersistedServerPid or readPersistedPid) and only attempt to kill
PIDs that match the persisted PID(s); in Windows branch (netstat parsing) and
Unix branch (fuser/lsof parsing) compare discovered PIDs against the persisted
PID and skip/klog any non-matching processes, and if no discovered PID matches
the persisted one return false and log that the tracked server PID was not
found; ensure writing the PID when starting the server (e.g., saveServerPid) and
handle missing/invalid PID file gracefully.

566-575: Minor redundancy in args construction for logging.

The args array on line 566 is constructed solely for logging purposes, while launchOpencodeServer internally constructs its own args. This is acceptable for debugging but could be simplified by having launchOpencodeServer return or log the args it uses.

The refactoring to use the shared helper is a good improvement for maintainability.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/commands/opencode/implementation.ts` around lines 566 - 575,
The local construction of the args array (const args = [...,
getCorsArgs(extraOrigins)]) is redundant because launchOpencodeServer builds its
own args; remove that local args construction and logging, and instead expose
the arg-builder from launchOpencodeServer (either by returning the args when
calling launchOpencodeServer or by creating a shared helper like
buildOpencodeArgs/getOpencodeArgs) so the caller can log the exact args and
launchOpencodeServer can reuse the same arg-builder; update the call site to use
getOpencodeArgs(...) for logger.log and pass the same args or rely on
launchOpencodeServer returning them, preserving existing logger.log lines (use
getCalycodeOpencodeConfigDir, getOpencodeWorkingDir and getCorsArgs names to
locate usages).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/cli/src/index.ts`:
- Around line 10-17: The native-host detection in index.ts (using commandIndex,
args and isDirectNativeHostInvocation) is missing the chrome-extension://
argument check present in index-bundled.ts; update the detection logic to also
detect a chromeExtensionArg (e.g., any arg starting with "chrome-extension://")
and route those invocations to startNativeHost() just like the bundled
entrypoint, ensuring args with chrome-extension:// are handled before falling
through to program.parseAsync().

---

Nitpick comments:
In `@packages/cli/src/commands/opencode/implementation.ts`:
- Around line 102-212: killProcessOnPort currently kills any process listening
on the target port; change it to read the persisted PID at
~/.calycode/opencode/server.pid (create helper like getPersistedServerPid or
readPersistedPid) and only attempt to kill PIDs that match the persisted PID(s);
in Windows branch (netstat parsing) and Unix branch (fuser/lsof parsing) compare
discovered PIDs against the persisted PID and skip/klog any non-matching
processes, and if no discovered PID matches the persisted one return false and
log that the tracked server PID was not found; ensure writing the PID when
starting the server (e.g., saveServerPid) and handle missing/invalid PID file
gracefully.
- Around line 566-575: The local construction of the args array (const args =
[..., getCorsArgs(extraOrigins)]) is redundant because launchOpencodeServer
builds its own args; remove that local args construction and logging, and
instead expose the arg-builder from launchOpencodeServer (either by returning
the args when calling launchOpencodeServer or by creating a shared helper like
buildOpencodeArgs/getOpencodeArgs) so the caller can log the exact args and
launchOpencodeServer can reuse the same arg-builder; update the call site to use
getOpencodeArgs(...) for logger.log and pass the same args or rely on
launchOpencodeServer returning them, preserving existing logger.log lines (use
getCalycodeOpencodeConfigDir, getOpencodeWorkingDir and getCorsArgs names to
locate usages).

In `@packages/cli/src/commands/opencode/index.ts`:
- Around line 246-252: The parsing branch handling the "--workdir" option
silently ignores the flag when it's the last arg (no value); update the block
that checks if (arg === '--workdir') to detect when passThroughArgs[i + 1] is
undefined and emit a clear warning (e.g., console.warn or the CLI logger)
stating that "--workdir" was provided without a value, instead of just
continuing; if desired, also consider failing early or showing usage, but at
minimum log the missing-value warning before continuing, while keeping the
existing behavior of setting explicitWorkdir = next when next is present.
- Line 19: The function registerOpencodeCommands has an untyped parameter
"program"; add an explicit type annotation (e.g., program: Command) by importing
the Command type from 'commander' at the top of the file (import type { Command
} from 'commander') and update the function signature to async function
registerOpencodeCommands(program: Command) { ... }; also update any local
references or tests that call registerOpencodeCommands if they rely on the
implicit any to ensure type compatibility.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ec664a7b-3325-4cdb-aaeb-7041ecd19590

📥 Commits

Reviewing files that changed from the base of the PR and between 3a026b8 and 27c2aeb.

📒 Files selected for processing (9)
  • .changeset/hot-worms-juggle.md
  • .changeset/yummy-trains-boil.md
  • docs/commands/oc-native-host.md
  • docs/commands/oc.md
  • docs/guides/opencode-setup.md
  • packages/cli/src/commands/opencode/implementation.ts
  • packages/cli/src/commands/opencode/index.ts
  • packages/cli/src/index-bundled.ts
  • packages/cli/src/index.ts

Comment thread packages/cli/src/index.ts Outdated
Comment on lines +10 to +17

const commandIndex = Math.max(args.lastIndexOf('opencode'), args.lastIndexOf('oc'));
const isDirectNativeHostInvocation =
commandIndex >= 0 &&
args[commandIndex + 1] === 'native-host' &&
commandIndex + 2 >= args.length;

if (isDirectNativeHostInvocation) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing chrome-extension:// argument handling compared to bundled entry point.

The index-bundled.ts file (lines 42-47 in the relevant snippet) includes an additional check for chrome-extension:// arguments that routes those invocations directly to startNativeHost(). This file lacks that check, meaning:

  • Bundled binary: chrome-extension://... args → startNativeHost()
  • This file: chrome-extension://... args → program.parseAsync() (Commander)

This could cause inconsistent behavior when the native messaging host is invoked by Chrome on different platforms. If the non-bundled entry point is ever used as the native host target, Chrome's invocation would fail.

Consider adding the same chromeExtensionArg check here for consistency:

🔧 Suggested fix
 const args = process.argv;
 exitIfLegacyXanoInvocation(args);

+const chromeExtensionArg = args.find((arg) => arg.startsWith('chrome-extension://'));
 const commandIndex = Math.max(args.lastIndexOf('opencode'), args.lastIndexOf('oc'));
 const isDirectNativeHostInvocation =
    commandIndex >= 0 &&
    args[commandIndex + 1] === 'native-host' &&
    commandIndex + 2 >= args.length;

-if (isDirectNativeHostInvocation) {
+if (chromeExtensionArg || isDirectNativeHostInvocation) {
    startNativeHost();
 } else {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/index.ts` around lines 10 - 17, The native-host detection in
index.ts (using commandIndex, args and isDirectNativeHostInvocation) is missing
the chrome-extension:// argument check present in index-bundled.ts; update the
detection logic to also detect a chromeExtensionArg (e.g., any arg starting with
"chrome-extension://") and route those invocations to startNativeHost() just
like the bundled entrypoint, ensuring args with chrome-extension:// are handled
before falling through to program.parseAsync().

@MihalyToth20 MihalyToth20 merged commit 44e1f3e into main Apr 28, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant