@parity-app/cli 0.0.0-stage → 0.1.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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +64 -2
  3. package/dist/bin.mjs +831 -0
  4. package/dist/client-DsTLQ2lT.mjs +286 -0
  5. package/dist/in-app.json +10 -0
  6. package/dist/index.d.mts +160 -0
  7. package/dist/index.mjs +1 -0
  8. package/dist/libraries/aria.lib.par +14516 -0
  9. package/dist/libraries/baseui.lib.par +8298 -0
  10. package/dist/libraries/buildkit-baseui.edits.json +3 -0
  11. package/dist/libraries/chakra.lib.par +539225 -0
  12. package/dist/libraries/fluent-icons.lib.par +2674 -0
  13. package/dist/libraries/fluent.lib.par +33703 -0
  14. package/dist/libraries/heroicons.lib.par +33 -0
  15. package/dist/libraries/hugeicons.lib.par +708 -0
  16. package/dist/libraries/lucide.lib.par +2123 -0
  17. package/dist/libraries/luma.lib.par +16362 -0
  18. package/dist/libraries/lyra.lib.par +16362 -0
  19. package/dist/libraries/maia.lib.par +16362 -0
  20. package/dist/libraries/mantine.lib.par +32935 -0
  21. package/dist/libraries/mira.lib.par +16362 -0
  22. package/dist/libraries/mui.lib.par +9817 -0
  23. package/dist/libraries/nova.lib.par +16363 -0
  24. package/dist/libraries/phosphor.lib.par +3060 -0
  25. package/dist/libraries/radix.lib.par +6890 -0
  26. package/dist/libraries/recharts.lib.par +5445 -0
  27. package/dist/libraries/rhea.lib.par +16362 -0
  28. package/dist/libraries/sera.lib.par +16362 -0
  29. package/dist/libraries/tabler.lib.par +5325 -0
  30. package/dist/libraries/vega.lib.par +16362 -0
  31. package/dist/published-BtL8RM6W.mjs +1 -0
  32. package/dist/published-CdXoUgfD.mjs +200 -0
  33. package/dist/src-8MhDV_sA.mjs +4780 -0
  34. package/dist/src-D9EMN48r.mjs +1306 -0
  35. package/dist/src-DXZqtm6z.mjs +53 -0
  36. package/dist/src-DYi23Ypb.mjs +1 -0
  37. package/dist/src-FF8eY6EI.mjs +2 -0
  38. package/package.json +50 -3
  39. package/skills/SKILL.md +96 -0
  40. package/skills/document.md +170 -0
  41. package/skills/execute.md +298 -0
  42. package/skills/guide/checking.md +56 -0
  43. package/skills/guide/components.md +48 -0
  44. package/skills/guide/design-system.md +52 -0
  45. package/skills/guide/mobile.md +32 -0
  46. package/skills/guide/states-and-modes.md +55 -0
  47. package/skills/guide/web-app.md +43 -0
