@getvitops/cli 0.5.0 → 0.7.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/CHANGELOG.md +169 -0
- package/README.md +34 -13
- package/dist/cli.mjs +178 -68
- package/dist/cli.mjs.map +1 -1
- package/package.json +9 -4
- package/skill/SKILL.md +46 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# @getvitops/cli
|
|
2
|
+
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 44de07f: Split the button pattern into two tiers named by intent: `.cta` (persuasion) and `.btn`
|
|
8
|
+
(affordance).
|
|
9
|
+
|
|
10
|
+
**Breaking: a bare `<button>` is no longer a filled brand-primary button.** It now renders as a
|
|
11
|
+
quiet interactive control — geometry, cursor, subtle hover, focus ring — with no fill, no
|
|
12
|
+
`font-weight: 600`, and no shadow.
|
|
13
|
+
|
|
14
|
+
**Migration:** add `class="cta"` to any button that should stay prominent. Submit buttons, hero
|
|
15
|
+
actions, and anything driving a conversion are the usual candidates; dialog closes, toolbar
|
|
16
|
+
buttons, icon buttons and toggles should keep the new default. If you want the old behaviour
|
|
17
|
+
globally, set `patterns.items.btn` in your `design-system.json` back to the previous filled base.
|
|
18
|
+
|
|
19
|
+
New in this release:
|
|
20
|
+
- **`.cta`** — filled, bolder, roomier, lifts on hover. It is a class, not an element rule, so it
|
|
21
|
+
finally works on `<a>` — which is what a call to action usually is, since it navigates. Role
|
|
22
|
+
variants: `.cta-{success,danger,warning,info}`.
|
|
23
|
+
- **`.btn`** — the affordance tier. Emitted as one zero-specificity `:where(button, .btn)` rule, so
|
|
24
|
+
a bare `<button>` gets it with no class, `.btn` carries it to any other tag, and any explicit
|
|
25
|
+
class (including `.cta`, or a component's own class) overrides it without `!important`.
|
|
26
|
+
- **`:where(a, .link)`** — the link pattern now pairs its element with a class the same way.
|
|
27
|
+
- A pattern may now set **both `element` and `class`**, emitting one combined
|
|
28
|
+
`:where(<element>, .<class>)` rule. This is the general mechanism behind the above.
|
|
29
|
+
- A pattern may declare **`fill: true|false`** to state whether states and role variants drive
|
|
30
|
+
`background-color` (plus `on-solid` text) or `color`, instead of relying on the previous
|
|
31
|
+
inference from the pattern's name and base declarations. Existing configs are unaffected — the
|
|
32
|
+
old inference is still the fallback.
|
|
33
|
+
|
|
34
|
+
**Breaking: `chip` is retired as vocabulary.** The two small-label patterns are now split by
|
|
35
|
+
behaviour, not size: **`badge`** is a _static_ label (status, count, category) and **`tag`** is an
|
|
36
|
+
_editable and/or dismissable_ one (e.g. entries in a filter list).
|
|
37
|
+
- `.chip-list` → **`.tag-list`**, and its `--*-chip-list` / `--chip-list-focus-color` tokens →
|
|
38
|
+
`--*-tag-list` / `--tag-list-focus-color`.
|
|
39
|
+
- `.chip-list__chip` and `.chip-list__chip-remove` are **removed**. A tag list is a list of tags, so
|
|
40
|
+
its items are now the existing `.tag` / `.tag__remove` — which also means they pick up tag role
|
|
41
|
+
variants. **Migration:** replace `<span class="chip-list__chip">x <button
|
|
42
|
+
class="chip-list__chip-remove">` with `<span class="tag">x <button class="tag__remove">`. Note the
|
|
43
|
+
items change appearance: `.tag` is outlined (border + neutral text) where the old chip was filled
|
|
44
|
+
with `--color-surface-muted`.
|
|
45
|
+
- The `radii.chip` primitive is **removed** from the example config; it was only ever an alias of
|
|
46
|
+
`--br-tag`. Consumers who set `--br-chip` should use `--br-tag`.
|
|
47
|
+
|
|
48
|
+
**Pattern geometry now resolves through the group alias layer.** Every grouped pattern already
|
|
49
|
+
emitted `--<prop>-<name>-group` aliases (e.g. `--br-btn-group: var(--br-control)`), but most
|
|
50
|
+
patterns bypassed them and hard-coded `var(--br-control, …)` into the rule. `btn`, `cta`, `badge`,
|
|
51
|
+
`tag`, `card` and `status` now reference the alias and restate only their deviations via
|
|
52
|
+
`overrides`, so the whole chain — `--p-btn` → `--p-btn-group` → `--p-control` → `--p-default` — is
|
|
53
|
+
live CSS custom properties, inspectable and editable in the browser. Computed values are unchanged.
|
|
54
|
+
|
|
55
|
+
Also fixed:
|
|
56
|
+
- Role variants on element patterns were emitted at specificity 0-1-1 (`button.danger`), which
|
|
57
|
+
outranked any plain class. They now emit as `:where(button, .btn).danger, .btn-danger` — both at
|
|
58
|
+
class specificity, and reachable from a non-`<button>` host.
|
|
59
|
+
- The `link` pattern declared `default_role: "brand-primary"` while hard-coding a `ui-primary` base
|
|
60
|
+
colour, so hovering shifted hue instead of intensifying. Its `default_role` is now `ui-primary`.
|
|
61
|
+
- `@getvitops/astro`'s `FormRenderer` defaulted its submit button to `class="btn btn-primary"`, a
|
|
62
|
+
class that never existed and a role that is not emitted; it now defaults to `.cta`.
|
|
63
|
+
- The Tailwind bundle is no longer assembled during `css` / `bricks` builds, where it was computed
|
|
64
|
+
and discarded (it also read every framework partial off disk).
|
|
65
|
+
|
|
66
|
+
- 44de07f: Shared toolchain version + changelogs that reach consumers.
|
|
67
|
+
- **`@getvitops/astro` now shares the toolchain version** (`core`/`generator`/`utils`/`cli`/`vite`),
|
|
68
|
+
so it moves from its own `0.4.x` line onto the group's. The number changes; the package does not —
|
|
69
|
+
install it at the same version as `@getvitops/cli`. It was already being bumped on every toolchain
|
|
70
|
+
release by its dependency updates, and it depends on core, generator, utils _and_ vite, so a
|
|
71
|
+
separate version line cost the same churn while leaving the compatible pairing implicit. The
|
|
72
|
+
lockstep is load-bearing: the generator ships a snapshot of core's CSS + web-component bundles
|
|
73
|
+
while the Astro integration copies the _installed_ core's bundles, so mismatched versions can leave
|
|
74
|
+
the CSS and the components disagreeing.
|
|
75
|
+
|
|
76
|
+
- **Every package now ships its `CHANGELOG.md` in the published tarball.** npm does not include
|
|
77
|
+
changelogs by default, so none of this history previously reached anyone who installed the
|
|
78
|
+
packages. Per-package history now reads from `node_modules/@getvitops/<pkg>/CHANGELOG.md`;
|
|
79
|
+
curated toolchain-level release notes live in the repo's root `CHANGELOG.md`.
|
|
80
|
+
|
|
81
|
+
### Patch Changes
|
|
82
|
+
|
|
83
|
+
- @getvitops/generator@0.7.0
|
|
84
|
+
- @getvitops/utils@0.7.0
|
|
85
|
+
|
|
86
|
+
## 0.6.0
|
|
87
|
+
|
|
88
|
+
### Minor Changes
|
|
89
|
+
|
|
90
|
+
- 2cc847d: Package-resident agent skill + `vitops docs`:
|
|
91
|
+
- `@getvitops/cli` now ships the `vitops-design-system` agent skill inside the package
|
|
92
|
+
(`skill/SKILL.md`). `vitops agents` no longer emits a generated skill into the repo — it
|
|
93
|
+
symlinks `.agents/skills/` and `.claude/skills/` entries to the installed package (logical
|
|
94
|
+
`node_modules/@getvitops/cli/skill` target, surviving version bumps) and writes the
|
|
95
|
+
AGENTS.md pointer block. Old generated-skill directories are migrated automatically;
|
|
96
|
+
`--docs-dir` keeps the emit-files layout.
|
|
97
|
+
- New `vitops docs [topic]` command prints reference docs to stdout, rendered live from the
|
|
98
|
+
project's `design-system.json` (topics: classes, authoring, formats, color, scales,
|
|
99
|
+
patterns, elements; `--all` concatenates).
|
|
100
|
+
- `renderSkill()` removed from `@getvitops/generator` (superseded by the packaged skill).
|
|
101
|
+
|
|
102
|
+
### Patch Changes
|
|
103
|
+
|
|
104
|
+
- Updated dependencies [2cc847d]
|
|
105
|
+
- @getvitops/generator@0.6.0
|
|
106
|
+
- @getvitops/utils@0.6.0
|
|
107
|
+
|
|
108
|
+
## 0.5.0
|
|
109
|
+
|
|
110
|
+
### Minor Changes
|
|
111
|
+
|
|
112
|
+
- Ship design-system context to downstream agents:
|
|
113
|
+
- JSON Schema descriptions: every `design-system.json` and site-config field now carries a
|
|
114
|
+
`description` (authored in the zod schemas via `desc()`), emitted into `schema.json` /
|
|
115
|
+
`site.schema.json` for editor hovers and agent consumption.
|
|
116
|
+
- New generated OKF docs: `authoring.md` (field reference walked from the JSON Schema),
|
|
117
|
+
`formats.md` (tailwind vs css vs bricks, including the TW_CLASH utilities Tailwind
|
|
118
|
+
provides natively), and `concepts/{color,scales,patterns}.md` (seeded OKLCH colour
|
|
119
|
+
system, fluid modular scales, pattern token cascade + override hooks).
|
|
120
|
+
- `vitops agents` now emits a generated `vitops-design-system` agent skill into
|
|
121
|
+
`.agents/skills/vitops-design-system/` (SKILL.md + the docs bundle as `references/`,
|
|
122
|
+
with an idempotent `.claude/skills/` symlink) and writes a compact pointer block into
|
|
123
|
+
`AGENTS.md`. Pass `--docs-dir` for the legacy docs-only layout.
|
|
124
|
+
- `TW_CLASH` and `BASE_HOOK` are exported from `@getvitops/generator`.
|
|
125
|
+
|
|
126
|
+
### Patch Changes
|
|
127
|
+
|
|
128
|
+
- Updated dependencies
|
|
129
|
+
- @getvitops/generator@0.5.0
|
|
130
|
+
- @getvitops/utils@0.5.0
|
|
131
|
+
|
|
132
|
+
## 0.4.0
|
|
133
|
+
|
|
134
|
+
### Patch Changes
|
|
135
|
+
|
|
136
|
+
- Updated dependencies [d7e6491]
|
|
137
|
+
- @getvitops/utils@0.4.0
|
|
138
|
+
- @getvitops/generator@0.4.0
|
|
139
|
+
|
|
140
|
+
## 0.3.0
|
|
141
|
+
|
|
142
|
+
### Patch Changes
|
|
143
|
+
|
|
144
|
+
- Updated dependencies
|
|
145
|
+
- @getvitops/utils@0.3.0
|
|
146
|
+
- @getvitops/generator@0.3.0
|
|
147
|
+
|
|
148
|
+
## 0.2.1
|
|
149
|
+
|
|
150
|
+
### Patch Changes
|
|
151
|
+
|
|
152
|
+
- Updated dependencies [d28aae7]
|
|
153
|
+
- @getvitops/generator@0.2.1
|
|
154
|
+
- @getvitops/utils@0.2.1
|
|
155
|
+
|
|
156
|
+
## 0.2.0
|
|
157
|
+
|
|
158
|
+
### Minor Changes
|
|
159
|
+
|
|
160
|
+
- d35515e: Add `vitops agents` — writes a managed, marker-delimited block into a consumer's `AGENTS.md`
|
|
161
|
+
(or `--out CLAUDE.md`) so AI coding agents can discover the CLI and the design-system class/element
|
|
162
|
+
vocabulary. Idempotent (re-run to update between the `<!-- vitops:start -->`/`<!-- vitops:end -->`
|
|
163
|
+
markers) and also emits the OKF docs bundle it points at (`--docs-dir`, default `.vitops/docs`).
|
|
164
|
+
|
|
165
|
+
### Patch Changes
|
|
166
|
+
|
|
167
|
+
- Updated dependencies
|
|
168
|
+
- @getvitops/generator@0.2.0
|
|
169
|
+
- @getvitops/utils@0.2.0
|
package/README.md
CHANGED
|
@@ -23,7 +23,8 @@ npx vitops generate --format bricks,css --out dist
|
|
|
23
23
|
| `vitops validate <file>` | schema-check (non-zero exit on error) |
|
|
24
24
|
| `vitops generate -i <file> -f <formats> -o <dir>` | generate `bricks` / `css` / `tailwind` output |
|
|
25
25
|
| `vitops favicon -i <svg\|png> -o <dir>` | generate a favicon set from a source image |
|
|
26
|
-
| `vitops agents [-o AGENTS.md] [--docs-dir <dir>]` |
|
|
26
|
+
| `vitops agents [-o AGENTS.md] [--docs-dir <dir>]` | link the agent skill + AGENTS.md pointer |
|
|
27
|
+
| `vitops docs [topic] [--all]` | print live reference docs to stdout |
|
|
27
28
|
|
|
28
29
|
## Using the output
|
|
29
30
|
|
|
@@ -79,22 +80,42 @@ The CLI only writes files — how they reach WordPress is up to you:
|
|
|
79
80
|
- **CI:** run `vitops generate --format bricks` in your pipeline and deploy the artifact the
|
|
80
81
|
same way you deploy the rest of the theme.
|
|
81
82
|
|
|
82
|
-
## Teaching AI agents (`vitops agents`)
|
|
83
|
+
## Teaching AI agents (`vitops agents` + `vitops docs`)
|
|
83
84
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
This package **ships an agent skill** (`skill/SKILL.md`, the [Agent Skills](https://code.claude.com/docs/en/skills)
|
|
86
|
+
format) that teaches AI coding agents to fetch design-system context on demand. Nothing is
|
|
87
|
+
generated into your repo — reference docs print live via `vitops docs`:
|
|
87
88
|
|
|
88
89
|
```sh
|
|
89
|
-
vitops
|
|
90
|
-
vitops
|
|
90
|
+
vitops docs # list topics
|
|
91
|
+
vitops docs classes # the class vocabulary, rendered from YOUR design-system.json
|
|
92
|
+
vitops docs authoring # every config field, from the JSON Schema
|
|
93
|
+
vitops docs formats # tailwind vs css vs bricks (incl. which utilities Tailwind owns)
|
|
91
94
|
```
|
|
92
95
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
Because output is rendered at call time from your config + the installed package version, it is
|
|
97
|
+
never stale. `vitops agents` wires up discovery:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
vitops agents # links the skill + updates ./AGENTS.md
|
|
101
|
+
vitops agents --out CLAUDE.md # different pointer file
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
It symlinks `.agents/skills/vitops-design-system` and `.claude/skills/vitops-design-system` to the
|
|
105
|
+
skill inside the installed package (the links target the logical `node_modules/@getvitops/cli/skill`
|
|
106
|
+
path, so they survive version bumps and reinstalls — re-run only if you delete them), and writes a
|
|
107
|
+
marker-delimited **managed block** into your `AGENTS.md` listing the CLI commands and `vitops docs`
|
|
108
|
+
topics. Re-running only replaces the content between the `<!-- vitops:start -->` /
|
|
109
|
+
`<!-- vitops:end -->` markers.
|
|
110
|
+
|
|
111
|
+
Prefer materialized files (offline/CI contexts, or agents that can't run commands)? The legacy
|
|
112
|
+
layout still works: `vitops agents --docs-dir .vitops/docs` writes the full docs bundle as files
|
|
113
|
+
and points the AGENTS.md block at them (no skill link).
|
|
99
114
|
|
|
100
115
|
Powered by [`@getvitops/generator`](https://www.npmjs.com/package/@getvitops/generator).
|
|
116
|
+
|
|
117
|
+
## Changelog
|
|
118
|
+
|
|
119
|
+
This package's history: [`CHANGELOG.md`](./CHANGELOG.md) (shipped in the npm tarball, so it
|
|
120
|
+
also reads from `node_modules/@getvitops/cli/CHANGELOG.md`). `@getvitops/core`, `generator`,
|
|
121
|
+
`utils`, `cli`, `vite` and `astro` share one version and are released together.
|
package/dist/cli.mjs
CHANGED
|
@@ -2,10 +2,99 @@
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { parseArgs } from "node:util";
|
|
4
4
|
import { existsSync, lstatSync, mkdirSync, readFileSync, readlinkSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
5
|
-
import { dirname, join, relative, resolve } from "node:path";
|
|
6
|
-
import { SCHEMA_URL, defaultConfig, generate, generateDocs,
|
|
5
|
+
import { dirname, join, parse, relative, resolve } from "node:path";
|
|
6
|
+
import { SCHEMA_URL, defaultConfig, generate, generateDocs, validate } from "@getvitops/generator";
|
|
7
7
|
import { generateFavicons } from "@getvitops/utils";
|
|
8
8
|
|
|
9
|
+
//#region src/agents.ts
|
|
10
|
+
/**
|
|
11
|
+
* Side-effect-free helpers for the `vitops agents` / `vitops docs` commands.
|
|
12
|
+
* Kept out of cli.ts (which runs main() on import) so they are unit-testable.
|
|
13
|
+
*/
|
|
14
|
+
const SKILL_NAME = "vitops-design-system";
|
|
15
|
+
/** Marker the 0.5.0-era generated skill carried; lets us migrate that layout. */
|
|
16
|
+
const GENERATED_MARKER = "<!-- GENERATED by @getvitops/cli";
|
|
17
|
+
/**
|
|
18
|
+
* `vitops docs` topics → docs-bundle paths (as returned by `generateDocs`).
|
|
19
|
+
* Order is the `--all` concatenation order.
|
|
20
|
+
*/
|
|
21
|
+
const TOPICS = {
|
|
22
|
+
classes: {
|
|
23
|
+
path: "css/classes.md",
|
|
24
|
+
summary: "CSS framework class vocabulary (colour, type, space, layout, animation, patterns)"
|
|
25
|
+
},
|
|
26
|
+
authoring: {
|
|
27
|
+
path: "authoring.md",
|
|
28
|
+
summary: "every design-system.json field, rendered from the JSON Schema"
|
|
29
|
+
},
|
|
30
|
+
formats: {
|
|
31
|
+
path: "formats.md",
|
|
32
|
+
summary: "tailwind vs css vs bricks: what's emitted vs what the platform provides"
|
|
33
|
+
},
|
|
34
|
+
color: {
|
|
35
|
+
path: "concepts/color.md",
|
|
36
|
+
summary: "seeded OKLCH scales, functional tokens, automatic dark mode"
|
|
37
|
+
},
|
|
38
|
+
scales: {
|
|
39
|
+
path: "concepts/scales.md",
|
|
40
|
+
summary: "fluid modular type & space scales"
|
|
41
|
+
},
|
|
42
|
+
patterns: {
|
|
43
|
+
path: "concepts/patterns.md",
|
|
44
|
+
summary: "pattern CSS: token cascade, override hooks, states, role variants"
|
|
45
|
+
},
|
|
46
|
+
elements: {
|
|
47
|
+
path: "bricks/elements.md",
|
|
48
|
+
summary: "Bricks Builder custom elements, controls, defaults"
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Find the installed package's skill directory by walking up from `cwd` looking
|
|
53
|
+
* for `node_modules/@getvitops/cli/skill/SKILL.md`. Returns the LOGICAL path
|
|
54
|
+
* (through the `node_modules/@getvitops/cli` link, unresolved) or null.
|
|
55
|
+
*
|
|
56
|
+
* Deliberately not derived from import.meta.url: under pnpm the running module's
|
|
57
|
+
* URL is the realpath in `node_modules/.pnpm/@getvitops+cli@<version>/…`, which
|
|
58
|
+
* changes on every version bump — a symlink to it would dangle after upgrades.
|
|
59
|
+
* The logical path is recreated by the package manager on every install, so a
|
|
60
|
+
* link through it always resolves to the currently installed version.
|
|
61
|
+
*/
|
|
62
|
+
function findSkillTarget(cwd) {
|
|
63
|
+
let dir = resolve(cwd);
|
|
64
|
+
const { root } = parse(dir);
|
|
65
|
+
for (;;) {
|
|
66
|
+
const skillDir = join(dir, "node_modules", "@getvitops", "cli", "skill");
|
|
67
|
+
if (existsSync(join(skillDir, "SKILL.md"))) return skillDir;
|
|
68
|
+
if (dir === root) return null;
|
|
69
|
+
dir = dirname(dir);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Idempotently symlink `linkPath` → `targetDir` (relative target). Replaces a
|
|
74
|
+
* stale symlink; migrates a real directory left by the old emitting `vitops
|
|
75
|
+
* agents` (identified by GENERATED_MARKER in its SKILL.md); refuses to clobber
|
|
76
|
+
* anything else. Returns a warning string, or null on success / no-op.
|
|
77
|
+
*/
|
|
78
|
+
function linkSkill(linkPath, targetDir) {
|
|
79
|
+
const target = relative(dirname(linkPath), resolve(targetDir));
|
|
80
|
+
try {
|
|
81
|
+
const st = lstatSync(linkPath, { throwIfNoEntry: false });
|
|
82
|
+
if (st && !st.isSymbolicLink()) {
|
|
83
|
+
const oldSkill = join(linkPath, "SKILL.md");
|
|
84
|
+
if (!(st.isDirectory() && existsSync(oldSkill) && readFileSync(oldSkill, "utf8").includes("<!-- GENERATED by @getvitops/cli"))) return `left ${linkPath} alone (exists and is not a symlink) — link it to ${targetDir} yourself if wanted`;
|
|
85
|
+
rmSync(linkPath, { recursive: true });
|
|
86
|
+
} else if (st) {
|
|
87
|
+
if (readlinkSync(linkPath) === target) return null;
|
|
88
|
+
rmSync(linkPath);
|
|
89
|
+
} else mkdirSync(dirname(linkPath), { recursive: true });
|
|
90
|
+
symlinkSync(target, linkPath);
|
|
91
|
+
return null;
|
|
92
|
+
} catch (err) {
|
|
93
|
+
return `could not symlink ${linkPath}: ${err.message}`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
//#endregion
|
|
9
98
|
//#region src/cli.ts
|
|
10
99
|
/**
|
|
11
100
|
* `vitops` — CLI for the Vitops design-system generator.
|
|
@@ -14,7 +103,8 @@ import { generateFavicons } from "@getvitops/utils";
|
|
|
14
103
|
* vitops init [--out design-system.json] [--force]
|
|
15
104
|
* vitops validate <design-system.json>
|
|
16
105
|
* vitops favicon --input <svg|png> --out <dir> [--low-res <svg|png>]
|
|
17
|
-
* vitops agents [--input <json>] [--out AGENTS.md] [--
|
|
106
|
+
* vitops agents [--input <json>] [--out AGENTS.md] [--docs-dir <dir>]
|
|
107
|
+
* vitops docs [topic] [--input <json>] [--all]
|
|
18
108
|
*
|
|
19
109
|
* Thin wrapper over @getvitops/generator (generation) and @getvitops/utils (favicons).
|
|
20
110
|
* Every client brings their own consumer-editable design-system.json.
|
|
@@ -31,7 +121,8 @@ Usage:
|
|
|
31
121
|
vitops init [options] Scaffold a starter design-system.json
|
|
32
122
|
vitops validate <file> Validate a config against the schema
|
|
33
123
|
vitops favicon [options] Generate a favicon set from a source image
|
|
34
|
-
vitops agents [options]
|
|
124
|
+
vitops agents [options] Link the design-system agent skill + AGENTS.md pointer
|
|
125
|
+
vitops docs [topic] Print live design-system reference docs to stdout
|
|
35
126
|
|
|
36
127
|
Generate options:
|
|
37
128
|
-i, --input <path> Config file (default: ./design-system.json)
|
|
@@ -48,12 +139,16 @@ Favicon options:
|
|
|
48
139
|
--low-res <path> Optional simplified source for the 16px icon
|
|
49
140
|
|
|
50
141
|
Agents options:
|
|
51
|
-
-i, --input <path> Config file (default: ./design-system.json)
|
|
142
|
+
-i, --input <path> Config file (default: ./design-system.json; validated if present)
|
|
52
143
|
-o, --out <path> Doc file to update, idempotently (default: ./AGENTS.md)
|
|
53
|
-
--
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
144
|
+
--docs-dir <dir> Legacy layout: write the docs bundle as files to this dir
|
|
145
|
+
instead of linking the packaged skill
|
|
146
|
+
|
|
147
|
+
Docs options:
|
|
148
|
+
<topic> classes | authoring | formats | color | scales | patterns | elements
|
|
149
|
+
(no topic: list topics with summaries)
|
|
150
|
+
-i, --input <path> Config file (default: ./design-system.json)
|
|
151
|
+
--all Print every topic, concatenated
|
|
57
152
|
|
|
58
153
|
Common:
|
|
59
154
|
-h, --help Show this help
|
|
@@ -207,29 +302,33 @@ function generatorAssetsDir() {
|
|
|
207
302
|
}
|
|
208
303
|
const AGENTS_START = "<!-- vitops:start -->";
|
|
209
304
|
const AGENTS_END = "<!-- vitops:end -->";
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
return
|
|
305
|
+
/** Print a live reference doc (rendered from the project's config) to stdout. */
|
|
306
|
+
function cmdDocs(argv) {
|
|
307
|
+
const { values, positionals } = parseArgs({
|
|
308
|
+
args: argv,
|
|
309
|
+
options: {
|
|
310
|
+
input: {
|
|
311
|
+
type: "string",
|
|
312
|
+
short: "i",
|
|
313
|
+
default: "design-system.json"
|
|
314
|
+
},
|
|
315
|
+
all: {
|
|
316
|
+
type: "boolean",
|
|
317
|
+
default: false
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
allowPositionals: true
|
|
321
|
+
});
|
|
322
|
+
const topic = positionals[0];
|
|
323
|
+
const topicList = () => Object.entries(TOPICS).map(([name, t]) => ` ${name.padEnd(10)} ${t.summary}`).join("\n");
|
|
324
|
+
if (!topic && !values.all) {
|
|
325
|
+
console.log(`vitops docs <topic> — print a live design-system reference to stdout\n\nTopics:\n${topicList()}\n\nAlso: vitops docs --all (every topic, concatenated)`);
|
|
326
|
+
return;
|
|
232
327
|
}
|
|
328
|
+
if (topic && !TOPICS[topic]) fail(`unknown topic "${topic}". Valid topics:\n${topicList()}`);
|
|
329
|
+
const docs = generateDocs(loadConfig(resolve(values.input)), generatorAssetsDir());
|
|
330
|
+
const paths = values.all ? Object.values(TOPICS).map((t) => t.path) : [TOPICS[topic].path];
|
|
331
|
+
process.stdout.write(paths.map((p) => docs[p]).join("\n"));
|
|
233
332
|
}
|
|
234
333
|
function cmdAgents(argv) {
|
|
235
334
|
const { values } = parseArgs({
|
|
@@ -245,48 +344,58 @@ function cmdAgents(argv) {
|
|
|
245
344
|
short: "o",
|
|
246
345
|
default: "AGENTS.md"
|
|
247
346
|
},
|
|
248
|
-
"skill-dir": {
|
|
249
|
-
type: "string",
|
|
250
|
-
default: join(".agents", "skills", SKILL_NAME)
|
|
251
|
-
},
|
|
252
347
|
"docs-dir": { type: "string" }
|
|
253
348
|
},
|
|
254
349
|
allowPositionals: false
|
|
255
350
|
});
|
|
256
351
|
const inputRel = values.input;
|
|
257
|
-
|
|
258
|
-
|
|
352
|
+
let ds = null;
|
|
353
|
+
if (existsSync(resolve(inputRel))) ds = loadConfig(resolve(inputRel));
|
|
354
|
+
else console.warn(` ⚠ ${inputRel} not found — run \`vitops init\` to scaffold one`);
|
|
259
355
|
const legacyDocsDir = values["docs-dir"];
|
|
260
|
-
|
|
261
|
-
let
|
|
262
|
-
|
|
263
|
-
docs
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
356
|
+
let summary;
|
|
357
|
+
let pointer;
|
|
358
|
+
if (legacyDocsDir) {
|
|
359
|
+
if (!ds) fail(`--docs-dir needs a config to render docs from (${inputRel} not found)`);
|
|
360
|
+
let docs = {};
|
|
361
|
+
try {
|
|
362
|
+
docs = generateDocs(ds, generatorAssetsDir());
|
|
363
|
+
} catch (err) {
|
|
364
|
+
fail(`could not generate docs: ${err.message}`);
|
|
365
|
+
}
|
|
366
|
+
for (const [rel, content] of Object.entries(docs)) {
|
|
367
|
+
const p = resolve(legacyDocsDir, rel);
|
|
368
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
369
|
+
writeFileSync(p, content);
|
|
370
|
+
}
|
|
371
|
+
summary = `wrote ${Object.keys(docs).length} docs to ${legacyDocsDir}/`;
|
|
372
|
+
pointer = [
|
|
373
|
+
"Prefer the framework’s utility + component classes over hand-written CSS.",
|
|
374
|
+
`Reference docs (regenerate with \`vitops agents --docs-dir ${legacyDocsDir}\`): \`${legacyDocsDir}/css/classes.md\`,`,
|
|
375
|
+
`\`${legacyDocsDir}/authoring.md\`, \`${legacyDocsDir}/formats.md\`, \`${legacyDocsDir}/bricks/elements.md\`.`
|
|
376
|
+
];
|
|
377
|
+
} else {
|
|
378
|
+
const target = findSkillTarget(process.cwd());
|
|
379
|
+
if (target) {
|
|
380
|
+
for (const dir of [".agents", ".claude"]) {
|
|
381
|
+
const warn = linkSkill(resolve(dir, "skills", SKILL_NAME), target);
|
|
382
|
+
if (warn) console.warn(` ⚠ ${warn}`);
|
|
383
|
+
}
|
|
384
|
+
summary = `linked {.agents,.claude}/skills/${SKILL_NAME} → ${target}`;
|
|
385
|
+
} else {
|
|
386
|
+
console.warn(` ⚠ could not find node_modules/@getvitops/cli/skill — install @getvitops/cli as a devDependency, then re-run \`vitops agents\``);
|
|
387
|
+
summary = "no skill linked";
|
|
388
|
+
}
|
|
389
|
+
pointer = [
|
|
390
|
+
"Prefer the framework’s utility + component classes over hand-written CSS.",
|
|
391
|
+
`Full design-system context lives in the \`${SKILL_NAME}\` skill (linked from`,
|
|
392
|
+
"`.agents/skills/` and `.claude/skills/` into the installed `@getvitops/cli`;",
|
|
393
|
+
"re-link with `vitops agents` if the links are deleted — they survive version",
|
|
394
|
+
"bumps). Reference docs print live, from this project’s config, via:",
|
|
395
|
+
"",
|
|
396
|
+
...Object.entries(TOPICS).map(([name, t]) => `- \`vitops docs ${name}\` — ${t.summary}`)
|
|
397
|
+
];
|
|
278
398
|
}
|
|
279
|
-
const pointer = legacyDocsDir ? [
|
|
280
|
-
"Prefer the framework’s utility + component classes over hand-written CSS.",
|
|
281
|
-
`Reference docs (regenerate with \`vitops agents\`): \`${docsDir}/css/classes.md\`,`,
|
|
282
|
-
`\`${docsDir}/authoring.md\`, \`${docsDir}/formats.md\`, \`${docsDir}/bricks/elements.md\`.`
|
|
283
|
-
] : [
|
|
284
|
-
"Prefer the framework’s utility + component classes over hand-written CSS.",
|
|
285
|
-
`Full design-system context lives in the \`${SKILL_NAME}\` skill at \`${skillDir}/\`:`,
|
|
286
|
-
"class vocabulary, `design-system.json` field reference, per-format output",
|
|
287
|
-
"differences (Tailwind vs Bricks vs CSS), colour/scale/pattern concepts, and the",
|
|
288
|
-
"Bricks element reference (under its `references/`). Regenerate with `vitops agents`."
|
|
289
|
-
];
|
|
290
399
|
const block = [
|
|
291
400
|
AGENTS_START,
|
|
292
401
|
"## Vitops design system",
|
|
@@ -324,7 +433,7 @@ function cmdAgents(argv) {
|
|
|
324
433
|
action = "created";
|
|
325
434
|
}
|
|
326
435
|
writeFileSync(outPath, next);
|
|
327
|
-
console.log(`✓ ${action} ${values.out} +
|
|
436
|
+
console.log(`✓ ${action} ${values.out} + ${summary}`);
|
|
328
437
|
}
|
|
329
438
|
async function main() {
|
|
330
439
|
const [command, ...rest] = process.argv.slice(2);
|
|
@@ -338,7 +447,8 @@ async function main() {
|
|
|
338
447
|
case "validate": return cmdValidate(rest);
|
|
339
448
|
case "favicon": return cmdFavicon(rest);
|
|
340
449
|
case "agents": return cmdAgents(rest);
|
|
341
|
-
|
|
450
|
+
case "docs": return cmdDocs(rest);
|
|
451
|
+
default: fail(`unknown command "${command}" (expected: generate | init | validate | favicon | agents | docs). Try: vitops --help`);
|
|
342
452
|
}
|
|
343
453
|
}
|
|
344
454
|
main().catch((err) => fail(err.message));
|
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * `vitops` — CLI for the Vitops design-system generator.\n *\n * vitops generate --input <json> --format <bricks|css|tailwind[,…]> --out <dir>\n * vitops init [--out design-system.json] [--force]\n * vitops validate <design-system.json>\n * vitops favicon --input <svg|png> --out <dir> [--low-res <svg|png>]\n * vitops agents [--input <json>] [--out AGENTS.md] [--skill-dir <dir>] [--docs-dir <dir>]\n *\n * Thin wrapper over @getvitops/generator (generation) and @getvitops/utils (favicons).\n * Every client brings their own consumer-editable design-system.json.\n */\nimport { parseArgs } from 'node:util';\nimport {\n writeFileSync,\n existsSync,\n readFileSync,\n mkdirSync,\n lstatSync,\n readlinkSync,\n rmSync,\n symlinkSync,\n} from 'node:fs';\nimport { resolve, join, dirname, relative } from 'node:path';\nimport { createRequire } from 'node:module';\nimport {\n generate,\n validate,\n defaultConfig,\n generateDocs,\n renderSkill,\n SCHEMA_URL,\n type Format,\n type DesignSystem,\n} from '@getvitops/generator';\nimport { generateFavicons } from '@getvitops/utils';\n\nconst FORMATS = new Set<Format>(['bricks', 'css', 'tailwind']);\n\nconst HELP = `vitops — generate design-system outputs from a design-system.json\n\nUsage:\n vitops generate [options] Generate platform output from a config\n vitops init [options] Scaffold a starter design-system.json\n vitops validate <file> Validate a config against the schema\n vitops favicon [options] Generate a favicon set from a source image\n vitops agents [options] Emit the design-system agent skill + AGENTS.md pointer\n\nGenerate options:\n -i, --input <path> Config file (default: ./design-system.json)\n -f, --format <list> bricks | css | tailwind (comma-separated; default: bricks)\n -o, --out <dir> Output directory (default: ./dist)\n\nInit options:\n -o, --out <path> Where to write (default: ./design-system.json)\n --force Overwrite an existing file\n\nFavicon options:\n -i, --input <path> Source SVG or PNG (required)\n -o, --out <dir> Output directory (default: ./public)\n --low-res <path> Optional simplified source for the 16px icon\n\nAgents options:\n -i, --input <path> Config file (default: ./design-system.json)\n -o, --out <path> Doc file to update, idempotently (default: ./AGENTS.md)\n --skill-dir <dir> Where the generated skill lands (default:\n ./.agents/skills/vitops-design-system; also symlinked from\n ./.claude/skills/vitops-design-system)\n --docs-dir <dir> Legacy layout: write only the docs bundle to this dir (no skill)\n\nCommon:\n -h, --help Show this help\n`;\n\nfunction fail(msg: string): never {\n console.error(`✖ ${msg}`);\n process.exit(1);\n}\n\nasync function cmdGenerate(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i', default: 'design-system.json' },\n format: { type: 'string', short: 'f', default: 'bricks' },\n out: { type: 'string', short: 'o', default: 'dist' },\n },\n allowPositionals: false,\n });\n const input = resolve(values.input as string);\n if (!existsSync(input)) fail(`config not found: ${input}`);\n const formats = (values.format as string)\n .split(',')\n .map((f) => f.trim())\n .filter(Boolean);\n for (const f of formats)\n if (!FORMATS.has(f as Format))\n fail(`unknown format \"${f}\" (expected: bricks | css | tailwind)`);\n\n for (const format of formats as Format[]) {\n try {\n const res = await generate({ input, format, outDir: values.out as string });\n console.log(`✓ ${format} → ${res.outDir} (${res.written.length} paths)`);\n } catch (err) {\n fail((err as Error).message);\n }\n }\n}\n\nfunction cmdInit(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n out: { type: 'string', short: 'o', default: 'design-system.json' },\n force: { type: 'boolean', default: false },\n },\n allowPositionals: false,\n });\n const out = resolve(values.out as string);\n if (existsSync(out) && !values.force) fail(`${out} already exists (use --force to overwrite)`);\n writeFileSync(out, JSON.stringify(defaultConfig(), null, 2) + '\\n');\n console.log(`✓ wrote ${out}`);\n console.log(\n ` Edit it, then: vitops generate --input ${values.out} --format tailwind --out src/styles`,\n );\n console.log(` Editors read the \"$schema\" (${SCHEMA_URL}) for autocomplete + validation.`);\n}\n\nfunction cmdValidate(argv: string[]) {\n const { values, positionals } = parseArgs({\n args: argv,\n options: { input: { type: 'string', short: 'i' } },\n allowPositionals: true,\n });\n const path = resolve((positionals[0] ?? values.input ?? 'design-system.json') as string);\n if (!existsSync(path)) fail(`config not found: ${path}`);\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf8'));\n } catch (err) {\n fail(`could not parse JSON: ${(err as Error).message}`);\n }\n const result = validate(raw);\n if (result.ok) {\n console.log(`✓ ${path} is valid`);\n return;\n }\n console.error(`✖ ${path} is invalid:`);\n for (const e of result.errors) console.error(` • ${e.path.join('.') || '(root)'}: ${e.message}`);\n process.exit(1);\n}\n\nasync function cmdFavicon(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i' },\n out: { type: 'string', short: 'o', default: 'public' },\n 'low-res': { type: 'string' },\n },\n allowPositionals: false,\n });\n if (!values.input) fail('favicon: --input <svg|png> is required');\n const source = resolve(values.input as string);\n if (!existsSync(source)) fail(`source not found: ${source}`);\n try {\n const written = await generateFavicons({\n source,\n outputDir: values.out as string,\n ...(values['low-res'] ? { lowResSource: resolve(values['low-res'] as string) } : {}),\n });\n console.log(`✓ favicons → ${values.out} (${written.length} files)`);\n } catch (err) {\n fail((err as Error).message);\n }\n}\n\n// Read + parse + validate a design-system.json, or exit with a message.\nfunction loadConfig(path: string): DesignSystem {\n if (!existsSync(path)) fail(`config not found: ${path}`);\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf8'));\n } catch (err) {\n fail(`could not parse JSON: ${(err as Error).message}`);\n }\n const result = validate(raw);\n if (!result.ok) {\n console.error(`✖ ${path} is invalid:`);\n for (const e of result.errors)\n console.error(` • ${e.path.join('.') || '(root)'}: ${e.message}`);\n process.exit(1);\n }\n return result.data;\n}\n\n// This CLI's own version (dist/cli.mjs → package-root package.json).\nfunction cliVersion(): string {\n try {\n return (\n JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version ??\n '0.0.0'\n );\n } catch {\n return '0.0.0';\n }\n}\n\n// The framework asset root shipped inside @getvitops/generator (holds the Bricks\n// PHP that generateDocs reads for the element reference).\nfunction generatorAssetsDir(): string {\n const pkg = createRequire(import.meta.url).resolve('@getvitops/generator/package.json');\n return join(dirname(pkg), 'assets');\n}\n\nconst AGENTS_START = '<!-- vitops:start -->';\nconst AGENTS_END = '<!-- vitops:end -->';\nconst SKILL_NAME = 'vitops-design-system';\n\n/**\n * Idempotently symlink `.claude/skills/vitops-design-system` → the skill dir so\n * Claude Code discovers the agent-agnostic `.agents/` skill. Replaces a stale\n * symlink; refuses to clobber a real file/dir. Returns a warning, or null on\n * success / nothing-to-do.\n */\nfunction linkClaudeSkill(skillDir: string): string | null {\n const linkPath = resolve('.claude', 'skills', SKILL_NAME);\n const target = relative(dirname(linkPath), resolve(skillDir));\n if (target === '') return null; // skill dir IS the .claude path\n try {\n const st = lstatSync(linkPath, { throwIfNoEntry: false });\n if (st && !st.isSymbolicLink())\n return `left ${linkPath} alone (exists and is not a symlink) — link it to ${skillDir} yourself if wanted`;\n if (st) {\n if (readlinkSync(linkPath) === target) return null;\n rmSync(linkPath);\n } else {\n mkdirSync(dirname(linkPath), { recursive: true });\n }\n symlinkSync(target, linkPath);\n return null;\n } catch (err) {\n return `could not symlink ${linkPath}: ${(err as Error).message}`;\n }\n}\n\nfunction cmdAgents(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i', default: 'design-system.json' },\n out: { type: 'string', short: 'o', default: 'AGENTS.md' },\n 'skill-dir': { type: 'string', default: join('.agents', 'skills', SKILL_NAME) },\n 'docs-dir': { type: 'string' },\n },\n allowPositionals: false,\n });\n const inputRel = values.input as string;\n const ds = loadConfig(resolve(inputRel));\n const skillDir = values['skill-dir'] as string;\n // Explicit --docs-dir = legacy layout: just the docs bundle, no skill.\n const legacyDocsDir = values['docs-dir'] as string | undefined;\n const docsDir = legacyDocsDir ?? join(skillDir, 'references');\n\n // Emit the OKF docs bundle so the AGENTS.md pointer resolves for every consumer\n // (only the `bricks` generate format writes docs/ otherwise).\n let docs: Record<string, string> = {};\n try {\n docs = generateDocs(ds, generatorAssetsDir());\n } catch (err) {\n fail(`could not generate docs: ${(err as Error).message}`);\n }\n for (const [rel, content] of Object.entries(docs)) {\n const p = resolve(docsDir, rel);\n mkdirSync(dirname(p), { recursive: true });\n writeFileSync(p, content);\n }\n\n let skillNote = '';\n if (!legacyDocsDir) {\n writeFileSync(resolve(skillDir, 'SKILL.md'), renderSkill(ds));\n const warn = linkClaudeSkill(skillDir);\n if (warn) console.warn(` ⚠ ${warn}`);\n skillNote = ` + skill at ${skillDir}/`;\n }\n\n const pointer = legacyDocsDir\n ? [\n 'Prefer the framework’s utility + component classes over hand-written CSS.',\n `Reference docs (regenerate with \\`vitops agents\\`): \\`${docsDir}/css/classes.md\\`,`,\n `\\`${docsDir}/authoring.md\\`, \\`${docsDir}/formats.md\\`, \\`${docsDir}/bricks/elements.md\\`.`,\n ]\n : [\n 'Prefer the framework’s utility + component classes over hand-written CSS.',\n `Full design-system context lives in the \\`${SKILL_NAME}\\` skill at \\`${skillDir}/\\`:`,\n 'class vocabulary, `design-system.json` field reference, per-format output',\n 'differences (Tailwind vs Bricks vs CSS), colour/scale/pattern concepts, and the',\n 'Bricks element reference (under its `references/`). Regenerate with `vitops agents`.',\n ];\n\n const block = [\n AGENTS_START,\n '## Vitops design system',\n '',\n `Styled with the Vitops design system (\\`@getvitops/*\\`); tokens live in \\`${inputRel}\\`.`,\n 'Generate output with the CLI:',\n '',\n '- `vitops generate --format tailwind --out src/styles` — Tailwind v4 / Astro',\n '- `vitops generate --format css --out dist` — standalone CSS',\n '- `vitops generate --format bricks --out <theme>/dist` — WordPress / Bricks',\n '- `vitops init` · `vitops validate` · `vitops favicon`',\n '',\n ...pointer,\n '',\n `<!-- regenerate: vitops agents · @getvitops/cli@${cliVersion()} -->`,\n AGENTS_END,\n ].join('\\n');\n\n const outPath = resolve(values.out as string);\n let next: string;\n let action: string;\n if (existsSync(outPath)) {\n const cur = readFileSync(outPath, 'utf8');\n const s = cur.indexOf(AGENTS_START);\n const e = cur.indexOf(AGENTS_END);\n if (s !== -1 && e !== -1 && e > s) {\n next = cur.slice(0, s) + block + cur.slice(e + AGENTS_END.length);\n action = 'updated block in';\n } else {\n next = cur.replace(/\\s*$/, '') + '\\n\\n' + block + '\\n';\n action = 'appended block to';\n }\n } else {\n mkdirSync(dirname(outPath), { recursive: true });\n next = block + '\\n';\n action = 'created';\n }\n writeFileSync(outPath, next);\n console.log(\n `✓ ${action} ${values.out} + wrote ${Object.keys(docs).length} docs to ${docsDir}/${skillNote}`,\n );\n}\n\nasync function main() {\n const [command, ...rest] = process.argv.slice(2);\n if (!command || command === '-h' || command === '--help' || command === 'help') {\n console.log(HELP);\n return;\n }\n switch (command) {\n case 'generate':\n return cmdGenerate(rest);\n case 'init':\n return cmdInit(rest);\n case 'validate':\n return cmdValidate(rest);\n case 'favicon':\n return cmdFavicon(rest);\n case 'agents':\n return cmdAgents(rest);\n default:\n fail(\n `unknown command \"${command}\" (expected: generate | init | validate | favicon | agents). Try: vitops --help`,\n );\n }\n}\n\nmain().catch((err) => fail((err as Error).message));\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":[],"sources":["../src/agents.ts","../src/cli.ts"],"sourcesContent":["/**\n * Side-effect-free helpers for the `vitops agents` / `vitops docs` commands.\n * Kept out of cli.ts (which runs main() on import) so they are unit-testable.\n */\nimport {\n existsSync,\n lstatSync,\n mkdirSync,\n readFileSync,\n readlinkSync,\n rmSync,\n symlinkSync,\n} from 'node:fs';\nimport { dirname, join, parse, relative, resolve } from 'node:path';\n\nexport const SKILL_NAME = 'vitops-design-system';\n\n/** Marker the 0.5.0-era generated skill carried; lets us migrate that layout. */\nexport const GENERATED_MARKER = '<!-- GENERATED by @getvitops/cli';\n\n/**\n * `vitops docs` topics → docs-bundle paths (as returned by `generateDocs`).\n * Order is the `--all` concatenation order.\n */\nexport const TOPICS: Record<string, { path: string; summary: string }> = {\n classes: {\n path: 'css/classes.md',\n summary: 'CSS framework class vocabulary (colour, type, space, layout, animation, patterns)',\n },\n authoring: {\n path: 'authoring.md',\n summary: 'every design-system.json field, rendered from the JSON Schema',\n },\n formats: {\n path: 'formats.md',\n summary: \"tailwind vs css vs bricks: what's emitted vs what the platform provides\",\n },\n color: {\n path: 'concepts/color.md',\n summary: 'seeded OKLCH scales, functional tokens, automatic dark mode',\n },\n scales: {\n path: 'concepts/scales.md',\n summary: 'fluid modular type & space scales',\n },\n patterns: {\n path: 'concepts/patterns.md',\n summary: 'pattern CSS: token cascade, override hooks, states, role variants',\n },\n elements: {\n path: 'bricks/elements.md',\n summary: 'Bricks Builder custom elements, controls, defaults',\n },\n};\n\n/**\n * Find the installed package's skill directory by walking up from `cwd` looking\n * for `node_modules/@getvitops/cli/skill/SKILL.md`. Returns the LOGICAL path\n * (through the `node_modules/@getvitops/cli` link, unresolved) or null.\n *\n * Deliberately not derived from import.meta.url: under pnpm the running module's\n * URL is the realpath in `node_modules/.pnpm/@getvitops+cli@<version>/…`, which\n * changes on every version bump — a symlink to it would dangle after upgrades.\n * The logical path is recreated by the package manager on every install, so a\n * link through it always resolves to the currently installed version.\n */\nexport function findSkillTarget(cwd: string): string | null {\n let dir = resolve(cwd);\n const { root } = parse(dir);\n for (;;) {\n const skillDir = join(dir, 'node_modules', '@getvitops', 'cli', 'skill');\n if (existsSync(join(skillDir, 'SKILL.md'))) return skillDir;\n if (dir === root) return null;\n dir = dirname(dir);\n }\n}\n\n/**\n * Idempotently symlink `linkPath` → `targetDir` (relative target). Replaces a\n * stale symlink; migrates a real directory left by the old emitting `vitops\n * agents` (identified by GENERATED_MARKER in its SKILL.md); refuses to clobber\n * anything else. Returns a warning string, or null on success / no-op.\n */\nexport function linkSkill(linkPath: string, targetDir: string): string | null {\n const target = relative(dirname(linkPath), resolve(targetDir));\n try {\n const st = lstatSync(linkPath, { throwIfNoEntry: false });\n if (st && !st.isSymbolicLink()) {\n const oldSkill = join(linkPath, 'SKILL.md');\n const isGenerated =\n st.isDirectory() &&\n existsSync(oldSkill) &&\n readFileSync(oldSkill, 'utf8').includes(GENERATED_MARKER);\n if (!isGenerated)\n return `left ${linkPath} alone (exists and is not a symlink) — link it to ${targetDir} yourself if wanted`;\n rmSync(linkPath, { recursive: true }); // old generated skill layout → replace\n } else if (st) {\n if (readlinkSync(linkPath) === target) return null;\n rmSync(linkPath);\n } else {\n mkdirSync(dirname(linkPath), { recursive: true });\n }\n symlinkSync(target, linkPath);\n return null;\n } catch (err) {\n return `could not symlink ${linkPath}: ${(err as Error).message}`;\n }\n}\n","#!/usr/bin/env node\n/**\n * `vitops` — CLI for the Vitops design-system generator.\n *\n * vitops generate --input <json> --format <bricks|css|tailwind[,…]> --out <dir>\n * vitops init [--out design-system.json] [--force]\n * vitops validate <design-system.json>\n * vitops favicon --input <svg|png> --out <dir> [--low-res <svg|png>]\n * vitops agents [--input <json>] [--out AGENTS.md] [--docs-dir <dir>]\n * vitops docs [topic] [--input <json>] [--all]\n *\n * Thin wrapper over @getvitops/generator (generation) and @getvitops/utils (favicons).\n * Every client brings their own consumer-editable design-system.json.\n */\nimport { parseArgs } from 'node:util';\nimport { writeFileSync, existsSync, readFileSync, mkdirSync } from 'node:fs';\nimport { resolve, join, dirname } from 'node:path';\nimport { createRequire } from 'node:module';\nimport {\n generate,\n validate,\n defaultConfig,\n generateDocs,\n SCHEMA_URL,\n type Format,\n type DesignSystem,\n} from '@getvitops/generator';\nimport { generateFavicons } from '@getvitops/utils';\nimport { findSkillTarget, linkSkill, SKILL_NAME, TOPICS } from './agents.ts';\n\nconst FORMATS = new Set<Format>(['bricks', 'css', 'tailwind']);\n\nconst HELP = `vitops — generate design-system outputs from a design-system.json\n\nUsage:\n vitops generate [options] Generate platform output from a config\n vitops init [options] Scaffold a starter design-system.json\n vitops validate <file> Validate a config against the schema\n vitops favicon [options] Generate a favicon set from a source image\n vitops agents [options] Link the design-system agent skill + AGENTS.md pointer\n vitops docs [topic] Print live design-system reference docs to stdout\n\nGenerate options:\n -i, --input <path> Config file (default: ./design-system.json)\n -f, --format <list> bricks | css | tailwind (comma-separated; default: bricks)\n -o, --out <dir> Output directory (default: ./dist)\n\nInit options:\n -o, --out <path> Where to write (default: ./design-system.json)\n --force Overwrite an existing file\n\nFavicon options:\n -i, --input <path> Source SVG or PNG (required)\n -o, --out <dir> Output directory (default: ./public)\n --low-res <path> Optional simplified source for the 16px icon\n\nAgents options:\n -i, --input <path> Config file (default: ./design-system.json; validated if present)\n -o, --out <path> Doc file to update, idempotently (default: ./AGENTS.md)\n --docs-dir <dir> Legacy layout: write the docs bundle as files to this dir\n instead of linking the packaged skill\n\nDocs options:\n <topic> classes | authoring | formats | color | scales | patterns | elements\n (no topic: list topics with summaries)\n -i, --input <path> Config file (default: ./design-system.json)\n --all Print every topic, concatenated\n\nCommon:\n -h, --help Show this help\n`;\n\nfunction fail(msg: string): never {\n console.error(`✖ ${msg}`);\n process.exit(1);\n}\n\nasync function cmdGenerate(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i', default: 'design-system.json' },\n format: { type: 'string', short: 'f', default: 'bricks' },\n out: { type: 'string', short: 'o', default: 'dist' },\n },\n allowPositionals: false,\n });\n const input = resolve(values.input as string);\n if (!existsSync(input)) fail(`config not found: ${input}`);\n const formats = (values.format as string)\n .split(',')\n .map((f) => f.trim())\n .filter(Boolean);\n for (const f of formats)\n if (!FORMATS.has(f as Format))\n fail(`unknown format \"${f}\" (expected: bricks | css | tailwind)`);\n\n for (const format of formats as Format[]) {\n try {\n const res = await generate({ input, format, outDir: values.out as string });\n console.log(`✓ ${format} → ${res.outDir} (${res.written.length} paths)`);\n } catch (err) {\n fail((err as Error).message);\n }\n }\n}\n\nfunction cmdInit(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n out: { type: 'string', short: 'o', default: 'design-system.json' },\n force: { type: 'boolean', default: false },\n },\n allowPositionals: false,\n });\n const out = resolve(values.out as string);\n if (existsSync(out) && !values.force) fail(`${out} already exists (use --force to overwrite)`);\n writeFileSync(out, JSON.stringify(defaultConfig(), null, 2) + '\\n');\n console.log(`✓ wrote ${out}`);\n console.log(\n ` Edit it, then: vitops generate --input ${values.out} --format tailwind --out src/styles`,\n );\n console.log(` Editors read the \"$schema\" (${SCHEMA_URL}) for autocomplete + validation.`);\n}\n\nfunction cmdValidate(argv: string[]) {\n const { values, positionals } = parseArgs({\n args: argv,\n options: { input: { type: 'string', short: 'i' } },\n allowPositionals: true,\n });\n const path = resolve((positionals[0] ?? values.input ?? 'design-system.json') as string);\n if (!existsSync(path)) fail(`config not found: ${path}`);\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf8'));\n } catch (err) {\n fail(`could not parse JSON: ${(err as Error).message}`);\n }\n const result = validate(raw);\n if (result.ok) {\n console.log(`✓ ${path} is valid`);\n return;\n }\n console.error(`✖ ${path} is invalid:`);\n for (const e of result.errors) console.error(` • ${e.path.join('.') || '(root)'}: ${e.message}`);\n process.exit(1);\n}\n\nasync function cmdFavicon(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i' },\n out: { type: 'string', short: 'o', default: 'public' },\n 'low-res': { type: 'string' },\n },\n allowPositionals: false,\n });\n if (!values.input) fail('favicon: --input <svg|png> is required');\n const source = resolve(values.input as string);\n if (!existsSync(source)) fail(`source not found: ${source}`);\n try {\n const written = await generateFavicons({\n source,\n outputDir: values.out as string,\n ...(values['low-res'] ? { lowResSource: resolve(values['low-res'] as string) } : {}),\n });\n console.log(`✓ favicons → ${values.out} (${written.length} files)`);\n } catch (err) {\n fail((err as Error).message);\n }\n}\n\n// Read + parse + validate a design-system.json, or exit with a message.\nfunction loadConfig(path: string): DesignSystem {\n if (!existsSync(path)) fail(`config not found: ${path}`);\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf8'));\n } catch (err) {\n fail(`could not parse JSON: ${(err as Error).message}`);\n }\n const result = validate(raw);\n if (!result.ok) {\n console.error(`✖ ${path} is invalid:`);\n for (const e of result.errors)\n console.error(` • ${e.path.join('.') || '(root)'}: ${e.message}`);\n process.exit(1);\n }\n return result.data;\n}\n\n// This CLI's own version (dist/cli.mjs → package-root package.json).\nfunction cliVersion(): string {\n try {\n return (\n JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version ??\n '0.0.0'\n );\n } catch {\n return '0.0.0';\n }\n}\n\n// The framework asset root shipped inside @getvitops/generator (holds the Bricks\n// PHP that generateDocs reads for the element reference).\nfunction generatorAssetsDir(): string {\n const pkg = createRequire(import.meta.url).resolve('@getvitops/generator/package.json');\n return join(dirname(pkg), 'assets');\n}\n\nconst AGENTS_START = '<!-- vitops:start -->';\nconst AGENTS_END = '<!-- vitops:end -->';\n\n/** Print a live reference doc (rendered from the project's config) to stdout. */\nfunction cmdDocs(argv: string[]) {\n const { values, positionals } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i', default: 'design-system.json' },\n all: { type: 'boolean', default: false },\n },\n allowPositionals: true,\n });\n const topic = positionals[0];\n const topicList = () =>\n Object.entries(TOPICS)\n .map(([name, t]) => ` ${name.padEnd(10)} ${t.summary}`)\n .join('\\n');\n if (!topic && !values.all) {\n console.log(\n `vitops docs <topic> — print a live design-system reference to stdout\\n\\nTopics:\\n${topicList()}\\n\\nAlso: vitops docs --all (every topic, concatenated)`,\n );\n return;\n }\n if (topic && !TOPICS[topic]) fail(`unknown topic \"${topic}\". Valid topics:\\n${topicList()}`);\n const ds = loadConfig(resolve(values.input as string));\n const docs = generateDocs(ds, generatorAssetsDir());\n const paths = values.all\n ? Object.values(TOPICS).map((t) => t.path)\n : [TOPICS[topic as string]!.path];\n process.stdout.write(paths.map((p) => docs[p]).join('\\n'));\n}\n\nfunction cmdAgents(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i', default: 'design-system.json' },\n out: { type: 'string', short: 'o', default: 'AGENTS.md' },\n 'docs-dir': { type: 'string' },\n },\n allowPositionals: false,\n });\n const inputRel = values.input as string;\n // The command is pure wiring: validate the config when present (fail on an\n // invalid one), but don't require it — docs are rendered live by `vitops docs`.\n let ds: DesignSystem | null = null;\n if (existsSync(resolve(inputRel))) ds = loadConfig(resolve(inputRel));\n else console.warn(` ⚠ ${inputRel} not found — run \\`vitops init\\` to scaffold one`);\n\n // Explicit --docs-dir = legacy layout: write the docs bundle as files, no skill.\n const legacyDocsDir = values['docs-dir'] as string | undefined;\n let summary: string;\n let pointer: string[];\n\n if (legacyDocsDir) {\n if (!ds) fail(`--docs-dir needs a config to render docs from (${inputRel} not found)`);\n let docs: Record<string, string> = {};\n try {\n docs = generateDocs(ds, generatorAssetsDir());\n } catch (err) {\n fail(`could not generate docs: ${(err as Error).message}`);\n }\n for (const [rel, content] of Object.entries(docs)) {\n const p = resolve(legacyDocsDir, rel);\n mkdirSync(dirname(p), { recursive: true });\n writeFileSync(p, content);\n }\n summary = `wrote ${Object.keys(docs).length} docs to ${legacyDocsDir}/`;\n pointer = [\n 'Prefer the framework’s utility + component classes over hand-written CSS.',\n `Reference docs (regenerate with \\`vitops agents --docs-dir ${legacyDocsDir}\\`): \\`${legacyDocsDir}/css/classes.md\\`,`,\n `\\`${legacyDocsDir}/authoring.md\\`, \\`${legacyDocsDir}/formats.md\\`, \\`${legacyDocsDir}/bricks/elements.md\\`.`,\n ];\n } else {\n // Link the packaged skill (ships inside @getvitops/cli) into the agent\n // discovery locations; nothing is generated into the repo.\n const target = findSkillTarget(process.cwd());\n if (target) {\n for (const dir of ['.agents', '.claude']) {\n const warn = linkSkill(resolve(dir, 'skills', SKILL_NAME), target);\n if (warn) console.warn(` ⚠ ${warn}`);\n }\n summary = `linked {.agents,.claude}/skills/${SKILL_NAME} → ${target}`;\n } else {\n console.warn(\n ` ⚠ could not find node_modules/@getvitops/cli/skill — install @getvitops/cli as a devDependency, then re-run \\`vitops agents\\``,\n );\n summary = 'no skill linked';\n }\n pointer = [\n 'Prefer the framework’s utility + component classes over hand-written CSS.',\n `Full design-system context lives in the \\`${SKILL_NAME}\\` skill (linked from`,\n '`.agents/skills/` and `.claude/skills/` into the installed `@getvitops/cli`;',\n 're-link with `vitops agents` if the links are deleted — they survive version',\n 'bumps). Reference docs print live, from this project’s config, via:',\n '',\n ...Object.entries(TOPICS).map(([name, t]) => `- \\`vitops docs ${name}\\` — ${t.summary}`),\n ];\n }\n\n const block = [\n AGENTS_START,\n '## Vitops design system',\n '',\n `Styled with the Vitops design system (\\`@getvitops/*\\`); tokens live in \\`${inputRel}\\`.`,\n 'Generate output with the CLI:',\n '',\n '- `vitops generate --format tailwind --out src/styles` — Tailwind v4 / Astro',\n '- `vitops generate --format css --out dist` — standalone CSS',\n '- `vitops generate --format bricks --out <theme>/dist` — WordPress / Bricks',\n '- `vitops init` · `vitops validate` · `vitops favicon`',\n '',\n ...pointer,\n '',\n `<!-- regenerate: vitops agents · @getvitops/cli@${cliVersion()} -->`,\n AGENTS_END,\n ].join('\\n');\n\n const outPath = resolve(values.out as string);\n let next: string;\n let action: string;\n if (existsSync(outPath)) {\n const cur = readFileSync(outPath, 'utf8');\n const s = cur.indexOf(AGENTS_START);\n const e = cur.indexOf(AGENTS_END);\n if (s !== -1 && e !== -1 && e > s) {\n next = cur.slice(0, s) + block + cur.slice(e + AGENTS_END.length);\n action = 'updated block in';\n } else {\n next = cur.replace(/\\s*$/, '') + '\\n\\n' + block + '\\n';\n action = 'appended block to';\n }\n } else {\n mkdirSync(dirname(outPath), { recursive: true });\n next = block + '\\n';\n action = 'created';\n }\n writeFileSync(outPath, next);\n console.log(`✓ ${action} ${values.out} + ${summary}`);\n}\n\nasync function main() {\n const [command, ...rest] = process.argv.slice(2);\n if (!command || command === '-h' || command === '--help' || command === 'help') {\n console.log(HELP);\n return;\n }\n switch (command) {\n case 'generate':\n return cmdGenerate(rest);\n case 'init':\n return cmdInit(rest);\n case 'validate':\n return cmdValidate(rest);\n case 'favicon':\n return cmdFavicon(rest);\n case 'agents':\n return cmdAgents(rest);\n case 'docs':\n return cmdDocs(rest);\n default:\n fail(\n `unknown command \"${command}\" (expected: generate | init | validate | favicon | agents | docs). Try: vitops --help`,\n );\n }\n}\n\nmain().catch((err) => fail((err as Error).message));\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getvitops/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "CLI for the Vitops design-system generator: generate, init, and validate a design-system.json.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
7
7
|
"vitops": "./dist/cli.mjs"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"dist"
|
|
10
|
+
"dist",
|
|
11
|
+
"skill",
|
|
12
|
+
"CHANGELOG.md"
|
|
11
13
|
],
|
|
12
14
|
"type": "module",
|
|
13
15
|
"exports": {
|
|
@@ -20,7 +22,10 @@
|
|
|
20
22
|
"access": "public"
|
|
21
23
|
},
|
|
22
24
|
"dependencies": {
|
|
23
|
-
"@getvitops/
|
|
24
|
-
"@getvitops/
|
|
25
|
+
"@getvitops/generator": "0.7.0",
|
|
26
|
+
"@getvitops/utils": "0.7.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"vitest": "^4.1.9"
|
|
25
30
|
}
|
|
26
31
|
}
|
package/skill/SKILL.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vitops-design-system
|
|
3
|
+
description: >-
|
|
4
|
+
Work with this project's Vitops design system. Use when styling or authoring
|
|
5
|
+
pages or components (choosing utility/pattern classes, colours, spacing,
|
|
6
|
+
typography), when editing design-system.json (tokens, palette, patterns,
|
|
7
|
+
scales, animations), when generating output (vitops generate --format
|
|
8
|
+
tailwind|css|bricks), or when asking what the design system provides on a
|
|
9
|
+
given platform (Tailwind vs Bricks vs standalone CSS).
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Vitops design system
|
|
13
|
+
|
|
14
|
+
This project is styled with the Vitops design system (`@getvitops/*`): a variable-driven
|
|
15
|
+
CSS framework generated from `design-system.json` (the single source of truth — semantic
|
|
16
|
+
colour roles, fluid type/space scales, component patterns, animation effects).
|
|
17
|
+
|
|
18
|
+
**Core rule:** prefer the framework's utility + component classes over hand-written CSS or
|
|
19
|
+
ad-hoc values — they encode the tokens, respond to dark mode, and update with the system.
|
|
20
|
+
|
|
21
|
+
## Getting the current reference docs
|
|
22
|
+
|
|
23
|
+
Run **`vitops docs <topic>`** — it prints the reference as markdown to stdout, generated
|
|
24
|
+
live from this project's `design-system.json` and the installed package version, so it is
|
|
25
|
+
never stale and always names the project's actual tokens. (If `vitops` isn't on PATH, use
|
|
26
|
+
`pnpm exec vitops docs <topic>` or `npx vitops docs <topic>`.)
|
|
27
|
+
|
|
28
|
+
| Run | When you need |
|
|
29
|
+
| ----------------------- | ---------------------------------------------------------------------- |
|
|
30
|
+
| `vitops docs classes` | which class to apply — the full class vocabulary as naming rules |
|
|
31
|
+
| `vitops docs authoring` | what a `design-system.json` field means / what's valid |
|
|
32
|
+
| `vitops docs formats` | tailwind vs css vs bricks output — incl. which utilities Tailwind owns |
|
|
33
|
+
| `vitops docs color` | how the colour system works (seeded OKLCH scales, roles, dark mode) |
|
|
34
|
+
| `vitops docs scales` | how the fluid type/space scales work |
|
|
35
|
+
| `vitops docs patterns` | how pattern CSS is assembled (token cascade, override hooks, states) |
|
|
36
|
+
| `vitops docs elements` | the custom Bricks Builder elements and their controls |
|
|
37
|
+
|
|
38
|
+
`vitops docs` (no topic) lists the topics; `vitops docs --all` prints everything.
|
|
39
|
+
|
|
40
|
+
## Other commands
|
|
41
|
+
|
|
42
|
+
- `vitops generate --format <tailwind|css|bricks>` — generate the platform output.
|
|
43
|
+
- `vitops init` / `vitops validate` — scaffold / check a `design-system.json`.
|
|
44
|
+
- `vitops agents` — (re-)link this skill into `.agents/skills/` + `.claude/skills/` and
|
|
45
|
+
refresh the AGENTS.md pointer block. The links point into the installed package and
|
|
46
|
+
survive version bumps; re-run only if they were deleted.
|