Skip to content

feat: honor ZCODE_HOME for the config and lazy-session store paths - #187

Merged
william0wang merged 2 commits into
william0wang:mainfrom
BrokkAi:feat/zcode-home
Sep 16, 2026
Merged

william0wang merged 2 commits into
william0wang:mainfrom
BrokkAi:feat/zcode-home

Conversation

@jbellis

@jbellis jbellis commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Problem

The credentials config path and the lazy-session alias store are pinned to ~/.zcode. A bridge cannot be pointed at an isolated ZCode install (a second account, a container mount, a test fixture) without moving the user's real home directory.

Change

zcodeHomeDir() in utils.ts is the single place that resolves the data root: ZCODE_HOME when set, else <home>/.zcode. ZCODE_CREDS_PATH and the lazy store's storePath() build on it. Default behaviour is unchanged when the variable is unset. The README documents the variable.

The hermetic test setup now clears ZCODE_HOME for the same reason it redirects HOME.

Tests

tests/utils.test.ts and tests/lazy-sessions.test.ts cover the variable set and unset.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DLQ3W2owia4SJBvzxSqvVc

Both the credentials/provider config and the lazy-session alias store were
pinned to `~/.zcode`, so a bridge could not be pointed at an isolated ZCode
install (a second account, a container mount, a test fixture) without moving
the user's real home.

`zcodeHomeDir()` in utils.ts is now the single place that resolves the data
root: `ZCODE_HOME` when set, else `<home>/.zcode`. `ZCODE_CREDS_PATH` and the
lazy store's `storePath()` both build on it. Default behaviour is unchanged
when the variable is unset.

`ZCODE_CREDS_PATH` stays a module-level const, so `ZCODE_HOME` must be set
before the process starts; the store path is resolved per call as before.
The hermetic test setup deletes `ZCODE_HOME` for the same reason it
redirects HOME: an exported value would point the suite at a real store.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DLQ3W2owia4SJBvzxSqvVc

@william0wang william0wang left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Reviewed (typecheck pass; targeted tests pass; the lazy store still goes through persist() and the hermetic setup clears ZCODE_HOME — both good).

Requesting one change before merge: the override is partial. zcodeHomeDir() is documented as the single data-root resolver, but these readers still build the real ~/.zcode from module-level homedir()/HOME constants:

  • src/config/skill-discovery.ts:45,48,170 (CLI config, plugin cache, user skills scan)
  • src/config/mcp-discovery.ts:48,49
  • src/config/plugin-commands.ts:19,27
  • src/i18n.ts:57 (settings.json locale detection)
  • src/tasks-index.ts:355 (the App's tasks-index.sqlite backing the remote session list)

With ZCODE_HOME pointed at an isolated install, credentials and lazy sessions follow the override while plugins/skills/MCP servers/locale/session-listing still read the real home — a silently split brain for exactly the second-account/container case the README promises. Either route them through zcodeHomeDir() (preferred) or narrow the README claim to "credentials and the lazy-session store".

Review follow-up on the ZCODE_HOME override: the discovery modules still
built the real ~/.zcode from module-level homedir() constants, so an
isolated data root split the bridge in two — credentials and lazy sessions
followed ZCODE_HOME while plugins, skills, MCP servers, locale detection
and the workspace list kept reading the user's real home.

zcodeHomeDir() is now the single resolver everywhere it claims to be:

- skill-discovery / mcp-discovery / plugin-commands: the CLI-config and
  plugin-cache path constants become per-call zcodeCliConfigPath() /
  zcodePluginCacheDir() helpers in utils.ts (deduplicating the three
  identical copies); the user-skills scan reads <zcode-home>/skills
- i18n: the desktop-app settings read follows the override
- tasks-index: the workspace exclusion rejects the override root, not the
  real ~/.zcode, when ZCODE_HOME is set

~/.agents/skills stays on the real home — it is a cross-agent convention,
not part of the ZCode data root. README's ZCODE_HOME row now lists every
follower. Per-call resolution (not module snapshots) means tests can stub
the env per case; each affected module gains a ZCODE_HOME test that
proves the real home is ignored while the override is honored.
@jbellis

jbellis commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Thanks! Addressed in a8ac07a — went with the preferred option: every flagged reader now goes through zcodeHomeDir().

The three identical CLI-config/plugin-cache path constants became shared per-call helpers (zcodeCliConfigPath() / zcodePluginCacheDir()) in utils.ts; the user-skills scan reads <zcode-home>/skills; i18n's setting.json read and tasks-index's workspace exclusion follow the override too. ~/.agents/skills deliberately stays on the real home — it's a cross-agent convention, not part of the ZCode data root. The README row now lists every follower instead of narrowing the claim.

Each affected module gained a ZCODE_HOME test that proves the real home is ignored while the override is honored (the i18n one required tightening that suite's fs mock from suffix-match to exact-match so it can actually discriminate the two roots).

@william0wang
william0wang merged commit 0593488 into william0wang:main Sep 16, 2026
2 checks passed
william0wang pushed a commit that referenced this pull request Sep 16, 2026
🤖 I have created a release *beep* *boop*
---


## [0.39.0](v0.38.0...v0.39.0) (2026-09-16)


### Features

* choose the initial session mode with ZCODE_ACP_MODE ([#189](#189)) ([a1aa2e0](a1aa2e0))
* honor ZCODE_HOME for the config and lazy-session store paths ([#187](#187)) ([0593488](0593488))
* pin the provider and model with ZCODE_PROVIDER and ZCODE_MODEL ([#188](#188)) ([6aa8999](6aa8999))

---
This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
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.

2 participants