spec-layer 0.1.0 → 0.2.1

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.
Files changed (3) hide show
  1. package/README.md +102 -11
  2. package/dist/cli.js +1072 -77
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -24,46 +24,137 @@ library id, record it once:
24
24
  npx spec-layer init --id lib_...
25
25
  ```
26
26
 
27
+ ## Installing, or not
28
+
29
+ `npx` needs no install step: it fetches the package and runs it. That is the
30
+ right choice for trying this once, and for a repo that pulls by hand.
31
+
32
+ Two cases want a real install instead. On a cold cache `npx` has to fetch the
33
+ package first, and confirming that is a prompt you do not want in an
34
+ unattended run. `--yes` answers it up front:
35
+
36
+ ```bash
37
+ npx --yes spec-layer status
38
+ ```
39
+
40
+ And a repo that pulls on a schedule should pin the version rather than
41
+ resolving the latest release on every run, so a CLI update never changes a
42
+ build you did not touch:
43
+
44
+ ```bash
45
+ npm install --save-dev spec-layer
46
+ ```
47
+
48
+ `npx spec-layer` then runs the pinned local copy, no `--yes` needed. Pinning
49
+ also keeps `.speclayer/manifest.json` on one format: 0.1.0 wrote no
50
+ `selection` field, and 0.2.0 does.
51
+
27
52
  ## Commands
28
53
 
29
54
  | Command | What it does |
30
55
  |---|---|
31
- | `init --id lib_... [--out DIR]` | Writes `speclayer.json` so later commands need no flags. |
32
- | `pull [--id lib_...] [--key sl_...]` | Fetches the library and writes it into `DIR` (default `.speclayer`). |
56
+ | `init --id lib_... [--out DIR] [selection]` | Writes `speclayer.json` so later commands need no flags. |
57
+ | `pull [--id lib_...] [--key sl_...] [selection]` | Fetches the library and writes it into `DIR` (default `.speclayer`). |
33
58
  | `status [--id lib_...] [--key sl_...]` | Checks freshness without writing. Exits `2` when the local copy is behind. |
59
+ | `list` | Lists every artifact in the last pull, with its file path or `not written`. |
60
+ | `show foundation [--canonical]` | Prints the Foundation's AI YAML to stdout. |
61
+ | `show component NAME [--canonical]` | Prints one component's AI YAML to stdout. |
34
62
 
35
63
  `--api URL` overrides the API origin (default `https://api.spec-layer.com`).
36
64
 
65
+ ## Pulling part of a library
66
+
67
+ By default `pull` writes the Foundation and every documented component. When
68
+ your repo implements only some of them, narrow what lands in `ai/`:
69
+
70
+ ```bash
71
+ npx spec-layer pull --only foundation # tokens and styles, no components
72
+ npx spec-layer pull --only components # components, no foundation
73
+ npx spec-layer pull --component Button --component "Text field"
74
+ ```
75
+
76
+ Names match by slug, so `button`, `Button`, and `icon-button` all find the
77
+ component they name. A name that matches nothing is an error listing what the
78
+ library holds, and nothing is written.
79
+
80
+ Record a selection once with `init` and plain `pull` reuses it:
81
+
82
+ ```bash
83
+ npx spec-layer init --id lib_... --component Button --component Card
84
+ ```
85
+
86
+ That stores an `include` block in `speclayer.json`:
87
+
88
+ ```json
89
+ {
90
+ "libraryId": "lib_...",
91
+ "outDir": ".speclayer",
92
+ "include": { "foundation": true, "components": ["Button", "Card"] }
93
+ }
94
+ ```
95
+
96
+ Selection flags on `pull` replace the stored selection for that run; they are
97
+ never merged with it.
98
+
99
+ The selection only decides which `ai/` files are written. `bundle.json`
100
+ always holds the whole library, so `list` and `show` can answer for any
101
+ artifact, written or not, and `status` compares one hash.
102
+
103
+ ## Reading one artifact
104
+
105
+ `show` prints exactly one artifact and nothing else, so it pipes cleanly:
106
+
107
+ ```bash
108
+ npx spec-layer show component Button # the compact AI YAML
109
+ npx spec-layer show foundation --canonical # the canonical v5 JSON artifact
110
+ ```
111
+
112
+ Both read the last pull from disk and need no key. When two components share a
113
+ name, `show` refuses to guess and points you at `list`.
114
+
37
115
  ## The pull key
38
116
 
39
- Every command reads the pull key from `SPEC_LAYER_KEY` or `--key`. It is never
40
- written to disk, and `speclayer.json` never contains it. Treat it as a secret:
41
- it grants read access to the published bundle. If it leaks, rotate it from the
42
- plugin's Library screen, which invalidates the old key immediately.
117
+ Every command that talks to the server reads the pull key from `SPEC_LAYER_KEY`
118
+ or `--key`. It is never written to disk, and `speclayer.json` never contains
119
+ it. Treat it as a secret: it grants read access to the published bundle. If it
120
+ leaks, rotate it from the plugin's Library screen. The old key stops working
121
+ once the change propagates, which can take up to about a minute.
43
122
 
44
123
  ## What `pull` writes
45
124
 
46
125
  ```text
47
126
  .speclayer/
48
127
  bundle.json the published bundle, verbatim
49
- manifest.json every artifact indexed by content hash and ai path
50
- ai/foundation.yaml tokens, styles, and modes (when the library has a Foundation)
51
- ai/components/<name>.yaml one file per documented component
128
+ manifest.json every artifact indexed by content hash and ai path, plus the selection
129
+ ai/foundation.yaml tokens, styles, and modes (when selected and the library has a Foundation)
130
+ ai/components/<name>.yaml one file per selected component
52
131
  ```
53
132
 
54
133
  Point your agent at `.speclayer/ai/`. The YAML there is the same compact form
55
134
  the plugin's **Copy for AI** puts on your clipboard; `bundle.json` additionally
56
135
  holds the full canonical artifacts if you need them.
57
136
 
137
+ In `manifest.json`, an artifact the selection left unwritten has `"aiPath":
138
+ null`. A manifest from CLI 0.1.0 has no `selection` field and means
139
+ everything was written.
140
+
58
141
  Writes stage into `.speclayer.partial` and rename into place, so an
59
- interrupted pull never leaves a half-written directory.
142
+ interrupted pull never leaves a half-written directory. `pull` refuses an
143
+ output directory that is the current directory, a parent of it, or an existing
144
+ non-empty directory it did not write, since the swap replaces that directory.
145
+
146
+ When nothing changed since the last pull with the same selection, `pull`
147
+ prints `Already up to date` and writes nothing. Every republish stamps a new
148
+ export id and time into the canonical artifacts, so `bundle.json` and
149
+ `manifest.json` change on each republish even when the content did not. The
150
+ `ai/` YAML files and the content hashes stay stable.
60
151
 
61
152
  ## Exit codes
62
153
 
63
154
  | Code | Meaning |
64
155
  |---|---|
65
156
  | `0` | Success, or `status` found the local copy up to date. |
66
- | `1` | Usage error, bad key or id, or a network or server failure. |
157
+ | `1` | Usage error, bad key or id, unknown component name, or a network or server failure. |
67
158
  | `2` | `status` only: the local copy is behind, or no local pull exists yet. |
68
159
 
69
160
  `status` is safe in CI: it writes nothing, and exit `2` is the signal to run