@alavida/agentpack 0.1.1

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/src/cli.js ADDED
@@ -0,0 +1,82 @@
1
+ import { Command } from 'commander';
2
+ import { createRequire } from 'node:module';
3
+ import { formatError, AgentpackError, EXIT_CODES } from './utils/errors.js';
4
+ import { output } from './utils/output.js';
5
+ import { skillsCommand } from './commands/skills.js';
6
+ import { pluginCommand } from './commands/plugin.js';
7
+
8
+ const require = createRequire(import.meta.url);
9
+ const pkg = require('../package.json');
10
+
11
+ export function createProgram() {
12
+ const program = new Command();
13
+
14
+ program
15
+ .name('agentpack')
16
+ .description('agentpack skills lifecycle CLI')
17
+ .version(pkg.version, '-V, --version', 'Show version number')
18
+ .option('--json', 'Output as JSON')
19
+ .option('-q, --quiet', 'Suppress non-essential output')
20
+ .option('-v, --verbose', 'Show detailed output')
21
+ .option('--workbench <path>', 'Override workbench context (name or path)');
22
+
23
+ program.addCommand(skillsCommand());
24
+ program.addCommand(pluginCommand());
25
+
26
+ program.addHelpText('after', `
27
+ Exit Codes:
28
+ 0 Success
29
+ 1 General error
30
+ 2 Usage or validation error
31
+ 3 Network error
32
+ 4 Not found
33
+
34
+ Run 'agentpack <command> --help' for details on a specific command.`);
35
+
36
+ program.action(() => {
37
+ program.help();
38
+ });
39
+
40
+ return program;
41
+ }
42
+
43
+ export function run(argv) {
44
+ const program = createProgram();
45
+
46
+ process.on('uncaughtException', (err) => {
47
+ const opts = program.opts?.() || {};
48
+ if (opts.json) {
49
+ output.json({ error: 'uncaught_exception', message: err.message });
50
+ } else {
51
+ output.error(formatError(err));
52
+ }
53
+ process.exit(EXIT_CODES.GENERAL);
54
+ });
55
+
56
+ process.on('unhandledRejection', (reason) => {
57
+ const err = reason instanceof Error ? reason : new Error(String(reason));
58
+ const opts = program.opts?.() || {};
59
+ if (opts.json) {
60
+ output.json({ error: 'unhandled_rejection', message: err.message });
61
+ } else {
62
+ output.error(formatError(err));
63
+ }
64
+ process.exit(EXIT_CODES.GENERAL);
65
+ });
66
+
67
+ program.parseAsync(argv).catch((err) => {
68
+ if (err instanceof AgentpackError) {
69
+ const opts = program.opts?.() || {};
70
+ if (opts.json) {
71
+ output.json({ error: err.code, message: err.message });
72
+ } else {
73
+ output.error(formatError(err));
74
+ }
75
+ process.exit(err.exitCode);
76
+ return;
77
+ }
78
+
79
+ output.error(formatError(err));
80
+ process.exit(EXIT_CODES.GENERAL);
81
+ });
82
+ }
@@ -0,0 +1,169 @@
1
+ import { Command } from 'commander';
2
+ import { buildPlugin, inspectPluginBundle, startPluginDev, validatePluginBundle } from '../lib/plugins.js';
3
+ import { output } from '../utils/output.js';
4
+ import { EXIT_CODES } from '../utils/errors.js';
5
+
6
+ export function pluginCommand() {
7
+ const cmd = new Command('plugin')
8
+ .description('Inspect and validate bundled plugin packaging');
9
+
10
+ cmd
11
+ .command('inspect')
12
+ .description('Inspect the bundle closure implied by a plugin package and its local skill requires')
13
+ .argument('<target>', 'Plugin directory path')
14
+ .action((target, opts, command) => {
15
+ const globalOpts = command.optsWithGlobals();
16
+ const result = inspectPluginBundle(target);
17
+
18
+ if (globalOpts.json) {
19
+ output.json(result);
20
+ return;
21
+ }
22
+
23
+ output.write(`Plugin: ${result.pluginName}`);
24
+ output.write(`Package: ${result.packageName}`);
25
+ output.write(`Version: ${result.packageVersion}`);
26
+ output.write(`Path: ${result.pluginPath}`);
27
+ output.write(`Local Skills: ${result.localSkills.length}`);
28
+ output.write(`Direct Bundled Packages: ${result.directPackages.length}`);
29
+ output.write(`Transitive Bundled Packages: ${result.transitivePackages.length}`);
30
+
31
+ output.write('');
32
+ output.write('Local Skills:');
33
+ for (const skill of result.localSkills) {
34
+ output.write(`- ${skill.localName}`);
35
+ output.write(` requires: ${skill.requires.length === 0 ? 'none' : skill.requires.join(', ')}`);
36
+ }
37
+
38
+ output.write('');
39
+ output.write('Direct Bundled Packages:');
40
+ if (result.directPackages.length === 0) {
41
+ output.write('- none');
42
+ } else {
43
+ for (const entry of result.directPackages) {
44
+ output.write(`- ${entry.packageName}`);
45
+ output.write(` skill: ${entry.skillName}`);
46
+ output.write(` version: ${entry.packageVersion}`);
47
+ output.write(` source: ${entry.source}`);
48
+ }
49
+ }
50
+
51
+ output.write('');
52
+ output.write('Transitive Bundled Packages:');
53
+ if (result.transitivePackages.length === 0) {
54
+ output.write('- none');
55
+ } else {
56
+ for (const entry of result.transitivePackages) {
57
+ output.write(`- ${entry.packageName}`);
58
+ output.write(` skill: ${entry.skillName}`);
59
+ output.write(` version: ${entry.packageVersion}`);
60
+ output.write(` source: ${entry.source}`);
61
+ }
62
+ }
63
+
64
+ if (result.unresolvedPackages.length > 0) {
65
+ output.write('');
66
+ output.write('Unresolved Packages:');
67
+ for (const packageName of result.unresolvedPackages) {
68
+ output.write(`- ${packageName}`);
69
+ }
70
+ }
71
+ });
72
+
73
+ cmd
74
+ .command('validate')
75
+ .description('Validate that a plugin package can vendor the standalone skills required by its local skills')
76
+ .argument('<target>', 'Plugin directory path')
77
+ .action((target, opts, command) => {
78
+ const globalOpts = command.optsWithGlobals();
79
+ const result = validatePluginBundle(target);
80
+
81
+ if (globalOpts.json) {
82
+ output.json(result);
83
+ if (!result.valid) process.exitCode = EXIT_CODES.VALIDATION;
84
+ return;
85
+ }
86
+
87
+ output.write(`Plugin: ${result.pluginName}`);
88
+ output.write(`Package: ${result.packageName}`);
89
+ output.write(`Status: ${result.valid ? 'valid' : 'invalid'}`);
90
+ output.write(`Issues: ${result.issueCount}`);
91
+ output.write(`Direct Bundled Packages: ${result.directPackageCount}`);
92
+ output.write(`Transitive Bundled Packages: ${result.transitivePackageCount}`);
93
+
94
+ if (result.issues.length > 0) {
95
+ output.write('');
96
+ output.write('Issues:');
97
+ for (const issue of result.issues) {
98
+ output.write(`- ${issue.code}`);
99
+ output.write(` message: ${issue.message}`);
100
+ if (issue.packageName) output.write(` package: ${issue.packageName}`);
101
+ if (issue.skillFile) output.write(` skill: ${issue.skillFile}`);
102
+ }
103
+ }
104
+
105
+ if (!result.valid) {
106
+ process.exitCode = EXIT_CODES.VALIDATION;
107
+ }
108
+ });
109
+
110
+ cmd
111
+ .command('build')
112
+ .description('Build a self-contained plugin artifact with vendored standalone skills')
113
+ .option('--clean', 'Remove the previous build output before building')
114
+ .argument('<target>', 'Plugin directory path')
115
+ .action((target, opts, command) => {
116
+ const globalOpts = command.optsWithGlobals();
117
+ const result = buildPlugin(target, { clean: opts.clean });
118
+
119
+ if (globalOpts.json) {
120
+ output.json(result);
121
+ return;
122
+ }
123
+
124
+ output.write(`Plugin: ${result.pluginName}`);
125
+ output.write(`Output: ${result.outputPath}`);
126
+ output.write(`Local Skills: ${result.localSkills.length}`);
127
+ output.write(`Vendored Skills: ${result.vendoredSkills.length}`);
128
+ });
129
+
130
+ cmd
131
+ .command('dev')
132
+ .description('Build a plugin artifact and watch the source tree for rebuilds')
133
+ .option('--clean', 'Remove the previous build output before the initial build')
134
+ .argument('<target>', 'Plugin directory path')
135
+ .action((target, opts, command) => {
136
+ const globalOpts = command.optsWithGlobals();
137
+ const session = startPluginDev(target, {
138
+ clean: opts.clean,
139
+ onBuild(result) {
140
+ if (globalOpts.json) {
141
+ output.json(result);
142
+ } else {
143
+ output.write(`Plugin: ${result.pluginName}`);
144
+ output.write(`Output: ${result.outputPath}`);
145
+ output.write(`Use with: claude --plugin-dir ${result.outputPath}`);
146
+ }
147
+ },
148
+ onRebuild(result) {
149
+ if (result?.error) {
150
+ output.error(`Rebuild failed: ${result.error.message}`);
151
+ return;
152
+ }
153
+
154
+ output.write(`Rebuilt plugin: ${result.pluginName}`);
155
+ output.write(`Output: ${result.outputPath}`);
156
+ },
157
+ });
158
+
159
+ const stop = () => {
160
+ session.close();
161
+ process.exit(0);
162
+ };
163
+
164
+ process.once('SIGTERM', stop);
165
+ process.once('SIGINT', stop);
166
+ });
167
+
168
+ return cmd;
169
+ }