Skip to content

feat(opencode): Added {env:VAR} substitution to markdown-based config parsing - #9261

Closed
Eric-Guo wants to merge 1 commit into
anomalyco:devfrom
Eric-Guo:substitute_env_in_markdown
Closed

Eric-Guo wants to merge 1 commit into
anomalyco:devfrom
Eric-Guo:substitute_env_in_markdown

Conversation

@Eric-Guo

@Eric-Guo Eric-Guo commented Jan 18, 2026 •

Copy link
Copy Markdown
Contributor

Close #5054

The key difference between this PR and #5092 is this PR allow ENV usage in markdown body.

I already including a real use case in document and give the warning of security concerns.

Notice current json configuration of prompt allow using ENV, so I think using ENV in markdown body should also allowed.

Other coding agent like kimi-cli using ENV in their system prompt, so security concerns is not as serious as the first sight.

Copilot AI review requested due to automatic review settings January 18, 2026 15:49
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Potential Duplicate Found:

Why they're related: Both PRs address the same issue (#5054) and implement the exact same feature: {env:VAR} substitution support in markdown-based configuration files. PR #5092 appears to have already resolved this issue, so PR #9261 may be a duplicate.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds environment variable substitution functionality to markdown-based agent configuration parsing. Users can now use the {env:VAR_NAME} syntax in both frontmatter and prompt content of markdown agent files, with unset variables being replaced with empty strings.

Changes:

  • Added substituteEnv() function to perform environment variable replacement using {env:VAR} syntax
  • Integrated environment variable substitution into the markdown parsing pipeline
  • Added comprehensive test coverage for the new functionality including edge cases
  • Updated documentation with usage examples and security guidance

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
packages/opencode/src/config/markdown.ts Implements the substituteEnv function and integrates it into the parse pipeline
packages/opencode/test/config/markdown.test.ts Adds comprehensive test suite with proper environment variable setup/teardown
packages/opencode/test/config/fixtures/env-frontmatter.md Test fixture demonstrating env var substitution in both frontmatter and content
packages/web/src/content/docs/agents.mdx Documents the new feature with usage examples and security considerations

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@ariane-emory

ariane-emory commented Jan 18, 2026 •

Copy link
Copy Markdown
Contributor

After consultation with a couple of models and further review of the code changes, I do believe that I have come to the conclusion that my take in #5092 does adhere more closely to the original requestor of the Issue's request in #5054 to provide replacement only in the YAML/frontmatter. The version here does expand the scope slightly by providing replacement throughout the body as well.

Whether this expansion in scope is desirable or not I'll leave to the maintainers to decide as I don't hold any strong opinion on that aspect myself.

In any case, either PR seems that it would give the original requestor the ability to do what they wanted to do surely the resolution of their issue would provide them with a pleasant surprise - and if they're happy, so am I, so hopefully one of these PRs will come in to a safe landing.

@Eric-Guo
Eric-Guo force-pushed the substitute_env_in_markdown branch from b4be2bf to db8a8c2 Compare January 18, 2026 17:41
@Eric-Guo

Copy link
Copy Markdown
Contributor Author

Thanks your review, I update the document with my real usage, I need ENV in markdown body, so hoping this PR can be choosen. (otherwise, I have to write the prompt in jsonc....)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +194 to +226
describe("ConfigMarkdown: env substitution", () => {
const tokenKey = "TEST_MCP_TOKEN"
const emptyKey = "EMPTY_ENV_VAR"
const prevToken = process.env[tokenKey]
const prevEmpty = process.env[emptyKey]
let parsed: Awaited<ReturnType<typeof ConfigMarkdown.parse>>

beforeAll(async () => {
process.env[tokenKey] = "abc123"
delete process.env[emptyKey]
parsed = await ConfigMarkdown.parse(import.meta.dir + "/fixtures/env-frontmatter.md")
})

afterAll(() => {
if (prevToken === undefined) delete process.env[tokenKey]
else process.env[tokenKey] = prevToken
if (prevEmpty === undefined) delete process.env[emptyKey]
else process.env[emptyKey] = prevEmpty
})

test("should substitute env vars in frontmatter", () => {
expect(parsed.data.description).toBe("Token is abc123")
})

test("should substitute missing env vars with empty string in frontmatter", () => {
expect(parsed.data.note).toBe("")
})

test("should substitute env vars in content", () => {
expect(parsed.content).toContain("Token: abc123")
expect(parsed.content).toContain("Missing: ")
})
})

Copilot AI Jan 18, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test only verifies that env variables are replaced with their values or empty strings, but doesn't test edge cases like nested braces, malformed patterns, or special characters in variable names. Consider adding test cases for: 1) Multiple substitutions in the same line, 2) Variables with underscores and numbers, 3) Malformed patterns like {env:} or {env:VAR with spaces}, 4) Variables that contain special regex characters.

Copilot uses AI. Check for mistakes.
```markdown title="~/.config/opencode/agents/mcdonalds.md"
---
name: "McDonalds"
description: Agent to help you ordering McDonalds

Copilot AI Jan 18, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description contains a grammatical error. It should be "Agent to help you order from McDonalds" instead of "Agent to help you ordering McDonalds".

Suggested change
description: Agent to help you ordering McDonalds
description: Agent to help you order from McDonalds

Copilot uses AI. Check for mistakes.
@ariane-emory

ariane-emory commented Jan 18, 2026 •

Copy link
Copy Markdown
Contributor

@Eric-Guo I expect that surely you must already be aware, but just in case: you can of course already achieve your terminal goal of using environment variable in the body by using shell expansions. It's not a markedly efficient way to do it, of course, since we're starting a whole shell just to get at an environment variable, but it does work, so it could perhaps suffice in the meantime.

Best of luck!

@Eric-Guo

Eric-Guo commented Jan 18, 2026 •

Copy link
Copy Markdown
Contributor Author

you can of course already achieve your terminal goal of using environment variable in the body by using shell expansions.

How to do that? I don't know it can, seems not mention in document.

It sounds useful but more crazy and less security (of course)...

But if I can do that, this PR is no need. 😊

@ariane-emory

ariane-emory commented Jan 18, 2026 •

Copy link
Copy Markdown
Contributor

You would do what is shown here: https://opencode.ai/docs/commands/#shell-output

Simply use a command such as echo ${SOME_ENVIRONMENT_VARIABLE}, as I show here in one of my own test commands (https://github.com/ariane-emory/opencode-config-supplemental/blob/main/command-disabled/debug-env.md):

Screenshot 2026-01-18 at 1 23 45 PM

As stated previously, it's probably not the most efficient way to do it, but it should work.

@Eric-Guo
Eric-Guo force-pushed the substitute_env_in_markdown branch from c675b6e to 39dcd7b Compare January 19, 2026 01:11
@Eric-Guo

Copy link
Copy Markdown
Contributor Author

What I known is command is need to trigger by user, anyway to let the command being triggerd automatically at starting, without user need to do any action? i.e. system prompt can calling command directly?

If answer is no, it's more my need....

@ariane-emory

ariane-emory commented Jan 19, 2026 •

Copy link
Copy Markdown
Contributor

The commands in the shell expansions run each time you run the slash command. This is in most cases beneficial: after all, if you run the date command, you want the current date every time and if you run ls to see the files in a directory you presumably want to know what files are there right now, not what files used to be there an hour ago during startup. This probably isn't usually so important for echoing environment variables that are in most cases unlikely to change during runtime, but there could perhaps be some corner case that I'm overlooking. No, slash commands cannot be called mechanically by system prompts, they are meant to be invoked by the user.

@Eric-Guo
Eric-Guo force-pushed the substitute_env_in_markdown branch 6 times, most recently from 6d02317 to 2fcd86e Compare January 22, 2026 02:53
@Eric-Guo
Eric-Guo force-pushed the substitute_env_in_markdown branch 4 times, most recently from d5e033a to 9cfdf94 Compare January 28, 2026 07:02
@Eric-Guo
Eric-Guo force-pushed the substitute_env_in_markdown branch 3 times, most recently from 4cc021c to becedb8 Compare January 29, 2026 11:45
@Eric-Guo
Eric-Guo force-pushed the substitute_env_in_markdown branch from becedb8 to 60905d0 Compare January 30, 2026 07:27
@thdxr
thdxr requested a review from adamdotdevin as a code owner January 30, 2026 14:35
@thdxr
thdxr force-pushed the dev branch 2 times, most recently from f1ae801 to 08fa7f7 Compare January 30, 2026 14:37
@Eric-Guo
Eric-Guo force-pushed the substitute_env_in_markdown branch 3 times, most recently from 60533cf to 35211b1 Compare February 9, 2026 13:45
@Eric-Guo
Eric-Guo force-pushed the substitute_env_in_markdown branch 2 times, most recently from 45f2d67 to a925782 Compare February 16, 2026 14:30
@Eric-Guo
Eric-Guo force-pushed the substitute_env_in_markdown branch 2 times, most recently from e986e86 to 2a941b7 Compare February 27, 2026 12:15
@Eric-Guo
Eric-Guo force-pushed the substitute_env_in_markdown branch from 2a941b7 to 949677d Compare March 4, 2026 07:10
@Eric-Guo
Eric-Guo force-pushed the substitute_env_in_markdown branch 2 times, most recently from 586653b to ec4b24b Compare March 17, 2026 06:04
@Eric-Guo
Eric-Guo force-pushed the substitute_env_in_markdown branch 2 times, most recently from 5ec17c6 to f3f97e6 Compare March 30, 2026 03:13
…nt definitions in .md now get env values injected before frontmatter/prompt parsing.
@rekram1-node

Copy link
Copy Markdown
Contributor

Automated PR Cleanup

Thank you for contributing to opencode.

Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions.

This PR was closed because it matched the following cleanup criteria:

  • The PR was created more than 1 month ago
  • The PR had fewer than 2 positive reactions
  • Positive reactions are counted as thumbs-up, heart, celebration, or rocket reactions on the PR

PRs created within the last month are not affected by this cleanup.

If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate.

Thanks again for taking the time to contribute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE]: {env:MY_VAR} support in agent yaml

4 participants