@oh-my-pi/cli 0.3.0 → 0.5.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 (108) hide show
  1. package/README.md +79 -84
  2. package/dist/cli.js +5025 -1016
  3. package/dist/commands/config.d.ts +27 -0
  4. package/dist/commands/config.d.ts.map +1 -1
  5. package/dist/commands/create.d.ts.map +1 -1
  6. package/dist/commands/doctor.d.ts +2 -0
  7. package/dist/commands/doctor.d.ts.map +1 -1
  8. package/dist/commands/env.d.ts.map +1 -1
  9. package/dist/commands/features.d.ts.map +1 -1
  10. package/dist/commands/info.d.ts.map +1 -1
  11. package/dist/commands/init.d.ts.map +1 -1
  12. package/dist/commands/install.d.ts +6 -0
  13. package/dist/commands/install.d.ts.map +1 -1
  14. package/dist/commands/link.d.ts +1 -0
  15. package/dist/commands/link.d.ts.map +1 -1
  16. package/dist/commands/list.d.ts.map +1 -1
  17. package/dist/commands/outdated.d.ts.map +1 -1
  18. package/dist/commands/search.d.ts.map +1 -1
  19. package/dist/commands/uninstall.d.ts +3 -0
  20. package/dist/commands/uninstall.d.ts.map +1 -1
  21. package/dist/commands/update.d.ts +1 -0
  22. package/dist/commands/update.d.ts.map +1 -1
  23. package/dist/commands/why.d.ts.map +1 -1
  24. package/dist/conflicts.d.ts +7 -2
  25. package/dist/conflicts.d.ts.map +1 -1
  26. package/dist/index.d.ts +1 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/lock.d.ts.map +1 -1
  29. package/dist/lockfile.d.ts +24 -3
  30. package/dist/lockfile.d.ts.map +1 -1
  31. package/dist/manifest.d.ts +12 -1
  32. package/dist/manifest.d.ts.map +1 -1
  33. package/dist/npm.d.ts +11 -0
  34. package/dist/npm.d.ts.map +1 -1
  35. package/dist/output.d.ts +51 -0
  36. package/dist/output.d.ts.map +1 -0
  37. package/dist/paths.d.ts +5 -0
  38. package/dist/paths.d.ts.map +1 -1
  39. package/dist/progress.d.ts +78 -0
  40. package/dist/progress.d.ts.map +1 -0
  41. package/dist/runtime.d.ts.map +1 -1
  42. package/dist/symlinks.d.ts +1 -0
  43. package/dist/symlinks.d.ts.map +1 -1
  44. package/package.json +24 -10
  45. package/.github/icon.png +0 -0
  46. package/.github/logo.png +0 -0
  47. package/.github/workflows/ci.yml +0 -32
  48. package/.github/workflows/publish.yml +0 -42
  49. package/biome.json +0 -29
  50. package/bun.lock +0 -109
  51. package/plugins/exa/README.md +0 -153
  52. package/plugins/exa/package.json +0 -56
  53. package/plugins/exa/tools/exa/company.ts +0 -35
  54. package/plugins/exa/tools/exa/index.ts +0 -66
  55. package/plugins/exa/tools/exa/linkedin.ts +0 -35
  56. package/plugins/exa/tools/exa/researcher.ts +0 -40
  57. package/plugins/exa/tools/exa/runtime.json +0 -4
  58. package/plugins/exa/tools/exa/search.ts +0 -46
  59. package/plugins/exa/tools/exa/shared.ts +0 -230
  60. package/plugins/exa/tools/exa/websets.ts +0 -62
  61. package/plugins/metal-theme/README.md +0 -13
  62. package/plugins/metal-theme/omp.json +0 -8
  63. package/plugins/metal-theme/package.json +0 -19
  64. package/plugins/metal-theme/themes/metal.json +0 -79
  65. package/plugins/subagents/README.md +0 -25
  66. package/plugins/subagents/agents/explore.md +0 -71
  67. package/plugins/subagents/agents/planner.md +0 -51
  68. package/plugins/subagents/agents/reviewer.md +0 -53
  69. package/plugins/subagents/agents/task.md +0 -46
  70. package/plugins/subagents/commands/architect-plan.md +0 -9
  71. package/plugins/subagents/commands/implement-with-critic.md +0 -10
  72. package/plugins/subagents/commands/implement.md +0 -10
  73. package/plugins/subagents/omp.json +0 -15
  74. package/plugins/subagents/package.json +0 -26
  75. package/plugins/subagents/tools/task/index.ts +0 -1019
  76. package/plugins/user-prompt/README.md +0 -130
  77. package/plugins/user-prompt/package.json +0 -19
  78. package/plugins/user-prompt/tools/user-prompt/index.ts +0 -235
  79. package/scripts/bump-version.sh +0 -52
  80. package/scripts/publish.sh +0 -35
  81. package/src/cli.ts +0 -242
  82. package/src/commands/config.ts +0 -384
  83. package/src/commands/create.ts +0 -203
  84. package/src/commands/doctor.ts +0 -305
  85. package/src/commands/enable.ts +0 -122
  86. package/src/commands/env.ts +0 -38
  87. package/src/commands/features.ts +0 -295
  88. package/src/commands/info.ts +0 -120
  89. package/src/commands/init.ts +0 -60
  90. package/src/commands/install.ts +0 -700
  91. package/src/commands/link.ts +0 -159
  92. package/src/commands/list.ts +0 -186
  93. package/src/commands/outdated.ts +0 -87
  94. package/src/commands/search.ts +0 -77
  95. package/src/commands/uninstall.ts +0 -124
  96. package/src/commands/update.ts +0 -170
  97. package/src/commands/why.ts +0 -136
  98. package/src/conflicts.ts +0 -116
  99. package/src/errors.ts +0 -22
  100. package/src/index.ts +0 -46
  101. package/src/lock.ts +0 -46
  102. package/src/lockfile.ts +0 -132
  103. package/src/manifest.ts +0 -360
  104. package/src/npm.ts +0 -206
  105. package/src/paths.ts +0 -137
  106. package/src/runtime.ts +0 -116
  107. package/src/symlinks.ts +0 -455
  108. package/tsconfig.json +0 -28
