@kentwynn/kgraph 0.1.2 → 0.1.4

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 CHANGED
@@ -82,28 +82,29 @@ kgraph context "auth token refresh" --json
82
82
 
83
83
  ## AI Tool Integrations
84
84
 
85
- KGraph writes local instruction files so AI tools know how to use the repository knowledge layer during normal coding chats.
85
+ KGraph writes local instruction files and command/prompt packs so AI tools can use the repository knowledge layer during normal coding chats.
86
86
 
87
- | Integration | Instruction file |
88
- | --- | --- |
89
- | Codex | `AGENTS.md` |
90
- | GitHub Copilot | `.github/copilot-instructions.md` |
91
- | Cursor | `.cursor/rules/kgraph.mdc` |
92
- | Claude Code | `CLAUDE.md` |
87
+ | Integration | Always-on guidance | KGraph command assets |
88
+ | --- | --- | --- |
89
+ | Codex | `AGENTS.md` | `.agents/skills/kgraph*/SKILL.md` |
90
+ | GitHub Copilot | `.github/copilot-instructions.md` | `.github/prompts/kgraph*.prompt.md` |
91
+ | Cursor | `.cursor/rules/kgraph.mdc` | `.cursor/rules/kgraph-commands.mdc` |
92
+ | Claude Code | `CLAUDE.md` | `.claude/commands/kgraph*.md` |
93
93
 
94
94
  Example:
95
95
 
96
96
  ```bash
97
- kgraph integrate add codex cursor
97
+ kgraph integrate add codex copilot cursor claude-code
98
98
  kgraph integrate list
99
99
  ```
100
100
 
101
- Generated instructions teach AI tools to:
101
+ This gives supported tools reusable KGraph workflows similar to Spec Kit-style commands:
102
+
103
+ - KGraph context: query `kgraph context "<topic>"` before broad repo exploration
104
+ - KGraph update: save durable chat/debugging/workflow discoveries to `.kgraph/inbox/`, then run `kgraph update`
105
+ - KGraph scan: run `kgraph scan` after refactors, file moves, renamed functions, or dependency changes
102
106
 
103
- - query `kgraph context "<topic>"` before broad repo exploration
104
- - save useful architecture, workflow, and debugging discoveries to `.kgraph/inbox/`
105
- - run `kgraph update` to turn notes into durable cognition
106
- - run `kgraph scan` after refactors, file moves, or renamed functions
107
+ The exact invocation depends on the host tool. Copilot uses prompt files, Codex uses skills, Cursor uses rules, and Claude Code uses command files.
107
108
 
108
109
  KGraph-managed instruction blocks preserve existing user-authored content.
109
110
 
@@ -115,7 +116,7 @@ KGraph-managed instruction blocks preserve existing user-authored content.
115
116
  - Markdown cognition inbox for AI chat summaries, decisions, gotchas, and debugging notes
116
117
  - Compact context output for AI assistants and scripts
117
118
  - JSON output for tool-friendly context retrieval
118
- - Integration management for Codex, Copilot, Cursor, and Claude Code
119
+ - Integration management and command packs for Codex, Copilot, Cursor, and Claude Code
119
120
  - Stale-reference handling when code changes over time
120
121
  - Local-first storage with human-readable JSON, YAML, and Markdown
121
122
 
@@ -0,0 +1 @@
1
+ export declare function renderRootHelp(useColor?: boolean): string;
@@ -0,0 +1,60 @@
1
+ import { Chalk } from "chalk";
2
+ import figlet from "figlet";
3
+ export function renderRootHelp(useColor = supportsColor()) {
4
+ const theme = new Chalk({ level: useColor ? 3 : 0 });
5
+ const command = (name, description) => ` ${theme.green(name.padEnd(30))} ${description}`;
6
+ const logo = renderLogo();
7
+ return [
8
+ "",
9
+ theme.hex("#7dd3fc").bold(logo),
10
+ "",
11
+ ` ${theme.bold("KGraph")} ${theme.dim("Persistent repo intelligence for AI coding tools")}`,
12
+ "",
13
+ ` ${theme.hex("#c084fc")("Build a local knowledge layer that helps Codex, Copilot, Cursor,")}`,
14
+ ` ${theme.hex("#c084fc")("and Claude Code reuse repo structure, decisions, and debugging history.")}`,
15
+ "",
16
+ theme.bold("Usage"),
17
+ " kgraph <command> [options]",
18
+ "",
19
+ theme.bold("Start"),
20
+ command("init", "Create .kgraph/ workspace"),
21
+ command("init --integrations codex,cursor", "Initialize and connect AI tools"),
22
+ "",
23
+ theme.bold("Workflows"),
24
+ command("scan", "Refresh file, symbol, import, and relationship maps"),
25
+ command("context \"auth token refresh\"", "Return compact context for an AI chat"),
26
+ command("update", "Process .kgraph/inbox Markdown cognition notes"),
27
+ "",
28
+ theme.bold("Integrations"),
29
+ command("integrate list", "Show configured AI tool integrations"),
30
+ command("integrate add codex copilot", "Write KGraph instructions for AI tools"),
31
+ command("integrate remove cursor", "Remove KGraph-managed instruction blocks"),
32
+ "",
33
+ theme.bold("Options"),
34
+ command("-V, --version", "Show version"),
35
+ command("-h, --help", "Show this help"),
36
+ "",
37
+ `${theme.yellow("Examples")}`,
38
+ " kgraph init --integrations codex,copilot,cursor",
39
+ " kgraph scan",
40
+ " kgraph context \"blog admin token usage\" --json",
41
+ "",
42
+ theme.dim("Docs: https://github.com/kentwynn/KGraph#readme"),
43
+ ""
44
+ ].join("\n");
45
+ }
46
+ function renderLogo() {
47
+ try {
48
+ return figlet.textSync("KGraph", {
49
+ font: "ANSI Shadow",
50
+ horizontalLayout: "default",
51
+ verticalLayout: "default"
52
+ });
53
+ }
54
+ catch {
55
+ return "KGraph";
56
+ }
57
+ }
58
+ function supportsColor() {
59
+ return Boolean(process.stdout.isTTY) && process.env.NO_COLOR === undefined;
60
+ }
package/dist/cli/index.js CHANGED
@@ -7,12 +7,22 @@ import { registerScanCommand } from "./commands/scan.js";
7
7
  import { registerUpdateCommand } from "./commands/update.js";
8
8
  import { registerContextCommand } from "./commands/context.js";
9
9
  import { registerIntegrateCommand } from "./commands/integrate.js";
