@indigoai-us/hq-cli 5.119.15 → 5.120.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
@@ -2,6 +2,15 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.120.0] — 2026-09-18
6
+
7
+ ### Added
8
+
9
+ - `hq agents provision` can reuse an existing Slack bot token through flags,
10
+ environment variables, or stdin. Socket Mode agents can also accept their
11
+ app-level token. HQ validates both tokens and the bot's required Slack scopes
12
+ before it creates the agent.
13
+
5
14
  ## [5.119.15] — 2026-09-18
6
15
 
7
16
  ### Fixed
@@ -3887,6 +3887,15 @@ export declare const COMMAND_CATALOG: readonly [{
3887
3887
  }, {
3888
3888
  readonly flags: "--api-key-env <VAR>";
3889
3889
  readonly description: "Env var holding the API key for --auth-mode apiKey (never pass the key as a flag)";
3890
+ }, {
3891
+ readonly flags: "--slack-bot-token <xoxb-token>";
3892
+ readonly description: "Reuse an existing Slack bot token; HQ_SLACK_BOT_TOKEN or --slack-tokens-stdin avoid shell history";
3893
+ }, {
3894
+ readonly flags: "--slack-app-token <xapp-token>";
3895
+ readonly description: "Socket Mode app token for --provider agents-v2; HQ_SLACK_APP_TOKEN or --slack-tokens-stdin avoid shell history";
3896
+ }, {
3897
+ readonly flags: "--slack-tokens-stdin";
3898
+ readonly description: "Read the bot token and optional app token from one or two stdin lines";
3890
3899
  }, {
3891
3900
  readonly flags: "--title <title>";
3892
3901
  readonly description: "Org-chart job title";
@@ -5025,6 +5025,18 @@ export const COMMAND_CATALOG = [
5025
5025
  "flags": "--api-key-env <VAR>",
5026
5026
  "description": "Env var holding the API key for --auth-mode apiKey (never pass the key as a flag)"
5027
5027
  },
5028
+ {
5029
+ "flags": "--slack-bot-token <xoxb-token>",
5030
+ "description": "Reuse an existing Slack bot token; HQ_SLACK_BOT_TOKEN or --slack-tokens-stdin avoid shell history"
5031
+ },
5032
+ {
5033
+ "flags": "--slack-app-token <xapp-token>",
5034
+ "description": "Socket Mode app token for --provider agents-v2; HQ_SLACK_APP_TOKEN or --slack-tokens-stdin avoid shell history"
5035
+ },
5036
+ {
5037
+ "flags": "--slack-tokens-stdin",
5038
+ "description": "Read the bot token and optional app token from one or two stdin lines"
5039
+ },
5028
5040
  {
5029
5041
  "flags": "--title <title>",
5030
5042
  "description": "Org-chart job title"
@@ -173,6 +173,9 @@ export interface ProvisionAgentInput {
173
173
  provider?: "codex" | "grok" | "claude" | "agents-v2";
174
174
  codexModel?: string;
175
175
  codexApiKey?: string;
176
+ /** Write-only Slack credentials, validated by hq-pro before creation. */
177
+ slackBotToken?: string;
178
+ slackAppToken?: string;
176
179
  idempotencyKey: string;
177
180
  title?: string;
178
181
  description?: string;
@@ -184,6 +187,21 @@ export interface ProvisionAgentInput {
184
187
  /** Funnel attribution: which client surface made the attempt. */
185
188
  surface?: AgentCreateSurface;
186
189
  }
190
+ export interface ProvisionSlackTokenOptions {
191
+ slackBotToken?: string;
192
+ slackAppToken?: string;
193
+ slackTokensStdin?: boolean;
194
+ }
195
+ export interface ProvisionSlackTokens {
196
+ botToken: string;
197
+ appToken?: string;
198
+ }
199
+ /**
200
+ * Resolve write-only Slack credentials without printing them. Flags are useful
201
+ * for automation; HQ_SLACK_BOT_TOKEN/HQ_SLACK_APP_TOKEN and stdin avoid shell
202
+ * history. Multiple sources are rejected so the selected credential is clear.
203
+ */
204
+ export declare function resolveProvisionSlackTokens(options: ProvisionSlackTokenOptions, environment?: Record<string, string | undefined>, readStdin?: () => Promise<string>): Promise<ProvisionSlackTokens | undefined>;
187
205
  /** Closed set shared with hq-pro's agent_create_* funnel contract. */
188
206
  export declare const CLI_AGENT_CREATE_SURFACE: "cli_agents_create";
189
207
  export type AgentCreateSurface = typeof CLI_AGENT_CREATE_SURFACE;
@@ -242,6 +242,51 @@ export function slugifyAgentName(name) {
242
242
  .replace(/[^a-z0-9]+/g, "-")
243
243
  .replace(/^-+|-+$/g, "");
244
244
  }
245
+ async function readProvisionSlackTokensFromStdin() {
246
+ let value = "";
247
+ for await (const chunk of process.stdin)
248
+ value += String(chunk);
249
+ return value;
250
+ }
251
+ function parseProvisionSlackTokensFromStdin(value) {
252
+ const lines = value
253
+ .split(/\r?\n/)
254
+ .map((line) => line.trim())
255
+ .filter(Boolean);
256
+ if (lines.length < 1 || lines.length > 2) {
257
+ throw new Error("--slack-tokens-stdin expects one line with the bot token and an optional second line with the Socket Mode app token.");
258
+ }
259
+ return { botToken: lines[0], ...(lines[1] ? { appToken: lines[1] } : {}) };
260
+ }
261
+ /**
262
+ * Resolve write-only Slack credentials without printing them. Flags are useful
263
+ * for automation; HQ_SLACK_BOT_TOKEN/HQ_SLACK_APP_TOKEN and stdin avoid shell
264
+ * history. Multiple sources are rejected so the selected credential is clear.
265
+ */
266
+ export async function resolveProvisionSlackTokens(options, environment = process.env, readStdin = readProvisionSlackTokensFromStdin) {
267
+ const optionBotToken = options.slackBotToken?.trim();
268
+ const optionAppToken = options.slackAppToken?.trim();
269
+ const environmentBotToken = environment.HQ_SLACK_BOT_TOKEN?.trim();
270
+ const environmentAppToken = environment.HQ_SLACK_APP_TOKEN?.trim();
271
+ const hasFlagOrEnvironment = Boolean(optionBotToken || optionAppToken || environmentBotToken || environmentAppToken);
272
+ if (options.slackTokensStdin) {
273
+ if (hasFlagOrEnvironment) {
274
+ throw new Error("Use --slack-tokens-stdin or the Slack token flags/environment variables, not both.");
275
+ }
276
+ return parseProvisionSlackTokensFromStdin(await readStdin());
277
+ }
278
+ if ((optionBotToken || optionAppToken) && (environmentBotToken || environmentAppToken)) {
279
+ throw new Error("Use Slack token flags or HQ_SLACK_BOT_TOKEN/HQ_SLACK_APP_TOKEN, not both.");
280
+ }
281
+ const botToken = optionBotToken || environmentBotToken;
282
+ const appToken = optionAppToken || environmentAppToken;
283
+ if (!botToken && !appToken)
284
+ return undefined;
285
+ if (!botToken) {
286
+ throw new Error("A Slack app token requires a Slack bot token.");
287
+ }
288
+ return { botToken, ...(appToken ? { appToken } : {}) };
289
+ }
245
290
  /** Closed set shared with hq-pro's agent_create_* funnel contract. */
246
291
  export const CLI_AGENT_CREATE_SURFACE = "cli_agents_create";
247
292
  /** Read hq-pro's company-specific creation prices and capacities. */
@@ -1132,6 +1177,9 @@ export function registerAgentsCommand(program) {
1132
1177
  .option("--model <model>", "Brain model, for example gpt-5.5 or grok-4.6")
1133
1178
  .option("--auth-mode <mode>", "Auth: subscription | apiKey (default subscription)", "subscription")
1134
1179
  .option("--api-key-env <VAR>", "Env var holding the API key for --auth-mode apiKey (never pass the key as a flag)")
1180
+ .option("--slack-bot-token <xoxb-token>", "Reuse an existing Slack bot token; HQ_SLACK_BOT_TOKEN or --slack-tokens-stdin avoid shell history")
1181
+ .option("--slack-app-token <xapp-token>", "Socket Mode app token for --provider agents-v2; HQ_SLACK_APP_TOKEN or --slack-tokens-stdin avoid shell history")
1182
+ .option("--slack-tokens-stdin", "Read the bot token and optional app token from one or two stdin lines")
1135
1183
  .option("--title <title>", "Org-chart job title")
1136
1184
  .option("--description <text>", "Short description / bio")
1137
1185
  .option("--size <size>", "Agent box size: basic | power | dev (omitted keeps the current default)")
@@ -1150,6 +1198,13 @@ export function registerAgentsCommand(program) {
1150
1198
  process.exit(1);
1151
1199
  }
1152
1200
  const provider = explicitProvider ?? (opts.model ? "agents-v2" : undefined);
1201
+ const slackTokens = await resolveProvisionSlackTokens(opts);
1202
+ if (slackTokens?.appToken && provider !== "agents-v2") {
1203
+ throw new Error("A Slack app token can only be supplied with --provider agents-v2 for Socket Mode.");
1204
+ }
1205
+ if (slackTokens && provider === "agents-v2" && !slackTokens.appToken) {
1206
+ throw new Error("--provider agents-v2 requires a Slack app token when reusing a Slack bot token.");
1207
+ }
1153
1208
  // claude is subscription-only on hq-pro (rejectIncompatibleProviderAuthMode
1154
1209
  // returns AGENT_PROVIDER_INCOMPATIBLE_WITH_AUTH_MODE). Catch it here so the
1155
1210
  // operator gets a direct message instead of a 400 from the control plane
@@ -1202,6 +1257,10 @@ export function registerAgentsCommand(program) {
1202
1257
  ...(provider ? { provider } : {}),
1203
1258
  ...(opts.model ? { codexModel: opts.model } : {}),
1204
1259
  ...(codexApiKey ? { codexApiKey } : {}),
1260
+ ...(slackTokens ? { slackBotToken: slackTokens.botToken } : {}),
1261
+ ...(slackTokens?.appToken
1262
+ ? { slackAppToken: slackTokens.appToken }
1263
+ : {}),
1205
1264
  idempotencyKey,
1206
1265
  ...(opts.title ? { title: opts.title } : {}),
1207
1266
  ...(opts.description ? { description: opts.description } : {}),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.119.15",
3
+ "version": "5.120.0",
4
4
  "description": "HQ by Indigo management CLI \u2014 modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {