lshed 0.15.2 → 0.15.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.15.4 — 2026-09-09
4
+
5
+ - `restore` now fills `${HOME}` in Claude Code MCP entries itself instead of leaving it for Claude Code. Claude Code expands `${VAR}` only from variables present in its environment, and Windows has no `HOME`; with it missing, Claude Code 2.1.265 reports "Missing environment variables: HOME" and does not start the server (checked with an isolated `CLAUDE_CONFIG_DIR` and a server command that leaves a marker file: with `HOME` set the marker appears, with `HOME` unset it does not). So a shed entry such as `"args": ["${HOME}/mcp/server.js"]` was placed verbatim and never worked on Windows. Secret placeholders (`${EXA_API_KEY}`) are still written as is and still expanded by Claude Code, so no secret value passes through lshed. The third Windows verification pass flagged the empty `HOME` as an open question.
6
+
7
+ ## 0.15.3 — 2026-09-09
8
+
9
+ - Fix: on a machine that cannot create file links (Windows without Developer Mode), `restore` in link mode placed a file part as a copy and then, on every later `restore`, replaced that copy again with a `~` line and the "could not link" notice, never settling on `=`. Found by the second Windows verification pass, where the `--link` test kept failing for this reason after 0.15.2 had fixed its first assertion. lshed now checks once per run whether the machine can link files; if it cannot, an identical copy counts as placed and is reported as `= agents/rev.md (copy; file links on Windows need Developer Mode)`. Directories are unaffected, since junctions always work. Turning Developer Mode on later and running `restore` again still converts the copies to links.
10
+
3
11
  ## 0.15.2 — 2026-09-08
4
12
 
5
13
  - A shed no longer carries the separators of the machine that made it. Home paths in settings and MCP entries are stored as `${HOME}/…` with `/` throughout, whether the value was written `C:\Users\me\.claude\hooks\x`, `C:/Users/me/.claude/hooks/x` or `/home/me/.claude/hooks/x`; before, a Windows shed kept `${HOME}\.claude\…`, which restored on Linux or WSL as `/home/me\.claude\…`, and a Windows path written with `/` was not recognized as the home directory at all and went into the shed with the user name in it. On Windows, `restore` now fills `${HOME}` as `C:/Users/me`, so the result has one kind of separator, a form Node, PowerShell, cmd and Git Bash all accept; the same applies to the Codex `config.toml`. Drift comparison ignores separators and case for `${HOME}` strings, so a value you wrote with backslashes does not show as drift against the shed. A shed written by an earlier version is normalized the next time `save` or `add` touches the entry; a value that version already placed on a Windows machine keeps its mixed separators until the entry is next rewritten, since it still counts as the same value.
package/README.ko.md CHANGED
@@ -439,7 +439,7 @@ Claude Code 플러그인은 자기 스킴을 가진 패키지입니다. `init`
439
439
  "headers": { "Authorization": "Bearer ${NOTION_AUTHORIZATION}" } }