10
+ import { renderRootHelp } from "./help.js";
10
11
  export function createProgram() {
11
12
  const program = new Command();
12
13
  program
13
14
  .name("kgraph")
14
15
  .description("Persistent repo intelligence for AI coding assistants")
15
- .version("0.1.1");
16
+ .version("0.1.2")
17
+ .addHelpText("beforeAll", renderRootHelp())
18
+ .helpOption(false);
19
+ program.option("-h, --help", "Show this help");
20
+ program.hook("preAction", (thisCommand) => {
21
+ if (thisCommand.opts().help) {
22
+ console.log(renderRootHelp());
23
+ process.exitCode = 0;
24
+ }
25
+ });
16
26
  registerInitCommand(program);
17
27
  registerScanCommand(program);
18
28
  registerUpdateCommand(program);
@@ -21,7 +31,13 @@ export function createProgram() {
21
31
  return program;
22
32
  }
23
33
  if (isCliEntrypoint()) {
24
- await createProgram().parseAsync(process.argv);
34
+ const program = createProgram();
35
+ if (process.argv.length <= 2 || process.argv.includes("-h") || process.argv.includes("--help")) {
36
+ console.log(renderRootHelp());
37
+ }
38
+ else {
39
+ await program.parseAsync(process.argv);
40
+ }
25
41
  }
26
42
  function isCliEntrypoint() {
27
43
  if (!process.argv[1]) {
@@ -4,7 +4,36 @@ import { pathExists } from "../storage/kgraph-paths.js";
4
4
  import { KGraphError } from "../cli/errors.js";
5
5
  export const DEFAULT_CONFIG = {
6
6
  include: ["**/*"],
7
- exclude: [".git", "node_modules", "dist", "build", ".next", "coverage", ".kgraph"],
7
+ exclude: [
8
+ ".git",
9
+ "node_modules",
10
+ "dist",
11
+ "build",
12
+ ".next",
13
+ "coverage",
14
+ ".kgraph",
15
+ ".npm-cache",
16
+ ".cache",
17
+ ".turbo",
18
+ ".vite",
19
+ ".nuxt",
20
+ ".output",
21
+ ".vercel",
22
+ ".serverless",
23
+ ".agents",
24
+ ".specify",
25
+ "specs",
26
+ ".cursor",
27
+ ".claude",
28
+ ".github/copilot-instructions.md",
29
+ ".github/prompts",
30
+ "AGENTS.md",
31
+ "CLAUDE.md",
32
+ "REQUIREMENTS.md",
33
+ "*.log",
34
+ "*.tgz",
35
+ ".DS_Store"
36
+ ],
8
37
  languages: {
9
38
  precise: [".js", ".jsx", ".ts", ".tsx"]
10
39
  },
@@ -39,7 +68,7 @@ export async function loadConfig(workspace) {
39
68
  export function normalizeConfig(config) {
40
69
  return {
41
70
  include: Array.isArray(config.include) ? config.include : DEFAULT_CONFIG.include,
42
- exclude: Array.isArray(config.exclude) ? config.exclude : DEFAULT_CONFIG.exclude,
71
+ exclude: mergeUnique(DEFAULT_CONFIG.exclude, Array.isArray(config.exclude) ? config.exclude : []),
43
72
  languages: {
44
73
  precise: Array.isArray(config.languages?.precise)
45
74
  ? config.languages.precise
@@ -52,6 +81,9 @@ export function normalizeConfig(config) {
52
81
  integrations: normalizeIntegrations(config.integrations)
53
82
  };
54
83
  }
84
+ function mergeUnique(base, extra) {
85
+ return [...new Set([...base, ...extra])];
86
+ }
55
87
  function normalizeIntegrations(value) {
56
88
  if (!Array.isArray(value)) {
57
89
  return [];
@@ -9,5 +9,31 @@ export const claudeCodeAdapter = {
9
9
  - Run \`kgraph update\` to preserve those notes as durable cognition.
10
10
  - Run \`kgraph scan\` after structural code changes.
11
11
  - Run \`kgraph visualize\` when visualization support is available and the user wants to inspect the current knowledge map.
12
+ `,
13
+ commandFiles: [
14
+ {
15
+ path: ".claude/commands/kgraph.md",
16
+ content: `Use KGraph persistent repo intelligence for the current request.
17
+
18
+ 1. Infer the topic from the user's request.
19
+ 2. Run \`kgraph context "<topic>"\`.
20
+ 3. Use the returned files, symbols, relationships, and cognition before broad exploration.
21
+ 4. Save durable discoveries to \`.kgraph/inbox/\` and run \`kgraph update\` when appropriate.
22
+ `
23
+ },
24
+ {
25
+ path: ".claude/commands/kgraph-update.md",
26
+ content: `Preserve useful chat knowledge in KGraph.
27
+
28
+ Create a concise Markdown note in \`.kgraph/inbox/\` from durable discoveries in this conversation, then run \`kgraph update\`.
29
+ `
30
+ },
31
+ {
32
+ path: ".claude/commands/kgraph-scan.md",
33
+ content: `Refresh KGraph structural maps.
34
+
35
+ Run \`kgraph scan\` after code structure changes and report the scan summary.
12
36
  `
37
+ }
38
+ ]
13
39
  };
@@ -9,5 +9,48 @@ export const codexAdapter = {
9
9
  - Run \`kgraph update\` after adding inbox notes so KGraph preserves durable cognition.
10
10
  - Run \`kgraph scan\` after file moves, function renames, refactors, or other structural changes.
11
11
  - When visualization support is available and the developer asks to inspect KGraph, run \`kgraph visualize\` and report the generated local artifact.
12
+ `,
13
+ commandFiles: [
14
+ {
15
+ path: ".agents/skills/kgraph/SKILL.md",
16
+ content: `---
17
+ name: "kgraph"
18
+ description: "Use KGraph persistent repo intelligence for the current coding task."
19
+ ---
20
+
21
+ Use this skill when the user asks to use KGraph, requests repo context, or asks you to avoid rediscovering repository structure.
22
+
23
+ Workflow:
24
+
25
+ 1. Infer the current topic from the user request.
26
+ 2. Run \`kgraph context "<topic>"\` before broad repo exploration.
27
+ 3. Use KGraph's files, symbols, relationships, and cognition as navigation hints.
28
+ 4. After durable discoveries, write a concise Markdown note to \`.kgraph/inbox/\`.
29
+ 5. Run \`kgraph update\` if you created an inbox note.
30
+ 6. Run \`kgraph scan\` after structural changes.
31
+ `
32
+ },
33
+ {
34
+ path: ".agents/skills/kgraph-update/SKILL.md",
35
+ content: `---
36
+ name: "kgraph-update"
37
+ description: "Preserve useful chat discoveries into KGraph cognition."
38
+ ---
39
+
40
+ Use this skill when the user asks to update KGraph memory or preserve what was learned.
41
+
42
+ Write a concise Markdown note under \`.kgraph/inbox/\` with durable architecture, debugging, workflow, file, symbol, or gotcha knowledge. Then run \`kgraph update\`.
43
+ `
44
+ },
45
+ {
46
+ path: ".agents/skills/kgraph-scan/SKILL.md",
47
+ content: `---
48
+ name: "kgraph-scan"
49
+ description: "Refresh KGraph structural maps after code changes."
50
+ ---
51
+
52
+ Run \`kgraph scan\` after files move, functions are renamed, folders are refactored, or dependencies change. Report the scan summary and any obvious exclude/config problems.
12
53
  `
54
+ }
55
+ ]
13
56
  };
@@ -9,5 +9,45 @@ export const copilotAdapter = {
9
9
  - Use \`kgraph update\` to process chat summaries and debugging conclusions into durable cognition.
10
10
  - Use \`kgraph scan\` when code structure changes.
11
11
  - Use \`kgraph visualize\` when visualization support is available and the developer asks to inspect the repository knowledge map.
12
+ `,
13
+ commandFiles: [
14
+ {
15
+ path: ".github/prompts/kgraph.prompt.md",
16
+ content: `---
17
+ mode: agent
18
+ description: Use KGraph persistent repo intelligence for this request
19
+ ---
20
+
21
+ Use KGraph for the current task.
22
+
23
+ 1. If the user provided a topic, run \`kgraph context "<topic>"\` first. If not, infer a concise topic from the request.
24
+ 2. Use the returned files, symbols, relationships, and cognition before broad repository exploration.
25
+ 3. If you discover durable architecture, debugging, workflow, or gotcha knowledge, create a Markdown note in \`.kgraph/inbox/\`.
26
+ 4. If you add an inbox note, run \`kgraph update\`.
27
+ 5. If code structure changed, run \`kgraph scan\`.
28
+ `
29
+ },
30
+ {
31
+ path: ".github/prompts/kgraph-update.prompt.md",
32
+ content: `---
33
+ mode: agent
34
+ description: Preserve recent useful chat knowledge in KGraph
35
+ ---
36
+
37
+ Create a concise Markdown cognition note in \`.kgraph/inbox/\` from the useful stable knowledge in this conversation, then run \`kgraph update\`.
38
+
39
+ Capture only durable information: architecture discoveries, debugging conclusions, workflow conventions, important files, important functions, and gotchas. Do not store temporary chatter.
40
+ `
41
+ },
42
+ {
43
+ path: ".github/prompts/kgraph-scan.prompt.md",
44
+ content: `---
45
+ mode: agent
46
+ description: Refresh KGraph structural maps after repository changes
47
+ ---
48
+
49
+ Run \`kgraph scan\` and report the number of files and symbols scanned. If scan output suggests generated/cache files were included, mention that the exclude configuration may need adjustment.
12
50
  `
51
+ }
52
+ ]
13
53
  };
@@ -14,5 +14,23 @@ alwaysApply: true
14
14
  - Run \`kgraph update\` after adding useful notes.
15
15
  - Run \`kgraph scan\` after refactors, moved folders, renamed functions, or other structure changes.
16
16
  - Run \`kgraph visualize\` when visualization support is available and the developer asks to inspect the KGraph map.
17
+ `,
18
+ commandFiles: [
19
+ {
20
+ path: ".cursor/rules/kgraph-commands.mdc",
21
+ content: `---
22
+ description: KGraph command workflows for repo context, update, and scan
23
+ alwaysApply: false
24
+ ---
25
+
26
+ # KGraph Commands
27
+
28
+ Use these workflows when the user asks for KGraph:
29
+
30
+ - KGraph context: run \`kgraph context "<topic>"\` before broad exploration.
31
+ - KGraph update: write durable findings to \`.kgraph/inbox/\`, then run \`kgraph update\`.
32
+ - KGraph scan: run \`kgraph scan\` after refactors, file moves, renamed functions, or dependency changes.
17
33
  `
34
+ }
35
+ ]
18
36
  };
@@ -4,6 +4,11 @@ export interface IntegrationAdapter {
4
4
  label: string;
5
5
  targetPath: string;
6
6
  instructions: string;
7
+ commandFiles?: IntegrationCommandFile[];
8
+ }
9
+ export interface IntegrationCommandFile {
10
+ path: string;
11
+ content: string;
7
12
  }
8
13
  export declare function listIntegrationAdapters(): IntegrationAdapter[];
9
14
  export declare function getIntegrationAdapter(name: string): IntegrationAdapter;
@@ -27,6 +27,7 @@ export async function addIntegrations(workspace, names) {
27
27
  };
28
28
  byName.set(adapter.name, next);
29
29
  await writeIntegrationInstructions(workspace.rootPath, adapter.targetPath, adapter.name, adapter.instructions);
30
+ await writeIntegrationCommandFiles(workspace.rootPath, adapter.commandFiles ?? []);
30
31
  changed.push(next);
31
32
  }
32
33
  config.integrations = [...byName.values()].sort((left, right) => left.name.localeCompare(right.name));
@@ -40,6 +41,7 @@ export async function removeIntegrations(workspace, names) {
40
41
  for (const name of removeNames) {
41
42
  const adapter = getIntegrationAdapter(name);
42
43
  await removeIntegrationInstructions(workspace.rootPath, adapter.targetPath, adapter.name);
44
+ await removeIntegrationCommandFiles(workspace.rootPath, adapter.commandFiles ?? []);
43
45
  removed.push(adapter.name);
44
46
  }
45
47
  config.integrations = config.integrations.filter((integration) => !removeNames.has(integration.name));
@@ -66,3 +68,15 @@ async function removeIntegrationInstructions(rootPath, targetPath, integrationNa
66
68
  }
67
69
  await writeFile(fullPath, next, "utf8");
68
70
  }
71
+ async function writeIntegrationCommandFiles(rootPath, files) {
72
+ for (const file of files) {
73
+ const fullPath = path.join(rootPath, file.path);
74
+ await mkdir(path.dirname(fullPath), { recursive: true });
75
+ await writeFile(fullPath, file.content.trimEnd() + "\n", "utf8");
76
+ }
77
+ }
78
+ async function removeIntegrationCommandFiles(rootPath, files) {
79
+ for (const file of files) {
80
+ await rm(path.join(rootPath, file.path), { force: true });
81
+ }
82
+ }
@@ -1,4 +1,5 @@
1
1
  import type { KGraphConfig } from "../types/config.js";
2
2
  export declare function shouldExclude(repoPath: string, config: KGraphConfig): boolean;
3
+ export declare function buildFastGlobIgnore(exclude: string[]): string[];
3
4
  export declare function detectLanguage(filePath: string): string;
4
5
  export declare function isPreciseLanguage(filePath: string, config: KGraphConfig): boolean;
@@ -10,11 +10,27 @@ const LANGUAGE_BY_EXTENSION = {
10
10
  ".yml": "yaml"
11
11
  };
12
12
  export function shouldExclude(repoPath, config) {
13
- const parts = repoPath.split(/[\\/]/);
14
- return config.exclude.some((pattern) => {
15
- const normalized = pattern.replace(/\/$/, "");
16
- return parts.includes(normalized) || repoPath === normalized || repoPath.startsWith(`${normalized}/`);
17
- });
13
+ const normalizedPath = normalizeRepoPath(repoPath);
14
+ return config.exclude.some((pattern) => matchesExcludePattern(normalizedPath, pattern));
15
+ }
16
+ export function buildFastGlobIgnore(exclude) {
17
+ const patterns = new Set();
18
+ for (const pattern of exclude) {
19
+ const normalized = normalizeRepoPath(pattern).replace(/\/$/, "");
20
+ if (!normalized) {
21
+ continue;
22
+ }
23
+ if (hasGlob(normalized)) {
24
+ patterns.add(normalized);
25
+ patterns.add(`**/${normalized}`);
26
+ continue;
27
+ }
28
+ patterns.add(normalized);
29
+ patterns.add(`**/${normalized}`);
30
+ patterns.add(`${normalized}/**`);
31
+ patterns.add(`**/${normalized}/**`);
32
+ }
33
+ return [...patterns];
18
34
  }
19
35
  export function detectLanguage(filePath) {
20
36
  return LANGUAGE_BY_EXTENSION[path.extname(filePath)] ?? "unknown";
@@ -22,3 +38,50 @@ export function detectLanguage(filePath) {
22
38
  export function isPreciseLanguage(filePath, config) {
23
39
  return config.languages.precise.includes(path.extname(filePath));
24
40
  }
41
+ function matchesExcludePattern(repoPath, pattern) {
42
+ const normalized = normalizeRepoPath(pattern).replace(/\/$/, "");
43
+ if (!normalized) {
44
+ return false;
45
+ }
46
+ if (hasGlob(normalized)) {
47
+ return globToRegExp(normalized).test(repoPath) || globToRegExp(`**/${normalized}`).test(repoPath);
48
+ }
49
+ if (repoPath === normalized || repoPath.startsWith(`${normalized}/`)) {
50
+ return true;
51
+ }
52
+ if (!normalized.includes("/")) {
53
+ return repoPath.split("/").includes(normalized);
54
+ }
55
+ return false;
56
+ }
57
+ function normalizeRepoPath(value) {
58
+ return value.replace(/\\/g, "/").replace(/^\.\/+/, "");
59
+ }
60
+ function hasGlob(pattern) {
61
+ return /[*?[\]{}]/.test(pattern);
62
+ }
63
+ function globToRegExp(pattern) {
64
+ let source = "";
65
+ for (let index = 0; index < pattern.length; index += 1) {
66
+ const char = pattern[index];
67
+ const next = pattern[index + 1];
68
+ if (char === "*" && next === "*") {
69
+ source += ".*";
70
+ index += 1;
71
+ continue;
72
+ }
73
+ if (char === "*") {
74
+ source += "[^/]*";
75
+ continue;
76
+ }
77
+ if (char === "?") {
78
+ source += "[^/]";
79
+ continue;
80
+ }
81
+ source += escapeRegExp(char);
82
+ }
83
+ return new RegExp(`^${source}$`);
84
+ }
85
+ function escapeRegExp(value) {
86
+ return value.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
87
+ }
@@ -2,7 +2,7 @@ import { readFile, stat } from "node:fs/promises";
2
2
  import crypto from "node:crypto";
3
3
  import path from "node:path";
4
4
  import fg from "fast-glob";
5
- import { detectLanguage, isPreciseLanguage, shouldExclude } from "./file-classifier.js";
5
+ import { buildFastGlobIgnore, detectLanguage, isPreciseLanguage, shouldExclude } from "./file-classifier.js";
6
6
  import { extractTsSymbols } from "./ts-symbol-extractor.js";
7
7
  export async function scanRepository(rootPath, config, previous) {
8
8
  const entries = await fg(config.include, {
@@ -10,7 +10,7 @@ export async function scanRepository(rootPath, config, previous) {
10
10
  dot: true,
11
11
  onlyFiles: true,
12
12
  unique: true,
13
- ignore: config.exclude.map((item) => `**/${item}/**`)
13
+ ignore: buildFastGlobIgnore(config.exclude)
14
14
  });
15
15
  const files = [];
16
16
  const symbols = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kentwynn/kgraph",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Persistent repo intelligence for AI coding assistants.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -38,8 +38,10 @@
38
38
  },
39
39
  "homepage": "https://github.com/kentwynn/KGraph#readme",
40
40
  "dependencies": {
41
+ "chalk": "^5.6.2",
41
42
  "commander": "^12.1.0",
42
43
  "fast-glob": "^3.3.2",
44
+ "figlet": "^1.11.0",
43
45
  "typescript": "^5.9.3",
44
46
  "yaml": "^2.5.1"
45
47
  },