@michaelhartmayer/agentctl 1.2.1 → 1.2.2

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/dist/ctl.js CHANGED
@@ -42,6 +42,18 @@ async function getCappedAncestor(dir, baseDir) {
42
42
  }
43
43
  return null;
44
44
  }
45
+ async function getMissingAncestorGroups(args, agentctlDir) {
46
+ const missing = [];
47
+ for (let i = 1; i < args.length; i++) {
48
+ const segments = args.slice(0, i);
49
+ const dir = path_1.default.join(agentctlDir, ...segments);
50
+ const manifestPath = path_1.default.join(dir, 'manifest.json');
51
+ if (!(await fs_extra_1.default.pathExists(manifestPath))) {
52
+ missing.push({ dir, name: segments[segments.length - 1] });
53
+ }
54
+ }
55
+ return missing;
56
+ }
45
57
  async function getContext(options) {
46
58
  const cwd = options.cwd || process.cwd();
47
59
  return {
@@ -54,56 +66,50 @@ async function getContext(options) {
54
66
  }
55
67
  async function scaffold(args, options = {}) {
56
68
  const ctx = await getContext(options);
57
- const isGlobal = !!options.global;
58
- const rootDir = isGlobal ? ctx.globalRoot : ctx.cwd;
59
- const agentctlDir = isGlobal ? rootDir : path_1.default.join(rootDir, '.agentctl');
69
+ const localRoot = ctx.localRoot || ctx.cwd;
70
+ const agentctlDir = path_1.default.join(localRoot, '.agentctl');
60
71
  const targetDir = path_1.default.join(agentctlDir, args.join(path_1.default.sep));
61
72
  const exists = await fs_extra_1.default.pathExists(targetDir);
62
- const cappedAncestor = isGlobal ? null : await getCappedAncestor(targetDir, agentctlDir);
63
- const isNewLocalRoot = !isGlobal && !(await fs_extra_1.default.pathExists(agentctlDir));
73
+ const cappedAncestor = await getCappedAncestor(targetDir, agentctlDir);
74
+ const missingAncestorGroups = await getMissingAncestorGroups(args, agentctlDir);
64
75
  const { effects } = ctl_1.Logic.planScaffold(args, ctx, {
65
76
  exists,
66
77
  cappedAncestor: cappedAncestor || undefined,
67
78
  type: 'scaffold',
68
- scope: isGlobal ? 'global' : 'local',
69
- isNewLocalRoot
79
+ missingAncestorGroups
70
80
  });
71
81
  await (0, effects_1.execute)(effects);
72
82
  }
73
83
  async function alias(args, target, options = {}) {
74
84
  const ctx = await getContext(options);
75
- const isGlobal = !!options.global;
76
- const rootDir = isGlobal ? ctx.globalRoot : ctx.cwd;
77
- const agentctlDir = isGlobal ? rootDir : path_1.default.join(rootDir, '.agentctl');
85
+ const localRoot = ctx.localRoot || ctx.cwd;
86
+ const agentctlDir = path_1.default.join(localRoot, '.agentctl');
78
87
  const targetDir = path_1.default.join(agentctlDir, args.join(path_1.default.sep));
79
88
  const exists = await fs_extra_1.default.pathExists(targetDir);
80
- const cappedAncestor = isGlobal ? null : await getCappedAncestor(targetDir, agentctlDir);
81
- const isNewLocalRoot = !isGlobal && !(await fs_extra_1.default.pathExists(agentctlDir));
89
+ const cappedAncestor = await getCappedAncestor(targetDir, agentctlDir);
90
+ const missingAncestorGroups = await getMissingAncestorGroups(args, agentctlDir);
82
91
  const { effects } = ctl_1.Logic.planScaffold(args, ctx, {
83
92
  exists,
84
93
  cappedAncestor: cappedAncestor || undefined,
85
94
  type: 'alias',
86
95
  target,
87
- scope: isGlobal ? 'global' : 'local',
88
- isNewLocalRoot
96
+ missingAncestorGroups
89
97
  });
90
98
  await (0, effects_1.execute)(effects);
91
99
  }
92
100
  async function group(args, options = {}) {
93
101
  const ctx = await getContext(options);
94
- const isGlobal = !!options.global;
95
- const rootDir = isGlobal ? ctx.globalRoot : ctx.cwd;
96
- const agentctlDir = isGlobal ? rootDir : path_1.default.join(rootDir, '.agentctl');
102
+ const localRoot = ctx.localRoot || ctx.cwd;
103
+ const agentctlDir = path_1.default.join(localRoot, '.agentctl');
97
104
  const targetDir = path_1.default.join(agentctlDir, args.join(path_1.default.sep));
98
105
  const exists = await fs_extra_1.default.pathExists(targetDir);
99
- const cappedAncestor = isGlobal ? null : await getCappedAncestor(targetDir, agentctlDir);
100
- const isNewLocalRoot = !isGlobal && !(await fs_extra_1.default.pathExists(agentctlDir));
106
+ const cappedAncestor = await getCappedAncestor(targetDir, agentctlDir);
107
+ const missingAncestorGroups = await getMissingAncestorGroups(args, agentctlDir);
101
108
  const { effects } = ctl_1.Logic.planScaffold(args, ctx, {
102
109
  exists,
103
110
  cappedAncestor: cappedAncestor || undefined,
104
111
  type: 'group',
105
- scope: isGlobal ? 'global' : 'local',
106
- isNewLocalRoot
112
+ missingAncestorGroups
107
113
  });
108
114
  await (0, effects_1.execute)(effects);
109
115
  }
@@ -192,14 +198,13 @@ async function installSkill(agent, options = {}) {
192
198
  }
193
199
  async function install(repoUrl, pathArgs, options = {}) {
194
200
  const ctx = await getContext(options);
195
- const isNewLocalRoot = !options.global && !(await fs_extra_1.default.pathExists(path_1.default.join(ctx.cwd, '.agentctl')));
196
201
  const installCtx = {
197
202
  repoUrl,
198
203
  pathParts: pathArgs,
199
204
  global: !!options.global,
200
205
  allowCollisions: !!options.allowCollisions,
201
- localRoot: options.global ? ctx.globalRoot : ctx.cwd,
202
- isNewLocalRoot,
206
+ localRoot: ctx.localRoot || ctx.cwd,
207
+ isNewLocalRoot: !options.global && !ctx.localRoot,
203
208
  globalRoot: ctx.globalRoot,
204
209
  osTmpdir: os_1.default.tmpdir()
205
210
  };
package/dist/effects.js CHANGED
@@ -46,7 +46,9 @@ async function execute(effects) {
46
46
  break;
47
47
  }
48
48
  case 'spawn': {
49
- const child = (0, child_process_1.spawn)(effect.command, effect.options);
49
+ const child = effect.args
50
+ ? (0, child_process_1.spawn)(effect.command, effect.args, effect.options)
51
+ : (0, child_process_1.spawn)(effect.command, effect.options);
50
52
  if (effect.onExit) {
51
53
  child.on('exit', effect.onExit);
52
54
  }
package/dist/index.js CHANGED
@@ -28,33 +28,33 @@ const ctl = program.command('ctl')
28
28
  .action((opts, command) => {
29
29
  command.help();
30
30
  })
31
- .addHelpText('after', `
32
- ${chalk_1.default.bold('Agentctl Paradigm:')}
33
- Agentctl acts as a unified control plane allowing both Humans and AI Agents
34
- to create, discover, and execute local shell commands. By running \`agentctl ctl scaffold <name>\`
35
- you create a directory in the \`.agentctl\` folder containing a \`manifest.json\`
36
- and a run script. This dynamically creates a new \`agentctl <name>\` command that
37
- is easily callable by agents and globally executable on your machine.
38
-
39
- Commands:
40
-
41
- ${chalk_1.default.bold('Creation')}
42
- scaffold [path...] create a new command
43
- alias [args...] create a shell alias
44
- group [path...] create a namespace group
45
-
46
- ${chalk_1.default.bold('Organize & Scope')}
47
- rm [options] [path...] delete a command
48
- mv [options] [src] [dest] rename/move a command
49
- global [options] [path...] make a command global
50
- local [options] [path...] make a command local
51
-
52
- ${chalk_1.default.bold('Information')}
53
- list list all commands
54
- inspect [path...] inspect command details
55
-
56
- ${chalk_1.default.bold('Integration')}
57
- install [options] [repoUrl] [pathParts...] install remote command group
31
+ .addHelpText('after', `
32
+ ${chalk_1.default.bold('Agentctl Paradigm:')}
33
+ Agentctl acts as a unified control plane allowing both Humans and AI Agents
34
+ to create, discover, and execute local shell commands. By running \`agentctl ctl scaffold <name>\`
35
+ you create a directory in the \`.agentctl\` folder containing a \`manifest.json\`
36
+ and a run script. This dynamically creates a new \`agentctl <name>\` command that
37
+ is easily callable by agents and globally executable on your machine.
38
+
39
+ Commands:
40
+
41
+ ${chalk_1.default.bold('Creation')}
42
+ scaffold [path...] create a new command
43
+ alias [args...] create a shell alias
44
+ group [path...] create a namespace group
45
+
46
+ ${chalk_1.default.bold('Organize & Scope')}
47
+ rm [options] [path...] delete a command
48
+ mv [options] [src] [dest] rename/move a command
49
+ global [options] [path...] make a command global
50
+ local [options] [path...] make a command local
51
+
52
+ ${chalk_1.default.bold('Information')}
53
+ list list all commands
54
+ inspect [path...] inspect command details
55
+
56
+ ${chalk_1.default.bold('Integration')}
57
+ install [options] [repoUrl] [pathParts...] install remote command group
58
58
  `);
59
59
  const withErrorHandling = (fn) => {
60
60
  return async (...args) => {
@@ -76,31 +76,30 @@ const normalizePath = (parts) => parts.flatMap(p => p.split(/[\s/\\:]+/).filter(
76
76
  ctl.command('scaffold')
77
77
  .description('Scaffold a new command directory with a manifest and starter script.')
78
78
  .argument('[path...]', 'Hierarchical path for the new command (e.g., "dev start" or "utils/cleanup")')
79
- .option('-g, --global', 'Create command in global scope')
80
79
  .summary('create a new command')
81
- .addHelpText('after', `
82
- Additional Info:
83
- This command creates a folder in your local .agentctl directory.
84
- Inside this newly created folder, it generates:
85
- - manifest.json: Metadata config to edit for your command.
86
- - command.sh/cmd: A starter script to edit for your actual logic.
87
-
88
- Manifest Schema (manifest.json) to edit:
89
- {
90
- "name": "<command_folder_name>",
91
- "description": "<insert command summary here>",
92
- "help": "<insert longer usage/help instructions here>",
93
- "type": "scaffold", // do not change!
94
- "run": "./command.cmd" // points to the script to execute
95
- }
96
-
97
- Note:
98
- - The "description" is displayed when you view this command in a list.
99
- - Commands must provide their own help implementation (e.g. by handling --help inside your script).
100
-
101
- Examples:
102
- $ agentctl ctl scaffold build:front
103
- $ agentctl ctl scaffold "build front" # Creates group 'build' and subcommand 'front'
80
+ .addHelpText('after', `
81
+ Additional Info:
82
+ This command creates a folder in your local .agentctl directory.
83
+ Inside this newly created folder, it generates:
84
+ - manifest.json: Metadata config to edit for your command.
85
+ - command.sh/cmd: A starter script to edit for your actual logic.
86
+
87
+ Manifest Schema (manifest.json) to edit:
88
+ {
89
+ "name": "<command_folder_name>",
90
+ "description": "<insert command summary here>",
91
+ "help": "<insert longer usage/help instructions here>",
92
+ "type": "scaffold", // do not change!
93
+ "run": "./command.cmd" // points to the script to execute
94
+ }
95
+
96
+ Note:
97
+ - The "description" is displayed when you view this command in a list.
98
+ - Commands must provide their own help implementation (e.g. by handling --help inside your script).
99
+
100
+ Examples:
101
+ $ agentctl ctl scaffold build:front
102
+ $ agentctl ctl scaffold "build front" # Creates group 'build' and subcommand 'front'
104
103
  `)
105
104
  .action(withErrorHandling(async (pathParts, opts, command) => {
106
105
  const normalized = normalizePath(pathParts);
@@ -108,17 +107,16 @@ Examples:
108
107
  command.help();
109
108
  return;
110
109
  }
111
- await (0, ctl_1.scaffold)(normalized, { global: opts.global });
110
+ await (0, ctl_1.scaffold)(normalized);
112
111
  }));
113
112
  ctl.command('alias')
114
113
  .description('Create a command that executes a raw shell string.')
115
114
  .argument('[args...]', 'Hierarchical path segments followed by the shell command target')
116
- .option('-g, --global', 'Create alias in global scope')
117
115
  .summary('create a shell alias')
118
- .addHelpText('after', `
119
- Examples:
120
- $ agentctl ctl alias dev logs "docker compose logs -f"
121
- $ agentctl ctl alias list-files "ls -la"
116
+ .addHelpText('after', `
117
+ Examples:
118
+ $ agentctl ctl alias dev logs "docker compose logs -f"
119
+ $ agentctl ctl alias list-files "ls -la"
122
120
  `)
123
121
  .action(withErrorHandling(async (args, opts, command) => {
124
122
  if (!args || args.length < 2) {
@@ -131,36 +129,35 @@ Examples:
131
129
  command.help();
132
130
  return;
133
131
  }
134
- await (0, ctl_1.alias)(name, target, { global: opts.global });
132
+ await (0, ctl_1.alias)(name, target);
135
133
  }));
136
134
  ctl.command('group')
137
135
  .description('Create a command group (namespace) to organize subcommands.')
138
136
  .argument('[path...]', 'Hierarchical path for the group (e.g., "dev" or "cloud/aws")')
139
- .option('-g, --global', 'Create group in global scope')
140
137
  .summary('create a namespace group')
141
- .addHelpText('after', `
142
- Additional Info:
143
- Groups allow you to categorize commands. Running a group command without
144
- subcommands will list all direct subcommands within that group.
145
-
146
- This command creates a folder in your local .agentctl directory.
147
- Inside this newly created folder, it generates a manifest.json.
148
-
149
- Group Schema (manifest.json) to edit:
150
- {
151
- "name": "<group_folder_name>",
152
- "description": "<insert group summary here>",
153
- "help": "<insert longer group description/instructions here>",
154
- "type": "group" // do not change!
155
- }
156
-
157
- Note:
158
- - The "description" is displayed when you view this group in a list.
159
- - The "help" is displayed when you call this group without a subcommand.
160
-
161
- Examples:
162
- $ agentctl ctl group dev
163
- $ agentctl ctl group "data pipelines" # Creates group 'data' and subgroup 'pipelines'
138
+ .addHelpText('after', `
139
+ Additional Info:
140
+ Groups allow you to categorize commands. Running a group command without
141
+ subcommands will list all direct subcommands within that group.
142
+
143
+ This command creates a folder in your local .agentctl directory.
144
+ Inside this newly created folder, it generates a manifest.json.
145
+
146
+ Group Schema (manifest.json) to edit:
147
+ {
148
+ "name": "<group_folder_name>",
149
+ "description": "<insert group summary here>",
150
+ "help": "<insert longer group description/instructions here>",
151
+ "type": "group" // do not change!
152
+ }
153
+
154
+ Note:
155
+ - The "description" is displayed when you view this group in a list.
156
+ - The "help" is displayed when you call this group without a subcommand.
157
+
158
+ Examples:
159
+ $ agentctl ctl group dev
160
+ $ agentctl ctl group "data pipelines" # Creates group 'data' and subgroup 'pipelines'
164
161
  `)
165
162
  .action(withErrorHandling(async (parts, opts, command) => {
166
163
  const normalized = normalizePath(parts);
@@ -168,17 +165,17 @@ Examples:
168
165
  command.help();
169
166
  return;
170
167
  }
171
- await (0, ctl_1.group)(normalized, { global: opts.global });
168
+ await (0, ctl_1.group)(normalized);
172
169
  }));
173
170
  ctl.command('rm')
174
171
  .description('Permanently remove a command or group.')
175
172
  .argument('[path...]', 'Command path to remove')
176
173
  .option('-g, --global', 'Remove from global scope instead of local')
177
174
  .summary('delete a command')
178
- .addHelpText('after', `
179
- Examples:
180
- $ agentctl ctl rm dev start
181
- $ agentctl ctl rm utils--global
175
+ .addHelpText('after', `
176
+ Examples:
177
+ $ agentctl ctl rm dev start
178
+ $ agentctl ctl rm utils--global
182
179
  `)
183
180
  .action(withErrorHandling(async (parts, opts, command) => {
184
181
  const normalized = normalizePath(parts);
@@ -194,10 +191,10 @@ ctl.command('mv')
194
191
  .argument('[dest]', 'New path (space-separated or quoted)')
195
192
  .option('-g, --global', 'Operate in global scope')
196
193
  .summary('rename/move a command')
197
- .addHelpText('after', `
198
- Examples:
199
- $ agentctl ctl mv "dev start" "dev begin"
200
- $ agentctl ctl mv utils scripts--global
194
+ .addHelpText('after', `
195
+ Examples:
196
+ $ agentctl ctl mv "dev start" "dev begin"
197
+ $ agentctl ctl mv utils scripts--global
201
198
  `)
202
199
  .action(withErrorHandling(async (src, dest, opts, command) => {
203
200
  const normalizedSrc = normalizePath(src ? [src] : []);
@@ -211,12 +208,12 @@ Examples:
211
208
  ctl.command('list')
212
209
  .description('List all available commands across local and global scopes.')
213
210
  .summary('list all commands')
214
- .addHelpText('after', `
215
- Output Columns:
216
- TYPE - scaffold, alias, or group
217
- SCOPE - local(project - specific) or global(user - wide)
218
- COMMAND - The path used to invoke the command
219
- DESCRIPTION - Brief text from the command's manifest
211
+ .addHelpText('after', `
212
+ Output Columns:
213
+ TYPE - scaffold, alias, or group
214
+ SCOPE - local(project - specific) or global(user - wide)
215
+ COMMAND - The path used to invoke the command
216
+ DESCRIPTION - Brief text from the command's manifest
220
217
  `)
221
218
  .action(withErrorHandling(async () => {
222
219
  const items = await (0, ctl_1.list)();
@@ -231,9 +228,9 @@ ctl.command('inspect')
231
228
  .description('Show the internal manifest and file system path of a command.')
232
229
  .argument('[path...]', 'Command path to inspect')
233
230
  .summary('inspect command details')
234
- .addHelpText('after', `
235
- Examples:
236
- $ agentctl ctl inspect dev start
231
+ .addHelpText('after', `
232
+ Examples:
233
+ $ agentctl ctl inspect dev start
237
234
  `)
238
235
  .action(withErrorHandling(async (parts, opts, command) => {
239
236
  const normalized = normalizePath(parts);
@@ -256,13 +253,13 @@ ctl.command('global')
256
253
  .option('-m, --move', 'Move the command (delete local after copying)')
257
254
  .option('-c, --copy', 'Copy the command (keep local version, default)')
258
255
  .summary('make a command global')
259
- .addHelpText('after', `
260
- Additional Info:
261
- Global commands are stored in your home directory and are available in any project.
262
-
263
- Examples:
264
- $ agentctl ctl global utils / cleanup
265
- $ agentctl ctl global dev / deploy--move
256
+ .addHelpText('after', `
257
+ Additional Info:
258
+ Global commands are stored in your home directory and are available in any project.
259
+
260
+ Examples:
261
+ $ agentctl ctl global utils / cleanup
262
+ $ agentctl ctl global dev / deploy--move
266
263
  `)
267
264
  .action(withErrorHandling(async (parts, opts, command) => {
268
265
  const normalized = normalizePath(parts);
@@ -278,10 +275,10 @@ ctl.command('local')
278
275
  .option('-m, --move', 'Move the command (delete global after pulling)')
279
276
  .option('-c, --copy', 'Copy the command (keep global version, default)')
280
277
  .summary('make a command local')
281
- .addHelpText('after', `
282
- Examples:
283
- $ agentctl ctl local utils / shared
284
- $ agentctl ctl local snippets / js--move
278
+ .addHelpText('after', `
279
+ Examples:
280
+ $ agentctl ctl local utils / shared
281
+ $ agentctl ctl local snippets / js--move
285
282
  `)
286
283
  .action(withErrorHandling(async (parts, opts, command) => {
287
284
  const normalized = normalizePath(parts);
@@ -298,14 +295,14 @@ ctl.command('install')
298
295
  .option('-g, --global', 'Install globally instead of locally')
299
296
  .option('--allow-collisions', 'Allow overwriting existing commands or merging into groups')
300
297
  .summary('install remote command group')
301
- .addHelpText('after', `
302
- Additional Info:
303
- Fetches the.agentctl folder from the remote repository and installs it into
304
- your local or global agentctl environment.
305
-
306
- Examples:
307
- $ agentctl ctl install https://github.com/org/repo-tools
308
- $ agentctl ctl install https://github.com/org/deploy-scripts deploy --global
298
+ .addHelpText('after', `
299
+ Additional Info:
300
+ Fetches the.agentctl folder from the remote repository and installs it into
301
+ your local or global agentctl environment.
302
+
303
+ Examples:
304
+ $ agentctl ctl install https://github.com/org/repo-tools
305
+ $ agentctl ctl install https://github.com/org/deploy-scripts deploy --global
309
306
  `)
310
307
  .action(withErrorHandling(async (repoUrl, pathParts, opts, command) => {
311
308
  if (!repoUrl) {
package/dist/logic/ctl.js CHANGED
@@ -21,15 +21,21 @@ exports.Logic = {
21
21
  if (options.cappedAncestor) {
22
22
  throw new Error(`Cannot nest command under capped command: ${options.cappedAncestor.relPath}`);
23
23
  }
24
- const isGlobal = options.scope === 'global';
25
- const rootDir = isGlobal ? ctx.globalRoot : ctx.cwd;
26
- const agentctlDir = isGlobal ? rootDir : path_1.default.join(rootDir, '.agentctl');
24
+ const localRoot = ctx.localRoot || ctx.cwd;
25
+ const agentctlDir = path_1.default.join(localRoot, '.agentctl');
27
26
  const cmdPath = args.join(path_1.default.sep);
28
27
  const targetDir = path_1.default.join(agentctlDir, cmdPath);
29
28
  const name = args[args.length - 1];
30
29
  const type = options.type || 'scaffold';
31
30
  const isWin = ctx.platform === 'win32';
32
31
  const effects = [{ type: 'mkdir', path: targetDir }];
32
+ for (const group of options.missingAncestorGroups || []) {
33
+ effects.push({
34
+ type: 'writeJson',
35
+ path: path_1.default.join(group.dir, 'manifest.json'),
36
+ content: { name: group.name, type: 'group' }
37
+ });
38
+ }
33
39
  const manifest = {
34
40
  name,
35
41
  description: '<insert summary>',
@@ -54,9 +60,6 @@ exports.Logic = {
54
60
  const logMsg = type === 'scaffold' ? `Scaffolded command: ${args.join(' ')}` :
55
61
  type === 'alias' ? `Aliased command: ${args.join(' ')} -> ${options.target}` :
56
62
  `Created group: ${args.join(' ')}`;
57
- if (options.isNewLocalRoot) {
58
- effects.unshift({ type: 'log', message: `Initialized new .agentctl folder in ${rootDir}` });
59
- }
60
63
  effects.push({ type: 'log', message: logMsg });
61
64
  return { effects };
62
65
  },
@@ -27,13 +27,17 @@ exports.AppLogic = {
27
27
  runCmd = path_1.default.resolve(cmdDir, runCmd);
28
28
  }
29
29
  runCmd = runCmd.replace(/{{DIR}}/g, cmdDir);
30
- const fullCommand = `${runCmd} ${remainingArgs.join(' ')}`;
30
+ const quoteArg = (arg) => /[\s"'\\$`]/.test(arg) ? JSON.stringify(arg) : arg;
31
+ const displayedArgs = remainingArgs.map(quoteArg).join(' ');
32
+ const fullCommand = displayedArgs ? `${runCmd} ${displayedArgs}` : runCmd;
33
+ const isAlias = manifest.type === 'alias';
31
34
  effects.push({ type: 'log', message: `[${scope}] Running: ${fullCommand}` }, {
32
35
  type: 'spawn',
33
- command: fullCommand,
36
+ command: isAlias ? fullCommand : runCmd,
37
+ args: isAlias ? undefined : remainingArgs,
34
38
  options: {
35
39
  cwd: process.cwd(),
36
- shell: true,
40
+ shell: isAlias,
37
41
  stdio: 'inherit',
38
42
  env: { ...process.env, AGENTCTL_SCOPE: scope }
39
43
  },
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "description": "Agent Controller - A unified interface for humans and AI agents",
7
- "version": "1.2.1",
7
+ "version": "1.2.2",
8
8
  "main": "dist/index.js",
9
9
  "bin": {
10
10
  "agentctl": "./dist/index.js"