Skip to content

op plugin run -- gh fails with "interactive IO not available" after successful biometric approval #575

Open

Description

@SamBarker

Environment:

  • op version: 2.32.0
  • gh version: 2.86.0
  • macOS: 26.2 (Build 25C56)
  • Context: Claude Code CLI tool (non-interactive subprocess, no TTY)

Description:

Running op plugin run -- gh api ... from a non-interactive shell (Claude Code's Bash tool, which has no TTY) triggers the 1Password biometric prompt as expected. After successfully approving the prompt, the command fails with:

[ERROR] 2026/02/12 21:13:17 interactive IO not available

Steps to Reproduce:

  1. Configure gh shell plugin with 1Password (alias gh='op plugin run -- gh')
  2. Run a gh command from a context with no TTY attached (e.g., a subprocess without a pseudo-terminal)
  3. 1Password biometric prompt appears and is approved
  4. Command fails with interactive IO not available

Expected Behavior:

After successful biometric approval, op should inject the credential and run gh to completion. The authentication gate has been passed — there should be no further need for interactive IO.

Actual Behavior:

op fails post-approval with interactive IO not available. The credential was presumably unlocked, but something in the post-auth flow requires a TTY that isn't present.

Workaround:

Bypass the plugin entirely and call the gh binary directly (e.g., /opt/homebrew/bin/gh), relying on gh's own stored auth token.

Notes:

  • tty returns not a tty and [[ -t 0 ]] is false in this context
  • This differs from #120 where the alias isn't available at all. Here, op plugin run is invoked explicitly and the biometric prompt works — the failure is post-authentication.
  • Once the session is cached (presumably from a recent approval), subsequent calls from the same non-TTY context succeed. This suggests the error only occurs during the initial credential provisioning flow.

Activity

  1. self-assigned this
    on May 1, 2026
  2. claco-dyania commented on May 19, 2026

    @claco-dyania

    Just hit this today. 1P gh auth was working fine. Token expired so I imported a new one and have clear the gh plugin and re-identified the token. Now for the first time, I'm getting this error on osx.

  3. mjangda commented on May 19, 2026

    @mjangda

    A workaround I've found is to use a PreToolUse hook to intercept Bash commands invoking gh and rewrite them to inject a token reference to 1Password.

    Ideally, this would just be fixed in 1Password CLI.


    The bash script at ~/.claude/hooks/op-gh-credentials.sh (update op://<vault>/<item>/<field> to point to your token entry or set the value in OP_GH_TOKEN_REF):

      #!/usr/bin/env bash
      # PreToolUse hook: wrap `gh` Bash commands with `op run` to inject
      # GH_TOKEN from 1Password. Override the secret ref with OP_GH_TOKEN_REF.
      set -uo pipefail
    
      command -v jq >/dev/null || exit 0
      command -v op >/dev/null || exit 0
    
      input=$(cat)
      read -r tool_name cmd < <(
        jq -r '[.tool_name, (.tool_input.command // "")] | @tsv' <<<"$input"
      ) || exit 0
    
      [[ $tool_name == Bash ]] || exit 0
    
      # Rewrite only bare `gh` invocations that aren't already op-wrapped.
      gh_re='(^|[[:space:];&|(])gh([[:space:]]|$)'
      op_re='(^|[[:space:];&|(])op[[:space:]]+(run|plugin)'
      [[ $cmd =~ $gh_re && ! $cmd =~ $op_re ]] || exit 0
    
      ref=${OP_GH_TOKEN_REF:-op://<vault>/<item>/<field>}
      new_cmd=$(printf 'GH_TOKEN=%q op run -- bash -c %q' "$ref" "$cmd")
    
      jq -nc --arg cmd "$new_cmd" '{
        hookSpecificOutput: {
          hookEventName: "PreToolUse",
          permissionDecision: "allow",
          updatedInput: { command: $cmd }
        }
      }'
    

    Then, registration in ~/.claude/settings.json:

      {
        "hooks": {
          "PreToolUse": [
            {
              "matcher": "Bash",
              "hooks": [
                {
                  "type": "command",
                  "command": "/Users/<you>/.claude/hooks/op-gh-credentials.sh",
                  "timeout": 5
                }
              ]
            }
          ]
        }
      }
    
  4. scottisloud commented on May 19, 2026

    @scottisloud
    Contributor

    A workaround I've found is to use a PreToolUse hook to intercept Bash commands invoking gh and rewrite them to inject a token reference to 1Password.

    Ideally, this would just be fixed in 1Password CLI.

    Ah, the PreToolUse hook was where I had landed too. Yours is a bit more robust than what I'd cooked up, which still left a couple rough edges, so I'll let yours be the canonical hook definition.

    We have this logged internally but don't have anything to share about future improvements on this front, yet.

  5. SamBarker commented on May 19, 2026

    @SamBarker
    Author

    I haven't specifically tested the proposed PreToolUse hook, I was trying to understand it properly before applying it... and Claude had this to say:

    Yes, exactly. The op plugin run path reads those plugin config files to decide which credential to inject based on context (repo, org, subcommand, etc.). The op run approach hardcodes a single secret reference and injects it as GH_TOKEN unconditionally — the plugin system is completely bypassed.
    So if your gh.json does anything like mapping different tokens to different orgs or repos, that nuance would be lost. Every gh call from Claude Code would get the same token regardless of which repo you're working in.

    Where the op run approach is what this PreToolUse hook does. So might well be the right choice for people but its not a universal solution. I'm off to do more digging for my local needs.

  6. scottisloud commented on Jul 16, 2026

    @scottisloud
    Contributor

    A fix for this shipped in version 2.35 of the 1Password CLI (release notes).
    EDIT: This issue was prematurely closed. This is internally-documented but remains unresolved at this time.

  7. ricky-wong commented on Jul 17, 2026

    @ricky-wong

    Still getting interactive IO not available. Am I missing something? I upgraded 1Password macOS from 8.12.26 to 8.12.28, 1Password CLI from 2.34.0 to 2.35.0, and disabled the hook in ~/.claude/settings.json. Turned the hook back on for now.

  8. scottisloud commented on Jul 20, 2026

    @scottisloud
    Contributor

    Still getting interactive IO not available. Am I missing something? I upgraded 1Password macOS from 8.12.26 to 8.12.28, 1Password CLI from 2.34.0 to 2.35.0, and disabled the hook in ~/.claude/settings.json. Turned the hook back on for now.

    Ack! @ricky-wong you aren't missing anything! My apologies, I actually posted the closing comment on the wrong issue. Re-opening this, and deleting the closing comment, as this remains un-resolved but logged internally.

    I apologize for the error!

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