@@ -0,0 +1,53 @@
1
+ import { p as parseLibraryManifest, u as libraryManifestExtension } from "./src-D9EMN48r.mjs";
2
+ import { createRequire } from "node:module";
3
+ import { readFile, readdir } from "node:fs/promises";
4
+ import { dirname, join } from "node:path";
5
+ import { existsSync } from "node:fs";
6
+ import semver from "semver";
7
+ // ../registry/src/index.ts
8
+ const require = createRequire(import.meta.url);
9
+ /**
10
+ * The folder the registry's files are in. The published CLI bundles this module and ships the files beside it, where
11
+ * the package can't be resolved. Otherwise they're found through the package's own `package.json`, so it's the same
12
+ * whether this module runs from source or bundled into the app.
13
+ */
14
+ function registryDir() {
15
+ const bundled = join(import.meta.dirname, "libraries");
16
+ if (existsSync(bundled)) return bundled;
17
+ return join(dirname(require.resolve("@parity-app/registry/package.json")), "libraries");
18
+ }
19
+ let cache;
20
+ /** Every file in the registry, read once. One that doesn't parse is skipped with a warning. */
21
+ function registryEntries(dir = registryDir()) {
22
+ if (dir !== registryDir()) return readEntries(dir);
23
+ cache ??= readEntries(dir);
24
+ return cache;
25
+ }
26
+ async function readEntries(dir) {
27
+ const files = (await readdir(dir).catch(() => [])).filter((file) => file.endsWith(libraryManifestExtension)).sort();
28
+ const entries = [];
29
+ for (const file of files) {
30
+ const path = join(dir, file);
31
+ try {
32
+ const manifest = parseLibraryManifest(JSON.parse(await readFile(path, "utf8")));
33
+ if (!manifest.package) throw new TypeError("/package: a registry file names the package it describes");
34
+ entries.push({
35
+ file,
36
+ path,
37
+ manifest
38
+ });
39
+ } catch (error) {
40
+ console.warn(`Skipping registry file ${file}: ${error instanceof Error ? error.message : String(error)}`);
41
+ }
42
+ }
43
+ return entries;
44
+ }
45
+ /** Whether a manifest describes this version of its package. A manifest without a range covers every version. */
46
+ function covers(manifest, version) {
47
+ const range = manifest.package?.range;
48
+ if (!range) return true;
49
+ if (!version) return false;
50
+ const parsed = semver.coerce(version, { includePrerelease: true });
51
+ return parsed !== null && semver.satisfies(parsed, range, { includePrerelease: true });
52
+ }
53
+ export { registryDir as n, registryEntries as r, covers as t };
@@ -0,0 +1 @@
1
+ export { t as covers, n as registryDir, r as registryEntries } from "./src-DXZqtm6z.mjs";
@@ -0,0 +1,2 @@
1
+ export { a as applyLibraryEdits, t as componentNode, y as generateId, n as librarySource, f as parseLibraryEdits, i as withLibraryContext } from "./src-D9EMN48r.mjs";
2
+ import "./src-8MhDV_sA.mjs";
package/package.json CHANGED
@@ -1,6 +1,53 @@
1
1
  {
2
2
  "name": "@parity-app/cli",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "description": "Drive the Parity app from a terminal or an agent: read state, run edits, take screenshots, serve MCP.",
7
+ "keywords": [
8
+ "parity",
9
+ "design",
10
+ "components",
11
+ "mcp",
12
+ "cli"
13
+ ],
14
+ "homepage": "https://github.com/betterapps-hq/parity/tree/main/packages/cli",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/betterapps-hq/parity.git",
18
+ "directory": "packages/cli"
19
+ },
20
+ "bugs": "https://github.com/betterapps-hq/parity/issues",
21
+ "engines": {
22
+ "node": ">=24"
23
+ },
24
+ "bin": {
25
+ "parity": "./dist/bin.mjs"
26
+ },
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.mts",
30
+ "default": "./dist/index.mjs"
31
+ }
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "skills"
36
+ ],
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "dependencies": {
41
+ "semver": "^7.8.5",
42
+ "typescript": "6.0.3"
43
+ },
44
+ "devDependencies": {
45
+ "@parity-app/core": "0.0.0",
46
+ "@parity-app/libgen": "0.0.0",
47
+ "@parity-app/registry": "0.0.0"
48
+ },
49
+ "scripts": {
50
+ "build": "vp pack",
51
+ "try-packed": "node scripts/try-packed.ts"
52
+ }
6
53
  }
