@wwjd/pi-graphify 0.2.0 → 0.4.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,26 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.4.0](https://github.com/WianVDM/pi-graphify/compare/pi-graphify-v0.3.0...pi-graphify-v0.4.0) (2026-07-12)
9
+
10
+
11
+ ### Features
12
+
13
+ * **commands:** add slash commands and unified /graphify menu ([7c7a566](https://github.com/WianVDM/pi-graphify/commit/7c7a566b4dcda3c7b2d166863a7704a98839669a))
14
+
15
+ ## [0.3.0](https://github.com/WianVDM/pi-graphify/compare/pi-graphify-v0.2.0...pi-graphify-v0.3.0) (2026-07-12)
16
+
17
+
18
+ ### Features
19
+
20
+ * **tools:** add build, query, path, explain, affected, and version tools ([5b8cb07](https://github.com/WianVDM/pi-graphify/commit/5b8cb0730f7c766dd00f40149e7abb6b1fce64fa))
21
+ * **tools:** add shared tool types and formatting helpers ([0efd421](https://github.com/WianVDM/pi-graphify/commit/0efd4214e6b4397c126abecb864ad947be896fa6))
22
+
23
+
24
+ ### Bug Fixes
25
+
26
+ * replace /graphify-build references with graphify CLI command ([63f4fb2](https://github.com/WianVDM/pi-graphify/commit/63f4fb25889719448f13c4dffb485164f7774c55))
27
+
8
28
  ## [0.2.0](https://github.com/WianVDM/pi-graphify/compare/pi-graphify-v0.1.0...pi-graphify-v0.2.0) (2026-07-12)
9
29
 
10
30
 
package/README.md CHANGED
@@ -1,93 +1,71 @@
1
1
  # pi-graphify
2
2
 
3
- A production-quality [pi](https://pi.dev) extension for [Graphify](https://github.com/Graphify-Labs/graphify).
3
+ A [Pi](https://pi.dev) extension that brings [Graphify](https://github.com/Graphify-Labs/graphify) knowledge graph capabilities into your agent sessions.
4
4
 
5
- This extension brings Graphify knowledge graph capabilities into your Pi sessions, making it easy to query, explore, and update codebase graphs without leaving the agent.
6
-
7
- > ⚠️ **Work in progress** — this package is in early development. The public API, tools, and commands will evolve as the extension matures toward a stable 1.0 release.
8
-
9
- ## Quick Start
5
+ ## Install
10
6
 
11
7
  ```bash
12
- # Install from a local path (during development)
13
- pi install .
14
-
15
- # Or run ephemerally without installing
16
- pi -e .
17
-
18
- # Type check
19
- npm run typecheck
20
-
21
- # Lint
22
- npm run lint
8
+ pi install @wwjd/pi-graphify
23
9
  ```
24
10
 
25
- ## What's Included
26
-
27
- ```
28
- pi-graphify/
29
- ├── extensions/
30
- │ └── index.ts # Extension entry point (tools, commands, events)
31
- ├── src/ # Core implementation
32
- ├── package.json # Pi manifest + npm config
33
- ├── tsconfig.json # TypeScript config (type checking only)
34
- ├── biome.json # Linter/formatter config
35
- ├── .gitignore
36
- ├── LICENSE
37
- ├── CHANGELOG.md
38
- ├── RELEASE.md # Versioning and release standards
39
- ├── AGENTS.md # Agent context / development conventions
40
- └── README.md
41
- ```
42
-
43
- ## Package Structure
44
-
45
- ### Extensions (`extensions/`)
46
-
47
- TypeScript modules that extend pi's behavior with custom tools, slash commands, and event handlers.
11
+ ## What it does
48
12
 
49
- ### Source (`src/`)
13
+ `pi-graphify` detects the Graphify CLI and a project's `graphify-out/graph.json` graph, then exposes Graphify operations as Pi tools and slash commands. It routes requests through a backend abstraction so the agent can use Graphify without worrying about whether it's talking to the CLI or (in the future) an MCP server.
50
14
 
51
- Pi-agnostic implementation logic. The `extensions/` layer imports from here and registers everything with Pi.
15
+ When a graph is present, the extension also injects a lightweight hint into the system prompt so the agent knows it can ask structural codebase questions via the graph.
52
16
 
53
- ## Development
17
+ ## Requirements
54
18
 
55
- ### Requirements
19
+ - [Graphify](https://github.com/Graphify-Labs/graphify) must be installed and on your `PATH`.
20
+ - The project must have a generated graph at `graphify-out/graph.json`.
56
21
 
57
- - Node.js 22+
58
- - npm 10+
59
- - pi CLI
60
-
61
- ### Scripts
22
+ ## Current commands
62
23
 
63
24
  | Command | Description |
64
- |---------|-------------|
65
- | `npm run typecheck` | TypeScript type checking (`tsc --noEmit`) |
66
- | `npm run lint` | Check lint + formatting (`biome check`) |
67
- | `npm run lint:fix` | Auto-fix lint + formatting issues |
68
- | `npm run format` | Format code only |
69
-
70
- ### Testing the package
71
-
72
- ```bash
73
- # Run ephemerally with no other extensions loaded
74
- pi -ne -e . --no-session
75
-
76
- # Test a specific tool in print mode
77
- pi -ne -e . --no-session -p "List the available tools."
78
- ```
79
-
80
- ## Publishing
81
-
82
- This package is intended for publication to npm so it can be listed on [pi.dev/packages](https://pi.dev/packages). CI/CD workflows for release automation are included under `.github/workflows/`.
83
-
84
- See `RELEASE.md` for versioning and release standards.
85
-
86
- Before publishing, update:
87
-
88
- - `package.json` author and repository fields
89
- - `README.md` with final usage instructions
90
- - `CHANGELOG.md` with release notes
25
+ |---|---|
26
+ | `/graphify` | Open the unified Graphify command menu. |
27
+ | `/graphify-build` | Build or incrementally update the Graphify knowledge graph. |
28
+ | `/graphify-query` | Ask a natural-language question against the graph. |
29
+ | `/graphify-path` | Find the shortest path between two graph nodes. |
30
+ | `/graphify-explain` | Explain a node and its connections in the graph. |
31
+ | `/graphify-affected` | Show the blast radius of changes to one or more files. |
32
+ | `/graphify-status` | Check whether a graph exists and whether the Graphify CLI is compatible. |
33
+ | `/graphify-version` | Report the installed Graphify version and compatibility status. |
34
+
35
+ ## Current tools
36
+
37
+ | Tool | Description |
38
+ |---|---|
39
+ | `graphify_status` | Check graph presence, path, and Graphify CLI compatibility. |
40
+ | `graphify_build` | Build or incrementally update the Graphify knowledge graph. |
41
+ | `graphify_query` | Ask a natural-language question against the graph. |
42
+ | `graphify_path` | Find the shortest path between two graph nodes. |
43
+ | `graphify_explain` | Explain a node and its connections in the graph. |
44
+ | `graphify_affected` | Show the blast radius of changes to one or more files. |
45
+ | `graphify_version` | Report the installed Graphify version and compatibility status. |
46
+
47
+ ## What's coming
48
+
49
+ Later phases will add background file watching, MCP backend support, ecosystem integrations, and release readiness work. See [plan/PLAN.md](plan/PLAN.md) for the full roadmap.
50
+
51
+ ## How it works
52
+
53
+ 1. On session start, the extension detects the installed Graphify version and looks for `graphify-out/graph.json`.
54
+ 2. If a graph is found, a hint is added to the agent context.
55
+ 3. Tools and commands route through a coordinator that selects the best available backend.
56
+
57
+ ## Status
58
+
59
+ This extension is in early development. The public API, tools, and commands will evolve as the extension matures toward a stable 1.0 release.
60
+
61
+ ## Documentation
62
+
63
+ - [Design](docs/DESIGN.md)
64
+ - [Architecture](docs/ARCHITECTURE.md)
65
+ - [Ecosystem](docs/ECOSYSTEM.md)
66
+ - [Versioning](docs/VERSIONING.md)
67
+ - [Release standards](RELEASE.md)
68
+ - [Agent context](AGENTS.md)
91
69
 
92
70
  ## License
93
71
 
@@ -0,0 +1,150 @@
1
+ # Local Development and Testing Guide
2
+
3
+ This guide covers how to install and test the local `pi-graphify` extension, plus how to install and uninstall the Graphify CLI for end-to-end verification.
4
+
5
+ ## Prerequisites
6
+
7
+ - [Pi](https://pi.dev) installed and on your PATH.
8
+ - Node.js 20+ and npm.
9
+ - Python 3.10+ (only needed when testing with the Graphify CLI).
10
+ - [uv](https://docs.astral.sh/uv/) or [pipx](https://pipx.pypa.io/) (recommended for Graphify).
11
+
12
+ ## Install the local pi-graphify extension
13
+
14
+ From the project root directory, run:
15
+
16
+ ```bash
17
+ pi install .
18
+ ```
19
+
20
+ This installs the local package into Pi so the extension is loaded on the next Pi session.
21
+
22
+ To verify the install, start Pi in any project and check that `/graphify-status` autocompletes.
23
+
24
+ ## Automated checks
25
+
26
+ Before running manual tests, run the static and automated checks:
27
+
28
+ ```bash
29
+ npm run typecheck
30
+ npm run lint
31
+ npm test
32
+ npm audit --audit-level=moderate
33
+ ```
34
+
35
+ All should pass.
36
+
37
+ ## Install the Graphify CLI
38
+
39
+ The official PyPI package is **`graphifyy`** (double-y). The CLI command is still `graphify`.
40
+
41
+ ### Recommended: uv
42
+
43
+ ```bash
44
+ uv tool install graphifyy
45
+ graphify --version
46
+ ```
47
+
48
+ ### Alternative: pipx
49
+
50
+ ```bash
51
+ pipx install graphifyy
52
+ graphify --version
53
+ ```
54
+
55
+ ### Alternative: pip
56
+
57
+ ```bash
58
+ pip install graphifyy
59
+ graphify --version
60
+ ```
61
+
62
+ After installing, `graphify` should be available on your PATH. If it is not, add the tool's bin directory to your PATH (for example, `~/.local/bin` for `uv tool` or `pipx`).
63
+
64
+ ## Build a graph for testing
65
+
66
+ You can build the graph with the Graphify CLI directly, or use the `/graphify-build` slash command once the extension is loaded.
67
+
68
+ The recommended approach for testing `pi-graphify` is a code-only graph. It skips semantic extraction, so it does not require an API key or extra Python dependencies:
69
+
70
+ ```bash
71
+ graphify . --code-only
72
+ ```
73
+
74
+ This creates a `graphify-out/` directory with `graph.json`, `graph.html`, and `GRAPH_REPORT.md`. It has been verified to work with the default `uv tool install graphifyy` setup.
75
+
76
+ If you want semantic extraction (docs, images, etc.), you need the `kimi` backend dependencies. Install them with:
77
+
78
+ ```bash
79
+ uv tool install "graphifyy[kimi]" --force
80
+ ```
81
+
82
+ Then run the full build:
83
+
84
+ ```bash
85
+ graphify .
86
+ ```
87
+
88
+ Inside Pi you can also run `/graphify` to open the command menu and select "Build graph", or type `/graphify-build` directly.
89
+
90
+ ## Verify the extension with Graphify installed
91
+
92
+ 1. Start Pi in a project with a built graph.
93
+ 2. You should see a notification: `Graphify graph ready: ...`.
94
+ 3. The supported tools should be available to the LLM. You can verify by asking: "What graphify tools are available?" or by checking the system prompt tool list.
95
+ 4. Test a slash command: type `/graphify` to open the menu, or `/graphify-status` to check graph status.
96
+ 5. Test a tool by asking: "Use the graphify graph to explain how auth works in this codebase."
97
+
98
+ ## Verify the extension without Graphify
99
+
100
+ 1. Uninstall Graphify (see below).
101
+ 2. Start Pi in a project.
102
+ 3. You should see a warning: `Graphify CLI was not detected on PATH...`.
103
+ 4. No `graphify_*` tools should be available to the LLM.
104
+ 5. `/graphify-status` should still work and report that no graph was found.
105
+
106
+ ## Uninstall the Graphify CLI
107
+
108
+ ### uv
109
+
110
+ ```bash
111
+ uv tool uninstall graphifyy
112
+ ```
113
+
114
+ ### pipx
115
+
116
+ ```bash
117
+ pipx uninstall graphifyy
118
+ ```
119
+
120
+ ### pip
121
+
122
+ ```bash
123
+ pip uninstall graphifyy
124
+ ```
125
+
126
+ After uninstalling, run `graphify --version` to confirm it is no longer on PATH.
127
+
128
+ ## Uninstall the local pi-graphify extension
129
+
130
+ ```bash
131
+ pi uninstall npm:@wwjd/pi-graphify
132
+ ```
133
+
134
+ Or remove the package manually from Pi's package directory if you installed it locally.
135
+
136
+ ## Troubleshooting
137
+
138
+ | Problem | Solution |
139
+ |---|---|
140
+ | `graphify` command not found after install | Ensure the tool bin directory is on your PATH. For `uv tool`, try `uv tool update-shell`. |
141
+ | Pi does not load the extension | Run `pi --version` and confirm the package is listed in `pi packages`. Try `/reload`. |
142
+ | Extension shows old version after changes | Run `pi install .` again, then start a fresh Pi session. |
143
+ | `graphify_status` returns "No Graphify graph found" | Build the graph first with `graphify . --code-only`. |
144
+ | Semantic extraction fails with `openai` package error | Run `graphify . --code-only` for a code-only graph, or install the `kimi` backend with `uv tool install "graphifyy[kimi]" --force`. |
145
+
146
+ ## References
147
+
148
+ - [Graphify repository](https://github.com/Graphify-Labs/graphify)
149
+ - [graphifyy on PyPI](https://pypi.org/project/graphifyy/)
150
+ - [Pi extensions documentation](https://pi.dev/docs/extensions)
@@ -4,11 +4,13 @@
4
4
  * Brings Graphify knowledge graph capabilities into Pi sessions:
5
5
  * - Detects existing graphify-out/graph.json in the project
6
6
  * - Registers LLM-callable tools (graphify_status, graphify_query, ...)
7
- * - Registers slash commands (/graphify-build, /graphify-status, ...)
7
+ * - Registers slash commands (/graphify-status, ...)
8
8
  * - Optionally watches source files for incremental rebuilds
9
9
  */
10
10
 
11
11
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
12
+ import { registerGraphifyCommands } from "../src/commands/index.js";
13
+ import { registerGraphifyMenuCommand } from "../src/commands/menu.js";
12
14
  import { GraphifyCoordinator } from "../src/coordinator.js";
13
15
  import { buildGraphifyHint, graphifyStatus } from "../src/graphify.js";
14
16
  import { registerGraphifyTools } from "../src/tools/index.js";
@@ -17,33 +19,22 @@ export default function (pi: ExtensionAPI) {
17
19
  // Coordinator is created per session and shared by tools and commands.
18
20
  let coordinator: GraphifyCoordinator | null = null;
19
21
  const getCoordinator = () => coordinator;
22
+ const registeredToolNames = new Set<string>();
20
23
 
21
- // ── 1. Register tools and commands synchronously ──────────────────
22
- registerGraphifyTools(pi, getCoordinator);
24
+ // ── 1. Register slash commands synchronously ─────────────────────
25
+ registerGraphifyCommands(pi, getCoordinator);
26
+ registerGraphifyMenuCommand(pi, getCoordinator);
23
27
 
24
- pi.registerCommand("graphify-status", {
25
- description: "Show Graphify graph status for the current project",
26
- handler: async (_args, ctx) => {
27
- const current = getCoordinator();
28
- if (!current) {
29
- ctx.ui.notify("Graphify is not initialized.", "warning");
30
- return;
31
- }
32
-
33
- const status = await current.status({ cwd: ctx.cwd });
34
- if (status.hasGraph && status.graphPath) {
35
- ctx.ui.notify(`Graphify graph ready: ${status.graphPath}`, "info");
36
- } else {
37
- ctx.ui.notify("No Graphify graph found. Run /graphify-build to create one.", "warning");
38
- }
39
- },
40
- });
41
-
42
- // ── 2. Initialize coordinator per session ─────────────────────────
28
+ // ── 2. Initialize coordinator and register tools per session ───────
29
+ // Tools are registered inside session_start so we can gate them by the
30
+ // coordinator's detected capabilities. Registering at load time would mean
31
+ // the LLM sees tools that may not be supported by the installed Graphify version.
43
32
  pi.on("session_start", async (_event, ctx) => {
44
33
  coordinator = new GraphifyCoordinator({ cwd: ctx.cwd });
45
34
  await coordinator.initialize();
46
35
 
36
+ registerGraphifyTools(pi, getCoordinator, { registeredToolNames });
37
+
47
38
  const status = await coordinator.status({ cwd: ctx.cwd });
48
39
  if (status.hasGraph && status.graphPath) {
49
40
  ctx.ui.notify(`Graphify graph ready: ${status.graphPath}`, "info");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wwjd/pi-graphify",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Graphify knowledge graph integration for Pi coding agent",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,7 +34,7 @@
34
34
  "access": "public"
35
35
  },
36
36
  "scripts": {
37
- "test": "echo \"No tests yet\" && exit 0",
37
+ "test": "node --test --import tsx src/tools/tools.test.ts src/commands/commands.test.ts src/commands/menu.test.ts src/extensions/extension-load.test.ts",
38
38
  "lint": "biome check .",
39
39
  "lint:fix": "biome check --write .",
40
40
  "format": "biome format --write .",
@@ -57,6 +57,7 @@
57
57
  "@earendil-works/pi-ai": "^0.74.0",
58
58
  "@earendil-works/pi-coding-agent": "^0.80.6",
59
59
  "@types/node": "^20.0.0",
60
+ "tsx": "^4.23.0",
60
61
  "typebox": "^1.1.24",
61
62
  "typescript": "^5.0.0"
62
63
  },
@@ -0,0 +1,47 @@
1
+ import type { GraphifyBackend, GraphifyCapabilities, GraphifyResult } from "./types.js";
2
+
3
+ export const allCapabilitiesEnabled = (): GraphifyCapabilities => ({
4
+ build: true,
5
+ query: true,
6
+ path: true,
7
+ explain: true,
8
+ affected: true,
9
+ add: true,
10
+ watch: true,
11
+ reflect: true,
12
+ mcp: true,
13
+ status: true,
14
+ version: true,
15
+ directedGraph: true,
16
+ incrementalUpdate: true,
17
+ semanticExtraction: true,
18
+ });
19
+
20
+ export interface MockBackendOptions {
21
+ version?: string;
22
+ capabilities?: GraphifyCapabilities;
23
+ run?: (operation: string, options: unknown) => Promise<GraphifyResult>;
24
+ }
25
+
26
+ export function createMockBackend(options: MockBackendOptions = {}): GraphifyBackend {
27
+ const {
28
+ version = "2.100.0",
29
+ capabilities = allCapabilitiesEnabled(),
30
+ run = async (operation) => ({
31
+ stdout: `ok: ${operation}`,
32
+ stderr: "",
33
+ exitCode: 0,
34
+ durationMs: 1,
35
+ backend: "cli",
36
+ feature: operation,
37
+ }),
38
+ } = options;
39
+
40
+ return {
41
+ type: "cli",
42
+ version,
43
+ capabilities,
44
+ run,
45
+ close: async () => {},
46
+ };
47
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * /graphify-affected — show files and nodes affected by changes to given files.
3
+ */
4
+
5
+ import { resolve } from "node:path";
6
+ import type { GraphifyCapabilities } from "../backends/types.js";
7
+ import { formatResultForCommand } from "./format.js";
8
+ import { notifyCommandError, requireCoordinatorWithCapability } from "./helpers.js";
9
+ import { splitArgs, usageError } from "./parse.js";
10
+ import type { CommandDefinition, CommandExecutor } from "./types.js";
11
+
12
+ const FEATURE: keyof GraphifyCapabilities = "affected";
13
+ const AFFECTED_USAGE = "<file> [file...]";
14
+
15
+ const executeAffected: CommandExecutor = async (ctx, getCoordinator, args) => {
16
+ if (!ctx.hasUI) return;
17
+
18
+ const coordinator = requireCoordinatorWithCapability(
19
+ ctx,
20
+ getCoordinator,
21
+ FEATURE,
22
+ "The installed Graphify version does not support affected analysis.",
23
+ );
24
+ if (!coordinator) return;
25
+
26
+ try {
27
+ const files = parseAffectedArgs(ctx.cwd, args);
28
+ const result = await coordinator.affected({ cwd: ctx.cwd, files });
29
+ ctx.ui.notify(formatResultForCommand(result), "info");
30
+ } catch (error) {
31
+ notifyCommandError(ctx, error);
32
+ }
33
+ };
34
+
35
+ export const affectedCommand: CommandDefinition = {
36
+ name: "graphify-affected",
37
+ label: "Show affected",
38
+ description: "Show files and nodes affected by changes to given files",
39
+ feature: FEATURE,
40
+ usage: AFFECTED_USAGE,
41
+ argMode: "input",
42
+ prompt: "Files to analyze",
43
+ placeholder: "src/index.ts src/utils.ts",
44
+ execute: executeAffected,
45
+ };
46
+
47
+ function parseAffectedArgs(cwd: string, args: string): string[] {
48
+ const tokens = splitArgs(args);
49
+ if (tokens.length === 0) {
50
+ throw usageError("graphify-affected", AFFECTED_USAGE);
51
+ }
52
+
53
+ return tokens.map((file) => resolveFile(cwd, file));
54
+ }
55
+
56
+ function resolveFile(cwd: string, file: string): string {
57
+ const absolute = resolve(cwd, file);
58
+ const normalizedCwd = resolve(cwd);
59
+ if (!absolute.startsWith(normalizedCwd)) {
60
+ throw new Error(`Invalid file path: ${file} is outside the project directory.`);
61
+ }
62
+ return absolute;
63
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * /graphify-build — build or update the Graphify knowledge graph.
3
+ */
4
+
5
+ import type { GraphifyCapabilities } from "../backends/types.js";
6
+ import { formatResultForCommand } from "./format.js";
7
+ import { notifyCommandError, requireCoordinatorWithCapability } from "./helpers.js";
8
+ import { parseBooleanFlag, splitArgs, usageError } from "./parse.js";
9
+ import type { CommandDefinition, CommandExecutor } from "./types.js";
10
+
11
+ const FEATURE: keyof GraphifyCapabilities = "build";
12
+ const BUILD_USAGE = "[--code-only] [--update] [--directed]";
13
+
14
+ const executeBuild: CommandExecutor = async (ctx, getCoordinator, args) => {
15
+ if (!ctx.hasUI) return;
16
+
17
+ const coordinator = requireCoordinatorWithCapability(
18
+ ctx,
19
+ getCoordinator,
20
+ FEATURE,
21
+ "The installed Graphify version does not support graph builds.",
22
+ );
23
+ if (!coordinator) return;
24
+
25
+ if (!ctx.isProjectTrusted()) {
26
+ ctx.ui.notify("Project trust is required to build the Graphify graph.", "warning");
27
+ return;
28
+ }
29
+
30
+ try {
31
+ const { codeOnly, update, directed } = parseBuildArgs(args);
32
+ const result = await coordinator.build({
33
+ cwd: ctx.cwd,
34
+ codeOnly,
35
+ update,
36
+ directed,
37
+ });
38
+ ctx.ui.notify(formatResultForCommand(result), "info");
39
+ } catch (error) {
40
+ notifyCommandError(ctx, error);
41
+ }
42
+ };
43
+
44
+ export const buildCommand: CommandDefinition = {
45
+ name: "graphify-build",
46
+ label: "Build graph",
47
+ description: "Build or incrementally update the Graphify knowledge graph",
48
+ feature: FEATURE,
49
+ usage: BUILD_USAGE,
50
+ argMode: "flags",
51
+ prompt: "Build graph (optional flags)",
52
+ placeholder: "--code-only --update --directed",
53
+ execute: executeBuild,
54
+ };
55
+
56
+ interface ParsedBuildArgs {
57
+ codeOnly: boolean | undefined;
58
+ update: boolean | undefined;
59
+ directed: boolean | undefined;
60
+ }
61
+
62
+ function parseBuildArgs(args: string): ParsedBuildArgs {
63
+ const tokens = splitArgs(args);
64
+ let result = parseBooleanFlag(tokens, "code-only", true);
65
+ const codeOnly = result.value;
66
+ result = parseBooleanFlag(result.rest, "update", true);
67
+ const update = result.value;
68
+ result = parseBooleanFlag(result.rest, "directed", true);
69
+ const directed = result.value;
70
+
71
+ const unknown = result.rest.find((t) => t.startsWith("--"));
72
+ if (unknown || result.rest.length > 0) {
73
+ throw usageError("graphify-build", BUILD_USAGE);
74
+ }
75
+
76
+ return { codeOnly, update, directed };
77
+ }