Skip to content

Running service never picks up opencode.jsonc edits on Linux (config-directory watcher unsupported) #56255

Closed as duplicate

Description

@jbmestelan

config: running service never picks up opencode.jsonc edits on Linux (config-directory watcher unsupported)

Summary

On Linux, a long-running background service keeps using the opencode.jsonc content it loaded at startup. Editing permissions/policies in ~/.config/opencode/opencode.jsonc has no effect for subsequent sessions, with no warning to the user, because the config-directory watcher fails to start. The user believes ask rules and deny policies are protecting them while the service runs with the previous (permissive) config.

Environment

  • opencode version: 2.0.31+22728d6
  • OS: Linux euterpe 6.12.91 #1-NixOS SMP PREEMPT_DYNAMIC Sat May 23 11:05:02 UTC 2026 x86_64 GNU/Linux (NixOS 25.11, unstable channel)
  • Terminal: TERM_PROGRAM=ghostty, TERM=xterm-256color, COLORTERM=truecolor
  • Shell: /run/current-system/sw/bin/zsh
  • Install/channel: channel=prod, local=false; installed from the Nix flake (nix store path /nix/store/nx8y73d8m4pac0v2144bqjjpbh8hfsmp-opencode-2.0.31+22728d6/bin/.opencode-wrapped); desktop client talking to the shared background service (opencode serve --service)
  • Active plugins: builtin only, no third-party plugins; the relevant one is opencode.config.location-watcher ({"id":"opencode.config.location-watcher","source":{"type":"builtin"},"features":{"server":true},"state":{"status":"active"}})

Reproduction

  1. Start the shared service with a minimal global config, so it is loaded at boot:

    { "$schema": "https://opencode.ai/config.json" }
  2. While the service is still running, replace the file with rules that must prompt or block:

    {
      "$schema": "https://opencode.ai/config.json",
      "permissions": [
        { "action": "external_directory", "resource": "*", "effect": "ask" },
        { "action": "shell", "resource": "*", "effect": "ask" }
      ],
      "policies": [
        { "action": "tool.use", "resource": "shell:sudo *", "effect": "deny" },
        { "action": "tool.use", "resource": "shell:rm -rf *", "effect": "deny" }
      ]
    }
  3. In a new session, have the agent run a shell command covered by the deny policy (for example sudo --version) and any other shell command.

Expected Behavior

The service reloads the config (or at minimum reports that it could not), so the new session prompts for shell/external_directory and sudo --version fails with Blocked by configuration policy.

Actual Behavior

The service keeps the config loaded at startup for the lifetime of the process:

  • sudo --version executed normally, and shell commands ran with no approval prompt at all.

  • rm -rf <dir> executed, even though shell:rm -rf * is a hard deny.

  • GET /api/config for the already-booted location returns the document with only the startup content, while the same file parsed in a fresh location returns the full rule set:

    $ opencode api get /api/config | jq -c '.[] | select(.type=="document") | (.info|keys)'
    ["$schema"]
    
    # same file, location that had not been booted before:
    $ opencode api get '/api/config?location[directory]=/tmp/scratch' | jq -c '.[] | select(.type=="document") | (.info|keys)'
    ["$schema","permissions","policies"]
  • At startup the config-directory subscription fails while other watchers start normally:

    timestamp=2026-10-16T18:44:38.471Z level=INFO  run=f797ba4f message="watcher subscribe" path=/home/jb/.config/opencode type=directory ignores=3 role=server
    timestamp=2026-10-16T18:44:38.473Z level=ERROR run=f797ba4f message="watcher backend not supported" directory=/home/jb/.config/opencode platform=linux role=server
    timestamp=2026-10-16T18:44:38.474Z level=INFO  run=f797ba4f message="watcher subscribe" path=/etc type=entries ignores=0 role=server
    timestamp=2026-10-16T18:44:38.474Z level=INFO  run=f797ba4f message="watcher started"  path=/etc type=entries backend=node ignores=0 role=server
    

    File-level watchers for AGENTS.md, skill, skills and entries watchers for /, /home, /home/jb all start with backend=node; only the recursive config-directory watch is unsupported. The error repeats on every location boot (12 occurrences in one session).

Additional Context

  • Workaround (verified): restarting the service picks the new config up. After opencode service restart, GET /api/config reports ["$schema","permissions","policies"], all five tool.use policies are present, and enforcement works as documented (approval prompts appear; denied commands are blocked).
  • Restarting fixes enforcement but not the root cause: the config-directory watcher still fails to start on Linux, so the next edit is silently ignored again.
  • Impact is security-relevant: permissions/policies are documented as the mechanism that makes an ask-by-default profile with un-liftable denies ("Policy … overrides an ask and an 'Allow always' approval alike") safe to run without a sandbox. In this situation those rules are simply absent, so the session falls back to the base policy { "action": "*", "resource": "*", "effect": "allow" }, and nothing is prompted or denied.
  • Timing in the reported case: the service booted at 20:44:38 local, the config was rewritten at 21:12:25 local, and sessions started afterwards still ran unrestricted.
  • Not caused by per-session modes: the service is launched as plain opencode serve --service (no --auto, --yolo, --dangerously-skip-permissions), no session has a permission mode set, and /api/permission/saved was empty at the time.
  • The config file is a mkOutOfStoreSymlink-style symlink from home-manager into the repo (~/.config/opencode/opencode.jsonc → /data/.../dotfiles/config/opencode/opencode.jsonc). The content parses correctly when read fresh, so this is not a JSONC/schema issue.
  • Suggestion: since a stale config is invisible, either support/poll the config directory on Linux, or log a warning when the config watcher cannot be established, and/or expose an explicit "config changed on disk, reload required" signal to clients.

Activity

  1. opencode-agent commented on Oct 16, 2026

    @opencode-agent
    Contributor

    Thanks for the very thorough report. I think this is a duplicate of #53210.

    The watcher backend not supported error is logged when OpenCode can't load its native recursive file watcher (@parcel/watcher). Only directory watches use it: the file and entries watchers use node's fs.watch, which is why those all start with backend=node and only the config-directory watch fails. #53210 explains why this happens on the Nix flake build: the bundled watcher.node links libstdc++.so.6, and the Nix wrapper doesn't make it available. Recursive watches then never start, and config edits never reach the running service. PR #53213 proposes a fix and is still open.

    Possible duplicates and related issues, ordered from most to least likely:

    Until it's fixed, opencode service restart works around it. #53920 also reports that opencode api post /api/location/reload applied a config change. The PR #53213 thread describes how to put libstdc++ on the watcher's library path. The release binary run through nix-ld reportedly loads the watcher fine.

    Your point that a stale security config gives no visible warning is a good one. It would be worth adding to #53210.

    The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.

  2. opencode-agent commented on Oct 17, 2026

    @opencode-agent
    Contributor

    Closing this as a duplicate of #53210, since there hasn't been a reply in the past day. The watcher backend not supported error for the config directory has the same cause described there: on the Nix flake build, the native recursive watcher can't load libstdc++.so.6. Please follow #53210 and PR #53213 for the fix. Your point that a stale security config gives no visible warning would be a useful addition there. Until it's fixed, opencode service restart picks up config edits. If your problem turns out to be different, reply here and we can reopen it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions