opencode-bonfire 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Bonfire Plugin for OpenCode
3
+ *
4
+ * Provides event hooks for:
5
+ * - Suggesting archive after PR merge
6
+ * - Preserving session context during compaction
7
+ */
8
+
9
+ import type { Plugin } from "@opencode-ai/plugin"
10
+ import { existsSync, readFileSync } from "fs"
11
+ import { join } from "path"
12
+
13
+ export const BonfirePlugin: Plugin = async ({ directory }) => {
14
+ const bonfirePath = join(directory, ".bonfire")
15
+ const indexPath = join(bonfirePath, "index.md")
16
+
17
+ return {
18
+ /**
19
+ * After tool execution - detect PR merges and suggest archiving
20
+ */
21
+ "tool.execute.after": async (input, output) => {
22
+ if (input.tool !== "bash") return
23
+
24
+ const command = input.args?.command as string | undefined
25
+ if (!command) return
26
+
27
+ const isPrMerge =
28
+ command.includes("gh pr merge") || command.includes("gh pr close")
29
+
30
+ const succeeded = !output.error && output.result
31
+
32
+ if (isPrMerge && succeeded && existsSync(indexPath)) {
33
+ return {
34
+ message: `PR merged! Run \`/bonfire-archive\` to archive this session.`,
35
+ }
36
+ }
37
+ },
38
+
39
+ /**
40
+ * Preserve bonfire context during session compaction
41
+ */
42
+ "experimental.session.compacting": async (_input, output) => {
43
+ if (existsSync(indexPath)) {
44
+ const content = readFileSync(indexPath, "utf-8")
45
+ output.context.push(`## Bonfire Session Context\n\n${content}`)
46
+ }
47
+ },
48
+ }
49
+ }
50
+
51
+ // Plugin auto-discovered by filename - no default export needed
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: bonfire-context
3
+ description: Load .bonfire/index.md context to understand ongoing work, previous decisions, blockers, and session history. Use when user references past work or asks about project status.
4
+ license: MIT
5
+ compatibility: opencode
6
+ metadata:
7
+ category: session-management
8
+ author: vieko
9
+ ---
10
+
11
+ # Bonfire Context
12
+
13
+ This skill loads project session context from `.bonfire/index.md` to provide continuity across AI coding sessions.
14
+
15
+ ## When to Use This Skill
16
+
17
+ Load this skill when the user:
18
+ - Asks about previous work or decisions
19
+ - References "last time", "previously", "before"
20
+ - Wants to know about blockers or pending issues
21
+ - Asks what the project status is
22
+ - Starts a significant task that might have prior context
23
+
24
+ ## Instructions
25
+
26
+ 1. Find the git root: `git rev-parse --show-toplevel`
27
+
28
+ 2. Check if `.bonfire/index.md` exists at the git root
29
+
30
+ 3. If it exists, read it to understand:
31
+ - Current project status and recent work
32
+ - Active decisions and their rationale
33
+ - Known blockers or pending issues
34
+ - Links to relevant specs or documentation
35
+
36
+ 4. Check `.bonfire/specs/` if the user asks about implementation specs
37
+
38
+ 5. Check `.bonfire/docs/` if the user asks about documented topics
39
+
40
+ ## File Structure
41
+
42
+ ```
43
+ .bonfire/
44
+ ├── index.md # Main session context (read this first)
45
+ ├── config.json # Project settings
46
+ ├── archive/ # Completed work history
47
+ ├── docs/ # Topic documentation
48
+ └── specs/ # Implementation specs
49
+ ```
50
+
51
+ ## Important
52
+
53
+ - This skill is for **reading** context, not updating it
54
+ - Session updates happen via `/bonfire-end` command
55
+ - Don't modify `.bonfire/index.md` unless explicitly asked
56
+ - If `.bonfire/` doesn't exist, the project may not use this pattern
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Bonfire Status Tool
3
+ *
4
+ * Returns structured session context for programmatic access.
5
+ */
6
+
7
+ import { tool } from "@opencode-ai/plugin"
8
+ import { existsSync, readFileSync } from "fs"
9
+
10
+ interface BonfireStatus {
11
+ exists: boolean
12
+ project?: string
13
+ status?: string
14
+ branch?: string
15
+ currentState?: string
16
+ priorities?: string[]
17
+ recentSession?: {
18
+ number: number
19
+ date: string
20
+ goal: string
21
+ }
22
+ }
23
+
24
+ function extractSection(content: string, header: string): string | undefined {
25
+ const regex = new RegExp(`## ${header}\\n\\n([\\s\\S]*?)(?=\\n## |$)`, "i")
26
+ const match = content.match(regex)
27
+ return match ? match[1].trim() : undefined
28
+ }
29
+
30
+ function extractPriorities(content: string): string[] {
31
+ const section = extractSection(content, "Next Session Priorities")
32
+ if (!section) return []
33
+ const lines = section.split("\n")
34
+ return lines
35
+ .filter((line) => line.match(/^\d+\./))
36
+ .map((line) =>
37
+ line
38
+ .replace(/^\d+\.\s*\*\*/, "")
39
+ .replace(/\*\*.*$/, "")
40
+ .trim()
41
+ )
42
+ .slice(0, 5)
43
+ }
44
+
45
+ function extractMetadata(content: string): {
46
+ project?: string
47
+ status?: string
48
+ branch?: string
49
+ } {
50
+ const projectMatch = content.match(/# Session Context: (.+)/)
51
+ const statusMatch = content.match(/\*\*Status\*\*: (.+)/)
52
+ const branchMatch = content.match(/\*\*Branch\*\*: `?([^`\n]+)`?/)
53
+ return {
54
+ project: projectMatch?.[1],
55
+ status: statusMatch?.[1],
56
+ branch: branchMatch?.[1],
57
+ }
58
+ }
59
+
60
+ function extractRecentSession(
61
+ content: string
62
+ ): { number: number; date: string; goal: string } | undefined {
63
+ const match = content.match(
64
+ /### Session (\d+) - ([\d-]+)[^\n]*\n\n\*\*Goal\*\*: (.+)/
65
+ )
66
+ if (!match) return undefined
67
+ return {
68
+ number: parseInt(match[1]),
69
+ date: match[2],
70
+ goal: match[3],
71
+ }
72
+ }
73
+
74
+ export default tool({
75
+ description:
76
+ "Get bonfire session status with structured context summary. Returns project info, current state, priorities, and recent session details.",
77
+ args: {},
78
+ async execute() {
79
+ const indexPath = ".bonfire/index.md"
80
+
81
+ if (!existsSync(indexPath)) {
82
+ const result: BonfireStatus = {
83
+ exists: false,
84
+ }
85
+ return JSON.stringify(result, null, 2)
86
+ }
87
+
88
+ const content = readFileSync(indexPath, "utf-8")
89
+ const metadata = extractMetadata(content)
90
+
91
+ const result: BonfireStatus = {
92
+ exists: true,
93
+ project: metadata.project,
94
+ status: metadata.status,
95
+ branch: metadata.branch,
96
+ currentState: extractSection(content, "Current State"),
97
+ priorities: extractPriorities(content),
98
+ recentSession: extractRecentSession(content),
99
+ }
100
+
101
+ return JSON.stringify(result, null, 2)
102
+ },
103
+ })
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "opencode-bonfire",
3
+ "version": "0.9.6",
4
+ "description": "A plugin that maintains a living context document—read at session start, updated at session end. Pick up exactly where you left off.",
5
+ "type": "module",
6
+ "bin": {
7
+ "opencode-bonfire": "./dist/cli.js"
8
+ },
9
+ "scripts": {
10
+ "copy-files": "rm -rf files && mkdir -p files && cp -r ../opencode/agent ../opencode/command ../opencode/plugin ../opencode/skill ../opencode/tool ../opencode/opencode.json ../opencode/package.json files/",
11
+ "build": "bun run copy-files && bun build src/cli.ts --outdir dist --target node",
12
+ "prepublishOnly": "bun run build"
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "files"
17
+ ],
18
+ "keywords": [
19
+ "opencode",
20
+ "ai",
21
+ "coding",
22
+ "session",
23
+ "context",
24
+ "plugin"
25
+ ],
26
+ "author": "vieko",
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/vieko/bonfire"
31
+ },
32
+ "homepage": "https://github.com/vieko/bonfire",
33
+ "devDependencies": {
34
+ "@types/node": "^20.0.0",
35
+ "typescript": "^5.0.0"
36
+ }
37
+ }