Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
90ad37f
feat: add {env:VAR} interpolation support to markdown frontmatter
ariane-emory Dec 5, 2025
4c89ebc
refactor: extract interpolateData function to reduce code churn
ariane-emory Dec 5, 2025
dbeeb67
refactor: reduce test code churn with helper function
ariane-emory Dec 5, 2025
7d498f9
refactor: rename interpolateData to interpolateEnvironmentVariables f…
ariane-emory Dec 5, 2025
c8f4921
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 5, 2025
f277413
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 5, 2025
6cb3bb7
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 5, 2025
454362e
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 6, 2025
c3ae916
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 6, 2025
e2b89fb
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 7, 2025
8150897
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 7, 2025
9d348b5
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 7, 2025
b45b2d7
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 7, 2025
0aadeea
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 8, 2025
9f0cb53
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 8, 2025
7a1f904
Fix TypeScript error: remove cacheKey from FileContents interface usage
ariane-emory Dec 8, 2025
14f7851
revert file
ariane-emory Dec 8, 2025
1f8d1f1
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 9, 2025
9f2e75d
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 9, 2025
43297fc
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 9, 2025
0d32508
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 10, 2025
96b0905
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 10, 2025
2ef2b89
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 10, 2025
a7684bd
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 10, 2025
eac918d
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 10, 2025
c6b21a0
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 10, 2025
2eece5e
Fix type error: useKittyKeyboard should be boolean
ariane-emory Dec 10, 2025
6e1a875
Merge remote-tracking branch 'upstream/dev' into feat/markdown-frontm…
ariane-emory Dec 10, 2025
729a402
fix: uncorrupt
ariane-emory Dec 11, 2025
e6a0675
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 11, 2025
3a7dc58
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 11, 2025
7bcb694
Merge branch 'dev' into repair/feat/markdown-frontmatter-interpolation
ariane-emory Dec 13, 2025
f5571b0
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 17, 2025
bcbee72
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 17, 2025
1aff921
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 18, 2025
c6b4627
Merge remote-tracking branch 'origin/dev' into feat/markdown-frontmat…
ariane-emory Dec 19, 2025
f043f65
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 19, 2025
a1c7091
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 20, 2025
9afaa8b
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 20, 2025
1390765
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 21, 2025
b583399
Update generated types after merge from dev
ariane-emory Dec 21, 2025
eb0e297
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 22, 2025
b0fceec
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 23, 2025
e71fd22
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 23, 2025
74856a8
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 23, 2025
67d1a88
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 23, 2025
b894d65
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 23, 2025
d7a1efe
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 24, 2025
3a379c1
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 24, 2025
b0782f9
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 24, 2025
16bfd74
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 24, 2025
1138764
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 25, 2025
5ad2e40
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 25, 2025
1b31e18
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 25, 2025
253f241
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 26, 2025
2af2d25
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 27, 2025
c15e41e
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 27, 2025
d15a0de
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 27, 2025
3e4e2dc
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 28, 2025
de9bf17
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 28, 2025
f20dbbe
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 28, 2025
d95d241
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 29, 2025
e94328a
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 29, 2025
782bd09
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 29, 2025
abb0f9c
Merge branch 'feat/markdown-frontmatter-interpolation' of github.com:…
ariane-emory Dec 29, 2025
2926707
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 29, 2025
e2ecfa1
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 29, 2025
1f558d9
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 29, 2025
0406a83
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 30, 2025
ad8cb42
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 30, 2025
a5d3f46
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 30, 2025
2282a5a
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 30, 2025
bbdd409
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 30, 2025
c61c763
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 30, 2025
bc4632b
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Dec 31, 2025
d8c2bfd
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 1, 2026
9046075
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 1, 2026
1eca9a5
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 1, 2026
874ffe1
Merge remote-tracking branch 'origin/dev' into feat/markdown-frontmat…
ariane-emory Jan 2, 2026
13b4909
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 3, 2026
daefe6a
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 3, 2026
3dfb635
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 4, 2026
ce78333
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 4, 2026
4ce8c6a
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 4, 2026
9219614
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 5, 2026
0ac8c53
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 5, 2026
0fcbead
tidy: refert a file
ariane-emory Jan 5, 2026
aff971e
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 5, 2026
da4c3fb
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 5, 2026
1094029
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 6, 2026
4eb3e4d
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 6, 2026
02e162a
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 6, 2026
cd4371c
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 6, 2026
d0c7970
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 6, 2026
b6359ae
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 7, 2026
74438c7
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 7, 2026
4807650
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 7, 2026
1280cf9
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 7, 2026
3b948be
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 7, 2026
1ce4247
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 11, 2026
3619415
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 13, 2026
a517299
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 13, 2026
ffa8c9f
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 13, 2026
2f0d623
Merge branch 'dev' into feat/markdown-frontmatter-interpolation
ariane-emory Jan 15, 2026
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
19 changes: 19 additions & 0 deletions packages/opencode/src/config/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,30 @@ export namespace ConfigMarkdown {
return Array.from(template.matchAll(SHELL_REGEX))
}