@@ -0,0 +1,96 @@
1
+ # Parity
2
+
3
+ Parity is a design canvas that draws a project's real components, from its own source, styled only with its own tokens.
4
+ A design here isn't a picture of the app: every button, card and table on the canvas is the project's component,
5
+ rendered by its builder. What you design is what the code can build, and the files are the source of truth.
6
+
7
+ Read this file first. Read `execute.md` and `document.md` before your first change; read a guide when the task calls for
8
+ it.
9
+
10
+ ## Files
11
+
12
+ | Read | When |
13
+ | --------------------------- | -------------------------------------------------------------------------------------- |
14
+ | `execute.md` | Before any change: the functions a snippet can call, with examples. Required. |
15
+ | `document.md` | Before any change: designs, nodes, styles, states and responsive patches. Required. |
16
+ | `guide/components.md` | Using the project's components, making component designs, instances and params, icons. |
17
+ | `guide/states-and-modes.md` | Loading, empty, error and other states; themes, viewports and locales. |
18
+ | `guide/checking.md` | Screenshots, layout problems, accessibility, the console, and trying a design. |
19
+ | `guide/design-system.md` | Composing screens from the project's components and tokens. |
20
+ | `guide/web-app.md` | Designing web app screens: dashboards, settings, lists, forms. |
21
+ | `guide/mobile.md` | Designing for phones and small viewports. |
22
+
23
+ ## Tools
24
+
25
+ The same tools are MCP tools and `parity` commands in a terminal. They act on a tab, which is one open project; the
26
+ active tab is the default.
27
+
28
+ | MCP | CLI | What it does |
29
+ | --------------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
30
+ | `get_app_state` | `parity state` | Designs, the selection, modes, components and token names, and what Parity detected (builder and config, package manager, installed versions). Start here. |
31
+ | `execute` | `parity exec` | Runs a JavaScript snippet against the designs. All changes land as one undo step. |
32
+ | `screenshot` | `parity screenshot <design>` | Renders a design in its states and modes, offscreen, and returns the images. |
33
+ | `find_problems` | `parity problems <design>` | Render errors, overflow, clipping and unknown components, per frame. |
34
+ | `check_accessibility` | `parity a11y <design>` | axe-core against WCAG 2.2 AA, per frame, on the layers that break each rule. |
35
+ | `get_console` | `parity console` | What the project's own code wrote to the console, on the canvas and offscreen. |
36
+ | `get_tabs` | `parity tabs` | The open projects. |
37
+ | `open_project` | `parity open <folder>` | Opens a project in a new tab. |
38
+ | `read_skill` | `parity skill [file]` | This skill. |
39
+
40
+ In a terminal, `parity tokens`, `parity components` and `parity props <Component>` read what designs can use without
41
+ writing a snippet. `parity components` also says which of the app's exports aren't components and why, which components
42
+ fail to draw on the canvas and why (often a missing provider, which a decorator adds), and what the person listed or
43
+ took off the list by hand.
44
+
45
+ When a library's components, tokens or icons don't show, `parity lib <package> --root <project>` describes the package
46
+ in a `.lib.par`: its components, tokens and the providers its frames need. It writes `./<id>.lib.par` in the current
47
+ folder, or prints with `--out -`. With no package it describes the app at `--root` into the `.lib.par` at its root,
48
+ keeping the designs there, so ask before running that in someone's project.
49
+
50
+ ## How to work
51
+
52
+ 1. **Get your bearings.** Call `get_app_state`. Note the designs, which one is selected (the person usually means that
53
+ one), the modes, and the components. Designs, states and nodes have ids; use them.
54
+ 2. **Look before you change.** Read the design with `Get("design-id", { depth: 3 })` in `execute`, and take a screenshot
55
+ of what's there. Find the components you need with `Components()` and their props with `Props()`.
56
+ 3. **Change it in one snippet.** Build or edit the design with `Insert`, `Update`, `Replace`, `Move` and the rest. A
57
+ snippet either applies whole, as one step the person can undo, or changes nothing. Name the layouts you make.
58
+ 4. **Cover every state.** A screen that loads has a loading state, a list has an empty one, a form has an error one. Add
59
+ them with `AddState`, as changes to the base design, not as copies.
60
+ 5. **Check every frame.** Screenshot the design in all its states and the modes it shows (`state: "all"`,
61
+ `mode: "shown"`). Run `find_problems` and `check_accessibility` too, and read the warnings `execute` returns: they're
62
+ usually a token that doesn't exist or a prop the component doesn't take. Fix what you find, then check again.
63
+ 6. **Say what you did.** Tell the person what changed and what you couldn't verify. Ask them to try anything interactive
64
+ themselves with the Interact tool (I), which hands their mouse and keyboard to the real components.
65
+
66
+ Your changes to designs are on the canvas but not saved: the person saves (Ctrl+S) or undoes them, as with their own
67
+ edits. Don't say they're saved. Token values from `SetTokens` are the same: they show at once, and go into the project's
68
+ stylesheet when the person saves.
69
+
70
+ ## Rules
71
+
72
+ - **Use the project's components.** `Components()` lists them; library components are namespaced, as in `nova/Button`,
73
+ and icons too, as in `lucide/Heart`. A name that isn't in the list renders as a placeholder. Don't rebuild a button,
74
+ card or input out of layouts and text when the project has one.
75
+ - **Use the project's tokens.** Colours, radii, shadows, fonts, sizes, leading and tracking name a token, such as
76
+ `muted-foreground`, `radius-lg` or `text-sm`, without the `--`. Lengths are steps of the spacing scale: `4` is four
77
+ spacing units (1rem in a default Tailwind project). `GetTokens()` lists them. Never write a raw colour or pixel value.
78
+ - **Prefer semantic colours** (`background`, `foreground`, `card`, `muted`, `muted-foreground`, `primary`, `border`,
79
+ `destructive`) over palette ones (`color-blue-500`). They change with the theme; palette colours don't.
80
+ - **Layout is auto layout.** A `layout` node is a flex box (or a grid with `display: "grid"`); children fill, hug or
81
+ take a fixed length. Avoid absolute positioning unless something truly overlaps, such as a badge on an avatar.
82
+ - **One design, every viewport.** Don't copy a screen for mobile. Patch it with `Responsive(node, "mobile", patch)`:
83
+ hide the sidebar, stack the columns, shrink the padding.
84
+ - **Real content.** Write the words the screen would show: names, numbers, dates and messages that fit the product.
85
+ Lorem ipsum hides layout problems.
86
+ - **Reuse what repeats.** When a row, card or list item appears more than twice, make it a component design with
87
+ `ExtractComponent`, so each copy is an instance with its own content.
88
+ - **Leave the canvas tidy.** New designs go into empty space (`FindEmptySpace`); `Overlaps()` tells you if boards
89
+ collide.
90
+
91
+ ## When something fails
92
+
93
+ `execute` returns an `editId` when a snippet throws, and nothing changes. Fix it with `editId` and `edits` (exact find
94
+ and replace on the snippet) instead of sending it all again. The error names the line. Common causes: a node path that
95
+ matches two designs (write it as `design/node`), a node property that doesn't exist, and a state change to something
96
+ states can't change (only `hidden`, `text`, `props` and `style`).
@@ -0,0 +1,170 @@
1
+ # Designs and nodes
2
+
3
+ A project's designs live in `.par` files at its root, as JSON. You change them through `execute`, which validates every
4
+ change, so you never edit the files by hand. This is the shape `GetDesign` and `Get` return and `Insert` takes.
5
+
6
+ ## Designs
7
+
8
+ A design is a screen or a component, drawn on the canvas as a board of frames: one frame per state and mode it shows.
9
+
10
+ | Field | What it is |
11
+ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
12
+ | `id` | Made from the name when the design is created. Stable; use it in paths. |
13
+ | `name` | What people see. |
14
+ | `kind` | `screen` (a page or view) or `component` (a reusable part that screens place as instances). |
15
+ | `root` | The design itself: one node, usually a layout. |
16
+ | `states` | Situations the whole design can be in, like loading or empty. The first is the base; the others store only what they change. |
17
+ | `params` | A component design's inputs, each with a `type` (`text`, `boolean`, `number`, `value`, `variant`) and a `default`. See Params and bindings. |
18
+ | `frames` | A fixed size per viewport, when the design isn't as wide as the viewport or as tall as its content. |
19
+ | `view` | How the canvas shows it: the main mode, the modes beside it, the state and the variant options shown. Not part of the design. |
20
+ | `context` | Components a component design is drawn inside on its own board, such as a table around a table row. |
21
+
22
+ ## Nodes
23
+
24
+ Every node has an `id` (given when it's inserted), and can have a `name`, `hidden`, `style` and `responsive`. Name the
25
+ layouts that group things ("Header", "Stats", "Actions"): the layers panel, state changes and paths all read better.
26
+
27
+ ### `layout`
28
+
29
+ A box that lays out its `children`: a flex box by default, or a grid. Most structure is layouts.
30
+
31
+ ```json
32
+ { "type": "layout", "name": "Actions", "style": { "direction": "row", "gap": 2, "justify": "end" }, "children": [] }
33
+ ```
34
+
35
+ ### `component`
36
+
37
+ One of the project's components. `component` is a name from `Components()`; `props` are its props; `slots` hold child
38
+ nodes, where `children` is what goes between its tags and any other slot becomes a prop that takes nodes.
39
+
40
+ ```json
41
+ {
42
+ "type": "component",
43
+ "component": "Button",
44
+ "props": { "variant": "outline", "size": "sm" },
45
+ "slots": {
46
+ "children": [
47
+ { "type": "component", "component": "lucide/Download" },
48
+ { "type": "text", "text": "Export" }
49
+ ]
50
+ }
51
+ }
52
+ ```
53
+
54
+ Text that's only a component's label can be its `children` prop instead: `"props": { "children": "Export" }`.
55
+
56
+ ### `instance`
57
+
58
+ A copy of one of the project's component designs. `design` is the component design's id, `args` give its params values
59
+ (an option's id for a variant), and `state` picks which of its states this copy shows.
60
+
61
+ ```json
62
+ { "type": "instance", "design": "stat-card", "args": { "label": "Active users", "value": "1,284" } }
63
+ ```
64
+
65
+ `overrides` holds what this copy changes inside the component, keyed by the inner node's id, or `nested/inner` for a
66
+ node inside a nested instance. Each is a patch like a state's (`hidden`, `text`, `props`, `style`). Everything the copy
67
+ doesn't override keeps following the component.
68
+
69
+ ```json
70
+ { "type": "instance", "design": "stat-card", "overrides": { "trend": { "hidden": true } } }
71
+ ```
72
+
73
+ A state's patches can reach inside an instance the same way, keyed `instance/inner`, so one copy can change in one
74
+ state.
75
+
76
+ ### `text`
77
+
78
+ Words. `tag` is `p` (the default), `span`, `h1` to `h4` or `strong`, and sets what the text is, not how it looks; size
79
+ and weight come from `style`.
80
+
81
+ ```json
82
+ { "type": "text", "tag": "h2", "text": "Recent activity", "style": { "size": "text-lg", "weight": 600 } }
83
+ ```
84
+
85
+ ### `image`
86
+
87
+ A picture: `src` is a path the project serves (`/images/team.jpg`) or a URL; `alt` describes it, or is empty when it's
88
+ decoration; `fit` is `cover` (the default), `contain` or `fill`; `credit` names its maker when a photo asks for it.
89
+
90
+ ## Style
91
+
92
+ Every value comes from the project. Lengths are steps of the spacing scale or the name of a length token; colours and
93
+ type name a token from `GetTokens()`, without the `--`.
94
+
95
+ | Key | Takes |
96
+ | ------------------------------------------------ | ------------------------------------------------------------------------- |
97
+ | `display` | `flex` (the default) or `grid` |
98
+ | `direction` | `column` (the default) or `row` |
99
+ | `columns`, `rows` | A grid's column or row count; all the same size |
100
+ | `gap`, `rowGap` | A length |
101
+ | `padding`, `margin` | A length, `[vertical, horizontal]` or `[top, right, bottom, left]` |
102
+ | `align` | Children across: `start`, `center`, `end`, `stretch` |
103
+ | `justify` | Children along: `start`, `center`, `end`, `between`, `around`, `evenly` |
104
+ | `wrap` | `true` to wrap a row |
105
+ | `width`, `height` | A length, `fill` (take the room the parent gives) or `hug` (fit content) |
106
+ | `minWidth`, `maxWidth`, `minHeight`, `maxHeight` | A length |
107
+ | `grow` | `true` to fill along the parent's direction |
108
+ | `self` | This node across its parent, overriding the parent's `align` |
109
+ | `colSpan`, `rowSpan` | Grid cells to span |
110
+ | `position`, `top`, `right`, `bottom`, `left` | `absolute`, placed against the parent's edges by lengths |
111
+ | `background`, `foreground`, `border` | A colour token |
112
+ | `borderWidth` | Pixels: 0, 1, 2, 4 or 8 |
113
+ | `borderStyle` | `solid`, `dashed` or `dotted` |
114
+ | `radius`, `shadow` | A radius or shadow token, such as `radius-lg` or `shadow-sm` |
115
+ | `opacity` | Percent, 0 to 100 |
116
+ | `overflow` | `visible`, `hidden` or `scroll` |
117
+ | `font`, `size`, `leading`, `tracking` | A token, such as `font-mono`, `text-sm`, `leading-tight`, `tracking-wide` |
118
+ | `weight` | A number: 400, 500, 600, 700 |
119
+ | `textAlign` | `start`, `center`, `end` or `justify` |
120
+ | `transform`, `decoration`, `italic` | `uppercase` and the like, `underline` or `line-through`, `true` |
121
+ | `lines` | Lines of text before an ellipsis |
122
+
123
+ A text layer sizes as Figma's text does, by its `width` and `height`: `width: "hug"` is auto width, one line as wide as
124
+ its text, wrapped only by a `maxWidth`; any other width, or none, with no `height` is auto height, wrapping at its width
125
+ and growing down; a `height` as well is fixed.
126
+
127
+ Type set on a layout applies to the text inside it. A component's own look comes from its props, so reach for a variant
128
+ (`variant: "secondary"`) before styling a component from outside.
129
+
130
+ ## States
131
+
132
+ A state's `overrides` map node ids to patches of `hidden`, `text`, `props` and `style`. A node a state doesn't mention
133
+ looks as it does in the base. States win over responsive patches.
134
+
135
+ ## Responsive
136
+
137
+ A node's `responsive` maps a viewport option's id (such as `tablet` or `mobile`) to a patch of the same four things,
138
+ applied in every mode on that viewport:
139
+
140
+ ```json
141
+ { "name": "Sidebar", "type": "instance", "design": "app-sidebar", "responsive": { "mobile": { "hidden": true } } }
142
+ ```
143
+
144
+ ## Params and bindings
145
+
146
+ Inside a component design, a node's `bind` takes its values from the component's params, so each instance shows its own:
147
+ `bind.text` names a text param, `bind.props` maps a prop to a param, and `bind.visible` names a boolean param that shows
148
+ or hides the node. `ExtractComponent` sets all of this up from the occurrences it replaces.
149
+
150
+ ```json
151
+ { "type": "text", "text": "Revenue", "bind": { "text": "label" } }
152
+ ```
153
+
154
+ A **variant** is a param whose `options` each patch the component design, the way a state does: a size or a tone the
155
+ instance chooses. Its `default` is an option's id, else the first option. An instance picks one in its `args`, and
156
+ `view.variants` picks which one the component's own board shows. Patches apply in this order: the viewport's, the
157
+ variant options', the state's, then the instance's overrides.
158
+
159
+ ```json
160
+ "params": {
161
+ "size": {
162
+ "type": "variant",
163
+ "default": "medium",
164
+ "options": [
165
+ { "id": "medium", "name": "Medium" },
166
+ { "id": "small", "name": "Small", "overrides": { "card": { "style": { "padding": 3 } } } }
167
+ ]
168
+ }
169
+ }
170
+ ```