Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions packages/opencode/src/command/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { MCP } from "../mcp"
import { Skill } from "../skill"
import PROMPT_INITIALIZE from "./template/initialize.txt"
import PROMPT_REVIEW from "./template/review.txt"
import PROMPT_BUG from "./template/bug.txt"
import { LegacyEvent } from "@opencode-ai/schema/legacy-event"

type State = {
Expand Down Expand Up @@ -46,6 +47,7 @@ export function hints(template: string) {
export const Default = {
INIT: "init",
REVIEW: "review",
BUG: "bug",
} as const

export interface Interface {
Expand Down Expand Up @@ -86,6 +88,15 @@ const layer = Layer.effect(
subtask: true,
hints: hints(PROMPT_REVIEW),
}
commands[Default.BUG] = {
name: Default.BUG,
description: "file a bug report [description], asks if omitted",
source: "command",
get template() {
return PROMPT_BUG
},
hints: hints(PROMPT_BUG),
}

for (const [name, command] of Object.entries(cfg.command ?? {})) {
commands[name] = {
Expand Down
39 changes: 39 additions & 0 deletions packages/opencode/src/command/template/bug.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
File a bug report for bolt (this CLI) based on what happened in this session.

User-provided description (may be empty):
$ARGUMENTS

## Step 1: Understand the bug

If the description above is empty, ask the user one short question: what went wrong and what did they expect instead. Do not ask anything else.

If the description is present, do not ask questions; work from it plus the session context.

## Step 2: Collect environment context

Gather these facts with quick commands, tolerating failures:
- bolt version: run `bolt --version` (fall back to the version in the running process if the binary is not on PATH)
- OS and architecture: run `uname -sm` (or read process.platform/arch on Windows)
- The model and agent in use for this session, if visible in context
- The last error output relevant to the bug, if any appeared in this session

Never include API keys, tokens, environment variable values, file contents unrelated to the bug, or private conversation content. Quote only the minimal error text needed to reproduce.

## Step 3: Draft the report

Compose a markdown report with exactly these sections:
- **Description**: one or two sentences, from the user's words
- **Steps to reproduce**: numbered, minimal, from what actually happened
- **Expected behavior**
- **Actual behavior**: include the minimal error output in a fenced block if there is one
- **Environment**: bolt version, OS/arch, model

Show the drafted report to the user and ask for confirmation before submitting. If they ask for edits, apply them and confirm again.

## Step 4: Submit

After confirmation, file the report:
1. Preferred: `gh issue create --repo bolt-builder/bolt-cli --title "<short title>" --body "<report>"` and print the returned issue URL.
2. If `gh` is missing or unauthenticated: print a prefilled new-issue link `https://github.com/bolt-builder/bolt-cli/issues/new?title=<url-encoded title>&body=<url-encoded report>` plus the raw markdown so the user can paste it manually.

End by telling the user exactly where the report went.
21 changes: 21 additions & 0 deletions packages/opencode/test/command/bug.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { describe, expect, test } from "bun:test"
import PROMPT_BUG from "@/command/template/bug.txt"
import { Command } from "@/command"

describe("bug command", () => {
test("is a registered default", () => {
expect(Command.Default.BUG).toBe("bug")
})

test("template takes the description as $ARGUMENTS", () => {
expect(Command.hints(PROMPT_BUG)).toEqual(["$ARGUMENTS"])
})

test("template carries the report contract", () => {
for (const section of ["Description", "Steps to reproduce", "Expected behavior", "Actual behavior", "Environment"])
expect(PROMPT_BUG).toContain(section)
expect(PROMPT_BUG).toContain("gh issue create --repo bolt-builder/bolt-cli")
expect(PROMPT_BUG).toContain("https://github.com/bolt-builder/bolt-cli/issues/new")
expect(PROMPT_BUG).toContain("Never include API keys")
})
})
Loading