Skip to content

feat: add per-workspace environment variables with terminal/agent injection#167

Merged
DeadWaveWave merged 6 commits intoDeadWaveWave:mainfrom
liusining:feat/workspace-environment-variables
Apr 15, 2026
Merged

feat: add per-workspace environment variables with terminal/agent injection#167
DeadWaveWave merged 6 commits intoDeadWaveWave:mainfrom
liusining:feat/workspace-environment-variables

Conversation

@liusining
Copy link
Copy Markdown
Contributor

@liusining liusining commented Apr 12, 2026

Summary

  • Add Environment Variables section to each project's settings page (below Workspace Worktree)
  • Data persisted as JSON in SQLite (environment_variables_json) with safe migration
  • Inject configured env vars into every terminal and agent launched within the workspace
  • Full i18n support (English + Chinese)

Changes

Storage & UI (commit 1)

  • Types: environmentVariables?: Record<string, string> on WorkspaceState / PersistedWorkspaceState
  • Database: New column with migration, read/write/normalize support
  • UI: WorkspaceSection with env var list, key/value inputs, add/remove actions
  • Wiring: Props threaded through AppShellSettingsPanelWorkspaceSection
  • Tests: 8 test cases for the environment variables section

Injection (commit 2)

  • DTOs: Added env?: Record<string, string> to SpawnTerminalInput and LaunchAgentInput
  • IPC validation: normalizeEnvPayload() with 100-entry cap, string-only values, trimmed keys
  • Terminal spawn: TerminalProfileResolver.resolveTerminalSpawn() merges input.env into process.env; spawnSession fallback path also merges
  • Agent launch: Workspace env vars merge into sessionEnv (internal vars like opencode server hostname take precedence)
  • Renderer callsites: environmentVariables threaded through all terminal creation paths (shortcut, context menu, terminal creation hook) and all agent paths (launcher, node lifecycle, task run/resume actions)
  • Worker sync: toShellWorkspaceStateForSync includes environmentVariables in merge + equality check

Test plan

  • pnpm check — zero type errors
  • pnpm vitest run — 132/132 test files, 515/515 tests pass
  • pnpm build — builds successfully
  • Manual: Open Settings → select a project → verify "Environment Variables" section appears
  • Manual: Add NODE_ENV=development, close and reopen settings, verify it persists
  • Manual: Open a terminal in the workspace → run echo $NODE_ENV → verify development
  • Manual: Launch an agent in the workspace → verify it inherits the env var
  • Manual: Remove an env var, verify it's gone from new terminals

🤖 Generated with Claude Code

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 12, 2026

CLA assistant check
All committers have signed the CLA.

@liusining liusining changed the title feat: add per-workspace environment variables settings feat: add per-workspace environment variables with terminal/agent injection Apr 12, 2026
@liusining liusining force-pushed the feat/workspace-environment-variables branch from 9c47b74 to 708f4e7 Compare April 12, 2026 10:18
@DeadWaveWave
Copy link
Copy Markdown
Owner

感谢这个 PR!整体思路很棒:把 workspace 级 environmentVariables 持久化,并透传到 pty.spawn / agent.launch,IPC 也做了 normalize(trim / string-only / 100-entry cap)。

我这边看下来有几个点建议尽快修一下,避免出现“workspace 潜在毛病/隐性抖动/变量丢失”:

  1. Worker Sync 合并会丢 environmentVariables(高优先级)
    src/app/renderer/shell/hooks/workerSync/
    mergeWorkspaceStateForSync.ts 的 toShellWorkspaceStateForSync()
    构造 nextWorkspace 时没把 environmentVariables 带进去,后面的
    workspace 等价判断也没比较它。
    这会导致:触发 worker-sync refresh 时 env 可能被清掉;并且因为
    worker-sync 的签名对比基于 persisted state(包含 env),可能出
    现“签名不一致→重复 refresh”的隐性抖动。
    建议:把 environmentVariables 加进 nextWorkspace,并像
    pullRequestBaseBranchOptions 一样做“deep-equal 则复用 existing
    引用”,同时纳入最终等价判断。
  2. env 的 guardrail 还不够(需要收紧)
    现在 normalizeEnvPayload(terminal/agent 两处)只做 trim +
    string-only + 100-entry cap,没有 env key 正则/长度上限,也没处
    理保留前缀(如 OPENCOVE_)。用户一旦填了非法 key 或覆盖内部变
    量,可能导致终端/Agent 启动失败或出现难排查的行为。
    建议至少加:key regex(如 ^[A-Za-z_][A-Za-z0-9_]
    $)+ key/value
    长度上限 + 过滤/拒绝 OPENCOVE_*。
  3. normalize 逻辑可抽共享
    normalizeEnvPayload 现在在 terminal/agent 两边各一份,后续容易
    漂移;可以抽到一个共享 helper。

另外:CI 现在有一个 check 没过,也麻烦一并修一下再继续 review/merge。

liusining and others added 3 commits April 14, 2026 00:32
Add an "Environment Variables" section to each project's settings page,
placed below the Workspace Worktree section. Users can configure key-value
environment variable pairs that will be injected into terminals and agents
launched within the workspace.

- Two-column UI (Key + Value) with Add/Remove controls
- Data persisted as JSON in SQLite with safe migration
- Full i18n support (English + Chinese)
- Consistent styling with existing settings panel components

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Thread per-workspace environment variables from settings UI through IPC
to the PTY and agent spawn paths, so variables configured in
Settings > Projects > Environment Variables are actually applied to
every terminal and agent launched within that workspace.

- Add env field to SpawnTerminalInput and LaunchAgentInput DTOs
- Validate and normalize env in IPC handlers (100-entry cap, string-only)
- Merge workspace env into process.env in TerminalProfileResolver and
  agent launch handler (internal session vars take precedence)
- Thread environmentVariables through all renderer callsites: terminal
  creation, keyboard shortcuts, context menu, agent launcher, agent
  node lifecycle, and task agent actions
- Add environmentVariables to workerSync merge module
- Install missing ws dependency required by controlSurface from main

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…r sync, guardrails

- Extract normalizeEnvPayload to shared ipc/normalize.ts (was duplicated
  in terminal and agent validate files)
- Add env key regex, key/value length limits, and OPENCOVE_* prefix filter
- Include environmentVariables in worker sync merge with deep-equal reuse
  and equality check to prevent env loss and refresh jitter
- Fix oxlint curly violations (braceless if statements)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@liusining liusining force-pushed the feat/workspace-environment-variables branch from 708f4e7 to 2bf3e0a Compare April 13, 2026 16:37
# Conflicts:
#	src/contexts/workspace/presentation/renderer/components/workspaceCanvas/hooks/useAgentLauncher.ts
#	src/contexts/workspace/presentation/renderer/components/workspaceCanvas/hooks/useAgentNodeLifecycle.ts
#	src/contexts/workspace/presentation/renderer/components/workspaceCanvas/hooks/useCanvasAgentSupport.ts
#	src/contexts/workspace/presentation/renderer/components/workspaceCanvas/hooks/useInteractions.paneNodeCreation.ts
#	src/contexts/workspace/presentation/renderer/components/workspaceCanvas/hooks/useTaskActions.agentSession.resume.ts
#	src/contexts/workspace/presentation/renderer/components/workspaceCanvas/hooks/useTaskActions.agentSession.run.ts
@DeadWaveWave DeadWaveWave merged commit 566ea52 into DeadWaveWave:main Apr 15, 2026
7 checks passed
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.

3 participants