Repository navigation
feat(util_paths): claudeHomePath() helper — centralize ~/.claude/ resolution (closes impl-gap #5 from #857) - #860
Merged
Merged
Conversation
…olution
Adds Python `claude_home_path(*subpath)` and TS `claudeHomePath(...subpath)`
to `src/util_paths.{py,ts}`. Both resolve a path under Claude Code's per-user
home directory (`~/.claude/` by default; `$CLAUDE_HOME` for override / testing).
Why this helper: per the 2026-05-18 workspace-design RFC (PR #858 + issue
#857) host-CLI dependency discussion, Sutando's dependency on `~/.claude/`
is real and accepted operationally — channel tokens (`channels/*/.env`),
agent memory (`projects/<hash>/memory/`), skill discovery (`skills/`),
settings (`settings.json`, `.claude.json`). We commit to Claude Code as the
host CLI today, but want the dependency surface countable so a future swap
is a 1-day grep+replace rather than a re-architecture.
This helper IS the "stop hedging on swap" discipline. New code that reads or
writes under `~/.claude/` should go through this helper. Existing callers
(discord-bridge.py, inline-tools.ts skill-loader, health-check.py memory
checks, etc.) can migrate opportunistically — not flag-day required.
Resolution: `$CLAUDE_HOME` if set, else `~/.claude/`. Does NOT create the
directory.
Both helpers verified locally:
- Python: `claude_home_path('channels', 'discord', 'access.json')` → `/Users/wangchi/.claude/channels/discord/access.json`
- TS: same shape, same result
- $CLAUDE_HOME override honored on both
- Full TS suite still 173/173 pass
Closes impl-gap #5 from issue #857.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 18, 2026
qingyun-wu
added a commit
that referenced
this pull request
May 18, 2026
…d in #860 PR #860 (Sutando-Mini) landed the `claudeHomePath(subpath)` / `claude_home_path(*subpath)` helper in `src/util_paths.{ts,py}`. This was Mini's implementation of host-CLI discipline #1 (greppable surface) from the workspace-design RFC sub-thread. Adds one paragraph to the public Host CLI section pointing at the helper: "Sutando code that needs to read or write inside the host CLI's home directory goes through a single helper... One canonical resolver = one grep target = a future swap is a 1-day grep+replace rather than re-architecture." Specific paths still stay internal per the established rule. This edit names the HELPER (now public in main) and the directive for new code; the inventory of paths the helper resolves remains in the workspace-private engineering note. Keeps the doc consistent with main and gives new contributors a clear "what to do when you need to touch ~/.claude/" answer without expanding the public scope.
qingyun-wu
added a commit
that referenced
this pull request
May 19, 2026
…d in #860 PR #860 (Sutando-Mini) landed the `claudeHomePath(subpath)` / `claude_home_path(*subpath)` helper in `src/util_paths.{ts,py}`. This was Mini's implementation of host-CLI discipline #1 (greppable surface) from the workspace-design RFC sub-thread. Adds one paragraph to the public Host CLI section pointing at the helper: "Sutando code that needs to read or write inside the host CLI's home directory goes through a single helper... One canonical resolver = one grep target = a future swap is a 1-day grep+replace rather than re-architecture." Specific paths still stay internal per the established rule. This edit names the HELPER (now public in main) and the directive for new code; the inventory of paths the helper resolves remains in the workspace-private engineering note. Keeps the doc consistent with main and gives new contributors a clear "what to do when you need to touch ~/.claude/" answer without expanding the public scope.
qingyun-wu
added a commit
that referenced
this pull request
May 19, 2026
…#858) * docs: workspace-design RFC — 3-space model (Code/State/Memory) Per Qingyun's 2026-05-18T20:56Z ask: "draft a design doc to share and align with other developer." Triggered by the workspace audit churn (~28 sites in 13 files, 16 PRs landed today) that closed the runtime- data divergence bug class but exposed the lack of a shared vocabulary. The doc names three concentric spaces: - Code (`$SUTANDO_REPO_DIR`) — public git, persistent - State (`$SUTANDO_WORKSPACE`) — per-machine, ephemeral - Memory (`$SUTANDO_PRIVATE_DIR`) — fleet-wide private git, persistent Memory has a `machine-<host>/` subdivision for per-Mac files (stand-identity, pending-questions) and a top-level for shared content (notes/, build_log.md, memory/). This matches the existing `personalPath` / `sharedPersonalPath` helpers in `src/util_paths.{py,ts}` — the design just names what already works. Includes: - Resolvers per language (Python, TS, Swift) for each space. - "What goes here" + "what doesn't" examples for each. - Multi-machine model + sync rules. - Test isolation pattern from #849 codified as discipline. - Migration cost analysis (low — mostly docs). - 6 open decisions for team RFC discussion (naming, env-var rename, host-id strategy, State sync exceptions, secrets, Sutando.app bundle reconciliation). Status: RFC. Companion tracking issue for the open decisions. Complements `docs/workspace-contract.md` (implementation reference) with the why + taxonomy. Drafted at `notes/workspace-design-draft-2026-05-18.md` (workspace, not in repo). This is the repo-side promotion after discussion. * docs(workspace-design): address sonichi's PR review nits (#1 + #4) Two small clarifications from sonichi's #858 review: 1. **"Memory falls back to State" is a feature, not a gap.** Previously framed as impl gap #3 in the open-decisions section, which reads like a TODO. Reframe inline at the Memory section: the fallback is intentional onboarding-friction reduction; fresh installs work without `SUTANDO_PRIVATE_DIR`. The lifecycle distinction is documented but not enforced. Stops a future contributor from "fixing" this by removing the fallback. 2. **IDE / editor config angle.** Added a short section before "Relationship to other docs" covering `.cursorrules`, `.claude/`, `.vscode/`. The 3-space model doesn't have a clean home for these — answer is the existing IDE-aware convention (`.gitignore` per-user variants, check in shared ones). Flagging because new contributors ask "should .cursorrules go in Memory?" and the answer (no, stays in Code-or-untracked per IDE convention) isn't obvious from the 3-space framing alone. Two other nits from the review are followup PRs, not addressed here: - (#2) Extract `mkdtempSync` test-isolation pattern to `tests/_helpers/temp-workspace.ts`. Worth a small follow-up — Mini offered to take it. - (#3) File the 7-item implementation-gaps list as separate issues so they don't bit-rot in the doc. Will do after owner sign-off on the alignment direction in #857. Mini's votes on the 6 alignment decisions in #857 are mostly aligned with the proposal; the deltas (per-read deprecation logging, `SUTANDO_HOST_LABEL` override, opt-in state-sync allowlist, secrets stay at .env) are good refinements worth incorporating into the doc once owner confirms direction. * docs(workspace-design): surface host-CLI dependency abstractly (no specific paths) Per Qingyun's 2026-05-18T21:25Z follow-up: even if we keep the specifics internal, we should acknowledge in the public design that Sutando depends on its host CLI's user-home for some agent-state surfaces — so a future swap to Codex / gemini-cli / etc. has a known migration cost. Adds a "Host CLI dependency surface" section before "Relationship to other docs": - Lists abstract dependency categories (agent memory, bridge auth, skill discovery, slash-command config). NO specific paths. - Calls out high-cost vs low-cost re-bind classes if we ever switch host CLIs. - Notes the "interop loss" angle — slash commands provided by the host CLI evaporate on swap. - Today's policy: surface lives in workspace-private engineering note, publication of paths defers until host CLI conventions stabilize. - Points contributors at the team channel to request the inventory when needed. Engineering inventory (specific paths, read/write inventory, per-path migration cost analysis) lives at `<workspace>/notes/host-cli-dependency-surface-2026-05-18.md` — not in this repo, per owner directive. * docs(workspace-design): comprehensive + self-contained (folded decisions inline) Per Qingyun's 2026-05-18T21:30Z direction: "make it as comprehensive and self-contained as possible so we can discuss across team members." Three structural improvements: 1. **Added "Why this doc exists" section up front** — names the audit churn that motivated the doc (16 PRs, ~28 sites) so a first-time reader has context without bouncing to PR history. 2. **Added "Quick decision: which space?" flowchart-ish section** — 3-step decision-flow for "where does this new path go." Catches the most common new-contributor question. 3. **Folded the 6 open decisions inline** with current proposal + alternatives + rationale + input-so-far for each. Previously linked out to #857; now self-contained. Each decision is its own discussable unit. Decision #4 (State sync) explicitly notes the shared-task-queue sub-thread and that the `state/fleet/` refinement is still open. 4. **Added "doc cadence" open question at the bottom** — async vs synchronous review of the RFC. Owner's call. The doc now stands on its own — a team member can read it, see all 6 decisions, see what's been said about each, and react without needing to crawl Discord history or PR comments. The host-CLI section stays abstract per owner directive (specific paths remain internal-only). Length: 169 → 235 lines (~40% growth, mostly in the decisions section). * docs(claude-md): point Workspace contract section at docs/workspace-design.md Per Qingyun's 2026-05-18T21:33Z ask: yes, CLAUDE.md should reference the new 3-space design doc so per-session agents know the vocabulary without re-deriving it from call-site spelunking. One-line edit at the top of the Workspace contract section: - Names the three spaces (Code / State / Memory) with their canonical env vars. - Points at `docs/workspace-design.md` for the full model + the "Quick decision: which space?" flowchart. Minimal — does NOT duplicate the design doc content into CLAUDE.md; the existing Workspace contract section already covers resolution + helpers + the SUTANDO_REPO_DIR clarification, which is the per-session-load info. The new pointer is just so agents know where to look when they need the design. Length: +1 paragraph (3 lines). * docs(workspace-design): reference the claudeHomePath helper now landed in #860 PR #860 (Sutando-Mini) landed the `claudeHomePath(subpath)` / `claude_home_path(*subpath)` helper in `src/util_paths.{ts,py}`. This was Mini's implementation of host-CLI discipline #1 (greppable surface) from the workspace-design RFC sub-thread. Adds one paragraph to the public Host CLI section pointing at the helper: "Sutando code that needs to read or write inside the host CLI's home directory goes through a single helper... One canonical resolver = one grep target = a future swap is a 1-day grep+replace rather than re-architecture." Specific paths still stay internal per the established rule. This edit names the HELPER (now public in main) and the directive for new code; the inventory of paths the helper resolves remains in the workspace-private engineering note. Keeps the doc consistent with main and gives new contributors a clear "what to do when you need to touch ~/.claude/" answer without expanding the public scope. * docs(workspace-design): mark all 6 decisions Ratified + link tracking issues Convergence pass on PR #858 per owner's "let's iterate, want to converge" ask. All 6 decisions had multiple endorsements and no objections — flip them from "Input so far: Endorsed" to "Ratified" and point at follow-up tracking issues where there's impl work to do: - Decision 2 (env var rename) → #870 - Decision 3 (SUTANDO_HOST_LABEL) → #871 - Decision 4 (State sync .sync-allowlist + state/fleet/ design) → #872 Decisions 1, 5, 6 are policy ratifications with no impl follow-up: - 1 (names): vocabulary lands with merge - 5 (secrets at .env): policy, cross-Mac keys workstream deferred separately - 6 (Sutando.app bundle): tracked under pre-existing 2026-05-13 issue Addresses sonichi's nit #3 from PR review ("file impl-gap list as separate issues"). With this commit, nits #1, #2, #3, #4 are all resolved (per PR description table).
Closed
3 tasks
liususan091219
pushed a commit
to liususan091219/sutando-fork
that referenced
this pull request
May 28, 2026
…olution (sonichi#860) Adds Python `claude_home_path(*subpath)` and TS `claudeHomePath(...subpath)` to `src/util_paths.{py,ts}`. Both resolve a path under Claude Code's per-user home directory (`~/.claude/` by default; `$CLAUDE_HOME` for override / testing). Why this helper: per the 2026-05-18 workspace-design RFC (PR sonichi#858 + issue sonichi#857) host-CLI dependency discussion, Sutando's dependency on `~/.claude/` is real and accepted operationally — channel tokens (`channels/*/.env`), agent memory (`projects/<hash>/memory/`), skill discovery (`skills/`), settings (`settings.json`, `.claude.json`). We commit to Claude Code as the host CLI today, but want the dependency surface countable so a future swap is a 1-day grep+replace rather than a re-architecture. This helper IS the "stop hedging on swap" discipline. New code that reads or writes under `~/.claude/` should go through this helper. Existing callers (discord-bridge.py, inline-tools.ts skill-loader, health-check.py memory checks, etc.) can migrate opportunistically — not flag-day required. Resolution: `$CLAUDE_HOME` if set, else `~/.claude/`. Does NOT create the directory. Both helpers verified locally: - Python: `claude_home_path('channels', 'discord', 'access.json')` → `/Users/wangchi/.claude/channels/discord/access.json` - TS: same shape, same result - $CLAUDE_HOME override honored on both - Full TS suite still 173/173 pass Closes impl-gap sonichi#5 from issue sonichi#857. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
liususan091219
pushed a commit
to liususan091219/sutando-fork
that referenced
this pull request
May 28, 2026
…sonichi#858) * docs: workspace-design RFC — 3-space model (Code/State/Memory) Per Qingyun's 2026-05-18T20:56Z ask: "draft a design doc to share and align with other developer." Triggered by the workspace audit churn (~28 sites in 13 files, 16 PRs landed today) that closed the runtime- data divergence bug class but exposed the lack of a shared vocabulary. The doc names three concentric spaces: - Code (`$SUTANDO_REPO_DIR`) — public git, persistent - State (`$SUTANDO_WORKSPACE`) — per-machine, ephemeral - Memory (`$SUTANDO_PRIVATE_DIR`) — fleet-wide private git, persistent Memory has a `machine-<host>/` subdivision for per-Mac files (stand-identity, pending-questions) and a top-level for shared content (notes/, build_log.md, memory/). This matches the existing `personalPath` / `sharedPersonalPath` helpers in `src/util_paths.{py,ts}` — the design just names what already works. Includes: - Resolvers per language (Python, TS, Swift) for each space. - "What goes here" + "what doesn't" examples for each. - Multi-machine model + sync rules. - Test isolation pattern from sonichi#849 codified as discipline. - Migration cost analysis (low — mostly docs). - 6 open decisions for team RFC discussion (naming, env-var rename, host-id strategy, State sync exceptions, secrets, Sutando.app bundle reconciliation). Status: RFC. Companion tracking issue for the open decisions. Complements `docs/workspace-contract.md` (implementation reference) with the why + taxonomy. Drafted at `notes/workspace-design-draft-2026-05-18.md` (workspace, not in repo). This is the repo-side promotion after discussion. * docs(workspace-design): address sonichi's PR review nits (sonichi#1 + sonichi#4) Two small clarifications from sonichi's sonichi#858 review: 1. **"Memory falls back to State" is a feature, not a gap.** Previously framed as impl gap sonichi#3 in the open-decisions section, which reads like a TODO. Reframe inline at the Memory section: the fallback is intentional onboarding-friction reduction; fresh installs work without `SUTANDO_PRIVATE_DIR`. The lifecycle distinction is documented but not enforced. Stops a future contributor from "fixing" this by removing the fallback. 2. **IDE / editor config angle.** Added a short section before "Relationship to other docs" covering `.cursorrules`, `.claude/`, `.vscode/`. The 3-space model doesn't have a clean home for these — answer is the existing IDE-aware convention (`.gitignore` per-user variants, check in shared ones). Flagging because new contributors ask "should .cursorrules go in Memory?" and the answer (no, stays in Code-or-untracked per IDE convention) isn't obvious from the 3-space framing alone. Two other nits from the review are followup PRs, not addressed here: - (sonichi#2) Extract `mkdtempSync` test-isolation pattern to `tests/_helpers/temp-workspace.ts`. Worth a small follow-up — Mini offered to take it. - (sonichi#3) File the 7-item implementation-gaps list as separate issues so they don't bit-rot in the doc. Will do after owner sign-off on the alignment direction in sonichi#857. Mini's votes on the 6 alignment decisions in sonichi#857 are mostly aligned with the proposal; the deltas (per-read deprecation logging, `SUTANDO_HOST_LABEL` override, opt-in state-sync allowlist, secrets stay at .env) are good refinements worth incorporating into the doc once owner confirms direction. * docs(workspace-design): surface host-CLI dependency abstractly (no specific paths) Per Qingyun's 2026-05-18T21:25Z follow-up: even if we keep the specifics internal, we should acknowledge in the public design that Sutando depends on its host CLI's user-home for some agent-state surfaces — so a future swap to Codex / gemini-cli / etc. has a known migration cost. Adds a "Host CLI dependency surface" section before "Relationship to other docs": - Lists abstract dependency categories (agent memory, bridge auth, skill discovery, slash-command config). NO specific paths. - Calls out high-cost vs low-cost re-bind classes if we ever switch host CLIs. - Notes the "interop loss" angle — slash commands provided by the host CLI evaporate on swap. - Today's policy: surface lives in workspace-private engineering note, publication of paths defers until host CLI conventions stabilize. - Points contributors at the team channel to request the inventory when needed. Engineering inventory (specific paths, read/write inventory, per-path migration cost analysis) lives at `<workspace>/notes/host-cli-dependency-surface-2026-05-18.md` — not in this repo, per owner directive. * docs(workspace-design): comprehensive + self-contained (folded decisions inline) Per Qingyun's 2026-05-18T21:30Z direction: "make it as comprehensive and self-contained as possible so we can discuss across team members." Three structural improvements: 1. **Added "Why this doc exists" section up front** — names the audit churn that motivated the doc (16 PRs, ~28 sites) so a first-time reader has context without bouncing to PR history. 2. **Added "Quick decision: which space?" flowchart-ish section** — 3-step decision-flow for "where does this new path go." Catches the most common new-contributor question. 3. **Folded the 6 open decisions inline** with current proposal + alternatives + rationale + input-so-far for each. Previously linked out to sonichi#857; now self-contained. Each decision is its own discussable unit. Decision sonichi#4 (State sync) explicitly notes the shared-task-queue sub-thread and that the `state/fleet/` refinement is still open. 4. **Added "doc cadence" open question at the bottom** — async vs synchronous review of the RFC. Owner's call. The doc now stands on its own — a team member can read it, see all 6 decisions, see what's been said about each, and react without needing to crawl Discord history or PR comments. The host-CLI section stays abstract per owner directive (specific paths remain internal-only). Length: 169 → 235 lines (~40% growth, mostly in the decisions section). * docs(claude-md): point Workspace contract section at docs/workspace-design.md Per Qingyun's 2026-05-18T21:33Z ask: yes, CLAUDE.md should reference the new 3-space design doc so per-session agents know the vocabulary without re-deriving it from call-site spelunking. One-line edit at the top of the Workspace contract section: - Names the three spaces (Code / State / Memory) with their canonical env vars. - Points at `docs/workspace-design.md` for the full model + the "Quick decision: which space?" flowchart. Minimal — does NOT duplicate the design doc content into CLAUDE.md; the existing Workspace contract section already covers resolution + helpers + the SUTANDO_REPO_DIR clarification, which is the per-session-load info. The new pointer is just so agents know where to look when they need the design. Length: +1 paragraph (3 lines). * docs(workspace-design): reference the claudeHomePath helper now landed in sonichi#860 PR sonichi#860 (Sutando-Mini) landed the `claudeHomePath(subpath)` / `claude_home_path(*subpath)` helper in `src/util_paths.{ts,py}`. This was Mini's implementation of host-CLI discipline sonichi#1 (greppable surface) from the workspace-design RFC sub-thread. Adds one paragraph to the public Host CLI section pointing at the helper: "Sutando code that needs to read or write inside the host CLI's home directory goes through a single helper... One canonical resolver = one grep target = a future swap is a 1-day grep+replace rather than re-architecture." Specific paths still stay internal per the established rule. This edit names the HELPER (now public in main) and the directive for new code; the inventory of paths the helper resolves remains in the workspace-private engineering note. Keeps the doc consistent with main and gives new contributors a clear "what to do when you need to touch ~/.claude/" answer without expanding the public scope. * docs(workspace-design): mark all 6 decisions Ratified + link tracking issues Convergence pass on PR sonichi#858 per owner's "let's iterate, want to converge" ask. All 6 decisions had multiple endorsements and no objections — flip them from "Input so far: Endorsed" to "Ratified" and point at follow-up tracking issues where there's impl work to do: - Decision 2 (env var rename) → sonichi#870 - Decision 3 (SUTANDO_HOST_LABEL) → sonichi#871 - Decision 4 (State sync .sync-allowlist + state/fleet/ design) → sonichi#872 Decisions 1, 5, 6 are policy ratifications with no impl follow-up: - 1 (names): vocabulary lands with merge - 5 (secrets at .env): policy, cross-Mac keys workstream deferred separately - 6 (Sutando.app bundle): tracked under pre-existing 2026-05-13 issue Addresses sonichi's nit sonichi#3 from PR review ("file impl-gap list as separate issues"). With this commit, nits sonichi#1, sonichi#2, sonichi#3, sonichi#4 are all resolved (per PR description table).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
claude_home_path(*subpath)(Python) andclaudeHomePath(...subpath)(TS) tosrc/util_paths.{py,ts}. Both resolve a path under Claude Code's per-user home directory (~/.claude/by default;$CLAUDE_HOMEfor override / testing).Closes implementation-gap #5 from issue #857 (workspace-design RFC tracking issue).
Motivation
Per the 2026-05-18 workspace-design RFC discussion in PR #858 + issue #857: Sutando's dependency on
~/.claude/is real and accepted operationally. Channel tokens, agent memory, skill discovery, settings — all live there. We commit to Claude Code as the host CLI today, but want the dependency surface countable so a future swap is a 1-day grep+replace rather than a re-architecture.This helper IS the "stop hedging on swap" discipline. ~20 LoC now, single grep surface for any future audit.
Usage
$CLAUDE_HOMEenv var overrides the base for tests + alt-host installs.Migration plan
Not flag-day. Existing callers (discord-bridge.py, inline-tools.ts skill-loader, health-check.py memory checks, etc.) can migrate opportunistically. New code that reads/writes under
~/.claude/should go through this helper.Test plan
claude_home_path('channels', 'discord', 'access.json')→ expected path$CLAUDE_HOMEoverride honored on bothnpx tsc --noEmitpasses🤖 Generated with Claude Code