@xscriptor/skill-devx 1.0.0 → 1.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 (3) hide show
  1. package/README.md +18 -11
  2. package/bin/install.js +103 -19
  3. package/package.json +6 -5
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <h1 align="center">@xscriptor/skill-devx</h1>
2
2
 
3
- <p>Development workflows skill for the DevX platform. Contains code structure conventions, platform mapping, design token system, and project organization guidelines.</p>
3
+ <p>Design and structure skill for the DevX UI (the <code>dev.xscriptor.com</code> resources pages). Documents the visual system, design tokens, typography, layout, motion, accessibility and code organization conventions.</p>
4
4
 
5
5
  <h2>Installation</h2>
6
6
 
@@ -11,30 +11,37 @@ npx @xscriptor/skill-devx
11
11
  npx @xscriptor/skill-devx --anthropic
12
12
 
13
13
  # Preview what will be installed
14
- npx @xscriptor/skill-devx --dry-run</code></pre>
14
+ npx @xscriptor/skill-devx --dry-run
15
+
16
+ # Use a local checkout of the skills repo (or XSCRIPTOR_SRC / XSCRIPTOR_SKILLS_DIR)
17
+ npx @xscriptor/skill-devx --src /path/to/xscriptor-ai</code></pre>
15
18
 
16
19
  <h2>Usage</h2>
17
20
 
18
- <p>Once installed, the skill is loaded automatically when working on DevX projects. Invoke it manually with <code>/devx</code> in Claude Code, or use <code>@devx</code> in OpenCode.</p>
21
+ <p>Once installed, the skill loads automatically when working on DevX pages. Invoke it manually with <code>/devx</code> in Claude Code or <code>@devx</code> in OpenCode.</p>
22
+
23
+ <p>This package ships only the installer. The skill content (<code>SKILL.md</code> plus its <code>references/</code>) is fetched from <a href="https://github.com/xscriptor-ai/skills">xscriptor-ai/skills</a> at install time, so it always matches the current source of truth.</p>
19
24
 
20
25
  <p>The skill covers:</p>
21
26
  <ul>
22
- <li><strong>Architecture</strong> — modular platform design, packages, apps separation</li>
23
- <li><strong>Code structure</strong> — module conventions, barrel exports, internal directories</li>
24
- <li><strong>Platform mapping</strong> — web, mobile, API conventions per platform</li>
25
- <li><strong>Design tokens</strong> — color, spacing, typography, elevation system</li>
26
- <li><strong>Layout system</strong> — responsive grid, breakpoints, container patterns</li>
27
+ <li><strong>Design system</strong> — visual language, tokens, typography and elevation</li>
28
+ <li><strong>Layout</strong> — responsive grid, breakpoints and container patterns</li>
29
+ <li><strong>Motion</strong> — transitions and interaction feedback</li>
30
+ <li><strong>Accessibility</strong> — contrast, focus and semantics</li>
31
+ <li><strong>Code structure</strong> — module conventions, barrel exports and internal directories</li>
32
+ <li><strong>Platform mapping</strong> — web, mobile and API conventions</li>
27
33
  </ul>
28
34
 
29
35
  <h2>Resources</h2>
30
36
 
31
37
  <ul>
32
- <li><a href="https://github.com/xscriptor/ai">github.com/xscriptor/ai</a></li>
38
+ <li><a href="https://github.com/xscriptor-ai/skills">github.com/xscriptor-ai/skills</a></li>
39
+ <li><a href="https://github.com/xscriptor-ai/packages">github.com/xscriptor-ai/packages</a></li>
33
40
  <li><a href="https://dev.xscriptor.com/en/resources/ai/">dev.xscriptor.com/en/resources/ai/</a></li>
34
41
  </ul>
35
42
 
36
43
  <hr>
37
44
 
38
45
  <p><strong>License:</strong> <a href="./LICENSE">MIT</a><br>
39
- <strong>Report issues:</strong> <a href="https://github.com/xscriptor/ai/issues">github.com/xscriptor/ai/issues</a><br>
40
- <strong>Changelog:</strong> <a href="https://github.com/xscriptor/ai/releases">github.com/xscriptor/ai/releases</a></p>
46
+ <strong>Report issues:</strong> <a href="https://github.com/xscriptor-ai/packages/issues">github.com/xscriptor-ai/packages/issues</a><br>
47
+ <strong>Changelog:</strong> <a href="https://github.com/xscriptor-ai/packages/releases">github.com/xscriptor-ai/packages/releases</a></p>
package/bin/install.js CHANGED
@@ -1,25 +1,102 @@
1
1
  #!/usr/bin/env node