440
440
  ```
441
441
 
442
- `restore`는 자리표시자를 그대로 씁니다. Claude Code가 서버를 띄울 때 환경에서 `${VAR}`를 채우므로 값은 셸에만 있습니다(`~/.zshrc`의 `export EXA_API_KEY=...` 등, 시크릿을 관리하는 방식대로). `restore`와 `status`는 프로필에 필요한데 설정되지 않은 변수를 나열합니다. 휴리스틱은 제안일 뿐입니다. 창고의 JSON을 고쳐 자리표시자를 더하거나 빼도 되고, `args`나 `url`에 토큰처럼 보이는 것이 있으면 `init`이 경고합니다. `save`는 기존 자리표시자를 유지하고 새로 생긴 시크릿 키를 마스킹하므로, 교체한 키가 실수로 창고에 새지 않습니다. `diff`는 자리표시자를 와일드카드로 비교해서, 실제 값을 가진 기기가 드리프트로 잡히지 않습니다.
442
+ `restore`는 자리표시자를 그대로 씁니다. Claude Code가 서버를 띄울 때 환경에서 `${VAR}`를 채우므로 값은 셸에만 있습니다. 예외는 `${HOME}` 하나로, 이것은 lshed가 직접 채웁니다. Claude Code는 환경에 있는 변수만 채우는데 Windows에는 `HOME`이 없고, 없으면 "Missing environment variables: HOME"을 내며 서버를 띄우지 않기 때문입니다(2.1.265로 확인)(`~/.zshrc`의 `export EXA_API_KEY=...` 등, 시크릿을 관리하는 방식대로). `restore`와 `status`는 프로필에 필요한데 설정되지 않은 변수를 나열합니다. 휴리스틱은 제안일 뿐입니다. 창고의 JSON을 고쳐 자리표시자를 더하거나 빼도 되고, `args`나 `url`에 토큰처럼 보이는 것이 있으면 `init`이 경고합니다. `save`는 기존 자리표시자를 유지하고 새로 생긴 시크릿 키를 마스킹하므로, 교체한 키가 실수로 창고에 새지 않습니다. `diff`는 자리표시자를 와일드카드로 비교해서, 실제 값을 가진 기기가 드리프트로 잡히지 않습니다.
443
443
 
444
444
  ## 설정
445
445
 
@@ -530,7 +530,7 @@ lshed scan 루트를 읽기만 하고 나
530
530
  ## 검증된 것
531
531
 
532
532
  - 테스트, CLI 스모크, 단독 실행파일이 push마다 **Ubuntu, macOS, Windows**(Node 20, 22)에서 돕니다. Windows는 `--link`에 junction을, 플러그인 설치에 `claude.cmd`를 씁니다. 스모크에는 한글 이름 스킬이 들어 있어, macOS의 파일 이름 정규화 차이나 Windows의 코드페이지 문제는 사용자 기기가 아니라 CI에서 먼저 실패합니다.
533
- - 개발자 모드가 꺼진 실제 Windows 11 PC(PowerShell 7과 cmd.exe, Node 24, 공백과 한글이 든 경로)에서도 npm 으로 설치한 lshed 0.15.1 로 같은 절차가 통과했습니다. `init`, 이미 설정이 있는 기기로의 `restore`, `--link`(스킬은 junction, 단일 파일은 안내와 함께 복사), `add`/`diff`/`save`, 프로필 전환, `codex`·`agents` 대상, 원격 없는 `sync`, 스모크까지입니다.
533
+ - 개발자 모드가 꺼진 실제 Windows 11 PC(PowerShell 7과 cmd.exe, Node 24, 공백과 한글이 든 경로)에서도 npm 으로 설치한 lshed 0.15.1 로 같은 절차가 통과했습니다. `init`, 이미 설정이 있는 기기로의 `restore`, `--link`(스킬은 junction, 단일 파일은 안내와 함께 복사), `add`/`diff`/`save`, 프로필 전환, `codex`·`agents` 대상, 원격 없는 `sync`, 스모크까지입니다. 같은 PC 에서 두 차례 더 확인했습니다. 0.15.2 는 거기서 만든 창고가 WSL 안에서 `/home/…/` 경로로 복원되고 옛 창고가 `save` 한 번으로 정규화되는 것을, 0.15.3 은 링크 모드가 복사로 놓았던 파일 부품을 `=` 로 안정시키고 창고가 바뀔 때만 다시 복사하는 것을 확인했습니다.
534
534
  - 개발하는 Linux 기기에서는 CI 너머까지 전체 명령을 돌려 봅니다. `install:`이 있는 git·GitHub 패키지의 `restore`와 `update`, 충돌까지 포함한 실제 원격과의 `sync`, `remove`/`prune`, 모든 `--agent` 대상, 환경변수 기본값, 실제 터미널을 거친 `restore --pick`, 컴파일된 Linux 바이너리까지입니다.
535
535
  - 다른 에이전트는 문서만이 아니라 도구 자체로 확인합니다. `scripts/vm/probe.sh`는 임시 창고를 도구의 실제 루트에 복원한 뒤, 스킬에 든 암호어, 지침 파일에 든 코드워드, `--link` 링크를 거친 같은 스킬을 비대화형으로 물어봅니다. Codex 0.153.2와 Antigravity CLI 1.1.27은 모든 검사를 통과했고(마지막 실행 2026-09-08, lshed 0.14.1), Gemini CLI·Copilot CLI·Cursor는 아직 파일 배치와 형식까지만 확인했습니다. 자세한 내용과 새 VM에서 전부 돌리는 cloud-init 파일은 `scripts/vm/README.md`에 있습니다.
536
536
  - 개발하는 기기에서는 실제 창고 하나를 매일 씁니다. Claude Code, Codex, Antigravity가 모두 `--link`로 그 창고를 읽고, 셋 다 `status`에 드리프트가 없습니다.
@@ -550,7 +550,7 @@ lshed scan 루트를 읽기만 하고 나
550
550
  - **`status`가 같은 새 항목을 계속 보여 준다** — 설치기 별칭이거나 임시 파일입니다. `lshed.yaml`의 `exclude:`에 넣으세요.
551
551
  - **restore가 MCP 변수가 없다고 한다** — 셸 프로필에서 export하고 Claude Code를 다시 시작하세요. `~/.claude.json`의 자리표시자는 맞게 들어간 것이고, Claude Code가 시작할 때 채웁니다.
552
552
  - **restore가 훅 경로를 엉뚱하게 썼다** — 창고는 홈 경로를 `${HOME}/…`로 담습니다. 이 기기에서 다른 곳을 가리켜야 하면 창고의 JSON을 `${HOME}`이나 다른 변수로 고치고 다시 `restore`하세요. 홈 밖의 경로(`D:\tools\x.exe`, `/opt/x`)는 쓴 그대로 옮겨지며, 휴대성은 사용자 몫입니다.
553
- - **Windows에서 `--link`가 파일을 복사했다** — 파일 하나짜리 링크는 개발자 모드가 필요합니다. 켜고 다시 `restore`하거나, 복사본을 두고 그 파일은 `save`로 다루세요.
553
+ - **Windows에서 `--link`가 파일을 복사했다** — 파일 하나짜리 링크는 개발자 모드가 필요합니다. 켜고 다시 `restore`하거나, 복사본을 그대로 두세요. 이후 `restore`는 그것을 `= … (copy; …)`로 알리고 건드리지 않으며, 편집은 `save`로 되가져옵니다.
554
554
  - **sync가 충돌로 멈췄다** — `cd <창고> && git pull --rebase`, 해결, `git rebase --continue`, 그리고 다시 `lshed sync`.
555
555
 
556
556
  ## 라이선스
package/README.md CHANGED
@@ -439,7 +439,7 @@ User-scope MCP servers live in `~/.claude.json`, next to machine IDs and session
439
439
  "headers": { "Authorization": "Bearer ${NOTION_AUTHORIZATION}" } }
440
440
  ```
441
441
 
442
- `restore` writes the placeholder as is. Claude Code expands `${VAR}` from the environment when it starts the server, so the value only ever lives in your shell (`export EXA_API_KEY=...` in `~/.zshrc`, or however you manage secrets). `restore` and `status` list the variables the profile needs that are not set. The heuristic is a suggestion: edit the JSON in the shed to add or remove placeholders, and `init` warns when something in `args` or `url` looks like a token. `save` keeps existing placeholders and masks new secret-looking keys, so a rotated key never leaks into the shed by accident. `diff` compares with placeholders as wildcards, so a machine holding real values is not drift.
442
+ `restore` writes the placeholder as is. Claude Code expands `${VAR}` from the environment when it starts the server, so the value only ever lives in your shell. The one exception is `${HOME}`, which lshed fills itself: Claude Code only expands variables that exist in its environment, Windows has no `HOME`, and with it missing Claude Code reports "Missing environment variables: HOME" and does not start the server (checked against 2.1.265) (`export EXA_API_KEY=...` in `~/.zshrc`, or however you manage secrets). `restore` and `status` list the variables the profile needs that are not set. The heuristic is a suggestion: edit the JSON in the shed to add or remove placeholders, and `init` warns when something in `args` or `url` looks like a token. `save` keeps existing placeholders and masks new secret-looking keys, so a rotated key never leaks into the shed by accident. `diff` compares with placeholders as wildcards, so a machine holding real values is not drift.
443
443
 
