@spader/dotllm 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.
package/package.json CHANGED
@@ -1,31 +1,31 @@
1
1
  {
2
2
  "name": "@spader/dotllm",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A simple CLI to clone, manage, and link repositories for LLM reference",
5
5
  "type": "module",
6
- "bin": {
7
- "dotllm": "src/cli/index.ts"
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/tspader/dotllm"
8
9
  },
9
- "scripts": {
10
- "check": "bunx tsc --noEmit",
11
- "prepublishOnly": "bun run check"
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "bin": {
14
+ "dotllm": "src/cli/index.js"
12
15
  },
13
16
  "files": [
14
- "src/**/*.ts",
17
+ "src/**/*.js",
15
18
  "README.md"
16
19
  ],
17
20
  "exports": {
18
- "./cli": "./src/cli/index.ts",
19
- "./cli/*": "./src/cli/*.ts",
20
- "./core": "./src/core/index.ts",
21
- "./core/*": "./src/core/*.ts"
21
+ "./cli": "./src/cli/index.js",
22
+ "./cli/*": "./src/cli/*.js",
23
+ "./core": "./src/core/index.js",
24
+ "./core/*": "./src/core/*.js"
22
25
  },
23
26
  "engines": {
24
27
  "bun": ">=1.1.0"
25
28
  },
26
- "publishConfig": {
27
- "access": "public"
28
- },
29
29
  "keywords": [
30
30
  "cli",
31
31
  "bun",
@@ -39,9 +39,5 @@
39
39
  "picocolors": "^1.1.1",
40
40
  "yargs": "^17.7.2",
41
41
  "zod": "^4.3.6"
42
- },
43
- "devDependencies": {
44
- "@types/bun": "latest",
45
- "@types/yargs": "^17.0.33"
46
42
  }
47
43
  }
@@ -1,177 +1,184 @@
1
+ // @bun
2
+ // src/cli/commands/add.ts
1
3
  import fs from "fs";
2
4
  import path from "path";
3
5
  import * as prompts from "@clack/prompts";
4
6
  import { z } from "zod";
5
- import { add } from "@spader/dotllm/core";
7
+ import { add, Config } from "@spader/dotllm/core";
6
8
  import { defaultTheme as t } from "@spader/dotllm/cli/theme";
7
- import type { CommandDef } from "@spader/dotllm/cli/yargs";
8
-
9
- const RepoShape = z.object({
10
- description: z.string().nullable().optional(),
9
+ var RepoShape = z.object({
10
+ description: z.string().nullable().optional()
11
11
  });
12
-
13
- function isUrl(value: string): boolean {
14
- return value.startsWith("http://") ||
15
- value.startsWith("https://") ||
16
- value.startsWith("git@") ||
17
- value.startsWith("ssh://");
12
+ function isUrl(value) {
13
+ return value.startsWith("http://") || value.startsWith("https://") || value.startsWith("git@") || value.startsWith("ssh://");
18
14
  }
19
-
20
- function stem(value: string): string {
15
+ function stem(value) {
21
16
  const clean = value.trim().replace(/\/+$/, "");
22
- if (clean.length === 0) return "";
23
-
17
+ if (clean.length === 0)
18
+ return "";
24
19
  if (clean.startsWith("git@")) {
25
20
  const raw = clean.split(":").slice(1).join(":");
26
21
  const seg = raw.split("/").filter(Boolean).pop() ?? raw;
27
22
  return seg.replace(/\.git$/, "");
28
23
  }
29
-
30
24
  if (isUrl(clean)) {
31
25
  const seg = clean.split("/").filter(Boolean).pop() ?? clean;
32
26
  const raw = seg.split("?")[0] ?? seg;
33
27
  const full = raw.split("#")[0] ?? raw;
34
28
  return full.replace(/\.git$/, "");
35
29
  }
36
-
37
30
  const base = path.basename(clean);
38
31
  const parsed = path.parse(base);
39
- if (parsed.name.length > 0) return parsed.name;
32
+ if (parsed.name.length > 0)
33
+ return parsed.name;
40
34
  return base;
41
35
  }
42
-
43
- function github(uri: string): { owner: string; repo: string } | null {
36
+ function github(uri) {
44
37
  const https = uri.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/);
45
38
  if (https) {
46
- return { owner: https[1]!, repo: https[2]! };
39
+ return { owner: https[1], repo: https[2] };
47
40
  }
48
-
49
41
  const ssh = uri.match(/^ssh:\/\/git@github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/);
50
42
  if (ssh) {
51
- return { owner: ssh[1]!, repo: ssh[2]! };
43
+ return { owner: ssh[1], repo: ssh[2] };
52
44
  }
53
-
54
45
  const scp = uri.match(/^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/);
55
46
  if (scp) {
56
- return { owner: scp[1]!, repo: scp[2]! };
47
+ return { owner: scp[1], repo: scp[2] };
57
48
  }
58
-
59
49
  return null;
60
50
  }
61
-
62
- function gitName(uri: string): string {
51
+ function gitName(uri) {
63
52
  const dir = path.resolve(uri);
64
- if (!fs.existsSync(dir)) return "";
65
- if (!fs.statSync(dir).isDirectory()) return "";
66
-
53
+ if (!fs.existsSync(dir))
54
+ return "";
55
+ if (!fs.statSync(dir).isDirectory())
56
+ return "";
67
57
  const proc = Bun.spawnSync(["git", "remote", "get-url", "origin"], {
68
58
  cwd: dir,
69
59
  stdout: "pipe",
70
- stderr: "pipe",
60
+ stderr: "pipe"
71
61
  });
72
- if (proc.exitCode !== 0) return "";
73
-
62
+ if (proc.exitCode !== 0)
63
+ return "";
74
64
  const out = proc.stdout.toString().trim();
75
- if (out.length === 0) return "";
65
+ if (out.length === 0)
66
+ return "";
76
67
  return stem(out);
77
68
  }
78
-
79
- async function remoteDescription(uri: string): Promise<string> {
69
+ async function remoteDescription(uri) {
80
70
  const repo = github(uri);
81
- if (!repo) return "";
82
-
71
+ if (!repo)
72
+ return "";
83
73
  const url = `https://api.github.com/repos/${repo.owner}/${repo.repo}`;
84
74
  const response = await fetch(url, {
85
75
  headers: {
86
76
  accept: "application/vnd.github+json",
87
- "user-agent": "dotllm",
88
- },
77
+ "user-agent": "dotllm"
78
+ }
89
79
  });
90
- if (!response.ok) return "";
91
-
80
+ if (!response.ok)
81
+ return "";
92
82
  const raw = await response.json();
93
83
  const result = RepoShape.safeParse(raw);
94
- if (!result.success) return "";
84
+ if (!result.success)
85
+ return "";
95
86
  return result.data.description ?? "";
96
87
  }
97
-
98
- async function prefill(uri: string): Promise<{ name: string; description: string }> {
88
+ async function prefill(uri) {
99
89
  const remote = isUrl(uri);
100
90
  const git = remote ? "" : gitName(uri);
101
91
  const name = git.length > 0 ? git : stem(uri);
102
92
  const description = remote ? await remoteDescription(uri) : "";
103
93
  return { name, description };
104
94
  }
105
-
106
- async function interactive(): Promise<void> {
95
+ async function interactive(namePrefill, descPrefill) {
107
96
  const uri = await prompts.text({
108
- message: "URL or local path to a git repo",
97
+ message: "URL or local path to a git repo"
109
98
  });
110
- if (prompts.isCancel(uri)) return;
111
-
99
+ if (prompts.isCancel(uri))
100
+ return;
112
101
  const input = uri.trim();
113
102
  const seed = await prefill(input);
114
-
115
103
  const name = await prompts.text({
116
- message: "Name (leave empty to auto-detect)",
117
- defaultValue: seed.name,
104
+ message: "Name",
105
+ initialValue: namePrefill ?? seed.name
118
106
  });
119
- if (prompts.isCancel(name)) return;
120
-
107
+ if (prompts.isCancel(name))
108
+ return;
121
109
  const description = await prompts.text({
122
110
  message: "Description",
123
- defaultValue: seed.description,
111
+ initialValue: descPrefill ?? seed.description
124
112
  });
125
- if (prompts.isCancel(description)) return;
126
-
113
+ if (prompts.isCancel(description))
114
+ return;
127
115
  await run(input, name || undefined, description || undefined);
128
116
  }
129
-
130
- async function run(uri: string, name?: string, description?: string): Promise<void> {
131
- const spinner = prompts.spinner();
132
- spinner.start(`Adding ${uri}`);
133
-
134
- const result = await add(uri, name, description);
117
+ function autoLink(name) {
118
+ const localFile = path.join(".llm", "dotllm.json");
119
+ if (!fs.existsSync(localFile))
120
+ return;
121
+ const local = Config.Local.read();
122
+ if (Config.Local.has(local, name))
123
+ return;
124
+ const global = Config.Global.read();
125
+ const repo = Config.Global.find(global, name);
126
+ if (!repo)
127
+ return;
128
+ Config.Local.write(Config.Local.add(local, repo));
129
+ prompts.log.step(`linked ${t.primary(name)}`);
130
+ }
131
+ async function run(uri, name, description) {
132
+ const spinner2 = prompts.spinner();
133
+ spinner2.start(`Adding ${uri}`);
134
+ const needSeed = !name || !description;
135
+ const seed = needSeed ? await prefill(uri) : { name: "", description: "" };
136
+ const resolved = name ?? seed.name;
137
+ const desc = description ?? seed.description;
138
+ const result = await add(uri, resolved || undefined, desc || undefined);
135
139
  if (!result.ok) {
136
- spinner.stop(t.error(result.error), 1);
140
+ spinner2.stop(t.error(result.error), 1);
137
141
  process.exit(1);
138
142
  return;
139
143
  }
140
-
141
- spinner.stop(`${t.success("added")} ${t.primary(result.entry.name)} ${t.link(result.storePath)}`);
144
+ spinner2.stop(`${t.success("added")} ${t.primary(result.entry.name)} ${t.link(result.storePath)}`);
145
+ autoLink(result.entry.name);
142
146
  }
143
-
144
- export const command: CommandDef = {
147
+ var command = {
145
148
  description: "Register a git repo as a reference",
146
149
  summary: "Add a repo to the registry",
147
150
  positionals: {
148
151
  uri: {
149
152
  type: "string",
150
- description: "URL or local path to a git repo",
151
- },
153
+ description: "URL or local path to a git repo"
154
+ }
152
155
  },
153
156
  options: {
154
157
  name: {
155
158
  alias: "n",
156
159
  type: "string",
157
- description: "Name override (defaults to repo name from git)",
160
+ description: "Name override (defaults to repo name from git)"
158
161
  },
159
162
  description: {
160
163
  alias: "d",
161
164
  type: "string",
162
- description: "Description of the reference",
163
- },
165
+ description: "Description of the reference"
166
+ }
164
167
  },
165
168
  handler: async (argv) => {
169
+ prompts.intro("dotllm add");
166
170
  const uri = typeof argv.uri === "string" && argv.uri.length > 0 ? argv.uri : undefined;
167
-
171
+ const name = typeof argv.name === "string" && argv.name.length > 0 ? argv.name : undefined;
172
+ const description = typeof argv.description === "string" && argv.description.length > 0 ? argv.description : undefined;
168
173
  if (!uri) {
169
- await interactive();
174
+ await interactive(name, description);
170
175
  return;
171
176
  }
172
-
173
- const name = typeof argv.name === "string" && argv.name.length > 0 ? argv.name : undefined;
174
- const description = typeof argv.description === "string" ? argv.description : undefined;
175
177
  await run(uri, name, description);
176
- },
178
+ }
179
+ };
180
+ export {
181
+ stem,
182
+ github,
183
+ command
177
184
  };
@@ -0,0 +1,45 @@
1
+ // @bun
2
+ // src/cli/commands/cd.ts
3
+ import path from "path";
4
+ import fs from "fs";
5
+ import { Config } from "@spader/dotllm/core";
6
+ import { defaultTheme as t } from "@spader/dotllm/cli/theme";
7
+ var command = {
8
+ description: "Open a subshell in a repo's store directory",
9
+ summary: "cd into a repo",
10
+ positionals: {
11
+ name: {
12
+ type: "string",
13
+ description: "Name of the repo",
14
+ required: true
15
+ }
16
+ },
17
+ handler: async (argv) => {
18
+ const name = String(argv.name);
19
+ const global = Config.Global.read();
20
+ const repo = Config.Global.find(global, name);
21
+ if (!repo) {
22
+ console.error(t.error(`No repo named "${name}" in registry`));
23
+ process.exit(1);
24
+ return;
25
+ }
26
+ const dir = path.join(Config.storeDir(), name);
27
+ if (!fs.existsSync(dir)) {
28
+ console.error(t.error(`Store path does not exist: ${dir}`));
29
+ process.exit(1);
30
+ return;
31
+ }
32
+ const shell = process.env.SHELL ?? "/bin/sh";
33
+ const proc = Bun.spawn([shell], {
34
+ cwd: dir,
35
+ stdin: "inherit",
36
+ stdout: "inherit",
37
+ stderr: "inherit"
38
+ });
39
+ const code = await proc.exited;
40
+ process.exit(code);
41
+ }
42
+ };
43
+ export {
44
+ command
45
+ };
@@ -0,0 +1,18 @@
1
+ // @bun
2
+ // src/cli/commands/index.ts
3
+ import { command } from "@spader/dotllm/cli/commands/add";
4
+ import { command as command2 } from "@spader/dotllm/cli/commands/remove";
5
+ import { command as command3 } from "@spader/dotllm/cli/commands/list";
6
+ import { command as command4 } from "@spader/dotllm/cli/commands/link";
7
+ import { command as command5 } from "@spader/dotllm/cli/commands/sync";
8
+ import { command as command6 } from "@spader/dotllm/cli/commands/which";
9
+ import { command as command7 } from "@spader/dotllm/cli/commands/cd";
10
+ export {
11
+ command6 as which,
12
+ command5 as sync,
13
+ command2 as remove,
14
+ command3 as list,
15
+ command4 as link,
16
+ command7 as cd,
17
+ command as add
18
+ };
@@ -0,0 +1,89 @@
1
+ // @bun
2
+ // src/cli/commands/link.ts
3
+ import * as prompts from "@clack/prompts";
4
+ import { Config, link, unlink, sync } from "@spader/dotllm/core";
5
+ import { defaultTheme as t } from "@spader/dotllm/cli/theme";
6
+ function printResult(result) {
7
+ const parts = [];
8
+ if (result.linked.length > 0)
9
+ parts.push(`${result.linked.length} added`);
10
+ if (result.removed.length > 0)
11
+ parts.push(`${result.removed.length} removed`);
12
+ if (result.unchanged.length > 0)
13
+ parts.push(`${result.unchanged.length} unchanged`);
14
+ if (parts.length === 0)
15
+ return;
16
+ prompts.log.step(parts.join(", "));
17
+ }
18
+ var command = {
19
+ description: "Interactively pick repos to link into .llm/reference/, or add/remove one by name",
20
+ summary: "Link references",
21
+ positionals: {
22
+ name: {
23
+ type: "string",
24
+ description: "Name of the repo to link, or omit for interactive"
25
+ }
26
+ },
27
+ options: {
28
+ remove: {
29
+ alias: "r",
30
+ type: "boolean",
31
+ description: "Remove the link instead of adding it"
32
+ }
33
+ },
34
+ handler: async (argv) => {
35
+ prompts.intro("dotllm link");
36
+ const name = typeof argv.name === "string" && argv.name.length > 0 ? argv.name : undefined;
37
+ const shouldRemove = argv.remove === true;
38
+ if (name) {
39
+ if (shouldRemove) {
40
+ const result = unlink(name);
41
+ if (!result.ok) {
42
+ prompts.log.error(t.error(result.error));
43
+ process.exit(1);
44
+ return;
45
+ }
46
+ prompts.log.step(`unlinked ${t.primary(name)}`);
47
+ return;
48
+ }
49
+ const global2 = Config.Global.read();
50
+ const repo = Config.Global.find(global2, name);
51
+ if (!repo) {
52
+ prompts.log.error(t.error(`No repo named "${name}" in registry`));
53
+ process.exit(1);
54
+ return;
55
+ }
56
+ const local2 = Config.Local.read();
57
+ Config.Local.write(Config.Local.add(local2, repo));
58
+ printResult(sync());
59
+ return;
60
+ }
61
+ const global = Config.Global.read();
62
+ if (global.repos.length === 0) {
63
+ console.log(t.dim("(no repos registered)"));
64
+ console.log(t.dim("use `dotllm add <path>` to register one"));
65
+ return;
66
+ }
67
+ const local = Config.Local.read();
68
+ const current = new Set(Object.keys(local.refs));
69
+ const selected = await prompts.multiselect({
70
+ message: "Select repos to link into .llm/reference/",
71
+ options: global.repos.map((r) => ({
72
+ value: r.name,
73
+ label: r.name,
74
+ hint: r.uri
75
+ })),
76
+ initialValues: global.repos.filter((r) => current.has(r.name)).map((r) => r.name),
77
+ required: false
78
+ });
79
+ if (prompts.isCancel(selected)) {
80
+ prompts.cancel("cancelled");
81
+ return;
82
+ }
83
+ const names = Array.isArray(selected) ? selected.filter((value) => typeof value === "string") : [];
84
+ printResult(link(names));
85
+ }
86
+ };
87
+ export {
88
+ command
89
+ };
@@ -0,0 +1,42 @@
1
+ // @bun
2
+ // src/cli/commands/list.ts
3
+ import * as prompts from "@clack/prompts";
4
+ import { Config } from "@spader/dotllm/core";
5
+ import { table } from "@spader/dotllm/cli/layout";
6
+ import { defaultTheme as t } from "@spader/dotllm/cli/theme";
7
+ var command = {
8
+ description: "List all registered repos",
9
+ summary: "Show the registry",
10
+ handler: () => {
11
+ prompts.intro("dotllm list");
12
+ const global = Config.Global.read();
13
+ if (global.repos.length === 0) {
14
+ console.log(t.dim("(no repos registered)"));
15
+ console.log(t.dim("use `dotllm add <path>` to register one"));
16
+ return;
17
+ }
18
+ const local = Config.Local.read();
19
+ const linked = new Set(Object.keys(local.refs));
20
+ table(["name", "kind", "uri", "description", "linked"], [
21
+ global.repos.map((r) => r.name),
22
+ global.repos.map((r) => r.kind),
23
+ global.repos.map((r) => r.uri),
24
+ global.repos.map((r) => r.description),
25
+ global.repos.map((r) => linked.has(r.name) ? "yes" : "no")
26
+ ], {
27
+ flex: [0, 0, 1, 1, 0],
28
+ noTruncate: [true, true, false, false, true],
29
+ truncate: ["end", "end", "start", "end", "end"],
30
+ format: [
31
+ (s) => t.primary(s),
32
+ (s) => s,
33
+ (s) => t.link(s),
34
+ (s) => s,
35
+ (s) => s.trim() === "yes" ? t.success(s) : s
36
+ ]
37
+ });
38
+ }
39
+ };
40
+ export {
41
+ command
42
+ };
@@ -1,28 +1,30 @@
1
- import { log } from "@clack/prompts";
1
+ // @bun
2
+ // src/cli/commands/remove.ts
3
+ import * as prompts from "@clack/prompts";
2
4
  import { remove } from "@spader/dotllm/core";
3
5
  import { defaultTheme as t } from "@spader/dotllm/cli/theme";
4
- import type { CommandDef } from "@spader/dotllm/cli/yargs";
5
-
6
- export const command: CommandDef = {
6
+ var command = {
7
7
  description: "Remove a repo from the registry",
8
8
  summary: "Remove a registered repo",
9
9
  positionals: {
10
10
  name: {
11
11
  type: "string",
12
12
  description: "Name of the reference to remove",
13
- required: true,
14
- },
13
+ required: true
14
+ }
15
15
  },
16
16
  handler: (argv) => {
17
+ prompts.intro("dotllm remove");
17
18
  const name = String(argv.name);
18
-
19
19
  const result = remove(name);
20
20
  if (!result.ok) {
21
- log.error(t.error(result.error));
21
+ prompts.log.error(t.error(result.error));
22
22
  process.exit(1);
23
23
  return;
24
24
  }
25
-
26
- log.step(`removed ${t.primary(name)}`);
27
- },
25
+ prompts.log.step(`removed ${t.primary(name)}`);
26
+ }
27
+ };
28
+ export {
29
+ command
28
30
  };
@@ -0,0 +1,45 @@
1
+ // @bun
2
+ // src/cli/commands/sync.ts
3
+ import * as prompts from "@clack/prompts";
4
+ import { pull, sync } from "@spader/dotllm/core";
5
+ import { defaultTheme as t } from "@spader/dotllm/cli/theme";
6
+ var command = {
7
+ description: "Re-create symlinks from .llm/dotllm.json",
8
+ summary: "Sync symlinks from local config",
9
+ handler: async () => {
10
+ prompts.intro("dotllm sync");
11
+ const result = sync();
12
+ if (result.linked.length === 0 && result.removed.length === 0 && result.missing.length === 0 && result.unchanged.length === 0) {
13
+ console.log(t.dim("(no refs in local config)"));
14
+ console.log(t.dim("use `dotllm link` to select repos"));
15
+ return;
16
+ }
17
+ const parts = [];
18
+ if (result.linked.length > 0)
19
+ parts.push(`${result.linked.length} added`);
20
+ if (result.removed.length > 0)
21
+ parts.push(`${result.removed.length} removed`);
22
+ if (result.unchanged.length > 0)
23
+ parts.push(`${result.unchanged.length} unchanged`);
24
+ if (result.missing.length > 0)
25
+ parts.push(`${result.missing.length} missing`);
26
+ if (parts.length > 0)
27
+ prompts.log.step(parts.join(", "));
28
+ const refs = [...new Set([...result.unchanged, ...result.linked])];
29
+ if (refs.length === 0) {
30
+ return;
31
+ }
32
+ const spinner2 = prompts.spinner();
33
+ spinner2.start(`Pulling ${refs.length} linked repo${refs.length === 1 ? "" : "s"}`);
34
+ const pulled = await pull(refs);
35
+ if (pulled.failed.length > 0) {
36
+ spinner2.stop(t.error(`pull failed for ${pulled.failed.length} repo${pulled.failed.length === 1 ? "" : "s"}`), 1);
37
+ process.exit(1);
38
+ return;
39
+ }
40
+ spinner2.stop(`${t.success("pulled")} ${pulled.count} repo${pulled.count === 1 ? "" : "s"}`);
41
+ }
42
+ };
43
+ export {
44
+ command
45
+ };
@@ -0,0 +1,30 @@
1
+ // @bun
2
+ // src/cli/commands/which.ts
3
+ import path from "path";
4
+ import { Config } from "@spader/dotllm/core";
5
+ import { defaultTheme as t } from "@spader/dotllm/cli/theme";
6
+ var command = {
7
+ description: "Print the absolute path to a repo in the store",
8
+ summary: "Show repo store path",
9
+ positionals: {
10
+ name: {
11
+ type: "string",
12
+ description: "Name of the repo",
13
+ required: true
14
+ }
15
+ },
16
+ handler: (argv) => {
17
+ const name = String(argv.name);
18
+ const global = Config.Global.read();
19
+ const repo = Config.Global.find(global, name);
20
+ if (!repo) {
21
+ console.error(t.error(`No repo named "${name}" in registry`));
22
+ process.exit(1);
23
+ return;
24
+ }
25
+ console.log(path.join(Config.storeDir(), name));
26
+ }
27
+ };
28
+ export {
29
+ command
30
+ };
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+
4
+ // src/cli/index.ts
5
+ import { build } from "@spader/dotllm/cli/yargs";
6
+ import { add, remove, list, link, sync, which, cd } from "@spader/dotllm/cli/commands/index";
7
+ var DotLlmCli;
8
+ ((DotLlmCli) => {
9
+ DotLlmCli.def = {
10
+ name: "dotllm",
11
+ description: "Manage git repo references symlinked into .llm/reference/",
12
+ commands: {
13
+ add,
14
+ remove,
15
+ list,
16
+ link,
17
+ sync,
18
+ which,
19
+ cd
20
+ }
21
+ };
22
+ function run() {
23
+ build(DotLlmCli.def).parse();
24
+ }
25
+ DotLlmCli.run = run;
26
+ })(DotLlmCli ||= {});
27
+ DotLlmCli.run();
28
+ export {
29
+ DotLlmCli
30
+ };