@nucleoicons/skills 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -2
- package/dist/api.d.ts +5 -0
- package/dist/api.js +20 -1
- package/dist/commands/setup.d.ts +2 -0
- package/dist/commands/setup.js +31 -10
- package/dist/commands/status.js +1 -0
- package/dist/commands/update.js +27 -4
- package/dist/config.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/install.js +2 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ CLI to install and update **Nucleo** MCP + icon skills on your machine.
|
|
|
4
4
|
|
|
5
5
|
Once installed, your AI coding tool can help you **use Nucleo icons in code**. Typical uses:
|
|
6
6
|
|
|
7
|
-
- Search icons by name or idea across your
|
|
7
|
+
- Search icons by name or idea across your installed families (Pro and/or free)
|
|
8
8
|
- Pick an icon and get the right React component or SVG for your project
|
|
9
9
|
- Customize icons when inserting them (color, secondary color, stroke width, duo opacity, corners)
|
|
10
10
|
|
|
@@ -14,15 +14,23 @@ Requires **Node.js 20+**.
|
|
|
14
14
|
|
|
15
15
|
## Install
|
|
16
16
|
|
|
17
|
+
**Pro** (Nucleo account — licensed families):
|
|
18
|
+
|
|
17
19
|
```bash
|
|
18
20
|
npx @nucleoicons/skills setup --target react --tools cursor
|
|
19
21
|
```
|
|
20
22
|
|
|
23
|
+
**Free** (no account — glass, arcade, isometric, flags, cursors, social-media, credit-cards):
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx @nucleoicons/skills setup --free --target react --tools cursor
|
|
27
|
+
```
|
|
28
|
+
|
|
21
29
|
**Required for setup:** `--target` (`react` or `vanilla`) and `--tools` (`cursor`, `claude`, `codex`).
|
|
22
30
|
|
|
23
31
|
```bash
|
|
24
32
|
npx @nucleoicons/skills setup --target react --tools cursor
|
|
25
|
-
npx @nucleoicons/skills setup --target vanilla --tools cursor,claude
|
|
33
|
+
npx @nucleoicons/skills setup --free --target vanilla --tools cursor,claude
|
|
26
34
|
```
|
|
27
35
|
|
|
28
36
|
Setup installs the package under your user home (`~/.nucleo/skills`) and configures the editors you choose (skills + MCP, no manual config step).
|
|
@@ -35,6 +43,8 @@ What Nucleo icon families do I have?
|
|
|
35
43
|
|
|
36
44
|
## Update
|
|
37
45
|
|
|
46
|
+
Same command for free and Pro — the CLI remembers which package you installed (`--free` is not needed again):
|
|
47
|
+
|
|
38
48
|
```bash
|
|
39
49
|
npx @nucleoicons/skills update
|
|
40
50
|
```
|
package/dist/api.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export interface SkillsReleaseFile {
|
|
|
27
27
|
export interface SkillsReleaseData {
|
|
28
28
|
version: string;
|
|
29
29
|
target: PackageTarget | string;
|
|
30
|
+
tier?: "free" | "pro" | string;
|
|
30
31
|
families: string[];
|
|
31
32
|
downloadReady: boolean;
|
|
32
33
|
files: SkillsReleaseFile[];
|
|
@@ -47,6 +48,10 @@ export declare function skillsLogin(email: string, password: string): Promise<Sk
|
|
|
47
48
|
* Response: { data: { version, families, files, downloadReady } }
|
|
48
49
|
*/
|
|
49
50
|
export declare function fetchSkillsRelease(token: string, target: PackageTarget): Promise<SkillsReleaseData>;
|
|
51
|
+
/**
|
|
52
|
+
* GET /skills/release-free?target=react|vanilla (no auth)
|
|
53
|
+
*/
|
|
54
|
+
export declare function fetchSkillsFreeRelease(target: PackageTarget): Promise<SkillsReleaseData>;
|
|
50
55
|
declare function formatBytes(bytes: number): string;
|
|
51
56
|
/** Download a remote file (signed R2 URL) to disk, with optional progress. */
|
|
52
57
|
export declare function downloadUrlToFile(url: string, destPath: string, onProgress?: (progress: DownloadProgress) => void): Promise<{
|
package/dist/api.js
CHANGED
|
@@ -83,7 +83,26 @@ export async function fetchSkillsRelease(token, target) {
|
|
|
83
83
|
if (!json.data?.version || !Array.isArray(json.data.files)) {
|
|
84
84
|
throw new ApiError("Release response missing version/files.", res.status, body);
|
|
85
85
|
}
|
|
86
|
-
return json.data;
|
|
86
|
+
return { ...json.data, tier: json.data.tier ?? "pro" };
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* GET /skills/release-free?target=react|vanilla (no auth)
|
|
90
|
+
*/
|
|
91
|
+
export async function fetchSkillsFreeRelease(target) {
|
|
92
|
+
const url = new URL(`${getApiBaseUrl()}/skills/release-free`);
|
|
93
|
+
url.searchParams.set("target", target);
|
|
94
|
+
const res = await fetch(url, {
|
|
95
|
+
headers: { Accept: "application/json" },
|
|
96
|
+
});
|
|
97
|
+
const body = await readErrorBody(res);
|
|
98
|
+
if (!res.ok) {
|
|
99
|
+
throw new ApiError(parseApiErrorMessage(body, `Could not fetch free release (${res.status}).`), res.status, body);
|
|
100
|
+
}
|
|
101
|
+
const json = JSON.parse(body);
|
|
102
|
+
if (!json.data?.version || !Array.isArray(json.data.files)) {
|
|
103
|
+
throw new ApiError("Free release response missing version/files.", res.status, body);
|
|
104
|
+
}
|
|
105
|
+
return { ...json.data, tier: json.data.tier ?? "free" };
|
|
87
106
|
}
|
|
88
107
|
function formatBytes(bytes) {
|
|
89
108
|
if (bytes < 1024) {
|
package/dist/commands/setup.d.ts
CHANGED
package/dist/commands/setup.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { mkdir } from "node:fs/promises";
|
|
2
1
|
import { confirm, select, checkbox } from "@inquirer/prompts";
|
|
3
|
-
import {
|
|
2
|
+
import { mkdir } from "node:fs/promises";
|
|
3
|
+
import { ApiError, fetchSkillsFreeRelease, fetchSkillsRelease } from "../api.js";
|
|
4
4
|
import { installRoot, nucleoHomeDir } from "../config.js";
|
|
5
5
|
import { buildMcp, ensureManifestTarget, installFromLocalDir, installFromRelease, readInstallManifest, } from "../install.js";
|
|
6
6
|
import { configureTool } from "../adapters/agents.js";
|
|
7
7
|
import { ensureSkillsSession, isInvalidTokenError } from "../session.js";
|
|
8
|
-
async function
|
|
8
|
+
async function fetchProReleaseWithSession(target, emailHint) {
|
|
9
9
|
let session = await ensureSkillsSession(emailHint);
|
|
10
10
|
try {
|
|
11
11
|
return await fetchSkillsRelease(session.token, target);
|
|
@@ -20,8 +20,9 @@ async function fetchReleaseWithSession(target, emailHint) {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
export async function runSetup(options = {}) {
|
|
23
|
-
|
|
24
|
-
console.log("
|
|
23
|
+
const free = Boolean(options.free);
|
|
24
|
+
console.log(free ? "\nNucleo Skills setup (free)" : "\nNucleo Skills setup");
|
|
25
|
+
console.log(free ? "─────────────────────────\n" : "───────────────────\n");
|
|
25
26
|
const target = options.target ??
|
|
26
27
|
(await select({
|
|
27
28
|
message: "Which package?",
|
|
@@ -57,13 +58,34 @@ export async function runSetup(options = {}) {
|
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
await installFromLocalDir(options.from);
|
|
60
|
-
await ensureManifestTarget(target
|
|
61
|
+
await ensureManifestTarget(target, {
|
|
62
|
+
tier: free ? "free" : "pro",
|
|
63
|
+
product: free ? "nucleo-skills-free" : "nucleo-skills",
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
else if (free) {
|
|
67
|
+
console.log(`Fetching free ${target} release…`);
|
|
68
|
+
let release;
|
|
69
|
+
try {
|
|
70
|
+
release = await fetchSkillsFreeRelease(target);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (error instanceof ApiError) {
|
|
74
|
+
throw new Error(error.message);
|
|
75
|
+
}
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
console.log(` Version: ${release.version}`);
|
|
79
|
+
console.log(` Families: ${release.families.join(", ")}`);
|
|
80
|
+
console.log(` Files: ${release.files.map((f) => f.id).join(", ")}`);
|
|
81
|
+
console.log("\nDownloading…");
|
|
82
|
+
await installFromRelease(release, target);
|
|
61
83
|
}
|
|
62
84
|
else {
|
|
63
85
|
console.log(`Fetching ${target} release…`);
|
|
64
86
|
let release;
|
|
65
87
|
try {
|
|
66
|
-
release = await
|
|
88
|
+
release = await fetchProReleaseWithSession(target, options.email);
|
|
67
89
|
}
|
|
68
90
|
catch (error) {
|
|
69
91
|
if (error instanceof ApiError) {
|
|
@@ -87,8 +109,7 @@ export async function runSetup(options = {}) {
|
|
|
87
109
|
console.log("\n✓ Done");
|
|
88
110
|
console.log(` Install path: ${installRoot()}`);
|
|
89
111
|
console.log(` Target: ${manifest?.target ?? target}`);
|
|
112
|
+
console.log(` Tier: ${manifest?.tier ?? (free ? "free" : "pro")}`);
|
|
90
113
|
console.log(` Version: ${manifest?.version ?? "(none)"}`);
|
|
91
|
-
console.log(
|
|
92
|
-
console.log("\nNext: reload MCP in your editor, then ask:");
|
|
93
|
-
console.log(' “What Nucleo icon families do I have?”\n');
|
|
114
|
+
console.log("\nReload MCP in your editor, then try asking about Nucleo icons.\n");
|
|
94
115
|
}
|
package/dist/commands/status.js
CHANGED
|
@@ -23,6 +23,7 @@ export async function runStatus() {
|
|
|
23
23
|
const manifest = await readInstallManifest();
|
|
24
24
|
console.log(`Version: ${manifest?.version ?? "(missing)"}`);
|
|
25
25
|
console.log(`Target: ${manifest?.target ?? "(missing)"}`);
|
|
26
|
+
console.log(`Tier: ${manifest?.tier ?? "(missing)"}`);
|
|
26
27
|
console.log(`Product: ${manifest?.product ?? "(missing)"}`);
|
|
27
28
|
console.log(`Families: ${(manifest?.families ?? []).join(", ") || "(none)"}`);
|
|
28
29
|
console.log(`MCP entry: ${existsSync(mcpEntryPath()) ? mcpEntryPath() : "(missing — run setup/update)"}`);
|
package/dist/commands/update.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { confirm } from "@inquirer/prompts";
|
|
2
|
-
import { ApiError, fetchSkillsRelease } from "../api.js";
|
|
2
|
+
import { ApiError, fetchSkillsFreeRelease, fetchSkillsRelease } from "../api.js";
|
|
3
3
|
import { installRoot } from "../config.js";
|
|
4
4
|
import { buildMcp, ensureManifestTarget, installFromLocalDir, installFromRelease, readInstallManifest, } from "../install.js";
|
|
5
5
|
import { configureTool } from "../adapters/agents.js";
|
|
6
6
|
import { ensureSkillsSession, isInvalidTokenError } from "../session.js";
|
|
7
|
-
async function
|
|
7
|
+
async function fetchProReleaseWithSession(target) {
|
|
8
8
|
let session = await ensureSkillsSession();
|
|
9
9
|
try {
|
|
10
10
|
return await fetchSkillsRelease(session.token, target);
|
|
@@ -18,6 +18,18 @@ async function fetchReleaseWithSession(target) {
|
|
|
18
18
|
throw error;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
+
function isFreeInstall(manifest) {
|
|
22
|
+
if (!manifest) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
if (manifest.tier === "free") {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
if (typeof manifest.product === "string" && manifest.product.includes("free")) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
21
33
|
export async function runUpdate(options = {}) {
|
|
22
34
|
console.log("\nNucleo Skills update");
|
|
23
35
|
console.log("────────────────────\n");
|
|
@@ -27,10 +39,14 @@ export async function runUpdate(options = {}) {
|
|
|
27
39
|
}
|
|
28
40
|
const target = manifest?.target ?? "react";
|
|
29
41
|
const localVersion = manifest?.version ?? "0.0.0";
|
|
42
|
+
const free = isFreeInstall(manifest);
|
|
30
43
|
if (options.from) {
|
|
31
44
|
console.log(`Updating from local folder:\n ${options.from}\n`);
|
|
32
45
|
await installFromLocalDir(options.from);
|
|
33
|
-
await ensureManifestTarget(target
|
|
46
|
+
await ensureManifestTarget(target, {
|
|
47
|
+
tier: free ? "free" : "pro",
|
|
48
|
+
product: free ? "nucleo-skills-free" : "nucleo-skills",
|
|
49
|
+
});
|
|
34
50
|
console.log("Building MCP…");
|
|
35
51
|
await buildMcp();
|
|
36
52
|
await reconfigure(options.tools);
|
|
@@ -41,7 +57,14 @@ export async function runUpdate(options = {}) {
|
|
|
41
57
|
}
|
|
42
58
|
let release;
|
|
43
59
|
try {
|
|
44
|
-
|
|
60
|
+
if (free) {
|
|
61
|
+
console.log("Channel: free");
|
|
62
|
+
release = await fetchSkillsFreeRelease(target);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log("Channel: pro");
|
|
66
|
+
release = await fetchProReleaseWithSession(target);
|
|
67
|
+
}
|
|
45
68
|
}
|
|
46
69
|
catch (error) {
|
|
47
70
|
if (error instanceof ApiError) {
|
package/dist/config.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export interface NucleoCredentials {
|
|
|
15
15
|
}
|
|
16
16
|
export interface InstallManifest {
|
|
17
17
|
product?: string;
|
|
18
|
+
/** free | pro — drives update channel without requiring --free again */
|
|
19
|
+
tier?: "free" | "pro" | string;
|
|
18
20
|
target?: PackageTarget | string;
|
|
19
21
|
version?: string;
|
|
20
22
|
families?: string[];
|
package/dist/index.js
CHANGED
|
@@ -54,6 +54,7 @@ program
|
|
|
54
54
|
.description("Sign in, download your licensed package, configure your editor")
|
|
55
55
|
.option("-t, --target <target>", "react | vanilla")
|
|
56
56
|
.option("--tools <list>", "comma-separated: cursor,claude,codex (default: prompt, or cursor with --yes)")
|
|
57
|
+
.option("--free", "Install free icon families (no Nucleo login)")
|
|
57
58
|
.option("--from <dir>", "Install from a local prepared package (skip API download)")
|
|
58
59
|
.option("--email <email>", "Nucleo account email (skip prompt)")
|
|
59
60
|
.option("-y, --yes", "Skip confirmation prompts")
|
|
@@ -70,6 +71,7 @@ program
|
|
|
70
71
|
tools,
|
|
71
72
|
email: opts.email,
|
|
72
73
|
yes: Boolean(opts.yes),
|
|
74
|
+
free: Boolean(opts.free),
|
|
73
75
|
});
|
|
74
76
|
}
|
|
75
77
|
catch (error) {
|
package/dist/install.js
CHANGED
|
@@ -173,7 +173,8 @@ export async function installFromRelease(release, target, root = installRoot())
|
|
|
173
173
|
await rm(downloadsDir, { recursive: true, force: true }).catch(() => undefined);
|
|
174
174
|
}
|
|
175
175
|
await writeInstallManifest({
|
|
176
|
-
product: "nucleo-skills",
|
|
176
|
+
product: release.tier === "free" ? "nucleo-skills-free" : "nucleo-skills",
|
|
177
|
+
tier: release.tier === "free" ? "free" : "pro",
|
|
177
178
|
target,
|
|
178
179
|
version: release.version,
|
|
179
180
|
families: release.families,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nucleoicons/skills",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "CLI to install and update Nucleo
|
|
3
|
+
"version": "0.1.7",
|
|
4
|
+
"description": "CLI to install and update Nucleo MCP + icon skills (Pro and free)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"nucleo-skills": "./dist/index.js"
|