Forgejo Action that runs opencode on /opencode mentions in issues and PRs, backed by NOMYO AI or any OpenAI-compatible model. https://www.nomyo.ai/
Find a file
2026-05-11 17:27:02 +02:00
node_modules initial commit 2026-05-11 11:18:49 +02:00
.gitignore fix: update workflow 2026-05-11 15:09:43 +02:00
action.yml feat: seperate read/write token for enhanced security 2026-05-11 17:27:02 +02:00
bun.lock initial commit 2026-05-11 11:18:49 +02:00
index.ts feat: seperate read/write token for enhanced security 2026-05-11 17:27:02 +02:00
LICENCE doc: update 2026-05-11 17:03:20 +02:00
package.json initial commit 2026-05-11 11:18:49 +02:00
README.md doc: update 2026-05-11 17:03:20 +02:00
tsconfig.json initial commit 2026-05-11 11:18:49 +02:00

opencode Forgejo Action

A Forgejo Action that runs opencode against a Nomyo (or any OpenAI-compatible) backend, triggered by comments on issues and merge requests.

Mention /opencode or /oc in a comment and opencode reads the thread, executes the requested task, and replies. For "fix" tasks it opens a merge request; for MR comments it commits to the same MR.

Features

Explain an issue

/opencode explain this issue

opencode reads the full thread and replies with an explanation.

Fix an issue

/opencode fix this

opencode creates a branch, implements the change, and opens a merge request.

Update an open MR

Delete the attachment from S3 when the note is removed /oc

opencode commits to the same MR branch.

Review specific code lines

Comment directly on lines in the MR's "Files" tab — opencode receives the file path, line numbers, and diff hunk as context.

/oc add error handling here

Installation

Prerequisites

  • A Forgejo instance with Actions enabled.
  • A runner that can run Docker containers (the example below uses docker-amd64 with node:lts-bookworm).
  • A Forgejo PAT (see scopes below) and a Nomyo API key.

Forgejo PAT scopes

Generate the token at Settings → Applications → Manage Access Tokens with these scopes:

Scope Used for
read:repository Clone, fetch repo info
write:repository Push commits and branches
read:issue Read issue/MR comments and metadata
write:issue Create + update comments, open MRs
read:user Resolve actor info (optional)

Secrets

In Repo Settings → Actions → Secrets add:

Secret Value
FORGEJO_TOKEN The PAT from above
NOMYO_API_KEY Your Nomyo API key

Workflow file

Add .forgejo/workflows/opencode.yml to the repo where you want opencode to respond. This example targets a Forgejo instance hosted under a subpath (bitfreedom.net/code/); adjust URLs and runs-on to match your setup.

name: opencode
on:
  issue_comment:
    types: [created]
  pull_request_review_comment:
    types: [created]

jobs:
  opencode:
    if: |
      contains(github.event.comment.body, '/oc') ||
      contains(github.event.comment.body, '/opencode')
    runs-on: docker-amd64
    container:
      image: node:lts-bookworm
    permissions:
      id-token: write
      contents: write
      pull-requests: write
      issues: write
    steps:
      - name: Install git, curl and Docker
        run: |
          apt-get update -qq
          apt-get install -y -qq git curl unzip docker.io

      - name: Start Docker daemon
        run: |
          dockerd --host=unix:///var/run/docker.sock --iptables=false --dns=8.8.8.8 --dns=8.8.4.4 > /tmp/dockerd.log 2>&1 &
          for i in $(seq 1 30); do
            sleep 2
            docker info > /dev/null 2>&1 && echo "Docker daemon ready" && exit 0
            echo "Waiting for Docker daemon... ($i/30)"
          done
          cat /tmp/dockerd.log
          exit 1

      - name: Checkout repository
        run: |
          git clone --depth=1 --branch "${{ github.ref_name }}" \
            "https://oauth2:${{ github.token }}@bitfreedom.net/code/${{ github.repository }}.git" \
            .

      - name: Fetch action source
        run: |
          git clone --depth=1 --branch v1 \
            "https://oauth2:${{ github.token }}@bitfreedom.net/code/nomyo-ai/actions.git" \
            ./.opencode-action

      - name: Run opencode
        uses: ./.opencode-action
        with:
          nomyo_api_key: ${{ secrets.NOMYO_API_KEY }}
          model: nomyo/unsloth/Qwen3.6-35B-A3B-GGUF:UD-Q4_K_M
          forgejo_api_url: https://bitfreedom.net/code/
          forgejo_token: ${{ secrets.FORGEJO_TOKEN }}

