spec-layer 0.2.1 → 0.4.0
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/README.md +99 -21
- package/dist/cli.js +1575 -57
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,19 +11,23 @@ and writes it to disk.
|
|
|
11
11
|
## Quick start
|
|
12
12
|
|
|
13
13
|
After publishing a library from the plugin's Library screen, it shows a setup
|
|
14
|
-
command. Run it in your repository:
|
|
14
|
+
command. Run it once in your repository:
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
|
|
17
|
+
npx spec-layer setup --id lib_... --key sl_...
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
That
|
|
21
|
-
|
|
20
|
+
That records the library id, stores the key in a gitignored
|
|
21
|
+
`speclayer.local.json`, and writes `.speclayer/`. Every later command needs no
|
|
22
|
+
flags at all:
|
|
22
23
|
|
|
23
24
|
```bash
|
|
24
|
-
npx spec-layer
|
|
25
|
+
npx spec-layer pull
|
|
25
26
|
```
|
|
26
27
|
|
|
28
|
+
`init` still writes the config without a key or a network call, for a repo
|
|
29
|
+
that supplies the key from the environment instead.
|
|
30
|
+
|
|
27
31
|
## Installing, or not
|
|
28
32
|
|
|
29
33
|
`npx` needs no install step: it fetches the package and runs it. That is the
|
|
@@ -47,17 +51,21 @@ npm install --save-dev spec-layer
|
|
|
47
51
|
|
|
48
52
|
`npx spec-layer` then runs the pinned local copy, no `--yes` needed. Pinning
|
|
49
53
|
also keeps `.speclayer/manifest.json` on one format: 0.1.0 wrote no
|
|
50
|
-
`selection` field, and 0.2.0 does.
|
|
54
|
+
`selection` field, and 0.2.0 onward does. `setup` needs 0.3.0 or later; earlier
|
|
55
|
+
versions have no such command, so the setup command the plugin copies fails
|
|
56
|
+
against them. The Foundation landing under `tokens/` as Design Tokens Format
|
|
57
|
+
Module 2025.10 files, rather than `ai/foundation.yaml`, needs 0.4.0 or later.
|
|
51
58
|
|
|
52
59
|
## Commands
|
|
53
60
|
|
|
54
61
|
| Command | What it does |
|
|
55
62
|
|---|---|
|
|
56
|
-
| `
|
|
63
|
+
| `setup --id lib_... --key sl_... [--out DIR] [selection]` | Writes `speclayer.json`, stores the key in `speclayer.local.json`, then pulls. The command the plugin copies. |
|
|
64
|
+
| `init --id lib_... [--out DIR] [selection]` | Writes `speclayer.json` so later commands need no flags. No key, no network. |
|
|
57
65
|
| `pull [--id lib_...] [--key sl_...] [selection]` | Fetches the library and writes it into `DIR` (default `.speclayer`). |
|
|
58
66
|
| `status [--id lib_...] [--key sl_...]` | Checks freshness without writing. Exits `2` when the local copy is behind. |
|
|
59
67
|
| `list` | Lists every artifact in the last pull, with its file path or `not written`. |
|
|
60
|
-
| `show foundation [--canonical]` | Prints the Foundation's
|
|
68
|
+
| `show foundation [--canonical]` | Prints the Foundation's DTCG document to stdout. |
|
|
61
69
|
| `show component NAME [--canonical]` | Prints one component's AI YAML to stdout. |
|
|
62
70
|
|
|
63
71
|
`--api URL` overrides the API origin (default `https://api.spec-layer.com`).
|
|
@@ -114,25 +122,70 @@ name, `show` refuses to guess and points you at `list`.
|
|
|
114
122
|
|
|
115
123
|
## The pull key
|
|
116
124
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
125
|
+
`spec-layer setup` stores the key in `speclayer.local.json` next to
|
|
126
|
+
`speclayer.json` and makes sure git ignores it before writing it. Every later
|
|
127
|
+
command in that directory needs no key. On POSIX systems the file is written
|
|
128
|
+
at mode `0600`; on Windows there is no equivalent permission bit, so it
|
|
129
|
+
inherits whatever the directory allows.
|
|
130
|
+
|
|
131
|
+
Commands that talk to the server resolve the key in this order:
|
|
132
|
+
|
|
133
|
+
1. `--key sl_...`
|
|
134
|
+
2. `SPEC_LAYER_KEY` in the environment
|
|
135
|
+
3. `speclayer.local.json`, when it was issued for the same library
|
|
136
|
+
|
|
137
|
+
Environment sits above the file so CI can supply a key without touching the
|
|
138
|
+
working tree. A stored key issued for a different library is ignored, and the
|
|
139
|
+
CLI says which library it belongs to rather than letting the server answer 401.
|
|
140
|
+
|
|
141
|
+
Treat the key as a secret: it grants read access to the published bundle.
|
|
142
|
+
`speclayer.local.json` is gitignored, never printed by any command, and never
|
|
143
|
+
copied into `speclayer.json`, `bundle.json`, `manifest.json`, or anything under
|
|
144
|
+
the output directory. If it leaks, rotate it from the plugin's Library screen,
|
|
145
|
+
then run the new setup command. The old key stops working once the change
|
|
146
|
+
propagates, which can take up to about a minute.
|
|
147
|
+
|
|
148
|
+
Re-running `setup` replaces the stored key and keeps the rest of your setup:
|
|
149
|
+
with no `--out` and no selection flag it preserves the output directory and the
|
|
150
|
+
`include` block already in `speclayer.json` rather than resetting them to the
|
|
151
|
+
defaults. Pass `--out` or a selection flag to change them. (`init` still
|
|
152
|
+
overwrites `speclayer.json` outright, which is what a first run is for.)
|
|
153
|
+
|
|
154
|
+
Outside a git working tree, the key is still stored and the CLI says it left
|
|
155
|
+
`.gitignore` alone. Inside one, `setup` refuses to write the key whenever it
|
|
156
|
+
cannot confirm the file will be ignored, and says what to do instead. Three
|
|
157
|
+
cases refuse:
|
|
158
|
+
|
|
159
|
+
- `.gitignore` cannot be written.
|
|
160
|
+
- git itself could not be run, anywhere inside a working tree.
|
|
161
|
+
- the entry is in `.gitignore`, but git still does not ignore the file. That
|
|
162
|
+
almost always means `speclayer.local.json` is already tracked, and the CLI
|
|
163
|
+
names `git rm --cached speclayer.local.json` as the way out.
|
|
164
|
+
|
|
165
|
+
git decides in every case. The entry sitting in `.gitignore` is not taken as
|
|
166
|
+
proof, because `git check-ignore` does not report a tracked file as ignored no
|
|
167
|
+
matter what the ignore rules say.
|
|
122
168
|
|
|
123
169
|
## What `pull` writes
|
|
124
170
|
|
|
125
171
|
```text
|
|
126
172
|
.speclayer/
|
|
127
|
-
bundle.json
|
|
128
|
-
manifest.json
|
|
129
|
-
|
|
130
|
-
|
|
173
|
+
bundle.json the published bundle, verbatim
|
|
174
|
+
manifest.json every artifact indexed by content hash and path, plus the selection
|
|
175
|
+
tokens/ the Foundation as Design Tokens Format Module 2025.10 files
|
|
176
|
+
<collection>.<mode>.json one file per collection and mode, rooted at the collection name
|
|
177
|
+
styles.typography.json text styles as typography composites (when present)
|
|
178
|
+
styles.effects.json effect styles as shadow composites (when present)
|
|
179
|
+
resolver.json Design Tokens Resolver Module 2025.10: sets, modifiers, order
|
|
180
|
+
spec-layer.meta.json Figma ids, scopes, code syntax, publication, keyed by DTCG path
|
|
181
|
+
report.json what DTCG could not express, with reasons and stable ids
|
|
182
|
+
ai/components/<name>.yaml one file per selected component
|
|
131
183
|
```
|
|
132
184
|
|
|
133
|
-
Point your agent at `.speclayer/ai/`. The
|
|
134
|
-
the plugin's **Copy for AI** puts on your
|
|
135
|
-
holds the full canonical artifacts if
|
|
185
|
+
Point your agent at `.speclayer/ai/` and `.speclayer/tokens/`. The component
|
|
186
|
+
YAML is the same compact form the plugin's **Copy for AI** puts on your
|
|
187
|
+
clipboard; `bundle.json` additionally holds the full canonical artifacts if
|
|
188
|
+
you need them.
|
|
136
189
|
|
|
137
190
|
In `manifest.json`, an artifact the selection left unwritten has `"aiPath":
|
|
138
191
|
null`. A manifest from CLI 0.1.0 has no `selection` field and means
|
|
@@ -147,7 +200,32 @@ When nothing changed since the last pull with the same selection, `pull`
|
|
|
147
200
|
prints `Already up to date` and writes nothing. Every republish stamps a new
|
|
148
201
|
export id and time into the canonical artifacts, so `bundle.json` and
|
|
149
202
|
`manifest.json` change on each republish even when the content did not. The
|
|
150
|
-
`ai/` YAML files and the content hashes stay stable.
|
|
203
|
+
`ai/` YAML files, the `tokens/` files, and the content hashes stay stable.
|
|
204
|
+
|
|
205
|
+
## Configuring the token output
|
|
206
|
+
|
|
207
|
+
`speclayer.json` may carry a `dtcg` block:
|
|
208
|
+
|
|
209
|
+
{
|
|
210
|
+
"libraryId": "lib_...",
|
|
211
|
+
"outDir": ".speclayer",
|
|
212
|
+
"dtcg": {
|
|
213
|
+
"values": "standard",
|
|
214
|
+
"units": { "Foundation/spacing/*": "px", "Foundation/radius/*": "px" }
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
`values` is `standard` (the 2025.10 object forms, the default) or `legacy`
|
|
219
|
+
(the string forms Style Dictionary 4 and Tokens Studio read today). `units`
|
|
220
|
+
promotes a number whose Figma scopes state no unit to a dimension. Keys are a
|
|
221
|
+
collection name, a slash, and a glob over the variable name. An override that
|
|
222
|
+
contradicts a stated scope is ignored and listed in `report.json`. Nothing is
|
|
223
|
+
inferred from a name. Changing the `dtcg` block re-projects `tokens/` on the
|
|
224
|
+
next `pull` even when the library has not been republished.
|
|
225
|
+
|
|
226
|
+
Point Style Dictionary at `.speclayer/tokens/` and load the files
|
|
227
|
+
`resolver.json` names for the mode you are building. The metadata sidecar and
|
|
228
|
+
the report are not token files; exclude them from token globs.
|
|
151
229
|
|
|
152
230
|
## Exit codes
|
|
153
231
|
|