Skip to content

feat: make getEnhancedPath() configurable via opencode-scheduler.json (extra PATH entries for launchd/systemd) #16

Description

@mdperez

Problem

On macOS, launchd does not inherit the user's shell PATH. The scheduler handles this by injecting a hardcoded PATH into the EnvironmentVariables block of the generated .plist:

function getEnhancedPath(): string {
  const paths = [
    "/opt/homebrew/bin",
    "/usr/local/bin",
    "/usr/bin",
    "/bin",
    "/usr/sbin",
    "/sbin",
  ]
  return paths.join(":")
}

Any tool installed outside these directories (e.g. in ~/.local/bin, ~/.cargo/bin, ~/.bun/bin, ~/.asdf/shims...) is invisible to scheduled jobs. The symptom is log lines like:

[rtk] rtk binary not found in PATH — plugin disabled

Why env.set.PATH doesn't fix it

SchedulerConfig already has an env.set field that users can configure in ~/.config/opencode/opencode-scheduler.json. However, env.set is applied to run-time environment (the opencode run invocation), not to the plist EnvironmentVariables block that launchd reads before even launching the supervisor. So setting PATH via env.set does not solve the problem for launchd/systemd scheduled runs.

Proposed solution

Add an extraPaths array to SchedulerConfig (and/or SchedulerEnvConfig) that gets prepended to the plist PATH during plist/unit generation:

type SchedulerConfig = {
  env?: SchedulerEnvConfig
  extraPaths?: string[]   // ← new field
}

Then in plist/systemd unit generation:

function getEnhancedPath(extraPaths: string[] = []): string {
  const basePaths = [
    "/opt/homebrew/bin",
    "/usr/local/bin",
    "/usr/bin",
    "/bin",
    "/usr/sbin",
    "/sbin",
  ]
  return [...extraPaths, ...basePaths].join(":")
}

And pass the config value when calling it:

const config = loadSchedulerConfig()
const enhancedPath = getEnhancedPath(config.extraPaths)

Users could then configure it in ~/.config/opencode/opencode-scheduler.json:

{
  "extraPaths": [
    "~/.local/bin",
    "~/.cargo/bin",
    "~/.bun/bin"
  ]
}

The scheduler would need to expand ~ to homedir() when building the path string.

Notes

  • This affects all platforms that inject PATH into OS scheduler units (launchd on macOS, systemd on Linux).
  • The cron and schtasks backends may need similar treatment.
  • A simpler alternative would be to also read PATH from env.set and prepend it to the generated plist PATH — but an explicit extraPaths field is clearer and avoids confusion with the run-time env.set semantics.

Environment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions