nodality 1.2.5 → 1.2.6
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/API.md +8 -4
- package/README.md +15 -1
- package/bin/install-skill.mjs +160 -0
- package/bin/nodality.js +12 -0
- package/dist/animator.cjs.js.LICENSE.txt +1 -1
- package/dist/animator.esm.js.LICENSE.txt +1 -1
- package/dist/audionew.cjs.js.LICENSE.txt +1 -1
- package/dist/audionew.esm.js.LICENSE.txt +1 -1
- package/dist/base.cjs.js.LICENSE.txt +1 -1
- package/dist/base.esm.js.LICENSE.txt +1 -1
- package/dist/beta-desktop-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/beta-desktop-bar.esm.js.LICENSE.txt +1 -1
- package/dist/beta-mobile-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/beta-mobile-bar.esm.js.LICENSE.txt +1 -1
- package/dist/bundle.umd.js +1 -1
- package/dist/bundle.umd.js.LICENSE.txt +1 -1
- package/dist/button.cjs.js.LICENSE.txt +1 -1
- package/dist/button.esm.js.LICENSE.txt +1 -1
- package/dist/card-getter.cjs.js.LICENSE.txt +1 -1
- package/dist/card-getter.esm.js.LICENSE.txt +1 -1
- package/dist/center.cjs.js.LICENSE.txt +1 -1
- package/dist/center.esm.js.LICENSE.txt +1 -1
- package/dist/checkbox.cjs.js.LICENSE.txt +1 -1
- package/dist/checkbox.esm.js.LICENSE.txt +1 -1
- package/dist/code.cjs.js.LICENSE.txt +1 -1
- package/dist/code.esm.js.LICENSE.txt +1 -1
- package/dist/container.cjs.js.LICENSE.txt +1 -1
- package/dist/container.esm.js.LICENSE.txt +1 -1
- package/dist/data-list.cjs.js.LICENSE.txt +1 -1
- package/dist/data-list.esm.js.LICENSE.txt +1 -1
- package/dist/designer.cjs.js +1 -1
- package/dist/designer.cjs.js.LICENSE.txt +1 -1
- package/dist/designer.esm.js +1 -1
- package/dist/designer.esm.js.LICENSE.txt +1 -1
- package/dist/element-mapper.cjs.js +1 -1
- package/dist/element-mapper.cjs.js.LICENSE.txt +1 -1
- package/dist/element-mapper.esm.js +1 -1
- package/dist/element-mapper.esm.js.LICENSE.txt +1 -1
- package/dist/finalresult.esm.js +1 -1
- package/dist/finalresult.esm.js.LICENSE.txt +1 -1
- package/dist/flex-card.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-card.esm.js.LICENSE.txt +1 -1
- package/dist/flex-grid.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-grid.esm.js.LICENSE.txt +1 -1
- package/dist/flex-row.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-row.esm.js.LICENSE.txt +1 -1
- package/dist/floating-input.cjs.js.LICENSE.txt +1 -1
- package/dist/floating-input.esm.js.LICENSE.txt +1 -1
- package/dist/free.cjs.js.LICENSE.txt +1 -1
- package/dist/free.esm.js.LICENSE.txt +1 -1
- package/dist/horizontal-scroller.cjs.js.LICENSE.txt +1 -1
- package/dist/horizontal-scroller.esm.js.LICENSE.txt +1 -1
- package/dist/image-picker.cjs.js.LICENSE.txt +1 -1
- package/dist/image-picker.esm.js.LICENSE.txt +1 -1
- package/dist/image.cjs.js.LICENSE.txt +1 -1
- package/dist/image.esm.js.LICENSE.txt +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.LICENSE.txt +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.LICENSE.txt +1 -1
- package/dist/keyframe-animation.cjs.js.LICENSE.txt +1 -1
- package/dist/keyframe-animation.esm.js.LICENSE.txt +1 -1
- package/dist/link-getter.cjs.js.LICENSE.txt +1 -1
- package/dist/link-getter.esm.js.LICENSE.txt +1 -1
- package/dist/link.cjs.js.LICENSE.txt +1 -1
- package/dist/link.esm.js.LICENSE.txt +1 -1
- package/dist/meta-adder.cjs.js.LICENSE.txt +1 -1
- package/dist/meta-adder.esm.js.LICENSE.txt +1 -1
- package/dist/modal-2025.cjs.js.LICENSE.txt +1 -1
- package/dist/modal-2025.esm.js.LICENSE.txt +1 -1
- package/dist/multiswitcher.cjs.js.LICENSE.txt +1 -1
- package/dist/multiswitcher.esm.js.LICENSE.txt +1 -1
- package/dist/new-nav-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/new-nav-bar.esm.js.LICENSE.txt +1 -1
- package/dist/picker.cjs.js.LICENSE.txt +1 -1
- package/dist/picker.esm.js.LICENSE.txt +1 -1
- package/dist/progress.cjs.js.LICENSE.txt +1 -1
- package/dist/progress.esm.js.LICENSE.txt +1 -1
- package/dist/radio.cjs.js.LICENSE.txt +1 -1
- package/dist/radio.esm.js.LICENSE.txt +1 -1
- package/dist/range.cjs.js.LICENSE.txt +1 -1
- package/dist/range.esm.js.LICENSE.txt +1 -1
- package/dist/scroll-video.cjs.js.LICENSE.txt +1 -1
- package/dist/scroll-video.esm.js.LICENSE.txt +1 -1
- package/dist/side-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/side-bar.esm.js.LICENSE.txt +1 -1
- package/dist/side-nav-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/side-nav-bar.esm.js.LICENSE.txt +1 -1
- package/dist/simple-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/simple-bar.esm.js.LICENSE.txt +1 -1
- package/dist/slider-2025.cjs.js.LICENSE.txt +1 -1
- package/dist/slider-2025.esm.js.LICENSE.txt +1 -1
- package/dist/spacer.cjs.js.LICENSE.txt +1 -1
- package/dist/spacer.esm.js.LICENSE.txt +1 -1
- package/dist/stack.cjs.js.LICENSE.txt +1 -1
- package/dist/stack.esm.js.LICENSE.txt +1 -1
- package/dist/stacker.cjs.js.LICENSE.txt +1 -1
- package/dist/stacker.esm.js.LICENSE.txt +1 -1
- package/dist/table.cjs.js.LICENSE.txt +1 -1
- package/dist/table.esm.js.LICENSE.txt +1 -1
- package/dist/text-field.cjs.js.LICENSE.txt +1 -1
- package/dist/text-field.esm.js.LICENSE.txt +1 -1
- package/dist/text.cjs.js.LICENSE.txt +1 -1
- package/dist/text.esm.js.LICENSE.txt +1 -1
- package/dist/theme.cjs.js.LICENSE.txt +1 -1
- package/dist/theme.esm.js.LICENSE.txt +1 -1
- package/dist/transform-anim.cjs.js.LICENSE.txt +1 -1
- package/dist/transform-anim.esm.js.LICENSE.txt +1 -1
- package/dist/ulist.cjs.js.LICENSE.txt +1 -1
- package/dist/ulist.esm.js.LICENSE.txt +1 -1
- package/dist/video.cjs.js.LICENSE.txt +1 -1
- package/dist/video.esm.js.LICENSE.txt +1 -1
- package/dist/wrap.cjs.js.LICENSE.txt +1 -1
- package/dist/wrap.esm.js.LICENSE.txt +1 -1
- package/dist/zoom-card.cjs.js.LICENSE.txt +1 -1
- package/dist/zoom-card.esm.js.LICENSE.txt +1 -1
- package/layout/animator.js +1 -1
- package/layout/audio.js +1 -1
- package/layout/audionew.js +1 -1
- package/layout/base.js +1 -1
- package/layout/beta-desktop-bar.js +1 -1
- package/layout/beta-mobile-bar.js +1 -1
- package/layout/button.js +1 -1
- package/layout/center.js +1 -1
- package/layout/checkbox.js +1 -1
- package/layout/circle.js +1 -1
- package/layout/code.js +1 -1
- package/layout/container.js +1 -1
- package/layout/dropdown-2025.js +1 -1
- package/layout/flex-card.js +1 -1
- package/layout/flex-grid.js +1 -1
- package/layout/flex-row.js +1 -1
- package/layout/form-components/custom.js +1 -1
- package/layout/form-components/data-list.js +1 -1
- package/layout/form-components/floating-input.js +1 -1
- package/layout/form-components/form-all.js +1 -1
- package/layout/form-components/form.js +1 -1
- package/layout/form-components/image-picker.js +1 -1
- package/layout/form-components/picker.js +1 -1
- package/layout/form-components/radio.js +1 -1
- package/layout/form-components/radiogroup.js +1 -1
- package/layout/form-components/range.js +1 -1
- package/layout/free.js +1 -1
- package/layout/grid-switcher.js +1 -1
- package/layout/grid.js +1 -1
- package/layout/horizontal-scroller.js +1 -1
- package/layout/image.js +1 -1
- package/layout/index.js +1 -1
- package/layout/link.js +1 -1
- package/layout/list.js +1 -1
- package/layout/meta-adder.js +1 -1
- package/layout/modal-2025.js +1 -1
- package/layout/morph.js +1 -1
- package/layout/multiswitcher.js +1 -1
- package/layout/nav-bar.js +1 -1
- package/layout/nav-factor/custom-div.js +1 -1
- package/layout/new-nav-bar.js +1 -1
- package/layout/polygon.js +1 -1
- package/layout/prerender-site.js +1 -1
- package/layout/prerender.js +1 -1
- package/layout/progress.js +1 -1
- package/layout/row.js +1 -1
- package/layout/scroll-video.js +1 -1
- package/layout/side-bar.js +1 -1
- package/layout/side-nav-bar.js +1 -1
- package/layout/simple-bar.js +1 -1
- package/layout/slider-2025.js +1 -1
- package/layout/spacer.js +1 -1
- package/layout/stack.js +1 -1
- package/layout/svg.js +1 -1
- package/layout/switcher.js +1 -1
- package/layout/table.js +1 -1
- package/layout/text-field.js +1 -1
- package/layout/text.js +1 -1
- package/layout/ulist.js +1 -1
- package/layout/video.js +1 -1
- package/layout/wrap.js +1 -1
- package/layout/zoom-card.js +1 -1
- package/lib/agent-surface.js +1 -1
- package/lib/card-getter.js +1 -1
- package/lib/codegen.js +1 -1
- package/lib/data.js +1 -1
- package/lib/designer.js +6 -2
- package/lib/element-mapper.js +5 -5
- package/lib/keyframe-animation.js +1 -1
- package/lib/link-getter.js +1 -1
- package/lib/morph-node.js +1 -1
- package/lib/raster-inspect.js +1 -1
- package/lib/raster-ops.js +1 -1
- package/lib/raster-presets.js +1 -1
- package/lib/scroll-video.js +1 -1
- package/lib/seo.js +1 -1
- package/lib/stacker.js +1 -1
- package/lib/suggest.js +1 -1
- package/lib/theme.js +1 -1
- package/lib/transform-anim.js +1 -1
- package/lib/transition.js +1 -1
- package/lib/validate-nodes.js +1 -1
- package/lib/webmcp-adapter.js +1 -1
- package/package.json +3 -2
- package/skills/nodality/SKILL.md +192 -0
package/API.md
CHANGED
|
@@ -104,9 +104,9 @@ Machine-readable index: https://nodalityjs.github.io/llms.txt
|
|
|
104
104
|
https://nodalityjs.github.io/docs/elements/polygon
|
|
105
105
|
- **Elements** — Elements are used to create UI.
|
|
106
106
|
https://nodalityjs.github.io/docs/elements/readme
|
|
107
|
-
- **Responsive wrapper** — The `Wrapper` class allows you to create a responsive element that can dynamically switch its layout between row and column orientations based on specified
|
|
107
|
+
- **Responsive wrapper** — The `Wrapper` class allows you to create a responsive element that can dynamically switch its layout between row and column orientations based on specified…
|
|
108
108
|
https://nodalityjs.github.io/docs/elements/responsive-wrapper
|
|
109
|
-
- **Complex** — The `Wrapper` class allows you to create a responsive element that can dynamically switch its layout between row and column orientations based on specified
|
|
109
|
+
- **Complex** — The `Wrapper` class allows you to create a responsive element that can dynamically switch its layout between row and column orientations based on specified…
|
|
110
110
|
https://nodalityjs.github.io/docs/elements/responsive
|
|
111
111
|
- **Row** — Row creates a simple element to allow you to organise children in a row.
|
|
112
112
|
https://nodalityjs.github.io/docs/elements/row
|
|
@@ -166,7 +166,7 @@ Machine-readable index: https://nodalityjs.github.io/llms.txt
|
|
|
166
166
|
https://nodalityjs.github.io/docs/guides/testing
|
|
167
167
|
- **Tooling** — Create Nodality package allows you to quickly bootstrap a new Nodality application.
|
|
168
168
|
https://nodalityjs.github.io/docs/guides/tooling
|
|
169
|
-
- **Transitions** — This library supports the **CSS View Transition API** to enable smooth animations when navigating between pages.\
|
|
169
|
+
- **Transitions** — This library supports the **CSS View Transition API** to enable smooth animations when navigating between pages.\ For example, you can build a carousel where…
|
|
170
170
|
https://nodalityjs.github.io/docs/guides/transitions
|
|
171
171
|
|
|
172
172
|
### nodes
|
|
@@ -198,10 +198,14 @@ Machine-readable index: https://nodalityjs.github.io/llms.txt
|
|
|
198
198
|
|
|
199
199
|
### raster
|
|
200
200
|
|
|
201
|
+
- **Agent surface – the page, as tools** — An `agent-surface` node lets an AI agent operate the page: move between morph views, submit a form you have allowed, and read what is on screen.
|
|
202
|
+
https://nodalityjs.github.io/docs/raster/agent-surface
|
|
201
203
|
- **Raster basics** — Raster ops run your element through a WebGL shader.
|
|
202
204
|
https://nodalityjs.github.io/docs/raster/basics
|
|
203
205
|
- **Composing a pipeline** — A chain is not a list of passes.
|
|
204
206
|
https://nodalityjs.github.io/docs/raster/composition
|
|
207
|
+
- **Morph – transitions as nodes** — A morph node describes which element *becomes* which, and on what interaction.
|
|
208
|
+
https://nodalityjs.github.io/docs/raster/morph
|
|
205
209
|
- **Raster ops** — Every node has an `op` and a set of options.
|
|
206
210
|
https://nodalityjs.github.io/docs/raster/ops
|
|
207
211
|
|
|
@@ -209,7 +213,7 @@ Machine-readable index: https://nodalityjs.github.io/llms.txt
|
|
|
209
213
|
|
|
210
214
|
- **Basics** — To create smooth scroll animations you can use the following:
|
|
211
215
|
https://nodalityjs.github.io/docs/scrollanimation/basics
|
|
212
|
-
- **Scroll Animation** — Create engaging scroll animation
|
|
216
|
+
- **Scroll Animation** — Create engaging scroll animation Continue to [Basics](basics.md) to get started.
|
|
213
217
|
https://nodalityjs.github.io/docs/scrollanimation/index
|
|
214
218
|
- **ScrollVideo** — Play video as you scroll.
|
|
215
219
|
https://nodalityjs.github.io/docs/scrollanimation/scrollvideo
|
package/README.md
CHANGED
|
@@ -78,7 +78,8 @@ const elements = [
|
|
|
78
78
|
];
|
|
79
79
|
|
|
80
80
|
const nodes = [
|
|
81
|
-
{ op: { name: "gradient"
|
|
81
|
+
{ op: { name: "gradient", gradient: "linear-gradient(90deg, #1d6fe0, #7fd1ff)" },
|
|
82
|
+
target: ["hero"] },
|
|
82
83
|
{ op: "dither", target: ["hero"], levels: 6, size: 2 },
|
|
83
84
|
];
|
|
84
85
|
|
|
@@ -118,6 +119,19 @@ prerendered HTML as a static manifest.
|
|
|
118
119
|
|
|
119
120
|
## For AI agents
|
|
120
121
|
|
|
122
|
+
One command sets up an agent IDE end to end:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
npx nodality skill
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
It installs the `/nodality` skill – the authoring workflow, the node
|
|
129
|
+
families, and the house rules the schema cannot encode – into Claude
|
|
130
|
+
Code (`.claude/skills/`) and Cursor (`.cursor/rules/`), and registers
|
|
131
|
+
the MCP server below in the project's config. Flags: `--claude`,
|
|
132
|
+
`--cursor`, `--global`, `--dir=<path>` for any other agent, `--no-mcp`.
|
|
133
|
+
Re-run it after upgrading nodality to refresh the skill in place.
|
|
134
|
+
|
|
121
135
|
`nodality mcp` runs a Model Context Protocol server over stdio, so a
|
|
122
136
|
generator writes against the real vocabulary instead of guessing at it:
|
|
123
137
|
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// bin/install-skill.mjs — `npx nodality skill`: install the /nodality
|
|
2
|
+
// skill into agent IDEs, the way `npx motion-ai` does for Motion.
|
|
3
|
+
//
|
|
4
|
+
// Targets:
|
|
5
|
+
// • Claude Code — copies skills/nodality/SKILL.md to
|
|
6
|
+
// <scope>/.claude/skills/nodality/SKILL.md, where scope is the
|
|
7
|
+
// project (cwd) or the home directory (--global).
|
|
8
|
+
// • Cursor — writes .cursor/rules/nodality.mdc (project only: Cursor
|
|
9
|
+
// has no global rules *directory*; global guidance there is a
|
|
10
|
+
// settings field, not a file this installer may write).
|
|
11
|
+
// • Anything else — --dir=<path> copies SKILL.md verbatim wherever a
|
|
12
|
+
// custom agent reads its instructions from.
|
|
13
|
+
//
|
|
14
|
+
// Unless --no-mcp is passed, project installs also register the MCP
|
|
15
|
+
// server (`npx nodality mcp`) in .mcp.json (Claude Code) and
|
|
16
|
+
// .cursor/mcp.json (Cursor), merging into whatever is already there.
|
|
17
|
+
// A global Claude install prints the `claude mcp add` line instead:
|
|
18
|
+
// the global registry lives inside ~/.claude.json alongside unrelated
|
|
19
|
+
// state, and this installer does not edit a file it does not own.
|
|
20
|
+
//
|
|
21
|
+
// Re-running upgrades in place: the skill file is overwritten, the MCP
|
|
22
|
+
// entry re-merged, and each line reports "installed" or "updated".
|
|
23
|
+
|
|
24
|
+
import fs from "node:fs";
|
|
25
|
+
import os from "node:os";
|
|
26
|
+
import path from "node:path";
|
|
27
|
+
import readline from "node:readline";
|
|
28
|
+
import { fileURLToPath } from "node:url";
|
|
29
|
+
|
|
30
|
+
const SKILL_SRC = path.join(
|
|
31
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
32
|
+
"..",
|
|
33
|
+
"skills",
|
|
34
|
+
"nodality",
|
|
35
|
+
"SKILL.md",
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const MCP_ENTRY = { command: "npx", args: ["nodality", "mcp"] };
|
|
39
|
+
|
|
40
|
+
// ─── helpers ────────────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
function log(line) {
|
|
43
|
+
console.log(`[nodality] ${line}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Copy with an installed/updated verdict so re-runs read as upgrades.
|
|
47
|
+
function place(src, dest, content) {
|
|
48
|
+
const existed = fs.existsSync(dest);
|
|
49
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
50
|
+
if (content !== undefined) fs.writeFileSync(dest, content);
|
|
51
|
+
else fs.copyFileSync(src, dest);
|
|
52
|
+
log(`${existed ? "updated " : "installed"} ${dest}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Merge our server into an existing config without touching anything
|
|
56
|
+
// else in it. A file that exists but does not parse is left alone and
|
|
57
|
+
// reported — clobbering a hand-edited config is worse than skipping.
|
|
58
|
+
function registerMcp(configPath) {
|
|
59
|
+
let config = {};
|
|
60
|
+
if (fs.existsSync(configPath)) {
|
|
61
|
+
try {
|
|
62
|
+
config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
63
|
+
} catch {
|
|
64
|
+
log(`SKIPPED ${configPath} — existing file is not valid JSON; add this by hand:`);
|
|
65
|
+
log(` "mcpServers": { "nodality": ${JSON.stringify(MCP_ENTRY)} }`);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const existed = fs.existsSync(configPath);
|
|
70
|
+
config.mcpServers = { ...config.mcpServers, nodality: MCP_ENTRY };
|
|
71
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
72
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
73
|
+
log(`${existed ? "updated " : "installed"} ${configPath} (mcpServers.nodality)`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// The Cursor variant of the skill: same body, Cursor's rule
|
|
77
|
+
// frontmatter. `alwaysApply: false` plus a description makes it an
|
|
78
|
+
// agent-requested rule, matching how the skill triggers in Claude Code.
|
|
79
|
+
function toCursorRule(skillText) {
|
|
80
|
+
const m = skillText.match(/^---\n([\s\S]*?)\n---\n/);
|
|
81
|
+
if (!m) throw new Error(`no frontmatter in ${SKILL_SRC}`);
|
|
82
|
+
const desc = m[1].match(/^description:\s*(.+)$/m);
|
|
83
|
+
if (!desc) throw new Error(`no description in ${SKILL_SRC} frontmatter`);
|
|
84
|
+
const body = skillText.slice(m[0].length);
|
|
85
|
+
return `---\ndescription: ${desc[1]}\nalwaysApply: false\n---\n${body}`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function ask(rl, question, def) {
|
|
89
|
+
return new Promise((resolve) => {
|
|
90
|
+
rl.question(`${question} [${def}] `, (a) => resolve(a.trim() || def));
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ─── entry ──────────────────────────────────────────────────────
|
|
95
|
+
|
|
96
|
+
export async function runSkillInstall(args) {
|
|
97
|
+
if (!fs.existsSync(SKILL_SRC)) {
|
|
98
|
+
console.error(`[nodality] skill source missing: ${SKILL_SRC}`);
|
|
99
|
+
process.exitCode = 1;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const flags = new Set(args.filter((a) => !a.startsWith("--dir=")));
|
|
104
|
+
const dirFlag = args.find((a) => a.startsWith("--dir="));
|
|
105
|
+
let claude = flags.has("--claude");
|
|
106
|
+
let cursor = flags.has("--cursor");
|
|
107
|
+
let global = flags.has("--global");
|
|
108
|
+
const customDir = dirFlag ? dirFlag.slice("--dir=".length) : null;
|
|
109
|
+
const wireMcp = !flags.has("--no-mcp");
|
|
110
|
+
|
|
111
|
+
// Interactive only when the user picked nothing and a human is
|
|
112
|
+
// attached; agents and CI get the full default install silently.
|
|
113
|
+
const chose = claude || cursor || customDir !== null;
|
|
114
|
+
if (!chose && process.stdin.isTTY && !flags.has("--yes")) {
|
|
115
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
116
|
+
const which = await ask(rl, "Install for which agents? (both / claude / cursor)", "both");
|
|
117
|
+
claude = which === "both" || which === "claude";
|
|
118
|
+
cursor = which === "both" || which === "cursor";
|
|
119
|
+
if (claude) {
|
|
120
|
+
const scope = await ask(rl, "Claude Code scope? (project / global)", "project");
|
|
121
|
+
global = scope === "global";
|
|
122
|
+
}
|
|
123
|
+
rl.close();
|
|
124
|
+
} else if (!chose) {
|
|
125
|
+
claude = true;
|
|
126
|
+
cursor = true;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const skillText = fs.readFileSync(SKILL_SRC, "utf8");
|
|
130
|
+
|
|
131
|
+
if (claude) {
|
|
132
|
+
const root = global ? os.homedir() : process.cwd();
|
|
133
|
+
place(SKILL_SRC, path.join(root, ".claude", "skills", "nodality", "SKILL.md"));
|
|
134
|
+
if (wireMcp) {
|
|
135
|
+
if (global) {
|
|
136
|
+
// ~/.claude.json holds per-project state beside the MCP
|
|
137
|
+
// registry; the supported route in is the CLI, so hand it over.
|
|
138
|
+
log("global MCP registration: run this once yourself:");
|
|
139
|
+
log(" claude mcp add nodality -s user -- npx nodality mcp");
|
|
140
|
+
} else {
|
|
141
|
+
registerMcp(path.join(process.cwd(), ".mcp.json"));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (cursor) {
|
|
147
|
+
if (global) {
|
|
148
|
+
log("SKIPPED Cursor — rules are per-project; re-run without --global inside a project.");
|
|
149
|
+
} else {
|
|
150
|
+
place(SKILL_SRC, path.join(process.cwd(), ".cursor", "rules", "nodality.mdc"), toCursorRule(skillText));
|
|
151
|
+
if (wireMcp) registerMcp(path.join(process.cwd(), ".cursor", "mcp.json"));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (customDir) {
|
|
156
|
+
place(SKILL_SRC, path.join(path.resolve(customDir), "SKILL.md"));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
log("done. Re-run this command after upgrading nodality to refresh the skill.");
|
|
160
|
+
}
|
package/bin/nodality.js
CHANGED
|
@@ -55,6 +55,15 @@ function showUsage() {
|
|
|
55
55
|
# { "mcpServers": { "nodality": {
|
|
56
56
|
# "command": "npx",
|
|
57
57
|
# "args": ["nodality", "mcp"] } } }
|
|
58
|
+
nodality skill [flags] # Install the /nodality skill into agent
|
|
59
|
+
# IDEs. No flags: interactive (or full
|
|
60
|
+
# default install when not a TTY).
|
|
61
|
+
# --claude --cursor pick agents
|
|
62
|
+
# --global Claude Code: user-wide
|
|
63
|
+
# (default: this project)
|
|
64
|
+
# --dir=<path> copy SKILL.md anywhere
|
|
65
|
+
# --no-mcp skip MCP registration
|
|
66
|
+
# Re-run after upgrading to refresh in place.
|
|
58
67
|
nodality help
|
|
59
68
|
|
|
60
69
|
Compile flags:
|
|
@@ -863,6 +872,9 @@ async function main() {
|
|
|
863
872
|
await runFanoutStandalone(rest);
|
|
864
873
|
} else if (command === "stage") {
|
|
865
874
|
await runStage(rest);
|
|
875
|
+
} else if (command === "skill") {
|
|
876
|
+
const { runSkillInstall } = await import("./install-skill.mjs");
|
|
877
|
+
await runSkillInstall(rest);
|
|
866
878
|
} else if (command === "mcp") {
|
|
867
879
|
// Lazily imported so that prerender/compile/stage pay nothing for a
|
|
868
880
|
// subcommand they never touch, and so a broken morph core cannot
|