lshed 0.17.4 → 0.17.5
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 +11 -0
- package/README.ko.md +156 -147
- package/README.md +139 -131
- package/dist/cli.js +162 -161
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,39 +9,9 @@ lshed init --shed ~/lshed # scan ~/.claude into a shed + write lshed.ya
|
|
|
9
9
|
lshed restore research # apply a profile anywhere
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
The shed is a plain directory. Put it in a git repo, Dropbox, whatever
|
|
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
|
-
|
|
15
|
-
|
|
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.
|
|
17
|
-
|
|
18
|
-
**When a plain git repository is enough.** You are one person, every machine gets the same setup, and everything in `~/.claude` is yours. Then make `~/.claude` itself a git repository and you should not install lshed. Git does the moving; the `.gitignore` only keeps machine state (sessions, caches) out of it:
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
cd ~/.claude && git init
|
|
22
|
-
printf 'projects/\ncache/\nsessions/\nshell-snapshots/\nhistory.jsonl\n*.bak*\n' > .gitignore
|
|
23
|
-
git add skills agents commands CLAUDE.md settings.json .gitignore && git commit -m init
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
No new concepts, no copy step: the directory you edit is the repository. `git push` here and `git clone <remote> ~/.claude` on the next machine is the whole restore.
|
|
27
|
-
|
|
28
|
-
**Where that stops working.** The repository above starts to hurt as soon as `~/.claude` is not just yours:
|
|
29
|
-
|
|
30
|
-
- **Toolkits you installed.** One cloned toolkit here is 1.6 GB and generated 53 alias skills next to the 4 you wrote. Raw git commits all of it, or you maintain the ignore list by hand.
|
|
31
|
-
- **Secrets inside one JSON file.** MCP servers and their tokens live in `~/.claude.json` together with unrelated state. File-level ignore cannot split them, so you either commit tokens or leave MCP out.
|
|
32
|
-
- **A machine that already has a setup.** `git clone` into a non-empty `~/.claude` is a merge you do by hand, and nothing tracks which files came from the repo and which were already there.
|
|
33
|
-
- **Different subsets per machine.** A headless server wants no browser toolkit and no MCP. Branches or templates can fake this, but nothing removes the parts you no longer want when you switch.
|
|
34
|
-
- **Choosing on the machine itself.** `git clone` is all or nothing. On a new box you want to look at what the shed has, category by category, and tick what this machine needs.
|
|
35
|
-
|
|
36
|
-
lshed exists for those five cases. It keeps the shed as a plain directory in git, and adds three ideas on top:
|
|
37
|
-
|
|
38
|
-
| Idea | What it gives you |
|
|
39
|
-
|---|---|
|
|
40
|
-
| **Components** | every skill / agent / command / instruction fragment / MCP server / settings key is one named part; toolkits you installed are recorded as a source and version, not copied. |
|
|
41
|
-
| **Profiles** | named recipes — `research`, `work`, `minimal` — that pick a subset of parts; write them in `lshed.yaml`, or let `restore --pick` build one from a checklist. |
|
|
42
|
-
| **Managed set** | lshed remembers what it placed, so switching profiles or restoring onto an existing machine removes only its own files and never touches yours. |
|
|
43
|
-
|
|
44
|
-
The trade: you edit in `~/.claude` and run `lshed save` to copy changes into the shed (or use `restore --link` on machines where you edit a lot, and skip the copy step), and lshed has to know each agent's layout, which the plain repository does not. If none of the five cases applies to you, the plain repository wins.
|
|
14
|
+
**Contents:** [Install](#install) · [Quick start](#quick-start) · [Why not just git?](#why-not-just-git) · [How to use it](#how-to-use-it) · [Reference](#reference) · [Trust](#trust) · [Troubleshooting](#troubleshooting) · [What has been verified](#what-has-been-verified)
|
|
45
15
|
|
|
46
16
|
## Install
|
|
47
17
|
|
|
@@ -80,7 +50,35 @@ lshed restore --pick --shed ~/lshed # or tick what this machine gets, ca
|
|
|
80
50
|
lshed check # optional: ask the agent whether it reads what was placed
|
|
81
51
|
```
|
|
82
52
|
|
|
83
|
-
If the other machine runs a different agent, add `--agent` to `restore` there; skills, the instructions file and MCP servers carry over, the rest is announced and skipped ([details](#other-agents-same-shed)).
|
|
53
|
+
If the other machine runs a different agent, add `--agent` to `restore` there; skills, the instructions file and MCP servers carry over, the rest is announced and skipped ([details](#other-agents-same-shed)). For a container or a dotfiles script that runs on every start, see [a new machine](#a-new-machine).
|
|
54
|
+
|
|
55
|
+
## Why not just git?
|
|
56
|
+
|
|
57
|
+
If you are one person, every machine gets the same setup, and everything in `~/.claude` is yours, make `~/.claude` itself a git repository and skip lshed:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
cd ~/.claude && git init
|
|
61
|
+
printf 'projects/\ncache/\nsessions/\nshell-snapshots/\nhistory.jsonl\n*.bak*\n' > .gitignore
|
|
62
|
+
git add skills agents commands CLAUDE.md settings.json .gitignore && git commit -m init
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
That stops working as soon as `~/.claude` is not just yours:
|
|
66
|
+
|
|
67
|
+
- **Toolkits you installed** — one cloned toolkit here is 1.6 GB and generated 53 alias skills next to the 4 you wrote. Raw git commits all of it, or you maintain the ignore list by hand.
|
|
68
|
+
- **Secrets inside one JSON file** — MCP servers and their tokens live in `~/.claude.json` together with unrelated state. You either commit tokens or leave MCP out.
|
|
69
|
+
- **A machine that already has a setup** — `git clone` into a non-empty `~/.claude` is a merge you do by hand, and nothing tracks which files came from the repo.
|
|
70
|
+
- **Different subsets per machine** — a headless server wants no browser toolkit and no MCP, and nothing removes the parts you no longer want when you switch.
|
|
71
|
+
- **Choosing on the machine itself** — `git clone` is all or nothing.
|
|
72
|
+
|
|
73
|
+
lshed keeps the shed as a plain directory in git and adds three ideas:
|
|
74
|
+
|
|
75
|
+
| Idea | What it gives you |
|
|
76
|
+
|---|---|
|
|
77
|
+
| **Components** | every skill / agent / command / instruction fragment / MCP server / settings key is one named part; toolkits you installed are recorded as a source and version, not copied. |
|
|
78
|
+
| **Profiles** | named recipes — `research`, `work`, `minimal` — that pick a subset of parts; write them in `lshed.yaml`, or let `restore --pick` build one from a checklist. |
|
|
79
|
+
| **Managed set** | lshed remembers what it placed, so switching profiles or restoring onto an existing machine removes only its own files and never touches yours. |
|
|
80
|
+
|
|
81
|
+
The trade: you edit in `~/.claude` and run `lshed save` to copy changes into the shed (or use `restore --link` where you edit a lot and skip the copy step).
|
|
84
82
|
|
|
85
83
|
## How to use it
|
|
86
84
|
|
|
@@ -114,7 +112,7 @@ lshed sync
|
|
|
114
112
|
|
|
115
113
|
### The loop: edit, save, sync
|
|
116
114
|
|
|
117
|
-
You edit skills where the agent reads them, in its own folder
|
|
115
|
+
You edit skills where the agent reads them, in its own folder. The shed does not change by itself.
|
|
118
116
|
|
|
119
117
|
```
|
|
120
118
|
lshed status # what profile is applied, what drifted, what is new
|
|
@@ -123,7 +121,7 @@ lshed save # copy local edits into the shed (or: lshed save skills/ad
|
|
|
123
121
|
lshed sync # commit the shed, pull, push
|
|
124
122
|
```
|
|
125
123
|
|
|
126
|
-
None of these need `--agent`: on a machine where only one agent has lshed state, they find it; where several do, they ask you to say which. `save` is the only path from the agent folder to the shed, and it only works for parts the shed owns
|
|
124
|
+
None of these need `--agent`: on a machine where only one agent has lshed state, they find it; where several do, they ask you to say which. `save` is the only path from the agent folder to the shed, and it only works for parts the shed owns. `sync` warns if you have unsaved edits so you do not push a shed that is behind your machine.
|
|
127
125
|
|
|
128
126
|
### A machine that already has a setup
|
|
129
127
|
|
|
@@ -146,7 +144,7 @@ lshed add windows-only mcp/my-local-server
|
|
|
146
144
|
lshed sync
|
|
147
145
|
```
|
|
148
146
|
|
|
149
|
-
Do not run `init` on such a machine just to look around
|
|
147
|
+
Do not run `init` on such a machine just to look around: `init` claims what it finds as lshed-managed, so a later `restore` from your real shed would treat those parts as removable (backed up, but removed). Use `lshed scan`, which only prints.
|
|
150
148
|
|
|
151
149
|
### A new machine
|
|
152
150
|
|
|
@@ -174,7 +172,26 @@ Some entries need environment variables that are not set. Secrets never go in th
|
|
|
174
172
|
mcp:notion: NOTION_AUTHORIZATION
|
|
175
173
|
```
|
|
176
174
|
|
|
177
|
-
Two things need you afterwards. Package `install:` commands are shell commands from a repository you cloned, so `restore` shows them and stops; run them yourself or rerun with `--yes
|
|
175
|
+
Two things need you afterwards. Package `install:` commands are shell commands from a repository you cloned, so `restore` shows them and stops; run them yourself or rerun with `--yes` (a command that fails under `--yes` does not stop the restore: the parts are placed, the failure is listed at the end, and `restore` exits 1). MCP servers reference secrets as `${VAR}`; export the variables in your shell and the agent fills them in. From then on `lshed restore` with no arguments reapplies the last profile, and the shed location is remembered.
|
|
176
|
+
|
|
177
|
+
**Containers and dotfiles scripts.** For a bootstrap that runs on every start, two flags keep it to one line. `--fresh-only` does nothing on a root that already has lshed state (exit 0, one line saying so), and `--agent installed` restores into every agent whose CLI is on `PATH`, one after another, each with its own state:
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
lshed restore default --shed ~/lshed --agent installed --fresh-only
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
Agents with a CLI here: claude-code, codex, agy
|
|
185
|
+
|
|
186
|
+
── claude-code ──
|
|
187
|
+
+ package gstack (clone https://github.com/garrytan/gstack.git @main → c8f0c4e)
|
|
188
|
+
…
|
|
189
|
+
── codex ──
|
|
190
|
+
· codex does not handle settings, skipped
|
|
191
|
+
…
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
`installed` looks for `claude`, `codex`, `gemini`, `copilot`, `agent` (Cursor) and `agy`; the folder-only `agents` target is left out because Codex fills `~/.agents/skills` already. A fresh machine has no state to remember the shed from, so `--shed` or `LSHED_HOME` is required, and `installed` does not go with `--pick` or `--root`. The run exits 1 if any agent's restore did, after every agent has been tried. A devcontainer that does exactly this — image with the agents and lshed, shed mounted at `/shed`, this command in the entrypoint — is at [agent-box](https://github.com/LeeSongHeon-LSH/agent-box).
|
|
178
195
|
|
|
179
196
|
### Picking instead of naming a profile
|
|
180
197
|
|
|
@@ -210,9 +227,9 @@ Profile "lab-box" saved to lshed.yaml. To use it on other machines, push it with
|
|
|
210
227
|
Profile "lab-box" applied: placed 4, removed 0, installed 1 package
|
|
211
228
|
```
|
|
212
229
|
|
|
213
|
-
Categories the shed has nothing in
|
|
230
|
+
Categories the shed has nothing in are skipped, not shown empty. The choice is always saved as a profile, named after the machine unless you type another name: that is what makes the next bare `lshed restore` reapply it, and what `lshed sync` carries to your other machines. If the shed already has a profile with that name, lshed asks before overwriting it.
|
|
214
231
|
|
|
215
|
-
`lshed restore default --pick` starts with `default`'s parts checked, so you can trim a profile for this machine instead of starting from nothing.
|
|
232
|
+
`lshed restore default --pick` starts with `default`'s parts checked, so you can trim a profile for this machine instead of starting from nothing. `--dry-run` shows the plan and writes neither `lshed.yaml` nor the agent folder. Ctrl+C at any screen leaves everything untouched. On a machine with no applied profile, a bare `lshed restore --shed ~/lshed` in a terminal opens the picker by itself; in a script or a pipe it asks for a profile name instead.
|
|
216
233
|
|
|
217
234
|
### Profiles
|
|
218
235
|
|
|
@@ -240,7 +257,7 @@ lshed restore server
|
|
|
240
257
|
+ lshed/instructions/server-rules.md
|
|
241
258
|
```
|
|
242
259
|
|
|
243
|
-
Switching removes only what the previous profile placed (`-`), keeps what both use (`=`), and rewrites what changed (`~`). Everything removed or overwritten goes to `~/.claude/lshed/backups/<timestamp>/` first. Packages are additive: a profile that does not list `gstack` leaves the clone alone.
|
|
260
|
+
Switching removes only what the previous profile placed (`-`), keeps what both use (`=`), and rewrites what changed (`~`). Everything removed or overwritten goes to `~/.claude/lshed/backups/<timestamp>/` first. Packages are additive: a profile that does not list `gstack` leaves the clone alone. Instructions fragments are ordered; `restore` writes a `CLAUDE.md` that `@`-imports each fragment, so editing a fragment in the shed shows up on the next `restore` and there is nothing to merge.
|
|
244
261
|
|
|
245
262
|
A profile can build on another one with `extends`, so a machine-specific profile lists only what is different:
|
|
246
263
|
|
|
@@ -258,17 +275,17 @@ profiles:
|
|
|
258
275
|
instructions: [lab-rules] # comes after default's `main`
|
|
259
276
|
```
|
|
260
277
|
|
|
261
|
-
Inheritance only adds. The parent's parts come first, then the profile's own
|
|
278
|
+
Inheritance only adds. The parent's parts come first, then the profile's own. To get *less* than the parent, do not extend it; list what you want. A missing parent or a cycle is reported as a `lshed.yaml` error before anything is touched.
|
|
262
279
|
|
|
263
|
-
Three things are easy to confuse
|
|
280
|
+
Three things are easy to confuse, and they are separate on purpose:
|
|
264
281
|
|
|
265
|
-
- **Stop using a part, keep it** — leave its id out of the profile. `restore` takes it off this machine (backed up); the part stays in the shed
|
|
266
|
-
- **A smaller inherited set** — `extends` only adds, so you cannot inherit a profile and drop one part from it. List the smaller set outright, or split a shared base out and extend that.
|
|
267
|
-
- **Delete a part from the shed** — `lshed remove <id>` (
|
|
282
|
+
- **Stop using a part, keep it** — leave its id out of the profile. `restore` takes it off this machine (backed up); the part stays in the shed and comes back when you list it again. This is the everyday, reversible "remove".
|
|
283
|
+
- **A smaller inherited set** — `extends` only adds, so you cannot inherit a profile and drop one part from it. List the smaller set outright, or split a shared base out and extend that.
|
|
284
|
+
- **Delete a part from the shed** — `lshed remove <id>` (refused while any profile still lists it) or `lshed prune` for whatever no profile uses. This is the permanent one.
|
|
268
285
|
|
|
269
286
|
### Other agents, same shed
|
|
270
287
|
|
|
271
|
-
Codex, Gemini CLI, Copilot CLI, Cursor and Google Antigravity (`agy`) all read skills from `<their config dir>/skills/<name>/SKILL.md`, the same layout Claude Code uses, and
|
|
288
|
+
Codex, Gemini CLI, Copilot CLI, Cursor and Google Antigravity (`agy`) all read skills from `<their config dir>/skills/<name>/SKILL.md`, the same layout Claude Code uses, and most also read the shared `~/.agents/skills/`. So one shed serves them all; pick the target with `--agent`. For Codex, skills go to `~/.agents/skills` because that is the location Codex documents, so use either `--agent codex` or `--agent agents` for skills on one machine, not both:
|
|
272
289
|
|
|
273
290
|
```
|
|
274
291
|
lshed restore --agent agents # ~/.agents/skills: every tool that follows the convention reads it
|
|
@@ -280,20 +297,20 @@ lshed restore --agent agy # ~/.gemini/config/skills + ~/.gemini/AG
|
|
|
280
297
|
| `--agent` | root | skills | instructions file | MCP servers |
|
|
281
298
|
|---|---|---|---|---|
|
|
282
299
|
| `claude-code` (default) | `~/.claude` or `$CLAUDE_CONFIG_DIR` | yes, plus agents, commands, settings | `CLAUDE.md`, `@`-imports fragments | `~/.claude.json` |
|
|
283
|
-
| `codex` | `~/.codex` or `$CODEX_HOME` | yes, in `~/.agents/skills`
|
|
300
|
+
| `codex` | `~/.codex` or `$CODEX_HOME` | yes, in `~/.agents/skills` | `AGENTS.md`, fragments concatenated | `config.toml` `[mcp_servers.*]` |
|
|
284
301
|
| `gemini` | `~/.gemini` | yes | `GEMINI.md`, concatenated | `settings.json` |
|
|
285
302
|
| `copilot` | `~/.copilot` or `$COPILOT_HOME` | yes | `copilot-instructions.md`, concatenated | `mcp-config.json` |
|
|
286
303
|
| `cursor` | `~/.cursor` | yes | none (Cursor's user rules live in its settings UI) | `mcp.json` |
|
|
287
|
-
| `agy` | `~/.gemini/config` | yes | `../AGENTS.md`, concatenated
|
|
304
|
+
| `agy` | `~/.gemini/config` | yes | `../AGENTS.md`, concatenated | `mcp_config.json` |
|
|
288
305
|
| `agents` | `~/.agents` | yes | none | none |
|
|
289
306
|
|
|
290
|
-
MCP entries are stored in the shed in Claude Code's shape and translated
|
|
307
|
+
MCP entries are stored in the shed in Claude Code's shape and translated into each tool's own format on the way out. For Codex and Cursor the config carries the variable *names*, so secret values never touch the file; Gemini, Antigravity and Copilot do not expand placeholders, so lshed fills them from your shell at `restore`. Codex's `config.toml` is edited table by table; your comments and other settings stay.
|
|
291
308
|
|
|
292
|
-
Each agent root keeps its own `lshed/state.json`, so restoring into `~/.codex` never touches what lshed placed in `~/.claude`, and each can use a different profile or `--link` choice. Parts the target does not understand are announced and skipped
|
|
309
|
+
Each agent root keeps its own `lshed/state.json`, so restoring into `~/.codex` never touches what lshed placed in `~/.claude`, and each can use a different profile or `--link` choice. Parts the target does not understand are announced and skipped (settings and Claude plugins for the other agents); `github:`/`git:` packages are cloned into every agent root that restores the profile, so give the other agents a profile without them if that is not what you want. `lshed init --agent codex` works too, and a shed made from Codex restores into Claude Code with `CLAUDE.md` generated from the same fragments. The shed's `agent:` is only a default for `--agent` (`$LSHED_AGENT` also works).
|
|
293
310
|
|
|
294
311
|
### Links instead of copies
|
|
295
312
|
|
|
296
|
-
On the machine where you do most of your editing, `restore --link` places skills, agents, commands and instruction fragments as links into the shed instead of copies. Edits
|
|
313
|
+
On the machine where you do most of your editing, `restore --link` places skills, agents, commands and instruction fragments as links into the shed instead of copies. Edits land in the shed directly, `diff` has nothing to report, and `save` has nothing to do; `lshed sync` is the whole loop.
|
|
297
314
|
|
|
298
315
|
```
|
|
299
316
|
$ lshed restore --link
|
|
@@ -305,7 +322,7 @@ $ lshed restore --link
|
|
|
305
322
|
Profile "default" applied (link): placed 4, removed 0
|
|
306
323
|
```
|
|
307
324
|
|
|
308
|
-
The choice is per machine and remembered: later `lshed restore` calls on that machine keep linking, `lshed status` shows `placement links`, and `restore --no-link` goes back to copies.
|
|
325
|
+
The choice is per machine and remembered: later `lshed restore` calls on that machine keep linking, `lshed status` shows `placement links`, and `restore --no-link` goes back to copies. MCP entries and settings keys are JSON values, not files, so they are always written. Switching profiles removes the links, never the shed behind them. On Windows, directories become junctions with no special permission; single-file parts need Developer Mode for a link, and without it lshed copies the file, says so, and treats it like any other copy.
|
|
309
326
|
|
|
310
327
|
### Adding things later
|
|
311
328
|
|
|
@@ -326,7 +343,7 @@ $ lshed add paper-review mcp/linear
|
|
|
326
343
|
2 added to the shed and to profile "default". Commit the shed: /home/me/lshed
|
|
327
344
|
```
|
|
328
345
|
|
|
329
|
-
`add` classifies exactly like `init`, appends to `lshed.yaml` without disturbing your comments, adds the parts to the current profile
|
|
346
|
+
`add` classifies exactly like `init`, appends to `lshed.yaml` without disturbing your comments, and adds the parts to the current profile. Without keys it only lists. `status` shows the count on its `outside` row. To put a part that is already in the shed into another profile, edit `profiles:` by hand.
|
|
330
347
|
|
|
331
348
|
### Keeping packages current
|
|
332
349
|
|
|
@@ -337,9 +354,7 @@ lshed update # fast-forward every package in the profile, refresh
|
|
|
337
354
|
lshed update gstack --yes # one package, and run its install: afterwards
|
|
338
355
|
```
|
|
339
356
|
|
|
340
|
-
Git packages are pinned by commit in `lshed.lock`; a new machine gets exactly that commit. Plugins cannot be pinned, so the lock records what got installed and `status` says when it differs
|
|
341
|
-
|
|
342
|
-
`update --dry-run` reads upstream without changing anything: `= (최신)` (up to date) when the clone already sits on the remote tip, `~ 0d1bd56 → 0530392` when a pull would move it, `?` when that cannot be known in advance. Git packages and marketplaces Claude Code cloned with git can be checked; Claude plugins and the official marketplace (not a git clone) cannot, so they show `?` and only a real `update` tells.
|
|
357
|
+
Git packages are pinned by commit in `lshed.lock`; a new machine gets exactly that commit. Plugins cannot be pinned, so the lock records what got installed and `status` says when it differs. `update --dry-run` can check git packages; Claude plugins show `?` and only a real `update` tells. A package that cannot be updated is reported and skipped, the rest are pulled.
|
|
343
358
|
|
|
344
359
|
### Housekeeping
|
|
345
360
|
|
|
@@ -361,13 +376,38 @@ lshed prune --yes # delete everything unused
|
|
|
361
376
|
| `~` | existed with different content, replaced (backed up) |
|
|
362
377
|
| `-` | removed (backed up) or excluded |
|
|
363
378
|
| `≡` | package: recorded by source, not copied |
|
|
364
|
-
| `·` | generated by an installer, skipped |
|
|
379
|
+
| `·` | generated by an installer, or not handled by this agent: skipped |
|
|
365
380
|
| `!` | needs your attention |
|
|
366
381
|
| `↑` `↓` | pushed / pulled (sync), updated (update) |
|
|
367
382
|
|
|
368
383
|
Errors go to stderr with exit code 1. Everything else is on stdout.
|
|
369
384
|
|
|
370
|
-
##
|
|
385
|
+
## Reference
|
|
386
|
+
|
|
387
|
+
### Commands
|
|
388
|
+
|
|
389
|
+
```
|
|
390
|
+
lshed init [--shed <dir>] [--profile <name>] [--exclude <id...>]
|
|
391
|
+
lshed add [keys...] [--all] put things that appeared since init into the shed
|
|
392
|
+
lshed restore [profile] [--pick] [--link | --no-link] [--dry-run] [--no-backup] [--yes] [--fresh-only]
|
|
393
|
+
lshed status applied profile, drift, packages, missing env, new things
|
|
394
|
+
lshed diff files (or JSON keys) that differ between local and shed
|
|
395
|
+
lshed save [ids...] copy local edits back into the shed
|
|
396
|
+
lshed sync [-m <msg>] [--no-push] [--dry-run] commit the shed, pull --rebase, push
|
|
397
|
+
lshed update [ids...] [--dry-run] [--yes] pull packages forward, refresh lshed.lock; --dry-run asks upstream only
|
|
398
|
+
lshed list [--unused] what is in the shed, and which profiles use it
|
|
399
|
+
lshed remove <key> drop a component or package from the shed
|
|
400
|
+
lshed prune [--yes] drop everything no profile uses
|
|
401
|
+
lshed scan list what the agent root holds, without writing anything
|
|
402
|
+
lshed check [--attempts <n>] [--timeout <s>] ask the agent's CLI whether it reads a skill lshed just placed (one or two small model calls)
|
|
403
|
+
lshed report [--open | --url] summary of this setup to paste into an issue; --open prefills one on GitHub, --url prints that link
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Keys are `category/id`, or just `id` when unambiguous: `skills/paper-review`, `mcp/exa`, `packages/gstack`. An id is the file or directory name the agent reads, in any script (`skills/논문리뷰` is fine); letters, digits, `.`, `_` and `-` are allowed, and `/` between segments for nested agents and commands.
|
|
407
|
+
|
|
408
|
+
Global options: `--shed <dir>` (or `LSHED_HOME`; after the first restore lshed remembers it), `--agent <name>` (or `LSHED_AGENT`; default is the shed's `agent:`, then `claude-code`; `installed` with `restore` means every agent whose CLI is on PATH), `--root <dir>` (agent config root, default is the agent's own).
|
|
409
|
+
|
|
410
|
+
### The manifest
|
|
371
411
|
|
|
372
412
|
`lshed.yaml` lives at the root of the shed. `init` generates it; edit it by hand from then on. `add` and `remove` edit it for you and keep your comments.
|
|
373
413
|
|
|
@@ -415,31 +455,31 @@ profiles:
|
|
|
415
455
|
```
|
|
416
456
|
|
|
417
457
|
- Component `source` accepts `file:<path relative to the shed>`. Package `source` accepts `github:owner/repo@ref`, `git:<url>#ref`, `claude-marketplace:<owner/repo>`, `claude-plugin:<name>@<marketplace>`.
|
|
418
|
-
-
|
|
458
|
+
- Categories for Claude Code: `skills`, `agents`, `commands`, `instructions`, `mcp`, `settings`. Other agents have `skills`, and `instructions` / `mcp` where the [table above](#other-agents-same-shed) says so.
|
|
419
459
|
- `ignore:` adds to the built-in list of things never copied: `node_modules`, `.git`, `__pycache__`, `.venv`, cache directories, `*.log`. Build output like `dist/` is not ignored by default, since some skills ship it.
|
|
420
460
|
- `exclude:` lists parts that exist locally but must not enter the shed. `init --exclude` writes it.
|
|
421
461
|
|
|
422
|
-
|
|
462
|
+
### Three kinds of things
|
|
423
463
|
|
|
424
464
|
A real `~/.claude` mixes three kinds of content, and they need different handling:
|
|
425
465
|
|
|
426
466
|
| Kind | Example | What lshed does |
|
|
427
467
|
|---|---|---|
|
|
428
|
-
| **Authored** | a skill you wrote, your `CLAUDE.md`, an MCP server you added | copies it into the shed |
|
|
429
|
-
| **Installed** | a toolkit you `git clone`d, a plugin | records source + commit; `restore` clones or installs it back |
|
|
468
|
+
| **Authored** | a skill you wrote, your `CLAUDE.md`, an MCP server you added | copies it into the shed; `save` copies edits back |
|
|
469
|
+
| **Installed** | a toolkit you `git clone`d, a plugin | records source + commit; `restore` clones or installs it back; `update` pulls it |
|
|
430
470
|
| **Generated** | stub skills an installer wrote for you | skips them; they return when the installer runs |
|
|
431
471
|
|
|
432
472
|
A directory with a `.git` and a remote becomes a **package**. A skill whose symlink points inside a package is treated as generated and skipped. Everything else is authored and copied. The rules that keep this safe:
|
|
433
473
|
|
|
434
|
-
- A package that is already present is never touched by `restore`. Your local checkout is yours. The one exception is `--yes`, which runs the package's `install:` again
|
|
435
|
-
- `install:` is a shell command. `restore` and `update` **print it and stop** unless you pass `--yes`. Plugin installs go through Claude Code's own package manager and run without it
|
|
474
|
+
- A package that is already present is never touched by `restore`. Your local checkout is yours. The one exception is `--yes`, which runs the package's `install:` again.
|
|
475
|
+
- `install:` is a shell command. `restore` and `update` **print it and stop** unless you pass `--yes`. Plugin installs go through Claude Code's own package manager and run without it.
|
|
436
476
|
- Packages are not part of the managed set. Switching profiles never deletes a clone.
|
|
437
477
|
|
|
438
478
|
Claude Code plugins are packages with their own scheme. `init` finds user-scope ones in `~/.claude/plugins`; `restore` adds the marketplace first, then runs `claude plugin install`. Project-scope plugins belong to their project and are not recorded.
|
|
439
479
|
|
|
440
|
-
|
|
480
|
+
### MCP servers and secrets
|
|
441
481
|
|
|
442
|
-
User-scope MCP servers live in `~/.claude.json`, next to machine IDs and session state. lshed treats each server as a component of category `mcp`: the shed holds `mcp/<name>.json`, and `restore` edits only the `mcpServers.<name>` key
|
|
482
|
+
User-scope MCP servers live in `~/.claude.json`, next to machine IDs and session state. lshed treats each server as a component of category `mcp`: the shed holds `mcp/<name>.json`, and `restore` edits only the `mcpServers.<name>` key, leaving everything else in that file alone.
|
|
443
483
|
|
|
444
484
|
**No secret value enters the shed.** `init` and `add` replace values under `env` and `headers` whose key contains a secret-looking word (`key`, `token`, `secret`, `password`, `auth`, `authorization`, `credential`, `cookie`, `session` — whole words, so `MAX_OUTPUT_TOKENS` is left alone) with a `${VAR}` placeholder:
|
|
445
485
|
|
|
@@ -450,57 +490,26 @@ User-scope MCP servers live in `~/.claude.json`, next to machine IDs and session
|
|
|
450
490
|
"headers": { "Authorization": "Bearer ${NOTION_AUTHORIZATION}" } }
|
|
451
491
|
```
|
|
452
492
|
|
|
453
|
-
`restore` writes the placeholder as is
|
|
493
|
+
`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). The one exception is `${HOME}`, which lshed fills itself because Windows has no `HOME`. `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. `save` keeps existing placeholders and masks new secret-looking keys, so a rotated key never leaks into the shed by accident, and `diff` treats placeholders as wildcards, so a machine holding real values is not drift.
|
|
454
494
|
|
|
455
|
-
|
|
495
|
+
### Settings
|
|
456
496
|
|
|
457
497
|
`~/.claude/settings.json` holds hooks, permissions, `env`, the model, the theme, and some state Claude Code writes for itself. lshed does not merge it. Each **top-level key is one component** of category `settings`: the shed holds `settings/permissions.json`, `settings/hooks.json`, and so on, and `restore` writes exactly those keys, leaving the rest of the file alone. A profile can carry `permissions` and `hooks` and leave `model` to each machine.
|
|
458
498
|
|
|
459
|
-
```
|
|
460
|
-
$ lshed add
|
|
461
|
-
3 outside the shed:
|
|
462
|
-
settings/hooks ! points into package gstack. If that install created it, exclude it: settings/hooks
|
|
463
|
-
settings/model
|
|
464
|
-
settings/theme
|
|
465
|
-
```
|
|
466
|
-
|
|
467
499
|
- `enabledPlugins` and `extraKnownMarketplaces` are never taken: the plugin and marketplace packages own them, and `restore` rebuilds them by installing those.
|
|
468
|
-
- Absolute paths under your home directory become `${HOME}/…` in the shed, so a hook command written on one machine works on another
|
|
469
|
-
- `env` is treated as a secret map: keys that look secret are masked, the rest
|
|
500
|
+
- Absolute paths under your home directory become `${HOME}/…` in the shed, always with `/`, so a hook command written on one machine works on another; on Windows `restore` writes it back as `C:/Users/me/…`, 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.
|
|
501
|
+
- `env` is treated as a secret map: keys that look secret are masked, the rest travel as they are.
|
|
470
502
|
- 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.
|
|
471
503
|
- 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.
|
|
472
504
|
|
|
473
|
-
## Commands
|
|
474
|
-
|
|
475
|
-
```
|
|
476
|
-
lshed init [--shed <dir>] [--profile <name>] [--exclude <id...>]
|
|
477
|
-
lshed add [keys...] [--all] put things that appeared since init into the shed
|
|
478
|
-
lshed restore [profile] [--pick] [--link | --no-link] [--dry-run] [--no-backup] [--yes] (--agent <name> to target another tool)
|
|
479
|
-
lshed status applied profile, drift, packages, missing env, new things
|
|
480
|
-
lshed diff files (or JSON keys) that differ between local and shed
|
|
481
|
-
lshed save [ids...] copy local edits back into the shed
|
|
482
|
-
lshed sync [-m <msg>] [--no-push] [--dry-run] commit the shed, pull --rebase, push
|
|
483
|
-
lshed update [ids...] [--dry-run] [--yes] pull packages forward, refresh lshed.lock; --dry-run asks upstream only
|
|
484
|
-
lshed list [--unused] what is in the shed, and which profiles use it
|
|
485
|
-
lshed remove <key> drop a component or package from the shed
|
|
486
|
-
lshed prune [--yes] drop everything no profile uses
|
|
487
|
-
lshed scan list what the agent root holds, without writing anything
|
|
488
|
-
lshed check [--attempts <n>] [--timeout <s>] ask the agent's CLI whether it reads a skill lshed just placed (one or two small model calls)
|
|
489
|
-
lshed report [--open | --url] summary of this setup to paste into an issue; --open prefills one on GitHub, --url prints that link
|
|
490
|
-
```
|
|
491
|
-
|
|
492
|
-
Keys are `category/id`, or just `id` when unambiguous: `skills/paper-review`, `mcp/exa`, `packages/gstack`. An id is the file or directory name the agent reads, in any script (`skills/논문리뷰` is fine); letters, digits, `.`, `_` and `-` are allowed, and `/` between segments for nested agents and commands.
|
|
493
|
-
|
|
494
|
-
Global options: `--shed <dir>` (or `LSHED_HOME`; after the first restore lshed remembers it), `--agent <name>` (or `LSHED_AGENT`; default is the shed's `agent:`, then `claude-code`), `--root <dir>` (agent config root, default is the agent's own, e.g. `~/.claude` or `~/.codex`).
|
|
495
|
-
|
|
496
505
|
### What `restore` does
|
|
497
506
|
|
|
498
507
|
0. Installs any package in the profile that is missing, at the version in `lshed.lock`.
|
|
499
508
|
1. Removes paths that the **previous** profile placed and the new one doesn't need.
|
|
500
|
-
2. Copies every part of the new profile into place (or links it
|
|
509
|
+
2. Copies every part of the new profile into place (or links it, with `--link` or on a machine that used it before); writes MCP entries and settings keys.
|
|
501
510
|
3. Regenerates the instructions file.
|
|
502
511
|
|
|
503
|
-
Anything it overwrites or removes is backed up first under
|
|
512
|
+
Anything it overwrites or removes is backed up first under `<root>/lshed/backups/<timestamp>/`, unless you pass `--no-backup`. Files lshed never placed are left alone. `--dry-run` prints the plan and writes nothing. With `--pick`, a checklist per non-empty category comes first and the result is saved to `lshed.yaml` as a profile before steps 0–3 run.
|
|
504
513
|
|
|
505
514
|
### What `sync` does
|
|
506
515
|
|
|
@@ -511,15 +520,7 @@ Anything it overwrites or removes is backed up first under `~/.claude/lshed/back
|
|
|
511
520
|
|
|
512
521
|
On a conflict it aborts the rebase, leaves the shed clean with your commit intact, and tells you to resolve with git. Without a remote it only commits. It never runs `save` for you.
|
|
513
522
|
|
|
514
|
-
###
|
|
515
|
-
|
|
516
|
-
The shed is the source of truth for authored parts: `save` copies local edits back for `file:` components, and a linked part is the shed. Packages are owned by their upstream: `update` pulls them, `save` ignores them.
|
|
517
|
-
|
|
518
|
-
### Trust
|
|
519
|
-
|
|
520
|
-
A shed is executable, not just data. `restore` places files into your agent's config, fills `${VAR}` from your shell into the configs it writes, and with `--yes` runs each package's `install:` shell command. So restore only a shed you trust as much as your own dotfiles, and keep yours private (a private git repo). Restoring someone else's shed is close to handing them your machine: its manifest can carry an `install:` command, and a config it writes can point an MCP server at a URL that then receives one of your secrets. lshed confines what it places to the agent's own root and rejects a package source that could smuggle a git option, but it cannot vouch for what a shed's `install:` runs or where a config sends a secret. Treat a shed you did not write like any other code you are about to run.
|
|
521
|
-
|
|
522
|
-
## Where things live
|
|
523
|
+
### Where things live
|
|
523
524
|
|
|
524
525
|
```
|
|
525
526
|
<shed>/
|
|
@@ -538,43 +539,50 @@ A shed is executable, not just data. `restore` places files into your agent's co
|
|
|
538
539
|
~/.claude.json mcpServers.<id> ← one key per mcp component; the rest of the file is untouched
|
|
539
540
|
|
|
540
541
|
~/.codex/ ~/.gemini/ ~/.copilot/ ~/.cursor/ ~/.gemini/config/ ~/.agents/
|
|
541
|
-
skills/ <instructions file> <mcp file> ← the same, per --agent (
|
|
542
|
+
skills/ <instructions file> <mcp file> ← the same, per --agent (codex skills live in ~/.agents/skills)
|
|
542
543
|
lshed/state.json lshed/backups/ ← each root keeps its own
|
|
543
544
|
```
|
|
544
545
|
|
|
545
546
|
`state.json` is per machine and is not part of the shed. If `CLAUDE_CONFIG_DIR` is set, lshed uses it as the root and writes `.claude.json` inside it, as Claude Code does.
|
|
546
547
|
|
|
547
|
-
##
|
|
548
|
-
|
|
549
|
-
- 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.
|
|
550
|
-
- 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).
|
|
551
|
-
- A fifth pass on the same PC (Windows PowerShell 5.1, Node 24, git 2.55, lshed 0.17.1 from npm) started from nothing: a private shed cloned over HTTPS, `restore default` fetched every package at the revision in the lock (a gstack update made on the Linux machine arrived at the same commit), `status` reported all nine packages in sync, `lshed check` got the passphrase back from Claude Code on the first attempt, and `report` showed the home directory as `~`. The pass found that `restore --yes` stopped at the first failing `install:` (gstack's `./setup` cannot start under cmd.exe) before placing anything; 0.17.2 fixed that and the same PC confirmed the fix: the failure is printed, the nine parts are placed, and the failed command is listed at the end.
|
|
552
|
-
- A sixth pass on the same PC (Windows PowerShell, Node 24, lshed 0.17.3 built from source) checked what the 0.17.2 review had turned up: nine arguments holding `&`, `|`, `(`, `^`, a quote and a trailing backslash came back from a real child process through `cmd.exe` unchanged, `lshed report` printed no `DEP0190` warning even under `--throw-deprecation`, `check` got the passphrase back on the first attempt and left no skill behind, a package whose clone cannot succeed no longer stops the restore, and `check` against a CLI that leaves a child holding the pipes returned in 2.2 seconds instead of hanging. It found that the cleanup after such a run hit `EBUSY` from inside a `finally` and replaced the whole result with that error; the fix in this release retries, keeps the result, and names whatever is left over.
|
|
553
|
-
- 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.
|
|
554
|
-
- 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.4 and Antigravity CLI 1.1.27 pass every check (last run 2026-09-09 with lshed 0.15.5); 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.
|
|
555
|
-
- 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.
|
|
556
|
-
- Everything above is one person's machines. If lshed works for you on a tool version or an OS not listed here, a [verification report](https://github.com/LeeSongHeon-LSH/lshed/issues/new?template=verified.yml) takes two minutes and becomes a line in this section. If it does not work, `lshed report` prints what a [bug report](https://github.com/LeeSongHeon-LSH/lshed/issues/new?template=bug.yml) needs: versions, the agent and its root, the applied profile and the names of what the shed holds. No values, no secrets, and your home directory shows as `~`. After a failed command lshed asks whether to open that form with the summary filled in; it never sends anything by itself, and `LSHED_REPORT=0` turns the question off. For the failure that makes no noise, an agent that simply does not read what was placed, `lshed check` asks the agent itself.
|
|
557
|
-
|
|
558
|
-
## Not in scope (yet)
|
|
548
|
+
## Trust
|
|
559
549
|
|
|
560
|
-
|
|
561
|
-
- Project-scope MCP servers (`.mcp.json`, `~/.claude.json` `projects.*`) and project-scope plugins. They belong to the project.
|
|
562
|
-
- For the other agents, only skills, the instructions file and MCP servers travel. Their own settings files, rules folders and plugins stay where they are.
|
|
550
|
+
A shed is executable, not just data. `restore` places files into your agent's config, fills `${VAR}` from your shell into the configs it writes, and with `--yes` runs each package's `install:` shell command. So restore only a shed you trust as much as your own dotfiles, and keep yours private. Restoring someone else's shed is close to handing them your machine: its manifest can carry an `install:` command, and a config it writes can point an MCP server at a URL that then receives one of your secrets. lshed confines what it places to the agent's own root and rejects a package source that could smuggle a git option, but it cannot vouch for what a shed's `install:` runs or where a config sends a secret. Treat a shed you did not write like any other code you are about to run.
|
|
563
551
|
|
|
564
552
|
## Troubleshooting
|
|
565
553
|
|
|
566
554
|
- **restore said everything is in place, but the agent does not see it** — `lshed check`. It puts a throwaway skill holding a random passphrase into the agent's skills folder, asks the agent's CLI for the passphrase the way a user would (`claude -p`, `codex exec`, `gemini -p`, `copilot -p`, `agent -p`, `agy -p`), and removes the skill. A ✔ means the location and format are right and the problem is elsewhere; a ✘ shows the agent's actual answer and is exactly what a bug report needs. It costs one or two small model calls and needs that CLI on this machine.
|
|
567
|
-
- **Something else went wrong** — `lshed report` prints the summary a bug report needs (nothing secret; check it yourself), `lshed report --open` puts it into a new issue form (`--url` prints the link instead
|
|
555
|
+
- **Something else went wrong** — `lshed report` prints the summary a bug report needs (nothing secret; check it yourself), `lshed report --open` puts it into a new issue form (`--url` prints the link instead). The same question is asked right after a failed command; answer no, or set `LSHED_REPORT=0`, and nothing happens.
|
|
568
556
|
- **"Shed location unknown. Pass --shed <dir> or set LSHED_HOME."** — do one of those. After one successful `restore`, lshed remembers it.
|
|
569
557
|
- **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.
|
|
570
558
|
- **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`.
|
|
571
559
|
- **`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.
|
|
572
560
|
- **`status` keeps listing the same new things** — they are installer aliases or scratch. Add them to `exclude:` in `lshed.yaml`.
|
|
573
|
-
-
|
|
574
|
-
- **restore
|
|
561
|
+
- **`status` shows `! <package> install: failed at the last restore`** — the parts are placed; only that package's `install:` did not finish. Fix whatever it needs and `lshed restore <profile> --yes`, or run the command it printed yourself.
|
|
562
|
+
- **restore says an MCP variable is missing** — export it in your shell profile and restart the agent. The placeholder in the config is correct; the agent (or lshed, for tools that do not expand) fills it.
|
|
563
|
+
- **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 are copied as written and are your job to keep portable.
|
|
575
564
|
- **`restore --yes` says an install command failed on Windows** — `install:` runs in cmd.exe there, so a `./setup` written for sh cannot start (`'.' is not recognized`). Everything else is placed; run the command from Git Bash (`cd ~/.claude/skills/<package> && ./setup`) and check the package's own requirements (gstack needs bun).
|
|
576
565
|
- **`--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.
|
|
577
566
|
- **sync stopped on a conflict** — `cd <shed> && git pull --rebase`, resolve, `git rebase --continue`, then `lshed sync` again.
|
|
567
|
+
- **A bootstrap script runs `restore` on every start** — add `--fresh-only`; see [a new machine](#a-new-machine).
|
|
568
|
+
|
|
569
|
+
## What has been verified
|
|
570
|
+
|
|
571
|
+
| Where | What |
|
|
572
|
+
|---|---|
|
|
573
|
+
| Ubuntu, macOS, Windows (CI, every push) | unit tests, a CLI smoke run of the whole walk (Korean skill name included), the standalone binaries |
|
|
574
|
+
| Windows 11 PC, no Developer Mode | six passes by hand with npm and source builds: `init`, `restore` next to an existing setup, `--link` (junctions), profile switch, `codex`/`agents` targets, `check`, `report`, `sync` |
|
|
575
|
+
| Linux (daily use) | one real shed read by Claude Code, Codex and Antigravity through `--link`; every command beyond CI, including `sync` conflicts and `--pick` |
|
|
576
|
+
| The agents themselves | a probe restores a throwaway shed and asks each tool for a passphrase kept in a skill, a codeword in the instructions file, and the skill again through a `--link`. Claude Code, Codex, Gemini CLI, Cursor and Antigravity answer; Copilot CLI is verified for placement and format so far. A weekly workflow repeats the placement part against the current CLIs |
|
|
577
|
+
| A brand-new machine | a devcontainer started from empty state restores into three agents on its entrypoint and passes `status`, `check` and `mcp list` for each, and skips the restore on restart |
|
|
578
|
+
|
|
579
|
+
Dates, versions and what each pass found are in [docs/VERIFICATION.md](https://github.com/LeeSongHeon-LSH/lshed/blob/main/docs/VERIFICATION.md). Everything there is one person's machines: if lshed works for you on a tool version or an OS not listed, a [verification report](https://github.com/LeeSongHeon-LSH/lshed/issues/new?template=verified.yml) takes two minutes; if it does not, `lshed report` prints what a [bug report](https://github.com/LeeSongHeon-LSH/lshed/issues/new?template=bug.yml) needs, with no values, no secrets, and your home shown as `~`.
|
|
580
|
+
|
|
581
|
+
## Not in scope (yet)
|
|
582
|
+
|
|
583
|
+
- Secrets beyond "name the variable". Encrypted values, `op://` references and OS keychains are possible later; today lshed is deliberately no better than dotfiles here.
|
|
584
|
+
- Project-scope MCP servers (`.mcp.json`, `~/.claude.json` `projects.*`) and project-scope plugins. They belong to the project.
|
|
585
|
+
- For the other agents, only skills, the instructions file and MCP servers travel. Their own settings files, rules folders and plugins stay where they are.
|
|
578
586
|
|
|
579
587
|
## License
|
|
580
588
|
|