lshed 0.15.1 → 0.15.3

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,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.15.3 — 2026-09-09
4
+
5
+ - 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.
6
+
7
+ ## 0.15.2 — 2026-09-08
8
+
9
+ - 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.
10
+ - `restore --dry-run` now lists the `install:` commands that a real run would leave for you, under the same "install command was not run" heading. Before, the dry run showed the clone but said nothing about the install, so the first sight of the command was the real run. Found on the Windows verification pass below.
11
+ - Fix: the `--link` integration test required file parts (`agents/*.md`, the instructions fragments) to be symbolic links, which on Windows needs Developer Mode. CI runners have that privilege; an ordinary Windows PC does not, and there `npm test` failed on a machine where the CLI itself behaved as designed (junction for directories, copy with a notice for files). The test now probes whether the machine can link files and expects the copy fallback otherwise, as the smoke suite already did.
12
+ - Verified on a real Windows 11 machine (PowerShell 7.6 and cmd.exe, Node 24, Developer Mode off), with lshed 0.15.1 from npm and shed and root paths containing spaces and Korean: `init`, `restore` into a machine with its own setup, `--link` with junctions and the copy fallback, `add`/`diff`/`save`, a profile switch with backups, the `codex` and `agents` targets, `sync` without a remote, `LSHED_HOME` and the remembered shed, and the repository's own smoke suite. Secrets stayed out of the shed, `--no-link` left the shed's files in place, and code pages 65001 and 949 both carried `skills/논문리뷰` through intact.
13
+
3
14
  ## 0.15.1 — 2026-09-08
4
15
 
5
16
  - `restore --yes` and `update --yes` now run a package's `install:` even when the package is already present or already up to date. Before, a first `restore` printed "rerun with '--yes'" but the rerun skipped the present package, so the command did nothing; only running the install by hand worked. Without `--yes` nothing changes: present packages are left alone and pending installs are only printed after a fresh clone.
package/README.ko.md CHANGED
@@ -454,7 +454,7 @@ $ lshed add
454
454
  ```
455
455
 
456
456
  - `enabledPlugins`와 `extraKnownMarketplaces`는 담지 않습니다. 플러그인·마켓플레이스 패키지의 몫이고, `restore`가 설치하면서 다시 만듭니다.
457
- - 홈 아래 절대 경로는 창고에서 `${HOME}/…`가 되어, 한 기기에서 쓴 훅 명령이 다른 기기에서도 돕니다. Claude Code는 `settings.json`의 변수를 채우지 않으므로 `restore`가 `${HOME}`과 `${VAR}`를 셸에서 직접 채우고, 없는 변수는 알린 뒤 자리표시자로 둡니다.
457
+ - 홈 아래 절대 경로는 창고에서 `${HOME}/…`가 되어, 한 기기에서 쓴 훅 명령이 다른 기기에서도 돕니다. `C:\Users\me\.claude\hooks\x`로 썼든 `/home/me/.claude/hooks/x`로 썼든 창고에서는 `${HOME}` 뒤가 늘 `/`라서, 창고 하나가 Windows·WSL·macOS·Linux를 함께 섬깁니다. Windows에서 `restore`는 이를 `C:/Users/me/.claude/hooks/x`로 되돌리며, 이 형태는 Node, PowerShell, cmd, Git Bash가 모두 읽습니다. Claude Code는 `settings.json`의 변수를 채우지 않으므로 `restore`가 `${HOME}`과 `${VAR}`를 셸에서 직접 채우고, 없는 변수는 알린 뒤 자리표시자로 둡니다.
458
458
  - `env`는 시크릿 맵으로 봅니다. 시크릿처럼 보이는 키는 마스킹하고 나머지(`CLAUDE_CODE_MAX_OUTPUT_TOKENS` 등)는 그대로 갑니다.
459
459
  - 패키지 안을 가리키는 값(툴킷 설치기가 쓴 훅)은 표시됩니다. 설치기가 다시 만들어 주는 것이면 `exclude:`에 넣고 `restore --yes`가 되살리게 두세요.
460
460
  - 창고가 키 전체를 소유하므로, 로컬에서 추가한 권한은 `diff`에 나타나고 다른 편집처럼 `save`로 창고에 들어갑니다.
@@ -530,6 +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
534
  - 개발하는 Linux 기기에서는 CI 너머까지 전체 명령을 돌려 봅니다. `install:`이 있는 git·GitHub 패키지의 `restore`와 `update`, 충돌까지 포함한 실제 원격과의 `sync`, `remove`/`prune`, 모든 `--agent` 대상, 환경변수 기본값, 실제 터미널을 거친 `restore --pick`, 컴파일된 Linux 바이너리까지입니다.
534
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`에 있습니다.
535
536
  - 개발하는 기기에서는 실제 창고 하나를 매일 씁니다. Claude Code, Codex, Antigravity가 모두 `--link`로 그 창고를 읽고, 셋 다 `status`에 드리프트가 없습니다.
@@ -542,14 +543,14 @@ lshed scan 루트를 읽기만 하고 나
542
543
 
543
544
  ## 문제 해결
544
545
 
545
- - **"창고 위치를 모릅니다"** — `--shed <dir>`를 주거나 `LSHED_HOME`을 설정하세요. `restore`가 한 번 성공하면 기억합니다.
546
+ - **"Shed location unknown. Pass --shed <dir> or set LSHED_HOME."** (창고 위치를 모름) — `--shed <dir>`를 주거나 `LSHED_HOME`을 설정하세요. `restore`가 한 번 성공하면 기억합니다.
546
547
  - **restore가 내 `CLAUDE.md`를 바꿨다** — `~/.claude/lshed/backups/<시각>/CLAUDE.md`에 있습니다. 내용을 창고의 조각으로 옮기고 그 조각을 프로필에 넣으세요.
547
548
  - **로컬에서 고친 스킬을 지키고 싶다** — `lshed diff`로 보고, `lshed save <id>`로 창고에 넣고, `lshed sync`.
548
549
  - **`status`가 패키지가 lock과 다르다고 한다** — 무언가가 lshed 몰래 clone이나 플러그인을 갱신했습니다(Claude Code는 플러그인을 자동 갱신합니다). `lshed update`가 새 버전을 기록합니다.
549
550
  - **`status`가 같은 새 항목을 계속 보여 준다** — 설치기 별칭이거나 임시 파일입니다. `lshed.yaml`의 `exclude:`에 넣으세요.
550
551
  - **restore가 MCP 변수가 없다고 한다** — 셸 프로필에서 export하고 Claude Code를 다시 시작하세요. `~/.claude.json`의 자리표시자는 맞게 들어간 것이고, Claude Code가 시작할 때 채웁니다.
551
- - **restore가 훅 경로를 엉뚱하게 썼다** — 창고는 홈 경로를 `${HOME}/…`로 담습니다. 이 기기에서 다른 곳을 가리켜야 하면 창고의 JSON을 `${HOME}`이나 다른 변수로 고치고 다시 `restore`하세요.
552
- - **Windows에서 `--link`가 파일을 복사했다** — 파일 하나짜리 링크는 개발자 모드가 필요합니다. 켜고 다시 `restore`하거나, 복사본을 두고 그 파일은 `save`로 다루세요.
552
+ - **restore가 훅 경로를 엉뚱하게 썼다** — 창고는 홈 경로를 `${HOME}/…`로 담습니다. 이 기기에서 다른 곳을 가리켜야 하면 창고의 JSON을 `${HOME}`이나 다른 변수로 고치고 다시 `restore`하세요. 홈 밖의 경로(`D:\tools\x.exe`, `/opt/x`)는 쓴 그대로 옮겨지며, 휴대성은 사용자 몫입니다.
553
+ - **Windows에서 `--link`가 파일을 복사했다** — 파일 하나짜리 링크는 개발자 모드가 필요합니다. 켜고 다시 `restore`하거나, 복사본을 그대로 두세요. 이후 `restore`는 그것을 `= … (copy; …)`로 알리고 건드리지 않으며, 편집은 `save`로 되가져옵니다.
553
554
  - **sync가 충돌로 멈췄다** — `cd <창고> && git pull --rebase`, 해결, `git rebase --continue`, 그리고 다시 `lshed sync`.
554
555
 
555
556
  ## 라이선스
package/README.md CHANGED
@@ -11,8 +11,6 @@ lshed restore research # apply a profile anywhere
11
11
 
12
12
  The shed is a plain directory. Put it in a git repo, Dropbox, whatever. `lshed sync` wraps the git part if you want it to. Works with Claude Code, and places the same shed into Codex, Gemini CLI, Copilot CLI, Cursor, Google Antigravity and the shared `~/.agents/skills`.
13
13
 
14
- > lshed's own output is in Korean; the terminal captures below are shown as they appear.
15
-
16
14
  ## Why
17
15
 
18
16
  Every new laptop, server, container or WSL box means setting up `~/.claude` again. The obvious fix is to put `~/.claude` itself in git, and for many people that is the right answer.
@@ -456,7 +454,7 @@ $ lshed add
456
454
  ```
457
455
 
458
456
  - `enabledPlugins` and `extraKnownMarketplaces` are never taken: the plugin and marketplace packages own them, and `restore` rebuilds them by installing those.
459
- - Absolute paths under your home directory become `${HOME}/…` in the shed, so a hook command written on one machine works on another. Claude Code does not expand variables in `settings.json`, so `restore` fills `${HOME}` and any `${VAR}` itself from your shell; unset variables are reported and left as placeholders.
457
+ - Absolute paths under your home directory become `${HOME}/…` in the shed, so a hook command written on one machine works on another. The shed always uses `/` after `${HOME}`, whether the path was written as `C:\Users\me\.claude\hooks\x` or `/home/me/.claude/hooks/x`, so one shed serves Windows, WSL, macOS and Linux; on Windows `restore` writes it back as `C:/Users/me/.claude/hooks/x`, which Node, PowerShell, cmd and Git Bash all accept. Claude Code does not expand variables in `settings.json`, so `restore` fills `${HOME}` and any `${VAR}` itself from your shell; unset variables are reported and left as placeholders.
460
458
  - `env` is treated as a secret map: keys that look secret are masked, the rest (`CLAUDE_CODE_MAX_OUTPUT_TOKENS`, …) travel as they are.
461
459
  - A value pointing inside a package (a hook a toolkit's installer wrote) is flagged. If the installer recreates it, put it in `exclude:` and let `restore --yes` bring it back.
462
460
  - Since the shed owns the whole key, extra permissions you grant locally show up in `diff` and go into the shed with `save`, like any other edit.
@@ -532,6 +530,7 @@ The shed is the source of truth for authored parts: `save` copies local edits ba
532
530
  ## What has been verified
533
531
 
534
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.
535
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.
536
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.
537
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.
@@ -544,14 +543,14 @@ The shed is the source of truth for authored parts: `save` copies local edits ba
544
543
 
545
544
  ## Troubleshooting
546
545
 
547
- - **"창고 위치를 모릅니다"** (shed location unknown) — pass `--shed <dir>` or set `LSHED_HOME`. After one successful `restore`, lshed remembers it.
546
+ - **"Shed location unknown. Pass --shed <dir> or set LSHED_HOME."** — do one of those. After one successful `restore`, lshed remembers it.
548
547
  - **restore replaced my `CLAUDE.md`** — it is in `~/.claude/lshed/backups/<timestamp>/CLAUDE.md`. Move its content into a fragment in the shed and add that fragment to your profile.
549
548
  - **I edited a skill locally and want to keep it** — `lshed diff` to see, `lshed save <id>` to push it into the shed, then `lshed sync`.
550
549
  - **`status` says a package differs from the lock** — something updated the clone or plugin behind lshed's back (Claude Code auto-updates plugins). `lshed update` records the new version.
551
550
  - **`status` keeps listing the same new things** — they are installer aliases or scratch. Add them to `exclude:` in `lshed.yaml`.
552
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.
553
- - **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.
554
- - **`--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.
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: later restores report it as `= … (copy; …)` and leave it alone, and `save` brings edits back from it.
555
554
  - **sync stopped on a conflict** — `cd <shed> && git pull --rebase`, resolve, `git rebase --continue`, then `lshed sync` again.
556
555
 
557
556
  ## License