Skip to content

fix: anchor session-injection hooks to the host-injected project dir - #37

Merged
zheng-weihao merged 2 commits into
orbcli:mainfrom
zheng-weihao:hook-cwd-anchor
Aug 14, 2026
Merged

fix: anchor session-injection hooks to the host-injected project dir#37
zheng-weihao merged 2 commits into
orbcli:mainfrom
zheng-weihao:hook-cwd-anchor

Conversation

@zheng-weihao

Copy link
Copy Markdown
Member

Summary

Hook CWD is not a cross-host contract: a host may run hooks from outside the project directory, and orbit's CWD-based workspace detection then silently skips <orbit-context> injection for the whole session ("not in a workspace" is a designed silent no-op, so nothing ever surfaces).

  • hooks/session-start.sh / session-resume.sh: anchor to the host-injected project dir before detection — CLAUDE_PROJECT_DIR (Claude Code's documented contract, also injected by Qoder), then QODER_PROJECT_DIR (Qoder's documented fallback). Guarded by [ -n ]/[ -d ] so empty/unset/invalid values and env-less hosts (codex sets hook CWD correctly by contract) pass through as a silent no-op; the cd suppresses stdout and stderr alike.
  • .opencode-plugin/plugin.ts: rawContext() anchors its BunShell to the SDK-provided PluginInput.directory via .cwd(...) instead of inheriting the opencode process cwd (which equals the project only when opencode was launched from it). directory is per-instance in opencode (plugin state is materialized per project directory, serve mode included), so the anchor names the session's project in every run mode.
  • docs: spec-hooks gains the Host-CWD anchoring contract entry; CHANGELOG under Bug or Regression.

Test plan

  • New tests/26_hook_cwd_anchor.bats pins the anchor chain across both shared scripts: fallback order, empty-string fallthrough, unset no-op, nonexistent/not-a-dir refusal (7 tests, 14 hook runs — all green).
  • New node test in .opencode-plugin/plugin.test.ts pins the .cwd(directory) call and output passthrough (18/18 green).
  • Full bats suite: 375/375 green.

Hook CWD is not a cross-host contract: a host may run hooks from outside
the project directory, and orbit's CWD-based workspace detection then
silently skips <orbit-context> injection ("not in a workspace" is a
designed silent no-op, so nothing surfaces).

- hooks/session-start.sh / session-resume.sh: cd to CLAUDE_PROJECT_DIR
  (Claude Code's documented contract, also injected by Qoder), falling
  back to QODER_PROJECT_DIR (Qoder's documented contract) — guarded by
  [ -n ]/[ -d ] so empty/unset/invalid values and env-less hosts (codex
  sets hook CWD correctly by contract) pass through unchanged; stdout
  and stderr of the cd are both suppressed.
- .opencode-plugin/plugin.ts: rawContext() anchors its shell to the
  SDK-provided PluginInput.directory via .cwd(...) instead of
  inheriting the opencode process cwd; the directory is per-instance,
  so the anchor names the session's project in every run mode.
- tests: bats contract for the anchor chain (order, guards,
  fallthrough); node test pinning the plugin's .cwd(directory) call.
- docs: spec-hooks states the host-CWD anchoring contract; CHANGELOG
  entry under Bug or Regression.

Signed-off-by: Zheng Weihao <zheng-weihao@outlook.com>
Signed-off-by: Zheng Weihao <zheng-weihao@outlook.com>
@zheng-weihao
zheng-weihao merged commit cbc7ddd into orbcli:main Aug 14, 2026
2 checks passed
@zheng-weihao
zheng-weihao deleted the hook-cwd-anchor branch August 24, 2026 11:07
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.

1 participant