@@ -1,295 +0,0 @@
1
- import { checkbox } from "@inquirer/prompts";
2
- import { loadPluginsJson, readPluginPackageJson, savePluginsJson } from "@omp/manifest";
3
- import { resolveScope } from "@omp/paths";
4
- import { getDefaultFeatures, getRuntimeConfigPath, readRuntimeConfig, writeRuntimeConfig } from "@omp/symlinks";
5
- import chalk from "chalk";
6
-
7
- export interface FeaturesOptions {
8
- global?: boolean;
9
- local?: boolean;
10
- json?: boolean;
11
- enable?: string[];
12
- disable?: string[];
13
- set?: string;
14
- }
15
-
16
- /**
17
- * Interactive feature selection for a plugin
18
- * omp features @oh-my-pi/exa
19
- */
20
- export async function interactiveFeatures(name: string, options: FeaturesOptions = {}): Promise<void> {
21
- const isGlobal = resolveScope(options);
22
- const pluginsJson = await loadPluginsJson(isGlobal);
23
-
24
- // Check if plugin exists
25
- if (!pluginsJson.plugins[name]) {
26
- console.log(chalk.yellow(`Plugin "${name}" is not installed.`));
27
- process.exitCode = 1;
28
- return;
29
- }
30
-
31
- const pkgJson = await readPluginPackageJson(name, isGlobal);
32
- if (!pkgJson) {
33
- console.log(chalk.red(`Could not read package.json for ${name}`));
34
- process.exitCode = 1;
35
- return;
36
- }
37
-
38
- const features = pkgJson.omp?.features;
39
- if (!features || Object.keys(features).length === 0) {
40
- console.log(chalk.yellow(`Plugin "${name}" has no configurable features.`));
41
- return;
42
- }
43
-
44
- // Get runtime config path and current enabled features
45
- const runtimePath = getRuntimeConfigPath(pkgJson, isGlobal);
46
- if (!runtimePath) {
47
- console.log(chalk.yellow(`Plugin "${name}" does not have a runtime.json config file.`));
48
- return;
49
- }
50
-
51
- const runtimeConfig = readRuntimeConfig(runtimePath);
52
- const enabledFeatures = runtimeConfig.features ?? getDefaultFeatures(features);
53
-
54
- // JSON output mode - just list
55
- if (options.json) {
56
- console.log(
57
- JSON.stringify(
58
- {
59
- plugin: name,
60
- features: Object.entries(features).map(([fname, fdef]) => ({
61
- name: fname,
62
- enabled: enabledFeatures.includes(fname),
63
- default: fdef.default !== false,
64
- description: fdef.description,
65
- variables: fdef.variables ? Object.keys(fdef.variables) : [],
66
- })),
67
- },
68
- null,
69
- 2,
70
- ),
71
- );
72
- return;
73
- }
74
-
75
- // Non-interactive mode - just list
76
- if (!process.stdout.isTTY || !process.stdin.isTTY) {
77
- listFeaturesNonInteractive(name, features, enabledFeatures);
78
- return;
79
- }
80
-
81
- // Interactive mode - checkbox prompt
82
- console.log(chalk.bold(`\nConfigure features for ${name}:\n`));
83
-
84
- const choices = Object.entries(features).map(([fname, fdef]) => {
85
- const optIn = fdef.default === false ? chalk.dim(" (opt-in)") : "";
86
- const desc = fdef.description ? chalk.dim(` - ${fdef.description}`) : "";
87
- return {
88
- name: `${fname}${optIn}${desc}`,
89
- value: fname,
90
- checked: enabledFeatures.includes(fname),
91
- };
92
- });
93
-
94
- try {
95
- const selected = await checkbox({
96
- message: "Select features to enable:",
97
- choices,
98
- pageSize: 15,
99
- });
100
-
101
- // Apply changes
102
- await applyFeatureChanges(name, runtimePath, features, enabledFeatures, selected);
103
- } catch (err) {
104
- // User cancelled (Ctrl+C)
105
- console.log(chalk.dim("\nCancelled."));
106
- }
107
- }
108
-
109
- /**
110
- * Non-interactive feature listing
111
- */
112
- function listFeaturesNonInteractive(
113
- name: string,
114
- features: Record<string, { description?: string; default?: boolean; variables?: Record<string, unknown> }>,
115
- enabledFeatures: string[],
116
- ): void {
117
- console.log(chalk.bold(`\nFeatures for ${name}:\n`));
118
-
119
- for (const [fname, fdef] of Object.entries(features)) {
120
- const isEnabled = enabledFeatures.includes(fname);
121
- const icon = isEnabled ? chalk.green("✓") : chalk.gray("○");
122
- const defaultStr = fdef.default === false ? chalk.dim(" (opt-in)") : "";
123
-
124
- console.log(`${icon} ${chalk.bold(fname)}${defaultStr}`);
125
- if (fdef.description) {
126
- console.log(chalk.dim(` ${fdef.description}`));
127
- }
128
- if (fdef.variables && Object.keys(fdef.variables).length > 0) {
129
- console.log(chalk.dim(` Variables: ${Object.keys(fdef.variables).join(", ")}`));
130
- }
131
- }
132
-
133
- console.log();
134
- console.log(chalk.dim(`Configure with: omp features ${name} --enable <feature> --disable <feature>`));
135
- console.log(chalk.dim(`Or set exactly: omp features ${name} --set feature1,feature2`));
136
- }
137
-
138
- /**
139
- * Apply feature changes - update both plugins.json (for config/env) and runtime.json (for runtime)
140
- */
141
- async function applyFeatureChanges(
142
- name: string,
143
- runtimePath: string,
144
- features: Record<string, { description?: string; default?: boolean; variables?: Record<string, unknown> }>,
145
- currentlyEnabled: string[],
146
- newEnabled: string[],
147
- isGlobal: boolean,
148
- ): Promise<void> {
149
- // Compute what changed
150
- const toDisable = currentlyEnabled.filter((f) => !newEnabled.includes(f));
151
- const toEnable = newEnabled.filter((f) => !currentlyEnabled.includes(f));
152
-
153
- if (toDisable.length === 0 && toEnable.length === 0) {
154
- console.log(chalk.yellow("\nNo changes to feature configuration."));
155
- return;
156
- }
157
-
158
- console.log(chalk.blue(`\nApplying changes...`));
159
-
160
- if (toDisable.length > 0) {
161
- console.log(chalk.dim(` Disabling: ${toDisable.join(", ")}`));
162
- }
163
- if (toEnable.length > 0) {
164
- console.log(chalk.dim(` Enabling: ${toEnable.join(", ")}`));
165
- }
166
-
167
- // Update plugins.json (source of truth for config/env commands)
168
- const pluginsJson = await loadPluginsJson(isGlobal);
169
- if (!pluginsJson.config) pluginsJson.config = {};
170
- if (!pluginsJson.config[name]) pluginsJson.config[name] = {};
171
- pluginsJson.config[name].features = newEnabled;
172
- await savePluginsJson(pluginsJson, isGlobal);
173
-
174
- // Also write to runtime.json (for runtime feature detection)
175
- await writeRuntimeConfig(runtimePath, { features: newEnabled });
176
-
177
- console.log(chalk.green(`\n✓ Features updated`));
178
- if (newEnabled.length > 0) {
179
- console.log(chalk.dim(` Enabled: ${newEnabled.join(", ")}`));
180
- } else {
181
- console.log(chalk.dim(` Enabled: none`));
182
- }
183
- }
184
-
185
- /**
186
- * Configure features for an installed plugin via CLI flags
187
- * omp features @oh-my-pi/exa --enable websets --disable search
188
- * omp features @oh-my-pi/exa --set search,websets
189
- */
190
- export async function configureFeatures(name: string, options: FeaturesOptions = {}): Promise<void> {
191
- const isGlobal = resolveScope(options);
192
- const pluginsJson = await loadPluginsJson(isGlobal);
193
-
194
- // Check if plugin exists
195
- if (!pluginsJson.plugins[name]) {
196
- console.log(chalk.yellow(`Plugin "${name}" is not installed.`));
197
- process.exitCode = 1;
198
- return;
199
- }
200
-
201
- const pkgJson = await readPluginPackageJson(name, isGlobal);
202
- if (!pkgJson) {
203
- console.log(chalk.red(`Could not read package.json for ${name}`));
204
- process.exitCode = 1;
205
- return;
206
- }
207
-
208
- const features = pkgJson.omp?.features;
209
- if (!features || Object.keys(features).length === 0) {
210
- console.log(chalk.yellow(`Plugin "${name}" has no configurable features.`));
211
- process.exitCode = 1;
212
- return;
213
- }
214
-
215
- const allFeatureNames = Object.keys(features);
216
-
217
- // Get runtime config
218
- const runtimePath = getRuntimeConfigPath(pkgJson, isGlobal);
219
- if (!runtimePath) {
220
- console.log(chalk.yellow(`Plugin "${name}" does not have a runtime.json config file.`));
221
- process.exitCode = 1;
222
- return;
223
- }
224
-
225
- const runtimeConfig = readRuntimeConfig(runtimePath);
226
- const currentlyEnabled = runtimeConfig.features ?? getDefaultFeatures(features);
227
-
228
- let newEnabled: string[];
229
-
230
- // Handle --set (explicit list)
231
- if (options.set !== undefined) {
232
- if (options.set === "*") {
233
- newEnabled = allFeatureNames;
234
- } else if (options.set === "") {
235
- newEnabled = [];
236
- } else {
237
- newEnabled = options.set.split(",").map((f) => f.trim()).filter(Boolean);
238
- // Validate
239
- for (const f of newEnabled) {
240
- if (!features[f]) {
241
- console.log(chalk.red(`Unknown feature "${f}". Available: ${allFeatureNames.join(", ")}`));
242
- process.exitCode = 1;
243
- return;
244
- }
245
- }
246
- }
247
- } else {
248
- // Handle --enable and --disable
249
- newEnabled = [...currentlyEnabled];
250
-
251
- if (options.enable) {
252
- for (const f of options.enable) {
253
- if (!features[f]) {
254
- console.log(chalk.red(`Unknown feature "${f}". Available: ${allFeatureNames.join(", ")}`));
255
- process.exitCode = 1;
256
- return;
257
- }
258
- if (!newEnabled.includes(f)) {
259
- newEnabled.push(f);
260
- }
261
- }
262
- }
263
-
264
- if (options.disable) {
265
- for (const f of options.disable) {
266
- if (!features[f]) {
267
- console.log(chalk.red(`Unknown feature "${f}". Available: ${allFeatureNames.join(", ")}`));
268
- process.exitCode = 1;
269
- return;
270
- }
271
- newEnabled = newEnabled.filter((e) => e !== f);
272
- }
273
- }
274
- }
275
-
276
- await applyFeatureChanges(name, runtimePath, features, currentlyEnabled, newEnabled);
277
-
278
- if (options.json) {
279
- console.log(JSON.stringify({ plugin: name, enabled: newEnabled }, null, 2));
280
- }
281
- }
282
-
283
- /**
284
- * Main features command handler
285
- * Routes to interactive or configure based on options
286
- */
287
- export async function featuresCommand(name: string, options: FeaturesOptions = {}): Promise<void> {
288
- // If any modification options are passed, configure via CLI
289
- if (options.enable || options.disable || options.set !== undefined) {
290
- await configureFeatures(name, options);
291
- } else {
292
- // Otherwise, show interactive UI (or list in non-TTY mode)
293
- await interactiveFeatures(name, options);
294
- }
295
- }
@@ -1,120 +0,0 @@
1
- import { npmInfo } from "@omp/npm";
2
- import chalk from "chalk";
3
-
4
- export interface InfoOptions {
5
- json?: boolean;
6
- versions?: boolean;
7
- allVersions?: boolean;
8
- }
9
-
10
- /**
11
- * Show detailed info about a package before install
12
- */
13
- export async function showInfo(packageName: string, options: InfoOptions = {}): Promise<void> {
14
- console.log(chalk.blue(`Fetching info for ${packageName}...`));
15
-
16
- try {
17
- const info = await npmInfo(packageName);
18
-
19
- if (!info) {
20
- console.log(chalk.red(`Package not found: ${packageName}`));
21
- process.exitCode = 1;
22
- return;
23
- }
24
-
25
- if (options.json) {
26
- console.log(JSON.stringify(info, null, 2));
27
- return;
28
- }
29
-
30
- console.log();
31
- console.log(chalk.bold.green(info.name) + chalk.dim(` v${info.version}`));
32
- console.log();
33
-
34
- if (info.description) {
35
- console.log(chalk.white(info.description));
36
- console.log();
37
- }
38
-
39
- // Author
40
- if (info.author) {
41
- const authorStr =
42
- typeof info.author === "string"
43
- ? info.author
44
- : `${info.author.name}${info.author.email ? ` <${info.author.email}>` : ""}`;
45
- console.log(chalk.dim("author: ") + authorStr);
46
- }
47
-
48
- // Homepage
49
- if (info.homepage) {
50
- console.log(chalk.dim("homepage: ") + info.homepage);
51
- }
52
-
53
- // Repository
54
- if (info.repository) {
55
- const repoUrl = typeof info.repository === "string" ? info.repository : info.repository.url;
56
- console.log(chalk.dim("repo: ") + repoUrl);
57
- }
58
-
59
- // Keywords
60
- if (info.keywords?.length) {
61
- console.log(chalk.dim("keywords: ") + info.keywords.join(", "));
62
- }
63
-
64
- // Dependencies
65
- if (info.dependencies && Object.keys(info.dependencies).length > 0) {
66
- console.log(chalk.dim("\ndependencies:"));
67
- for (const [depName, depVersion] of Object.entries(info.dependencies)) {
68
- console.log(chalk.dim(` ${depName}: ${depVersion}`));
69
- }
70
- }
71
-
72
- // Is it an omp plugin?
73
- const isOmpPlugin = info.keywords?.includes("omp-plugin");
74
- if (isOmpPlugin) {
75
- console.log(chalk.green("\n✓ This is an omp plugin"));
76
- } else {
77
- console.log(chalk.yellow("\n⚠ This package does not have the omp-plugin keyword"));
78
- console.log(chalk.dim(" It may work, but might not have omp.install configuration"));
79
- }
80
-
81
- // Show what files will be installed
82
- if (info.omp?.install?.length) {
83
- console.log(chalk.dim("\nFiles to install:"));
84
- for (const entry of info.omp.install) {
85
- console.log(chalk.dim(` ${entry.src} → ${entry.dest}`));
86
- }
87
- }
88
-
89
- // Versions
90
- if (options.versions || options.allVersions) {
91
- if (info["dist-tags"]) {
92
- console.log(chalk.dim("\ndist-tags:"));
93
- for (const [tag, version] of Object.entries(info["dist-tags"])) {
94
- console.log(chalk.dim(` ${tag}: `) + version);
95
- }
96
- }
97
-
98
- if (info.versions?.length) {
99
- console.log(chalk.dim("\nall versions:"));
100
- if (options.allVersions) {
101
- // Show all versions
102
- console.log(chalk.dim(` ${info.versions.join(", ")}`));
103
- } else {
104
- // Show last 10
105
- const versionsToShow = info.versions.slice(-10);
106
- console.log(chalk.dim(` ${versionsToShow.join(", ")}`));
107
- if (info.versions.length > 10) {
108
- console.log(chalk.dim(` ... and ${info.versions.length - 10} more (use --all-versions to see all)`));
109
- }
110
- }
111
- }
112
- }
113
-
114
- console.log();
115
- console.log(chalk.dim(`Install with: omp install ${packageName}`));
116
- } catch (err) {
117
- console.log(chalk.red(`Error fetching info: ${(err as Error).message}`));
118
- process.exitCode = 1;
119
- }
120
- }
@@ -1,60 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { mkdir, writeFile } from "node:fs/promises";
3
- import { PROJECT_PI_DIR, PROJECT_PLUGINS_JSON } from "@omp/paths";
4
- import chalk from "chalk";
5
-
6
- /**
7
- * Format permission-related errors with actionable guidance
8
- */
9
- function formatPermissionError(err: NodeJS.ErrnoException, path: string): string {
10
- if (err.code === "EACCES" || err.code === "EPERM") {
11
- return `Permission denied: Cannot write to ${path}. Check directory permissions or run with appropriate privileges.`;
12
- }
13
- return err.message;
14
- }
15
-
16
- export interface InitOptions {
17
- force?: boolean;
18
- }
19
-
20
- /**
21
- * Initialize .pi/plugins.json in current project
22
- */
23
- export async function initProject(options: InitOptions = {}): Promise<void> {
24
- // Check if already exists
25
- if (existsSync(PROJECT_PLUGINS_JSON) && !options.force) {
26
- console.log(chalk.yellow(`${PROJECT_PLUGINS_JSON} already exists.`));
27
- console.log(chalk.dim("Use --force to overwrite"));
28
- process.exitCode = 1;
29
- return;
30
- }
31
-
32
- try {
33
- // Create .pi directory
34
- await mkdir(PROJECT_PI_DIR, { recursive: true });
35
-
36
- // Create plugins.json
37
- const pluginsJson = {
38
- plugins: {},
39
- disabled: [],
40
- };
41
-
42
- await writeFile(PROJECT_PLUGINS_JSON, JSON.stringify(pluginsJson, null, 2));
43
-
44
- console.log(chalk.green(`✓ Created ${PROJECT_PLUGINS_JSON}`));
45
- console.log();
46
- console.log(chalk.dim("Next steps:"));
47
- console.log(chalk.dim(" 1. Add plugins: omp install <package> --save"));
48
- console.log(chalk.dim(" 2. Or edit plugins.json directly"));
49
- console.log(chalk.dim(" 3. Run: omp install (to install all)"));
50
- } catch (err) {
51
- const error = err as NodeJS.ErrnoException;
52
- if (error.code === "EACCES" || error.code === "EPERM") {
53
- console.log(chalk.red(formatPermissionError(error, PROJECT_PI_DIR)));
54
- console.log(chalk.dim(" Check directory permissions or run with appropriate privileges."));
55
- } else {
56
- console.log(chalk.red(`Error initializing project: ${error.message}`));
57
- }
58
- process.exitCode = 1;
59
- }
60
- }