2
2
  // @xscriptor/skill-devx - Install the DevX development skill.
3
- // Usage: npx @xscriptor/skill-devx [--opencode|--anthropic|--dry-run]
4
- import { existsSync, mkdirSync, copyFileSync, readdirSync, statSync } from "fs";
3
+ // Usage: npx @xscriptor/skill-devx [--opencode|--anthropic|--dry-run] [--src DIR]
4
+ import {
5
+ existsSync, mkdirSync, copyFileSync, readdirSync, statSync,
6
+ writeFileSync, mkdtempSync, rmSync,
7
+ } from "fs";
8
+ import { execFileSync } from "child_process";
5
9
  import { join, dirname } from "path";
10
+ import { tmpdir } from "os";
6
11
  import { fileURLToPath } from "url";
7
12
 
8
13
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
- const PKG_DIR = join(__dirname, "..");
10
- const REPO_DIR = join(PKG_DIR, "..", "..");
14
+ const SKILL_NAME = "devx";
15
+ // Location of this skill inside the xscriptor-ai/skills repository.
16
+ const SKILL_REL = join("web-fullstack", "devtools", "devx");
17
+ const REF = process.env.XSCRIPTOR_REF || "main";
18
+ const SKILLS_REPO = "xscriptor-ai/skills";
19
+ const AGENTS_REPO = "xscriptor-ai/agents";
11
20
 
12
21
  function dstPath(target) {
13
22
  const home = process.env.HOME || process.env.USERPROFILE || "";
14
- if (target === "anthropic") return join(home, ".claude", "skills", "devx");
23
+ if (target === "anthropic") return join(home, ".claude", "skills", SKILL_NAME);
15
24
  const xdg = process.env.XDG_CONFIG_HOME || join(home, ".config");
16
- return join(xdg, "opencode", "skills", "devx");
25
+ return join(xdg, "opencode", "skills", SKILL_NAME);
17
26
  }
18
27
 