444
444
  ## Settings
445
445
 
@@ -530,7 +530,7 @@ The shed is the source of truth for authored parts: `save` copies local edits ba
530
530
  ## What has been verified
531
531
 
532
532
  - Tests, a CLI smoke run and the standalone binaries run on every push on **Ubuntu, macOS and Windows** (Node 20 and 22). Windows uses junctions for `--link` and `claude.cmd` for plugin installs. The smoke run includes a skill with a Korean name, so a filename-normalization difference on macOS or a code-page problem on Windows would fail there, not on a user's machine.
533
- - On a real Windows 11 PC without Developer Mode (PowerShell 7 and cmd.exe, Node 24, paths with spaces and Korean) the same walk passed with lshed 0.15.1 from npm: `init`, `restore` next to an existing setup, `--link` (junctions for skills, copies with a notice for single files), `add`/`diff`/`save`, a profile switch, the `codex` and `agents` targets, `sync` without a remote, and the smoke suite.
533
+ - On a real Windows 11 PC without Developer Mode (PowerShell 7 and cmd.exe, Node 24, paths with spaces and Korean) the same walk passed with lshed 0.15.1 from npm: `init`, `restore` next to an existing setup, `--link` (junctions for skills, copies with a notice for single files), `add`/`diff`/`save`, a profile switch, the `codex` and `agents` targets, `sync` without a remote, and the smoke suite. Two follow-up passes on the same PC confirmed 0.15.2 (a shed made there restores with `/home/…/` paths inside WSL, an older shed is normalized by one `save`) and 0.15.3 (link mode settles on `=` for the file parts it had to copy, and re-copies them only when the shed changes).
534
534
  - On the Linux development machine the whole command set is exercised beyond CI: git and GitHub packages with `install:` through `restore` and `update`, `sync` against a real remote including a conflict, `remove`/`prune`, every `--agent` target, the environment-variable defaults, `restore --pick` through a real terminal, and the compiled Linux binary.
535
535
  - The other agents are checked against the tools themselves, not just their docs. `scripts/vm/probe.sh` restores a throwaway shed into a tool's real root and asks the tool, non-interactively, for a passphrase kept in a skill, a codeword kept in the instructions file, and the same skill again through a `--link` symlink. Codex 0.153.2 and Antigravity CLI 1.1.27 pass every check (last run 2026-09-08 with lshed 0.14.1); Gemini CLI, Copilot CLI and Cursor are verified for file placement and format so far. `scripts/vm/README.md` has the details and a cloud-init file for running the whole thing on a fresh VM.
536
536
  - One real shed is in daily use on the machine this is developed on: Claude Code, Codex and Antigravity all read it through `--link`, and `status` reports no drift for any of the three.
@@ -550,7 +550,7 @@ The shed is the source of truth for authored parts: `save` copies local edits ba
550
550
  - **`status` keeps listing the same new things** — they are installer aliases or scratch. Add them to `exclude:` in `lshed.yaml`.
551
551
  - **restore says an MCP variable is missing** — export it in your shell profile and restart Claude Code. The placeholder in `~/.claude.json` is correct; Claude Code fills it at startup.
552
552
  - **restore wrote a hook with the wrong path** — the shed stores home paths as `${HOME}/…`. If a command points elsewhere on this machine, edit the JSON in the shed to use `${HOME}` or another variable and `restore` again. Paths outside your home directory (`D:\tools\x.exe`, `/opt/x`) are copied as written and are your job to keep portable.
553
- - **`--link` copied a file on Windows** — single-file links need Developer Mode. Turn it on and `restore` again, or keep the copy and use `save` for that file.
553
+ - **`--link` copied a file on Windows** — single-file links need Developer Mode. Turn it on and `restore` again, or keep the copy: later restores report it as `= … (copy; …)` and leave it alone, and `save` brings edits back from it.
554
554
  - **sync stopped on a conflict** — `cd <shed> && git pull --rebase`, resolve, `git rebase --continue`, then `lshed sync` again.
555
555
 
556
556
  ## License