// Perform {env:VAR} interpolation on frontmatter data only
function interpolateEnvironmentVariables(obj: any): any {
if (typeof obj === "string") {
return obj.replace(/\{env:([^}]+)\}/g, (_, varName) => {
return process.env[varName] || ""
})
} else if (Array.isArray(obj)) {
return obj.map(interpolateEnvironmentVariables)
} else if (obj && typeof obj === "object") {
const result: any = {}
for (const [key, value] of Object.entries(obj)) {
result[key] = interpolateEnvironmentVariables(value)
}
return result
}
return obj
}

export async function parse(filePath: string) {
const template = await Bun.file(filePath).text()

try {
const md = matter(template)
md.data = interpolateEnvironmentVariables(md.data)
return md
} catch (err) {
throw new FrontmatterError(
Expand Down
85 changes: 85 additions & 0 deletions packages/opencode/test/config/markdown.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,88 @@ test("should not match email addresses", () => {
const emailMatches = ConfigMarkdown.files(emailTest)
expect(emailMatches.length).toBe(0)
})

// Helper function to reduce test code duplication
async function parseMarkdownWithEnv(markdown: string) {
const tempFile = `/tmp/test-agent-${Date.now()}.md`
await Bun.write(tempFile, markdown)
try {
return await ConfigMarkdown.parse(tempFile)
} finally {
await Bun.file(tempFile).delete()
}
}

// Tests for {env:VAR} interpolation in frontmatter
test("should interpolate {env:VAR} in frontmatter", async () => {
process.env.TEST_MODEL = "gpt-4"
process.env.TEST_DESCRIPTION = "Test agent description"

const markdownWithEnv = `---
description: "{env:TEST_DESCRIPTION}"
model: "{env:TEST_MODEL}"
mode: primary
---

# Agent Content

This is the agent content.`

const result = await parseMarkdownWithEnv(markdownWithEnv)

expect(result.data.description).toBe("Test agent description")
expect(result.data.model).toBe("gpt-4")
expect(result.data.mode).toBe("primary")
expect(result.content).toContain("Agent Content")
})

test("should handle missing environment variables gracefully", async () => {
delete process.env.NONEXISTENT_VAR

const markdownWithMissingEnv = `---
description: "Description with {env:NONEXISTENT_VAR} missing"
model: "gpt-3.5-turbo"
---

# Agent Content`

const result = await parseMarkdownWithEnv(markdownWithMissingEnv)

expect(result.data.description).toBe("Description with missing")
expect(result.data.model).toBe("gpt-3.5-turbo")
})

test("should interpolate multiple environment variables in same field", async () => {
process.env.PREFIX = "AI"
process.env.SUFFIX = "Assistant"

const markdownWithMultipleEnv = `---
description: "{env:PREFIX} {env:SUFFIX}"
model: "gpt-4"
---

# Agent Content`

const result = await parseMarkdownWithEnv(markdownWithMultipleEnv)

expect(result.data.description).toBe("AI Assistant")
expect(result.data.model).toBe("gpt-4")
})

test("should not interpolate {env:VAR} in markdown body content", async () => {
process.env.BODY_VAR = "should not appear"

const markdownWithEnvInBody = `---
description: "Test agent"
model: "gpt-4"
---

# Agent Content

This should not interpolate: {env:BODY_VAR}`

const result = await parseMarkdownWithEnv(markdownWithEnvInBody)

expect(result.data.description).toBe("Test agent")
expect(result.content).toContain("{env:BODY_VAR}")
})