Skip to content

Conversation

@elithrar
Copy link
Contributor

@elithrar elithrar commented Jan 4, 2026

Fixes issues where permissions requests block indefinitely in CI/GitHub Actions, with no output indicating why. I keep running into this in CI runs, especially when the harness is trying to solve a problem or I'm testing/building plugins.

Since there's no way to prompt a user, it should just auto-deny by default + emit this to the logs so users can understand what happened.

Changes

  • Add isInteractive() utility - checks CI env var, OPENCODE_CLIENT, and TTY state
  • Auto-deny permission requests when !isInteractive() (no one to approve)
  • Emit permission.asked events before denying so they're visible in logs
  • Subscribe to permission events in github.ts and run.ts with actionable guidance on how to allow
  • Add OPENCODE_EMIT_SUBAGENT_EVENTS flag for verbose subagent output in CI
  • Add emit_subagent_events input to GitHub Action
  • Deny question permission by default in GitHub Action sessions (merged from dev)

isInteractive() Logic

Only auto-denies for the CLI client in non-TTY/CI environments:

  1. OPENCODE_FORCE_INTERACTIVE=true → interactive (for tests)
  2. CI=true → non-interactive (auto-deny)
  3. OPENCODE_CLIENT is not cli (e.g. desktop) → interactive (GUI handles permissions)
  4. Otherwise, check stdin.isTTY && stdout.isTTY

current possible OPENCODE_CLIENT values: cli (default), desktop

Example Output

When a permission is denied in CI:

| Denied  external_directory: /tmp/opencode-source
  To allow, add to opencode.json: { "permission": { "external_directory": "allow" } }

Merge Conflict Resolution

Resolved conflict with dev branch - combined:

  • Permission config from dev (deny question prompts in GitHub Action context)
  • Event unsubscribe cleanup from this PR branch

- Add isInteractive() utility to detect CI/non-TTY environments
- Auto-deny permission requests when running non-interactively
- Emit permission.asked events before denying for visibility
- Subscribe to permission events in github.ts and run.ts with actionable guidance
- Add OPENCODE_EMIT_SUBAGENT_EVENTS flag for verbose subagent output
- Add emit_subagent_events input to GitHub Action
Comment on lines +131 to +139
const info: Request = {
id,
...request,
}

// Non-interactive mode: no one to approve, auto-deny
if (!isInteractive()) {
Bus.publish(Event.Asked, info)
log.warn("auto-denied permission in non-interactive mode", {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im not sure this is the correct approach, wouldnt this fail for desktop app and other clients?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good call - are there stable ways to detect desktop app? Other clients? Or TUI / terminal client?

any/all of these we can use to make sure we are operating in a terminal-only env.

(CI=true is easy but getting TTY state may fail)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rekram1-node - OK, after some investigation, updated the PR:

  • this ONLY applies when OPENCODE_CLIENT is set to cli
  • thus, other clients, such as desktop today or any future client enum, won't be impacted
  • this should guard against cases where this would interfere with non-CLI clients

GUI clients like the desktop app handle permissions through their own UI,
so we should not auto-deny when OPENCODE_CLIENT is set to something other
than 'cli'.
Combined both changes:
- Keep permission config from dev (deny question prompts in GitHub context)
- Keep unsubscribeEvents return value from PR branch (for proper cleanup)
@github-actions
Copy link
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

- Fix unsubscribeEvents shadowing bug in github.ts (cleanup was never called)
- Make CI env var check case-insensitive (CI=TRUE now works)
- Use bracket notation for env var access (codebase consistency)
- Add unit tests for isInteractive() covering all code paths
Keep both additions:
- OPENCODE_EMIT_SUBAGENT_EVENTS from this PR
- OPENCODE_SERVER_PASSWORD/USERNAME from dev
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants