You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[FEATURE]: {env:MY_VAR} support in agent yaml #5054
For the sake of models reading this Issue: the code that opencode uses to read this syntax in the opencode.json configuration file can be found in packages/opencode/src/config/config.ts somewhere near line ~725 or so.
consistent behaviour should apply to agents and commands. Not sure if skills can also define a model (haven't use them yet) but if yes then same behaviour there.
Actually the {env:... should work not only work in front matter for model but also in the body of prompt - this would allow simple and powerful per-project customization of generic prompts. Example use case:
I've an agent for managing jira tasks via mcp. It could have generic body + additional context at the end evaluated from the command. Then I could have project specific env vars set before I start Opencode (some convinience script that reads customizations for project and put's into env var would do the trick).
@juliusz-cwiakalski Using a different symbol such as | seems, to me, like it would be a bit clearer than making the : character polysemous and giving it two different meanings when found in different positions, why not {env:SOMEVAR|a_default_value}?
@ariane-emory have no strong opinion, syntax I provided is consistent with Bash syntax - but I'm fine with any other as long as it's well documented :)
@juliusz-cwiakalski Fair point. I don't myself use that syntax very often in bash and, being very tired when I made the comment, had momentarily forgotten about it. I retract my critique.
@Eric-Guo@juliusz-cwiakalski's comment about bash syntax triggered a realization I hadn't previously thought of to dawn on me: if users have written themselves custom agents meant to write (or revise) custom slash commands, performing this substitution in the body could be a breaking change for those agents.
If the substitution were only performed in the frontmatter, a slim possibility of breakage remains: it could still break agents meant to revise slash commands that themselves used environment variable substitution in their own frontmatter or that included examples of the frontmatter of slash commands that themselves used environment variable substitution in their frontmatter - consider the scenario of an agent meant to add frontmatter using environment variable substitution to slash command), but I suspect that the possibility of breakage would be much lower.
In those scenarios, describind in-body environment variable substitution "the old way", using shell expansion with echo $SOMEVAR could be less ambiguous. This may cause you to think about the possibility of slash commands commands that revise/create commands which themselve use shell expansions: that is indeed a similar corner case, but it's a pre-existing problem: we're already living in that world and trying to fix that existing problem would most certainly be out-of-scope-scope for this PR anyhow since it's dealing with agents, not commands.
Much of this new critique would be also true for your other PR that permits {env:VARf) substitution in command bodies.
In those scenarios, describind in-body environment variable substitution "the old way", using shell expansion with echo $SOMEVAR
I'm ok to let {env:MY_VAR} lives only in frontmatter, as long as I can do {exec:ECHO $MY_VAR} in markdown body when define prompt, because it's much powerful feature and cover my case. (#9261)
But I haven't see any feature request for {exec:ECHO $MY_VAR} in agent markdown definition file so I guess we probably need to close this feature request first.
It would be pity if @juliusz-cwiakalski@ariane-emory finally decide to let {env:MY_VAR} lives only in frontmatter only. as it's quite an inconsistent design (why MD body not work for {env:MY_VAR}?), also lead {exec:ECHO $MY_VAR} become a require for me.
if users have written themselves custom agents meant to write (or revise) custom slash commands
They should write custom slash command by themself, at least look at the what agent has generated for them.
@Eric-Guo I am in no way involved in making any decisions with regards to what actually ends up getting merged, all I can do is comment and offer my personal opinions: it is, ultimately, up to the team to decide what gets merged, not I. :)
I do disagree pretty strongly with the claim that 'should write custom slash command by themself': I have agents write (or more often revise) custom slash commands for me all the time and it is a very powerful technique.
Very often, the first step will be that I'll hastily write the initial version of a command, and try it out knowing full well that it probably isn't perfect.
Inevitably, something will go awry, and then I'll call my/revise-command command that instructs the model to study what went wrong and to rewrite the command to prevent the same problem from reoccurring in the future. After doing this two or three revision cycles, I usually get a golden command that never fails.
This technique has saved me a whole lot of work and caught corner cases in the commands that I might have never discovered on my own.
Then you need improve the document for the custom command to including your usage case.
I also having a question, the custom command can running shell directly, so even in a rare case, you can write !echo '{env:MY_VAR}' to get what you need. But for my usage case ( {exec:ECHO $MY_VAR} in markdown body), I need propose a new FEATURE request and following PR.
Have I mention your frontmatter only {exec:ECHO $MY_VAR} design inconsistent? I'm very willing to mention it again, it's design inconsistent.
@Eric-Guo The documentation for custom commands doesn't really make any effort to dive into the million different ways that custom slash commands might be used (which is perfectly fine, in my opinion). Custom slash commands are an open-ended feature that can be used in innumerable ways. IMO there's not a clear reason why my particular use case should be singled out as deserving special attention in the documentation.
Personally, I think mine is more consistent with the existing design of only using the {env:SOMEVAR} syntax in configurations: frontmatter is parsed/validated according to the very same Zod schemas as configurations, it is in essence an embedded piece of configuration in these markdown files. There's no precedent for using that syntax outside of configurations. You are, of course, entirely free to disagree with my assessment and I do encourage you to do so: neither you nor I will make the final decision here, and it's always better if the team member that does has more well-argued opinions (and PRs) to weigh so that they may select the best option from amongst them.
!echo '{env:MY_VAR}' is an unnecessarily complex way of achieving the intended goal: it's simpler to just !echo "$MY_VAR", which already works. For this purpose, the syntax you proposed simply adds an extra 5 characters, paying this cost in length to buy no clear gain.
@Eric-Guo Ah-hah. The syntax I gave does work in command Markdown. IMO, the simplest consistency improvement would to reuse that established syntax. Allowing shell expansions in agent Markdown files would likely open up many other possibilities I haven't myself thought of yet as well.
I would 100% support a PR to extend the established shell expansion syntax to agent Markdown files with thumbs ups and friendly comments, but as I'm headed to bed soon anyhow I'll refrain from doing so for the moment and invite you to do so yourself if you'd care to. If you're not interested or are too busy, perhaps I might try my hand at it tomorrow.
Thanks for pushing this forward — adding my perspective as a user of agents/commands across multiple repos.
My opinion
I strongly prefer that interpolation works in the markdown body as well, not only in frontmatter. In practice, the body is where the productivity win is: dynamic folder names, per-repo customization blocks, injected context, etc. I also like the idea of allowing not only env vars, but (optionally) command output.
A “safe but flexible” design idea
To reduce ambiguity / unintended substitutions, I’d propose a two-step mechanism:
Resolve dynamic values only in frontmatter (env / file / exec), producing a small set of explicitly-declared variables.
Allow interpolation in the body only for those declared variables, e.g. {var:FOO} (or similar).
This means:
No “free-form” {env:...} substitution inside body text unless it was explicitly declared.
You get body-level flexibility without surprising agents that generate prompts/commands containing {env:...} as literal examples.
It also provides a clean mental model: frontmatter defines variables; body consumes them.
Use cases I want to support
Default model with env override
Example: pick a sensible default model, but allow overriding it via env (or a .env file).
Programmatic folder/file naming (date-based, etc.)
Example: in a command body, generate a path containing YYYY-MM-DD using date.
Generic agents with per-repo customization
Example: a generic Jira/task agent, where each repo can inject JIRA_PROJECT_KEY, custom JQL, org-specific tags, etc., without forking the whole agent.
Syntax: I’m flexible
I don’t have a strong preference on syntax — I mainly care that it’s:
readable,
documented,
consistent across agents + commands (and ideally skills too, if they support model selection).
That said, here are examples using one possible format. If the project prefers a different delimiter, I’m fine with that.
Proposed example syntax (one option)
Frontmatter resolves env, exec, file into declared variables
{env:NAME:-default} for env with default (bash-style).
{exec:...} for command output (optionally gated / opt-in).
Body only interpolates {var:NAME} (only declared vars).
Example: agent markdown (frontmatter + body)
---
description: Generic task manager agent (repo-customizable)mode: primary# Model selection: default + env overridemodel: "{env:OPENCODE_HIGH_MODEL:-anthropic/claude-opus-4-5}"# Declare “safe” variables resolved only here:vars:
JIRA_PROJECT: "{env:JIRA_PROJECT_KEY:-MV}"JIRA_BASE_URL: "{env:JIRA_BASE_URL:-https://jira.example.com}"DEFAULT_JQL: "{env:JIRA_DEFAULT_JQL:-project={var:JIRA_PROJECT} AND statusCategory != Done}"
---
You are a task management agent for this repository.Repo customization:
- Jira base: {var:JIRA_BASE_URL}
- Jira project key: {var:JIRA_PROJECT}
- Default query: {var:DEFAULT_JQL}When creating or updating tasks, use the repo’s conventions and include:
- component/service name inferred from repository structure
- labels: ai-agent, delivery
Notes:
Only {var:...} is expanded in body.
{env:...} never appears in body, avoiding accidental substitutions in generated examples.
Activity
github-actions commentedon Dec 4, 2025
This issue might be a duplicate of existing issues. Please check:
modelmanaged by env vars and plan support #2580:modelmanaged by env vars and plan support - requests ability to change the model field with environment variablesFeel free to ignore if these don't address your specific use case.
ariane-emory commentedon Dec 5, 2025
For the sake of models reading this Issue: the code that opencode uses to read this syntax in the
opencode.jsonconfiguration file can be found inpackages/opencode/src/config/config.tssomewhere near line ~725 or so.Issue #5082 is indeed very similar.
feat: add {env:VAR} interpolation support to markdown frontmatter
strangemonad commentedon Dec 5, 2025
I'm also using the same workaround trick for both agents and commands. Would love the same env and file interpolation in all yaml front-matter.
juliusz-cwiakalski commentedon Jan 21, 2026
I'd like to extend the original request so it also should support defaults in case env is not set, something like:
consistent behaviour should apply to agents and commands. Not sure if skills can also define a model (haven't use them yet) but if yes then same behaviour there.
Actually the
{env:...should work not only work in front matter for model but also in the body of prompt - this would allow simple and powerful per-project customization of generic prompts. Example use case:I've an agent for managing jira tasks via mcp. It could have generic body + additional context at the end evaluated from the command. Then I could have project specific env vars set before I start Opencode (some convinience script that reads customizations for project and put's into env var would do the trick).
ariane-emory commentedon Jan 21, 2026
@juliusz-cwiakalski Using a different symbol such as
|seems, to me, like it would be a bit clearer than making the:character polysemous and giving it two different meanings when found in different positions, why not{env:SOMEVAR|a_default_value}?juliusz-cwiakalski commentedon Jan 21, 2026
@ariane-emory have no strong opinion, syntax I provided is consistent with Bash syntax - but I'm fine with any other as long as it's well documented :)
ariane-emory commentedon Jan 21, 2026
@juliusz-cwiakalski Fair point. I don't myself use that syntax very often in bash and, being very tired when I made the comment, had momentarily forgotten about it. I retract my critique.
ariane-emory commentedon Jan 21, 2026
@Eric-Guo @juliusz-cwiakalski's comment about bash syntax triggered a realization I hadn't previously thought of to dawn on me: if users have written themselves custom agents meant to write (or revise) custom slash commands, performing this substitution in the body could be a breaking change for those agents.
If the substitution were only performed in the frontmatter, a slim possibility of breakage remains: it could still break agents meant to revise slash commands that themselves used environment variable substitution in their own frontmatter or that included examples of the frontmatter of slash commands that themselves used environment variable substitution in their frontmatter - consider the scenario of an agent meant to add frontmatter using environment variable substitution to slash command), but I suspect that the possibility of breakage would be much lower.
In those scenarios, describind in-body environment variable substitution "the old way", using shell expansion with
echo $SOMEVARcould be less ambiguous. This may cause you to think about the possibility of slash commands commands that revise/create commands which themselve use shell expansions: that is indeed a similar corner case, but it's a pre-existing problem: we're already living in that world and trying to fix that existing problem would most certainly be out-of-scope-scope for this PR anyhow since it's dealing with agents, not commands.Much of this new critique would be also true for your other PR that permits
{env:VARf)substitution in command bodies.Eric-Guo commentedon Jan 22, 2026
I'm ok to let {env:MY_VAR} lives only in frontmatter, as long as I can do {exec:ECHO $MY_VAR} in markdown body when define prompt, because it's much powerful feature and cover my case. (#9261)
But I haven't see any feature request for {exec:ECHO $MY_VAR} in agent markdown definition file so I guess we probably need to close this feature request first.
It would be pity if @juliusz-cwiakalski @ariane-emory finally decide to let {env:MY_VAR} lives only in frontmatter only. as it's quite an inconsistent design (why MD body not work for {env:MY_VAR}?), also lead {exec:ECHO $MY_VAR} become a require for me.
They should write custom slash command by themself, at least look at the what agent has generated for them.
ariane-emory commentedon Jan 22, 2026
@Eric-Guo I am in no way involved in making any decisions with regards to what actually ends up getting merged, all I can do is comment and offer my personal opinions: it is, ultimately, up to the team to decide what gets merged, not I. :)
I do disagree pretty strongly with the claim that 'should write custom slash command by themself': I have agents write (or more often revise) custom slash commands for me all the time and it is a very powerful technique.
Very often, the first step will be that I'll hastily write the initial version of a command, and try it out knowing full well that it probably isn't perfect.
Inevitably, something will go awry, and then I'll call my
/revise-commandcommand that instructs the model to study what went wrong and to rewrite the command to prevent the same problem from reoccurring in the future. After doing this two or three revision cycles, I usually get a golden command that never fails.This technique has saved me a whole lot of work and caught corner cases in the commands that I might have never discovered on my own.
Eric-Guo commentedon Jan 22, 2026
Then you need improve the document for the custom command to including your usage case.
I also having a question, the custom command can running shell directly, so even in a rare case, you can write !
echo '{env:MY_VAR}'to get what you need. But for my usage case ( {exec:ECHO $MY_VAR} in markdown body), I need propose a new FEATURE request and following PR.Have I mention your frontmatter only {exec:ECHO $MY_VAR} design inconsistent? I'm very willing to mention it again, it's design inconsistent.
ariane-emory commentedon Jan 22, 2026
@Eric-Guo The documentation for custom commands doesn't really make any effort to dive into the million different ways that custom slash commands might be used (which is perfectly fine, in my opinion). Custom slash commands are an open-ended feature that can be used in innumerable ways. IMO there's not a clear reason why my particular use case should be singled out as deserving special attention in the documentation.
Personally, I think mine is more consistent with the existing design of only using the
{env:SOMEVAR}syntax in configurations: frontmatter is parsed/validated according to the very same Zod schemas as configurations, it is in essence an embedded piece of configuration in these markdown files. There's no precedent for using that syntax outside of configurations. You are, of course, entirely free to disagree with my assessment and I do encourage you to do so: neither you nor I will make the final decision here, and it's always better if the team member that does has more well-argued opinions (and PRs) to weigh so that they may select the best option from amongst them.!
echo '{env:MY_VAR}'is an unnecessarily complex way of achieving the intended goal: it's simpler to just !echo "$MY_VAR", which already works. For this purpose, the syntax you proposed simply adds an extra 5 characters, paying this cost in length to buy no clear gain.Eric-Guo commentedon Jan 22, 2026
I tested in current dev, both
!echo '{env:MY_VAR}'and!echo "$MY_VAR"not working in agent prompt.Now the problem is not inconsistent, it's not working following your suggestion. 🤷
ariane-emory commentedon Jan 22, 2026
@Eric-Guo Ah-hah. The syntax I gave does work in command Markdown. IMO, the simplest consistency improvement would to reuse that established syntax. Allowing shell expansions in agent Markdown files would likely open up many other possibilities I haven't myself thought of yet as well.
I would 100% support a PR to extend the established shell expansion syntax to agent Markdown files with thumbs ups and friendly comments, but as I'm headed to bed soon anyhow I'll refrain from doing so for the moment and invite you to do so yourself if you'd care to. If you're not interested or are too busy, perhaps I might try my hand at it tomorrow.
Eric-Guo commentedon Jan 23, 2026
I'm OK if #9261 can be merge, I'm not yet need shell expansion syntax in my daily needs.
juliusz-cwiakalski commentedon Jan 23, 2026
Thanks for pushing this forward — adding my perspective as a user of agents/commands across multiple repos.
My opinion
I strongly prefer that interpolation works in the markdown body as well, not only in frontmatter. In practice, the body is where the productivity win is: dynamic folder names, per-repo customization blocks, injected context, etc. I also like the idea of allowing not only env vars, but (optionally) command output.
A “safe but flexible” design idea
To reduce ambiguity / unintended substitutions, I’d propose a two-step mechanism:
{var:FOO}(or similar).This means:
{env:...}substitution inside body text unless it was explicitly declared.{env:...}as literal examples.It also provides a clean mental model: frontmatter defines variables; body consumes them.
Use cases I want to support
Example: pick a sensible default model, but allow overriding it via env (or a
.envfile).Example: in a command body, generate a path containing
YYYY-MM-DDusingdate.Example: a generic Jira/task agent, where each repo can inject
JIRA_PROJECT_KEY, custom JQL, org-specific tags, etc., without forking the whole agent.Syntax: I’m flexible
I don’t have a strong preference on syntax — I mainly care that it’s:
That said, here are examples using one possible format. If the project prefers a different delimiter, I’m fine with that.
Proposed example syntax (one option)
Frontmatter resolves
env,exec,fileinto declared variables{env:NAME:-default}for env with default (bash-style).{exec:...}for command output (optionally gated / opt-in).{var:NAME}(only declared vars).Example: agent markdown (frontmatter + body)
Notes:
{var:...}is expanded in body.{env:...}never appears in body, avoiding accidental substitutions in generated examples.Example: command markdown (date-based folder name)
Alternative defaults delimiter (also acceptable)
If the project prefers a different delimiter for defaults, e.g.
{env:NAME|default}instead of bash-style:-, I’m also fine with that. For example:{env:OPENCODE_HIGH_MODEL|anthropic/claude-opus-4-5}{env:JIRA_PROJECT_KEY|MV}The important part for me is:
Summary
Happy to adapt the syntax examples to whatever the project decides — the behavior matters most.
github-actions commentedon Mar 26, 2026
To stay organized issues are automatically closed after 90 days of no activity. If the issue is still relevant please open a new one.