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
Problem
On macOS,
launchddoes not inherit the user's shell PATH. The scheduler handles this by injecting a hardcodedPATHinto theEnvironmentVariablesblock of the generated.plist: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:Why
env.set.PATHdoesn't fix itSchedulerConfigalready has anenv.setfield that users can configure in~/.config/opencode/opencode-scheduler.json. However,env.setis applied to run-time environment (theopencode runinvocation), not to the plistEnvironmentVariablesblock that launchd reads before even launching the supervisor. So settingPATHviaenv.setdoes not solve the problem for launchd/systemd scheduled runs.Proposed solution
Add an
extraPathsarray toSchedulerConfig(and/orSchedulerEnvConfig) that gets prepended to the plist PATH during plist/unit generation:Then in plist/systemd unit generation:
And pass the config value when calling it:
Users could then configure it in
~/.config/opencode/opencode-scheduler.json:{ "extraPaths": [ "~/.local/bin", "~/.cargo/bin", "~/.bun/bin" ] }The scheduler would need to expand
~tohomedir()when building the path string.Notes
cronandschtasksbackends may need similar treatment.PATHfromenv.setand prepend it to the generated plist PATH — but an explicitextraPathsfield is clearer and avoids confusion with the run-timeenv.setsemantics.Environment
opencode-schedulerv1.3.0~/.local/bin