Why the manual clone?

act_runner's uses: parser expects https://<host>/<owner>/<repo> — it does not handle a Forgejo instance hosted under a subpath (e.g. bitfreedom.net/code/). For subpath instances, clone the action source into ./.opencode-action and reference it as a local action (uses: ./.opencode-action). If your Forgejo lives at a domain root, you can replace those two steps with uses: <your-host>/nomyo-ai/actions@v1 directly.

Configuration

Input Required Default Description
model Yes Model in the form provider/model. The provider name becomes a custom opencode provider; the action registers it as an @ai-sdk/openai-compatible provider pointing at nomyo_api_url.
nomyo_api_key Yes API key for the OpenAI-compatible backend.
nomyo_api_url No https://chat.nomyo.ai/api Base URL of the OpenAI-compatible endpoint. The adapter calls ${baseURL}/chat/completions.
forgejo_api_url No https://bitfreedom.net/code/ Forgejo instance base URL.
forgejo_token No Forgejo PAT (see scopes above).
agent No Primary agent name to use.
share No auto Share the opencode session (true/false). Defaults to true for public repos.
prompt No Custom prompt override.
mentions No /opencode,/oc Comma-separated trigger phrases.
variant No Provider-specific reasoning effort (high, max, minimal, …).

Supported Events

Event Triggered by Notes
issue_comment Comment on an issue or MR Body must contain a mention phrase
pull_request_review_comment Comment on a specific line in an MR's Files tab Receives file path, line number, and diff hunk

Architecture

This action is a composite action. On each run it:

  1. Installs Bun and the opencode CLI.
  2. Runs bun install inside the action source.
  3. Registers ${MODEL%/*} as a custom opencode provider via OPENCODE_CONFIG_CONTENT and the API key via OPENCODE_AUTH_CONTENT.
  4. Spawns opencode serve locally and talks to it over HTTP (/session/{id}/message).
  5. Resolves the event, builds a prompt with thread/diff context, sends it to opencode, and posts the response as a comment (and, for "fix" intents, opens an MR).

There is no compiled dist/ artifact — index.ts is executed directly by Bun.

Development

Local test loop (requires Bun and opencode on PATH):

export NOMYO_API_KEY="..."
export NOMYO_API_URL="https://chat.nomyo.ai/api"
export FORGEJO_API_URL="https://bitfreedom.net/code/"
export FORGEJO_TOKEN="..."
export MODEL="nomyo/unsloth/Qwen3.6-35B-A3B-GGUF:UD-Q4_K_M"
export GITHUB_RUN_ID="test-run"
export GITHUB_RUN_NUMBER="1"
export GITHUB_SERVER_URL="https://bitfreedom.net/code"
export GITHUB_REPOSITORY="owner/repo"
export GITHUB_REF_NAME="main"
export GITHUB_ACTOR="testuser"
export GITHUB_EVENT_NAME="issue_comment"
export GITHUB_EVENT_PATH="/tmp/event.json"

cat > /tmp/event.json <<'EOF'
{
  "repository": { "owner": { "login": "owner" }, "name": "repo", "full_name": "owner/repo" },
  "issue": { "number": 1, "index": 1, "title": "Test", "body": "Test", "user": { "login": "testuser" } },
  "comment": { "id": 1, "body": "/oc explain this", "user": { "login": "testuser" } }
}
EOF

bun install
bun run index.ts

License

MIT