Skip to content

permission.ask plugin hook is bypassed for first-encounter commands (needsAsk=true) #19927

Closed as not planned

Description

@YumaKakuya

Description

Summary
The permission.ask plugin hook in packages/opencode/src/permission/index.ts is currently wrapped in an if (!needsAsk) guard, which means it only fires for commands that already have an “allow” rule. For first-encounter commands where needsAsk=true, the hook is completely bypassed.

This effectively prevents plugins from intercepting or customizing the permission flow for first-encounter commands — the scenario where additional context from plugins is most valuable.

Current behavior
User runs new command → needsAsk=true → hook SKIPPED → standard dialog shown
User runs known command → needsAsk=false → hook fires → plugin can customize

Expected behavior
User runs any command → hook fires with current status ("ask" or "allow") → plugin can override → dialog shown accordingly

Why this matters for plugins
A plugin that wants to provide additional context about commands (e.g., risk assessment, documentation links, custom approval workflows) can only do so for commands the user has already approved. The first encounter — where additional context is most valuable — is unreachable.

Proposed fix
Remove the if (!needsAsk) guard so Plugin.trigger("permission.ask", ...) fires unconditionally. The hook already receives the current permissionStatus (“ask” or “allow”), so plugins can make informed decisions based on the existing status.

let permissionStatus: "ask" | "deny" | "allow" = needsAsk ? "ask" : "allow"

  • if (!needsAsk) {
    const hookResult = yield* Effect.tryPromise(() => Plugin.trigger(
    "permission.ask",
    { sessionID: request.sessionID, permission: request.permission, patterns: request.patterns, metadata: request.metadata },
    { status: permissionStatus },
    )).pipe(Effect.option)
    if (hookResult._tag === "Some") {
    permissionStatus = hookResult.value.status
    }
  • }

Backward compatibility
When no plugin is registered for permission.ask, behavior is identical to current
Existing plugins that only handle needsAsk=false cases continue to work (they receive status: "allow" as before)
The only difference is that plugins now also receive status: "ask" events they previously couldn’t see

Notes
This is a 2-line removal (the if and closing brace)
Backward compatible: no behavioral change when no plugin is registered for this hook
Minor test consideration: Permission.list() calls immediately after Permission.ask() may need to account for the hook firing asynchronously on the new path
I noticed the permission module has been undergoing some refactoring recently. Happy to adapt this proposal to align with the current direction if the approach changes.

Plugins

No response

OpenCode version

No response

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

No response

Terminal

No response

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Mar 29, 2026
  2. github-actions commented on Mar 29, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    • [FEATURE]: Wire the permission.ask plugin hook #19469: "[FEATURE]: Wire the permission.ask plugin hook" — this issue also identifies that the permission.ask plugin hook is not triggered, and proposes wiring it in permission/index.ts. The root cause and proposed fix are essentially the same.
  3. YumaKakuya commented on Mar 29, 2026

    @YumaKakuya
    Author

    Related: #19469 — appears to describe the same underlying issue.
    My analysis points to the if (!needsAsk) guard as the specific cause.

  4. YumaKakuya commented on Apr 2, 2026

    @YumaKakuya
    Author

    I put together a small PR for this so the behavior can be evaluated concretely with a narrow diff and a regression test.

  5. removed
    bugSomething isn't working
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  6. github-actions commented on Jul 3, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

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

Metadata

Metadata

Assignees

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