19
- function srcPath() {
20
- const p = join(PKG_DIR, "skills", "web", "dev", "devx");
21
- const r = join(REPO_DIR, "skills", "web", "dev", "devx", "devx");
22
- return existsSync(p) ? p : r;
28
+ // Walk up from this file until we find the packages repo root (.git).
29
+ function repoRoot() {
30
+ let dir = __dirname;
31
+ for (let i = 0; i < 8; i++) {
32
+ if (existsSync(join(dir, ".git"))) return dir;
33
+ const parent = dirname(dir);
34
+ if (parent === dir) break;
35
+ dir = parent;
36
+ }
37
+ return dirname(dirname(__dirname));
38
+ }
39
+
40
+ function bases() {
41
+ const list = [];
42
+ const srcIndex = process.argv.indexOf("--src");
43
+ if (srcIndex >= 0 && process.argv[srcIndex + 1]) list.push(process.argv[srcIndex + 1]);
44
+ if (process.env.XSCRIPTOR_SRC) list.push(process.env.XSCRIPTOR_SRC);
45
+ if (process.env.XSCRIPTOR_SKILLS_DIR) list.push(process.env.XSCRIPTOR_SKILLS_DIR);
46
+ if (process.env.XSCRIPTOR_AGENTS_DIR) list.push(process.env.XSCRIPTOR_AGENTS_DIR);
47
+ const root = repoRoot();
48
+ list.push(root); // skills repo nested at repo root
49
+ list.push(join(root, "..")); // sibling checkout: <workspace>/skills
50
+ list.push(join(root, "..", ".."));
51
+ list.push(process.cwd());
52
+ return list;
53
+ }
54
+
55
+ function localSource(target) {
56
+ for (const base of bases()) {
57
+ if (target === "anthropic") {
58
+ const found = [
59
+ join(base, "claude", "skills", SKILL_NAME),
60
+ join(base, "agents", "claude", "skills", SKILL_NAME),
61
+ ].find(existsSync);
62
+ if (found) return found;
63
+ } else {
64
+ const found = [
65
+ join(base, SKILL_REL), // base is the skills repo itself
66
+ join(base, "skills", SKILL_REL), // base is a workspace containing skills/
67
+ ].find(existsSync);
68
+ if (found) return found;
69
+ }
70
+ }
71
+ return undefined;
72
+ }
73
+
74
+ async function fetchRepo(repo) {
75
+ const url = `https://codeload.github.com/${repo}/tar.gz/refs/heads/${REF}`;
76
+ console.log(` downloading ${repo}@${REF}`);
77
+ const res = await fetch(url, { redirect: "follow" });
78
+ if (!res.ok) throw new Error(`GET ${url} -> ${res.status}`);
79
+ const dir = mkdtempSync(join(tmpdir(), "xscriptor-skill-"));
80
+ const tgz = join(dir, "src.tgz");
81
+ writeFileSync(tgz, Buffer.from(await res.arrayBuffer()));
82
+ try {
83
+ execFileSync("tar", ["-xzf", tgz, "-C", dir, "--strip-components=1"], { stdio: "ignore" });
84
+ } catch {
85
+ rmSync(dir, { recursive: true, force: true });
86
+ mkdirSync(dir, { recursive: true });
87
+ execFileSync("git", ["clone", "--depth", "1", "--branch", REF, `https://github.com/${repo}.git`, dir], { stdio: "ignore" });
88
+ }
89
+ rmSync(tgz, { force: true });
90
+ return dir;
91
+ }
92
+
93
+ async function remoteSource(target) {
94
+ if (target === "anthropic") {
95
+ const dir = await fetchRepo(AGENTS_REPO);
96
+ return join(dir, "claude", "skills", SKILL_NAME);
97
+ }
98
+ const dir = await fetchRepo(SKILLS_REPO);
99
+ return join(dir, SKILL_REL);
23
100
  }
24
101
 
25
102
  function copyDir(s, d, dry) {
@@ -35,14 +112,21 @@ function copyDir(s, d, dry) {
35
112
  return c;
36
113
  }
37
114
 
38
- const args = process.argv.slice(2);
39
- const target = args.includes("--anthropic") ? "anthropic" : "opencode";
40
- const dryRun = args.includes("--dry-run");
41
- const src = srcPath();
42
- const dst = dstPath(target);
115
+ async function main() {
116
+ const args = process.argv.slice(2);
117
+ const target = args.includes("--anthropic") ? "anthropic" : "opencode";
118
+ const dryRun = args.includes("--dry-run");
119
+ const dst = dstPath(target);
120
+ const src = localSource(target) || await remoteSource(target);
121
+
122
+ if (!existsSync(src)) throw new Error(`skill source not found: ${src}`);
43
123
 
44
- if (!existsSync(src)) { console.error("Skill source not found"); process.exit(1); }
124
+ console.log(`==> @xscriptor/skill-devx -> ${dst}\n`);
125
+ const c = copyDir(src, dst, dryRun);
126
+ console.log(dryRun ? `\n==> Would install ${c} files` : `\n==> ${c} files installed`);
127
+ }
45
128
 
46
- console.log(`==> @xscriptor/skill-devx -> ${dst}\n`);
47
- const c = copyDir(src, dst, dryRun);
48
- console.log(dryRun ? `\n==> Would install ${c} files` : `\n==> ${c} files installed`);
129
+ main().catch(err => {
130
+ console.error(`error: ${err.message}`);
131
+ process.exit(1);
132
+ });
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@xscriptor/skill-devx",
3
- "version": "1.0.0",
4
- "description": "DevX development workflows skill for OpenCode and Claude Code. Code structure, platform mapping, and project conventions.",
5
- "keywords": ["opencode", "claude-code", "skill", "devx", "development"],
6
- "homepage": "https://github.com/xscriptor/ai",
3
+ "version": "1.1.0",
4
+ "description": "DevX UI skill for OpenCode and Claude Code. Design system, tokens, typography, layout, motion, accessibility and project conventions for the DevX resources pages.",
5
+ "keywords": ["opencode", "claude-code", "skill", "devx", "design-system"],
6
+ "homepage": "https://github.com/xscriptor-ai/packages",
7
+ "bugs": { "url": "https://github.com/xscriptor-ai/packages/issues" },
7
8
  "license": "MIT",
8
9
  "author": "xscriptor (https://xscriptor.com)",
9
- "repository": { "type": "git", "url": "git+https://github.com/xscriptor/ai.git" },
10
+ "repository": { "type": "git", "url": "git+https://github.com/xscriptor-ai/packages.git", "directory": "packages/skills/web-fullstack/devtools/devx" },
10
11
  "bin": { "skill-devx": "./bin/install.js" },
11
12
  "type": "module",
12
13
  "files": ["bin/", "LICENSE", "README.md"],