@audienti/cli 0.1.9 → 0.1.11

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
@@ -4,6 +4,19 @@ All notable changes to the Audienti CLI are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.1.11] - 2026-07-15
8
+
9
+ ### Added
10
+
11
+ - Add `audienti users select <account_user_id|email|name|me>` to save a default account user for CLI commands that accept `me` or default to the current operator.
12
+
13
+ ## [0.1.10] - 2026-07-15
14
+
15
+ ### Added
16
+
17
+ - Add `audienti motions update <motn_id> --status <draft|preparing|active|paused|archived>` plus `activate`, `pause`, and `archive` shortcuts for motion/play lifecycle status management.
18
+ - Add `audienti motions delete <motn_id> --confirm <yes|true|Y|y>` to delete a motion/play through the API cleanup path.
19
+
7
20
  ## [0.1.9] - 2026-07-15
8
21
 
9
22
  ### Added
package/README.md CHANGED
@@ -30,12 +30,18 @@ Create an Audienti API token through the product, then configure this machine:
30
30
  audienti auth token <token>
31
31
  audienti accounts list --json
32
32
  audienti accounts select <acct_id>
33
+ audienti users list
34
+ audienti users select <account_user_id|email|name|me>
33
35
  ```
34
36
 
35
37
  The CLI writes its local configuration to `~/.config/audienti/config.json` with
36
38
  owner-only permissions. Do not place a production token in an agent prompt,
37
39
  repository file, issue, or CI secret.
38
40
 
41
+ The selected account user is used when commands accept `me` or default to the
42
+ current operator, such as `audienti users activity`, `audienti analytics users`,
43
+ and `audienti prospects assign --assigned-user me`.
44
+
39
45
  ## Agent Workflows
40
46
 
41
47
  Start with the built-in, production-safe workflow guide:
@@ -54,11 +60,14 @@ Common inspection commands:
54
60
  audienti operator next --plan
55
61
  audienti writer test-run <prsp_id>
56
62
  audienti motions analytics <motn_id>
63
+ audienti motions update <motn_id> --status paused
64
+ audienti motions activate <motn_id>
65
+ audienti motions delete <motn_id> --confirm yes
57
66
  audienti prospects show <prsp_id> --json
58
67
  audienti prospects list --profiles
59
68
  audienti prospects list --assigned-user unassigned
60
69
  audienti prospects assign <prsp_id> --assigned-user me
61
- audienti users activity me --window 7d
70
+ audienti users activity --window 7d
62
71
  audienti analytics prospects --window 24h
63
72
  audienti analytics users --user me --window 30d
64
73
  audienti analytics visibility --window 24h --user me
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@audienti/cli",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Agent-first command-line client for Audienti.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -56,6 +56,9 @@ audienti prospects assign <prsp_id> --assigned-user me --json
56
56
  audienti users activity me --window 7d --json
57
57
  audienti prospects import-batch --file prospects.csv --motion <motn_id> --assigned-user me --json
58
58
  audienti lists create --name "Target list" --json
59
+ audienti motions update <motn_id> --status paused --json
60
+ audienti motions activate <motn_id> --json
61
+ audienti motions delete <motn_id> --confirm yes --json
59
62
  audienti operator next --json
60
63
  audienti operator next --plan
61
64
  audienti analytics prospects --window 24h --json
package/src/api-client.js CHANGED
@@ -134,6 +134,19 @@ export class AudientiClient {
134
134
  });
135
135
  }
136
136
 
137
+ updateMotion(accountId, motionId, body) {
138
+ return this.requestJson(accountPath(accountId, ["motions", motionId]), {
139
+ method: "PATCH",
140
+ body
141
+ });
142
+ }
143
+
144
+ deleteMotion(accountId, motionId) {
145
+ return this.requestJson(accountPath(accountId, ["motions", motionId]), {
146
+ method: "DELETE"
147
+ });
148
+ }
149
+
137
150
  cloneMotion(accountId, motionId, body) {
138
151
  return this.requestJson(accountPath(accountId, ["motions", motionId, "clone"]), {
139
152
  method: "POST",
package/src/cli.js CHANGED
@@ -25,15 +25,18 @@ const DEFAULT_PROFILE_IDENTIFIERS = [
25
25
  "email/profile"
26
26
  ];
27
27
  const DELETE_CONFIRMATION_VALUES = new Set(["yes", "true", "y"]);
28
+ const MOTION_STATUS_VALUES = new Set(["draft", "preparing", "active", "paused", "archived"]);
28
29
  const PROSPECTS_ADD_NOTE_USAGE = "Usage: audienti prospects add-note <prsp_id> (--message <text> [--type <note|steer|voicemail_outreach|video_outreach>] [--engagement-type <key>] | --payload <file.json>) [--json] [--account <acct_id>]";
29
30
  const PROSPECTS_ADD_STEER_USAGE = "Usage: audienti prospects add-steer <prsp_id> (--message <text> [--engagement-type <key>] | --payload <file.json>) [--json] [--account <acct_id>]";
30
31
  const PROSPECTS_ADD_PROFILE_USAGE = "Usage: audienti prospects add-profile <prsp_id> --url <profile_url|email|phone> [--json] [--account <acct_id>]";
31
32
  const PROSPECTS_REPORT_BAD_PROFILE_USAGE = "Usage: audienti prospects report-bad-profile <prsp_id> <prof_id|citation_id> [--json] [--account <acct_id>]";
32
33
  const PROSPECTS_ASSIGN_USAGE = "Usage: audienti prospects assign <prsp_id> [prsp_id...] --assigned-user <id|me|unassign> [--json] [--account <acct_id>]";
33
34
  const PROSPECTS_IMPORT_BATCH_USAGE = "Usage: audienti prospects import-batch --file <csv|jsonl|json> [--list <list_id>] [--motion <motn_id>] [--assigned-user <id|me>] [--json] [--account <acct_id>]";
34
- const USERS_ACTIVITY_USAGE = "Usage: audienti users activity <account_user_id|me> [--mode <actor|account_usage>] [--window <24h|7d|30d>] [--platform <linkedin|email|gmail>] [--query <text>] [--limit <n>] [--page <n>] [--json] [--account <acct_id>]";
35
+ const USERS_ACTIVITY_USAGE = "Usage: audienti users activity [account_user_id|me] [--mode <actor|account_usage>] [--window <24h|7d|30d>] [--platform <linkedin|email|gmail>] [--query <text>] [--limit <n>] [--page <n>] [--json] [--account <acct_id>]";
35
36
  const WRITER_TEST_RUN_USAGE = "Usage: audienti writer test-run <prsp_id> [--json] [--mode <report|plan|step>] [--branch <both|no-accept|accepted>] [--step <step_key|row_number>] [--no-cache] [--clear-cache] [--account <acct_id>]";
36
37
  const MOTIONS_ANALYTICS_USAGE = "Usage: audienti motions analytics <motn_id> [--window 30d] [--json] [--account <acct_id>]";
38
+ const MOTIONS_UPDATE_USAGE = "Usage: audienti motions update <motn_id> --status <draft|preparing|active|paused|archived> [--json] [--account <acct_id>]";
39
+ const MOTIONS_DELETE_USAGE = "Usage: audienti motions delete <motn_id> --confirm <yes|true|Y|y> [--json] [--account <acct_id>]";
37
40
  const MOTIONS_CLONE_USAGE = "Usage: audienti motions clone <motn_id> --name <text> [--json] [--account <acct_id>]";
38
41
  const MOTIONS_MOVE_PROSPECTS_USAGE = "Usage: audienti motions move-prospects <source_motn_id> --target <target_motn_id> <prsp_id> [prsp_id...] [--json] [--account <acct_id>]";
39
42
  const ANALYTICS_PROSPECTS_USAGE = "Usage: audienti analytics prospects [--window 24h] [--cohort-start YYYY-MM-DD --cohort-end YYYY-MM-DD] [--motion <motn_id>] [--provenance <source>] [--user <account_user_id|email|name|me>] [--json] [--account <acct_id>]";
@@ -120,6 +123,7 @@ async function dispatch(argv, context) {
120
123
  if (normalizedResource === "accounts" && action === "list") return accountsList(rest, context, { accountOverride });
121
124
  if (normalizedResource === "accounts" && action === "select") return accountsSelect(rest, context);
122
125
  if (normalizedResource === "users" && action === "list") return usersList(rest, context, { accountOverride });
126
+ if (normalizedResource === "users" && action === "select") return usersSelect(rest, context, { accountOverride });
123
127
  if (normalizedResource === "users" && action === "activity") return usersActivity(rest, context, { accountOverride });
124
128
  if (normalizedResource === "offers" && action === "list") return offersList(rest, context, { accountOverride });
125
129
  if (normalizedResource === "offers" && action === "create") return offersCreate(rest, context, { accountOverride });
@@ -141,6 +145,9 @@ async function dispatch(argv, context) {
141
145
  if (normalizedResource === "motions" && action === "prospects") return motionsProspects(rest, context, { accountOverride });
142
146
  if (normalizedResource === "motions" && action === "add-prospects") return motionsAddProspects(rest, context, { accountOverride });
143
147
  if (normalizedResource === "motions" && action === "create") return motionsCreate(rest, context, { accountOverride });
148
+ if (normalizedResource === "motions" && action === "update") return motionsUpdate(rest, context, { accountOverride });
149
+ if (normalizedResource === "motions" && ["activate", "pause", "archive"].includes(action)) return motionsStatusShortcut(action, rest, context, { accountOverride });
150
+ if (normalizedResource === "motions" && action === "delete") return motionsDelete(rest, context, { accountOverride });
144
151
  if (normalizedResource === "motions" && action === "clone") return motionsClone(rest, context, { accountOverride });
145
152
  if (normalizedResource === "motions" && action === "move-prospects") return motionsMoveProspects(rest, context, { accountOverride });
146
153
  if (normalizedResource === "prospects" && action === "list") return prospectsList(rest, context, { accountOverride });
@@ -268,6 +275,14 @@ async function authStatus(args, context, { accountOverride } = {}) {
268
275
  } else {
269
276
  writeLine(context.stdout, "Active account: none selected");
270
277
  }
278
+
279
+ const accountUser = defaultAccountUserConfig(config, { accountOverride });
280
+ if (accountUser.id) {
281
+ const name = accountUser.name ? `${accountUser.name} ` : "";
282
+ writeLine(context.stdout, `Default account user: ${name}(${accountUser.id})`);
283
+ } else {
284
+ writeLine(context.stdout, "Default account user: none selected");
285
+ }
271
286
  }
272
287
 
273
288
  async function authLogout(args, context) {
@@ -289,7 +304,10 @@ async function configList(args, context) {
289
304
  host: config.host || null,
290
305
  token: config.token ? maskToken(config.token) : null,
291
306
  accountId: config.accountId || null,
292
- accountName: config.accountName || null
307
+ accountName: config.accountName || null,
308
+ accountUserId: config.accountUserId || null,
309
+ accountUserName: config.accountUserName || null,
310
+ accountUserEmail: config.accountUserEmail || null
293
311
  };
294
312
 
295
313
  if (values.json) return writeJson(context.stdout, payload);
@@ -305,6 +323,13 @@ async function configList(args, context) {
305
323
  } else {
306
324
  writeLine(context.stdout, "Active account: none selected");
307
325
  }
326
+
327
+ if (payload.accountUserId) {
328
+ const name = payload.accountUserName ? `${payload.accountUserName} ` : "";
329
+ writeLine(context.stdout, `Default account user: ${name}(${payload.accountUserId})`);
330
+ } else {
331
+ writeLine(context.stdout, "Default account user: none selected");
332
+ }
308
333
  }
309
334
 
310
335
  async function accountsList(args, context, { accountOverride } = {}) {
@@ -353,7 +378,10 @@ async function accountsSelect(args, context) {
353
378
  await writeConfig({
354
379
  ...config,
355
380
  accountId: account.prefix_id,
356
- accountName: account.name
381
+ accountName: account.name,
382
+ accountUserId: account.prefix_id === config.accountId ? config.accountUserId : undefined,
383
+ accountUserName: account.prefix_id === config.accountId ? config.accountUserName : undefined,
384
+ accountUserEmail: account.prefix_id === config.accountId ? config.accountUserEmail : undefined
357
385
  }, { env: context.env });
358
386
 
359
387
  writeLine(context.stdout, `Selected account ${account.name} (${account.prefix_id}).`);
@@ -383,6 +411,46 @@ function resolveAccountSelection(accounts, term) {
383
411
  throw new CommandError(`Account term "${requested}" matched multiple accounts: ${options}.`);
384
412
  }
385
413
 
414
+ function resolveAccountUserSelection(users, term) {
415
+ const requested = String(term || "").trim();
416
+ if (!requested) return null;
417
+
418
+ if (requested.toLowerCase() === "me") {
419
+ const currentUsers = users.filter((candidate) => candidate.current);
420
+ if (currentUsers.length === 1) return currentUsers[0];
421
+ if (currentUsers.length > 1) throw new CommandError("The token matched multiple current account users.");
422
+ return null;
423
+ }
424
+
425
+ const exactId = users.find((candidate) => String(candidate.id) === requested);
426
+ if (exactId) return exactId;
427
+
428
+ const normalizedRequested = requested.toLowerCase();
429
+ const exactEmail = users.find((candidate) => String(candidate.email || "").toLowerCase() === normalizedRequested);
430
+ if (exactEmail) return exactEmail;
431
+
432
+ const exactName = users.find((candidate) => String(candidate.name || "").toLowerCase() === normalizedRequested);
433
+ if (exactName) return exactName;
434
+
435
+ const matches = users.filter((candidate) => {
436
+ const id = String(candidate.id || "").toLowerCase();
437
+ const name = String(candidate.name || "").toLowerCase();
438
+ const email = String(candidate.email || "").toLowerCase();
439
+ return id.includes(normalizedRequested) || name.includes(normalizedRequested) || email.includes(normalizedRequested);
440
+ });
441
+
442
+ if (matches.length === 1) return matches[0];
443
+ if (matches.length === 0) return null;
444
+
445
+ const options = matches.map(accountUserLabel).join(", ");
446
+ throw new CommandError(`Account user term "${requested}" matched multiple account users: ${options}.`);
447
+ }
448
+
449
+ function accountUserLabel(accountUser) {
450
+ const name = accountUser?.name || accountUser?.email || `Account user ${accountUser?.id}`;
451
+ return `${name} (${accountUser?.id})`;
452
+ }
453
+
386
454
  async function listsList(args, context, { accountOverride } = {}) {
387
455
  const { values, positionals } = parseCommandArgs(args, jsonOptions());
388
456
  if (positionals.length > 0) throw new CommandError("Usage: audienti lists list [--json] [--account <acct_id>]");
@@ -405,6 +473,29 @@ async function usersList(args, context, { accountOverride } = {}) {
405
473
  renderUsers(users, context);
406
474
  }
407
475
 
476
+ async function usersSelect(args, context, { accountOverride } = {}) {
477
+ const { positionals } = parseCommandArgs(args, {});
478
+ if (positionals.length !== 1) throw new CommandError("Usage: audienti users select <account_user_id|email|name|me> [--account <acct_id>]");
479
+
480
+ const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
481
+ const users = await client.users(accountId);
482
+ const accountUser = resolveAccountUserSelection(users, positionals[0]);
483
+ if (!accountUser) {
484
+ throw new CommandError(`Account user ${positionals[0]} does not exist or is not visible in account ${accountId}.`);
485
+ }
486
+
487
+ await writeConfig({
488
+ ...config,
489
+ accountId,
490
+ accountName: accountOverride && accountOverride !== config.accountId ? undefined : config.accountName,
491
+ accountUserId: String(accountUser.id),
492
+ accountUserName: accountUser.name,
493
+ accountUserEmail: accountUser.email
494
+ }, { env: context.env });
495
+
496
+ writeLine(context.stdout, `Selected account user ${accountUserLabel(accountUser)}.`);
497
+ }
498
+
408
499
  async function usersActivity(args, context, { accountOverride } = {}) {
409
500
  const { values, positionals } = parseCommandArgs(args, {
410
501
  ...jsonOptions(),
@@ -415,10 +506,10 @@ async function usersActivity(args, context, { accountOverride } = {}) {
415
506
  limit: { type: "string" },
416
507
  page: { type: "string" }
417
508
  });
418
- if (positionals.length !== 1) throw new CommandError(USERS_ACTIVITY_USAGE);
509
+ if (positionals.length > 1) throw new CommandError(USERS_ACTIVITY_USAGE);
419
510
 
420
- const { client, accountId } = await requireAccountContext(context, { accountOverride });
421
- const payload = await client.userActivity(accountId, positionals[0], compactObject({
511
+ const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
512
+ const payload = await client.userActivity(accountId, resolveAccountUserId(positionals[0] || "me", config, { accountOverride }), compactObject({
422
513
  mode: values.mode,
423
514
  window: values.window,
424
515
  platform: values.platform,
@@ -782,11 +873,11 @@ async function motionsAddProspects(args, context, { accountOverride } = {}) {
782
873
  }
783
874
 
784
875
  const [motionId, ...prospectIds] = positionals;
785
- const { client, accountId } = await requireAccountContext(context, { accountOverride });
876
+ const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
786
877
  const { payload, rejected } = await performBulkMutation(() =>
787
878
  client.addMotionProspects(accountId, motionId, compactObject({
788
879
  prospect_ids: prospectIds,
789
- assigned_user_id: values["assigned-user"]
880
+ assigned_user_id: resolveAccountUserId(values["assigned-user"], config, { accountOverride })
790
881
  })));
791
882
  if (values.json) {
792
883
  writeJson(context.stdout, payload);
@@ -818,6 +909,68 @@ async function motionsCreate(args, context, { accountOverride } = {}) {
818
909
  renderMotion(created, context);
819
910
  }
820
911
 
912
+ async function motionsDelete(args, context, { accountOverride } = {}) {
913
+ const { values, positionals } = parseCommandArgs(args, {
914
+ ...jsonOptions(),
915
+ confirm: { type: "string" }
916
+ });
917
+ const normalizedConfirm = String(values.confirm || "").trim().toLowerCase();
918
+ if (positionals.length !== 1 || !DELETE_CONFIRMATION_VALUES.has(normalizedConfirm)) {
919
+ throw new CommandError(MOTIONS_DELETE_USAGE);
920
+ }
921
+
922
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
923
+ const payload = await client.deleteMotion(accountId, positionals[0]);
924
+ if (values.json) return writeJson(context.stdout, payload);
925
+
926
+ writeLine(context.stdout, `Deleted motion ${display(payload?.name)} (${display(payload?.prefix_id)}).`);
927
+ }
928
+
929
+ async function motionsUpdate(args, context, { accountOverride } = {}) {
930
+ const { values, positionals } = parseCommandArgs(args, {
931
+ ...jsonOptions(),
932
+ status: { type: "string" }
933
+ });
934
+ if (positionals.length !== 1 || !values.status) {
935
+ throw new CommandError(MOTIONS_UPDATE_USAGE);
936
+ }
937
+
938
+ return updateMotionStatus(positionals[0], values.status, context, { accountOverride, json: values.json });
939
+ }
940
+
941
+ async function motionsStatusShortcut(action, args, context, { accountOverride } = {}) {
942
+ const usage = `Usage: audienti motions ${action} <motn_id> [--json] [--account <acct_id>]`;
943
+ const { values, positionals } = parseCommandArgs(args, jsonOptions());
944
+ if (positionals.length !== 1) {
945
+ throw new CommandError(usage);
946
+ }
947
+
948
+ const statusByAction = {
949
+ activate: "active",
950
+ pause: "paused",
951
+ archive: "archived"
952
+ };
953
+ return updateMotionStatus(positionals[0], statusByAction[action], context, { accountOverride, json: values.json });
954
+ }
955
+
956
+ async function updateMotionStatus(motionId, status, context, { accountOverride, json } = {}) {
957
+ const normalizedStatus = String(status || "").trim().toLowerCase();
958
+ if (!MOTION_STATUS_VALUES.has(normalizedStatus)) {
959
+ throw new CommandError(MOTIONS_UPDATE_USAGE);
960
+ }
961
+
962
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
963
+ const motion = await client.updateMotion(accountId, motionId, {
964
+ motion: {
965
+ status: normalizedStatus
966
+ }
967
+ });
968
+ if (json) return writeJson(context.stdout, motion);
969
+
970
+ writeLine(context.stdout, `Updated motion ${display(motion?.name)} (${display(motion?.prefix_id)}) to ${display(motion?.status)}.`);
971
+ renderMotion(motion, context);
972
+ }
973
+
821
974
  async function motionsClone(args, context, { accountOverride } = {}) {
822
975
  const { values, positionals } = parseCommandArgs(args, {
823
976
  ...jsonOptions(),
@@ -890,7 +1043,7 @@ async function prospectsList(args, context, { accountOverride } = {}) {
890
1043
  if (values.motion && values.play) throw new CommandError("Choose one motion filter: use either --motion or --play.");
891
1044
  if (values.company && values["company-profile"]) throw new CommandError("Choose one company filter: use either --company or --company-profile.");
892
1045
 
893
- const { client, accountId } = await requireAccountContext(context, { accountOverride });
1046
+ const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
894
1047
  const query = compactObject({
895
1048
  query: values.query,
896
1049
  company: values.company,
@@ -899,7 +1052,7 @@ async function prospectsList(args, context, { accountOverride } = {}) {
899
1052
  play_id: values.play,
900
1053
  list_id: values.list,
901
1054
  stage: values.stage,
902
- assigned_user_id: values["assigned-user"],
1055
+ assigned_user_id: resolveAccountUserId(values["assigned-user"], config, { accountOverride }),
903
1056
  limit: values.limit,
904
1057
  offset: values.offset,
905
1058
  page: values.page,
@@ -923,11 +1076,12 @@ async function prospectsAssign(args, context, { accountOverride } = {}) {
923
1076
  throw new CommandError(PROSPECTS_ASSIGN_USAGE);
924
1077
  }
925
1078
 
926
- const { client, accountId } = await requireAccountContext(context, { accountOverride });
1079
+ const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
1080
+ const assignedUserId = resolveAccountUserId(values["assigned-user"], config, { accountOverride });
927
1081
  const { payload, rejected } = await performBulkMutation(() =>
928
1082
  client.assignProspects(accountId, {
929
1083
  prospect_ids: positionals,
930
- assigned_user_id: values["assigned-user"]
1084
+ assigned_user_id: assignedUserId
931
1085
  }));
932
1086
  if (values.json) {
933
1087
  writeJson(context.stdout, payload);
@@ -936,7 +1090,7 @@ async function prospectsAssign(args, context, { accountOverride } = {}) {
936
1090
 
937
1091
  const successLabel = values["assigned-user"] === "unassign" ?
938
1092
  `Unassigned ${successCount(payload)} prospects.` :
939
- `Assigned ${successCount(payload)} prospects to ${display(values["assigned-user"])}.`;
1093
+ `Assigned ${successCount(payload)} prospects to ${display(assignedUserId)}.`;
940
1094
  renderBulkMutationResult(payload, context, {
941
1095
  successLabel,
942
1096
  zeroSuccessLabel: "No prospects were assigned."
@@ -1345,12 +1499,12 @@ async function prospectsImport(args, context, { accountOverride } = {}) {
1345
1499
  throw new CommandError("Usage: audienti prospects import <linkedin_url> [--list <list_id>] [--motion <motn_id>] [--assigned-user <id|me>] [--json] [--account <acct_id>]");
1346
1500
  }
1347
1501
 
1348
- const { client, accountId } = await requireAccountContext(context, { accountOverride });
1502
+ const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
1349
1503
  const payload = await client.prospectImport(accountId, compactObject({
1350
1504
  linkedin_url: positionals[0],
1351
1505
  list_id: values.list,
1352
1506
  motion_id: values.motion,
1353
- assigned_user_id: values["assigned-user"]
1507
+ assigned_user_id: resolveAccountUserId(values["assigned-user"], config, { accountOverride })
1354
1508
  }));
1355
1509
  if (values.json) return writeJson(context.stdout, payload);
1356
1510
 
@@ -1372,7 +1526,7 @@ async function prospectsImportBatch(args, context, { accountOverride } = {}) {
1372
1526
  const rows = await readProspectImportBatchFile(values.file);
1373
1527
  if (rows.length === 0) throw new CommandError("Import batch file did not contain any prospects.");
1374
1528
 
1375
- const { client, accountId } = await requireAccountContext(context, { accountOverride });
1529
+ const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
1376
1530
  const result = {
1377
1531
  summary: {
1378
1532
  total: rows.length,
@@ -1388,7 +1542,7 @@ async function prospectsImportBatch(args, context, { accountOverride } = {}) {
1388
1542
  linkedin_url: row.linkedin_url,
1389
1543
  list_id: row.list_id || values.list,
1390
1544
  motion_id: row.motion_id || values.motion,
1391
- assigned_user_id: row.assigned_user_id || values["assigned-user"]
1545
+ assigned_user_id: resolveAccountUserId(row.assigned_user_id || values["assigned-user"], config, { accountOverride })
1392
1546
  });
1393
1547
 
1394
1548
  try {
@@ -1546,8 +1700,8 @@ async function analyticsProspects(args, context, { accountOverride } = {}) {
1546
1700
  const { values, positionals } = parseCommandArgs(args, analyticsProspectsOptions());
1547
1701
  if (positionals.length > 0) throw new CommandError(ANALYTICS_PROSPECTS_USAGE);
1548
1702
 
1549
- const { client, accountId } = await requireAccountContext(context, { accountOverride });
1550
- const payload = await client.analyticsProspects(accountId, analyticsQuery(values));
1703
+ const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
1704
+ const payload = await client.analyticsProspects(accountId, analyticsQuery(values, config, { accountOverride }));
1551
1705
  if (values.json) return writeJson(context.stdout, payload);
1552
1706
 
1553
1707
  renderAnalyticsProspects(payload, context);
@@ -1566,13 +1720,13 @@ async function analyticsProspectsCohortAnalysis(args, context, { accountOverride
1566
1720
 
1567
1721
  const weeks = normalizedCohortAnalysisWeeks(values.weeks);
1568
1722
  const cohorts = weeklyCohorts({ weeks, now: currentDate(context) });
1569
- const { client, accountId } = await requireAccountContext(context, { accountOverride });
1723
+ const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
1570
1724
  const rows = [];
1571
1725
 
1572
1726
  for (const cohort of cohorts) {
1573
1727
  const payload = await client.analyticsProspects(accountId, compactObject({
1574
1728
  window: values.window,
1575
- account_user_id: values.user,
1729
+ account_user_id: resolveAccountUserId(values.user, config, { accountOverride }),
1576
1730
  motion_id: values.motion,
1577
1731
  provenance: values.provenance,
1578
1732
  cohort_start: cohort.start_date,
@@ -1601,8 +1755,8 @@ async function analyticsUsers(args, context, { accountOverride } = {}) {
1601
1755
  validateDatePair(values.start, values.end, "--start", "--end");
1602
1756
  validateDatePair(values["cohort-start"], values["cohort-end"], "--cohort-start", "--cohort-end");
1603
1757
 
1604
- const { client, accountId } = await requireAccountContext(context, { accountOverride });
1605
- const payload = await client.analyticsUsers(accountId, analyticsUsersQuery(values));
1758
+ const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
1759
+ const payload = await client.analyticsUsers(accountId, analyticsUsersQuery(values, config, { accountOverride }));
1606
1760
  if (values.json) return writeJson(context.stdout, payload);
1607
1761
 
1608
1762
  renderAnalyticsUsers(payload, context);
@@ -1612,8 +1766,8 @@ async function analyticsVisibility(args, context, { accountOverride } = {}) {
1612
1766
  const { values, positionals } = parseCommandArgs(args, analyticsOptions());
1613
1767
  if (positionals.length > 0) throw new CommandError("Usage: audienti analytics visibility [--window 24h] [--user <account_user_id|email|name|me>] [--json] [--account <acct_id>]");
1614
1768
 
1615
- const { client, accountId } = await requireAccountContext(context, { accountOverride });
1616
- const payload = await client.analyticsVisibility(accountId, analyticsQuery(values));
1769
+ const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
1770
+ const payload = await client.analyticsVisibility(accountId, analyticsQuery(values, config, { accountOverride }));
1617
1771
  if (values.json) return writeJson(context.stdout, payload);
1618
1772
 
1619
1773
  renderAnalyticsVisibility(payload, context);
@@ -1623,8 +1777,8 @@ async function analyticsContent(args, context, { accountOverride } = {}) {
1623
1777
  const { values, positionals } = parseCommandArgs(args, analyticsOptions());
1624
1778
  if (positionals.length > 0) throw new CommandError("Usage: audienti analytics content [--window 24h] [--user <account_user_id|email|name|me>] [--json] [--account <acct_id>]");
1625
1779
 
1626
- const { client, accountId } = await requireAccountContext(context, { accountOverride });
1627
- const payload = await client.analyticsContent(accountId, analyticsQuery(values));
1780
+ const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
1781
+ const payload = await client.analyticsContent(accountId, analyticsQuery(values, config, { accountOverride }));
1628
1782
  if (values.json) return writeJson(context.stdout, payload);
1629
1783
 
1630
1784
  renderAnalyticsContent(payload, context);
@@ -1671,6 +1825,25 @@ async function requireAccountContext(context, { accountOverride } = {}) {
1671
1825
  };
1672
1826
  }
1673
1827
 
1828
+ function resolveAccountUserId(value, config = {}, { accountOverride } = {}) {
1829
+ const rawValue = String(value || "").trim();
1830
+ if (!rawValue) return undefined;
1831
+ if (rawValue.toLowerCase() !== "me") return rawValue;
1832
+
1833
+ return defaultAccountUserConfig(config, { accountOverride }).id || "me";
1834
+ }
1835
+
1836
+ function defaultAccountUserConfig(config = {}, { accountOverride } = {}) {
1837
+ if (!config.accountUserId) return {};
1838
+ if (accountOverride && accountOverride !== config.accountId) return {};
1839
+
1840
+ return {
1841
+ id: String(config.accountUserId),
1842
+ name: config.accountUserName,
1843
+ email: config.accountUserEmail
1844
+ };
1845
+ }
1846
+
1674
1847
  function clientFromConfig(config, context) {
1675
1848
  return new AudientiClient({
1676
1849
  host: config.host || DEFAULT_HOST,
@@ -1782,21 +1955,21 @@ function analyticsUsersOptions() {
1782
1955
  };
1783
1956
  }
1784
1957
 
1785
- function analyticsQuery(values) {
1958
+ function analyticsQuery(values, config = {}, { accountOverride } = {}) {
1786
1959
  return compactObject({
1787
1960
  window: values.window,
1788
1961
  cohort_start: values["cohort-start"],
1789
1962
  cohort_end: values["cohort-end"],
1790
1963
  motion_id: values.motion,
1791
1964
  provenance: values.provenance,
1792
- account_user_id: values.user
1965
+ account_user_id: resolveAccountUserId(values.user, config, { accountOverride })
1793
1966
  });
1794
1967
  }
1795
1968
 
1796
- function analyticsUsersQuery(values) {
1969
+ function analyticsUsersQuery(values, config = {}, { accountOverride } = {}) {
1797
1970
  const hasDateRange = Boolean(values.start || values.end);
1798
1971
  return compactObject({
1799
- account_user_id: values.user || "me",
1972
+ account_user_id: resolveAccountUserId(values.user || "me", config, { accountOverride }),
1800
1973
  window: hasDateRange ? undefined : (values.window || "30d"),
1801
1974
  start_date: values.start,
1802
1975
  end_date: values.end,
@@ -3594,6 +3767,7 @@ const HELP_TOPICS = new Map([
3594
3767
  " audienti auth token <token> Save an API token",
3595
3768
  " audienti accounts list See accounts available to this token",
3596
3769
  " audienti accounts select <acct_id> Use one account by default",
3770
+ " audienti users select <user> Use one account user by default",
3597
3771
  " audienti help agent-workflows Common agent/operator paths",
3598
3772
  "",
3599
3773
  "Work areas:",
@@ -3601,7 +3775,8 @@ const HELP_TOPICS = new Map([
3601
3775
  " audienti auth status",
3602
3776
  " audienti config list",
3603
3777
  " audienti users list",
3604
- " audienti users activity <account_user_id|me>",
3778
+ " audienti users select <account_user_id|email|name|me>",
3779
+ " audienti users activity [account_user_id|me]",
3605
3780
  "",
3606
3781
  " Motions / plays",
3607
3782
  " audienti motions list",
@@ -3609,6 +3784,10 @@ const HELP_TOPICS = new Map([
3609
3784
  " audienti motions analytics <motn_id>",
3610
3785
  " audienti motions prospects <motn_id>",
3611
3786
  " audienti motions create --payload <file.json>",
3787
+ " audienti motions update <motn_id> --status <state>",
3788
+ " audienti motions activate <motn_id>",
3789
+ " audienti motions pause <motn_id>",
3790
+ " audienti motions delete <motn_id> --confirm <yes|true|Y|y>",
3612
3791
  " audienti motions clone <motn_id> --name <text>",
3613
3792
  " audienti motions move-prospects <source_motn_id> --target <target_motn_id> <prsp_id> [prsp_id...]",
3614
3793
  " Tip: `plays` is accepted anywhere `motions` is accepted.",
@@ -3717,7 +3896,8 @@ const HELP_TOPICS = new Map([
3717
3896
  " Host: string",
3718
3897
  " Token: masked string",
3719
3898
  " User: string",
3720
- " Active account: account name and acct_ id, or none selected"
3899
+ " Active account: account name and acct_ id, or none selected",
3900
+ " Default account user: account user name and id, or none selected"
3721
3901
  ].join("\n")],
3722
3902
 
3723
3903
  ["auth logout", [
@@ -3751,7 +3931,8 @@ const HELP_TOPICS = new Map([
3751
3931
  " Exists: yes|no",
3752
3932
  " Host: string or none",
3753
3933
  " Token: masked string or none",
3754
- " Active account: account name and acct_ id, or none selected"
3934
+ " Active account: account name and acct_ id, or none selected",
3935
+ " Default account user: account user name and id, or none selected"
3755
3936
  ].join("\n")],
3756
3937
 
3757
3938
  ["accounts", [
@@ -3796,12 +3977,13 @@ const HELP_TOPICS = new Map([
3796
3977
  ["users", [
3797
3978
  "Usage:",
3798
3979
  " audienti users list [--json]",
3799
- " audienti users activity <account_user_id|me> [--json]",
3980
+ " audienti users select <account_user_id|email|name|me>",
3981
+ " audienti users activity [account_user_id|me] [--json]",
3800
3982
  "",
3801
3983
  "Status: implemented",
3802
3984
  "",
3803
3985
  "Purpose:",
3804
- " List the account users that can be used as motion principals or assignees.",
3986
+ " List and select the account users that can be used as motion principals or assignees.",
3805
3987
  "",
3806
3988
  "CLI synonym:",
3807
3989
  " `principals` is accepted anywhere `users` is accepted"
@@ -3825,6 +4007,24 @@ const HELP_TOPICS = new Map([
3825
4007
  " current: boolean"
3826
4008
  ].join("\n")],
3827
4009
 
4010
+ ["users select", [
4011
+ "Usage:",
4012
+ " audienti users select <account_user_id|email|name|me> [--account <acct_id>]",
4013
+ "",
4014
+ "Status: implemented",
4015
+ "",
4016
+ "Purpose:",
4017
+ " Save a default account user for commands that accept `me` or default to the current operator.",
4018
+ "",
4019
+ "Behavior:",
4020
+ " Validates the account user against `audienti users list` for the active account before saving.",
4021
+ " Selecting a different account with `audienti accounts select` clears the saved account user.",
4022
+ " Passing --account selects the account user for that account and makes it the active account.",
4023
+ "",
4024
+ "API:",
4025
+ " GET /api/v1/accounts/:account_id/users.json"
4026
+ ].join("\n")],
4027
+
3828
4028
  ["users activity", [
3829
4029
  "Usage:",
3830
4030
  ` ${USERS_ACTIVITY_USAGE.slice("Usage: ".length)}`,
@@ -3835,7 +4035,7 @@ const HELP_TOPICS = new Map([
3835
4035
  " Inspect one workspace user's outbound activity feed and action summary.",
3836
4036
  "",
3837
4037
  "Input shape:",
3838
- " account_user_id: integer account user id, or me for the authenticated token user",
4038
+ " account_user_id: integer account user id, or me for the saved default account user when configured",
3839
4039
  " mode: actor | account_usage",
3840
4040
  " window: 24h | 7d | 30d",
3841
4041
  " platform: linkedin | email | gmail",
@@ -4205,10 +4405,15 @@ const HELP_TOPICS = new Map([
4205
4405
  " audienti motions prospects <motn_id> [--json]",
4206
4406
  " audienti motions add-prospects <motn_id> <prsp_id> [prsp_id...] [--json]",
4207
4407
  " audienti motions create --payload <file.json> [--json]",
4408
+ " audienti motions update <motn_id> --status <draft|preparing|active|paused|archived> [--json]",
4409
+ " audienti motions activate <motn_id> [--json]",
4410
+ " audienti motions pause <motn_id> [--json]",
4411
+ " audienti motions archive <motn_id> [--json]",
4412
+ " audienti motions delete <motn_id> --confirm <yes|true|Y|y> [--json]",
4208
4413
  " audienti motions clone <motn_id> --name <text> [--json]",
4209
4414
  " audienti motions move-prospects <source_motn_id> --target <target_motn_id> <prsp_id> [prsp_id...] [--json]",
4210
4415
  "",
4211
- "Status: read, create, clone, status, and prospect attachment commands implemented",
4416
+ "Status: read, create, status update, delete, clone, status, and prospect attachment commands implemented",
4212
4417
  "",
4213
4418
  "CLI synonym:",
4214
4419
  " `plays` is accepted anywhere `motions` is accepted",
@@ -4410,6 +4615,92 @@ const HELP_TOPICS = new Map([
4410
4615
  " }"
4411
4616
  ].join("\n")],
4412
4617
 
4618
+ ["motions update", [
4619
+ "Usage:",
4620
+ ` ${MOTIONS_UPDATE_USAGE.slice("Usage: ".length)}`,
4621
+ "",
4622
+ "Status: implemented",
4623
+ "",
4624
+ "Purpose:",
4625
+ " Change one motion or play's lifecycle status.",
4626
+ "",
4627
+ "Input shape:",
4628
+ " motn_id: motn_ prefix id",
4629
+ " status: draft | preparing | active | paused | archived",
4630
+ "",
4631
+ "Behavior:",
4632
+ " Updates only the motion status. Other motion configuration stays unchanged.",
4633
+ "",
4634
+ "API:",
4635
+ " PATCH /api/v1/accounts/:account_id/motions/:id.json",
4636
+ "",
4637
+ "JSON body:",
4638
+ " {",
4639
+ " \"motion\": {",
4640
+ " \"status\": \"paused\"",
4641
+ " }",
4642
+ " }"
4643
+ ].join("\n")],
4644
+
4645
+ ["motions activate", [
4646
+ "Usage:",
4647
+ " audienti motions activate <motn_id> [--json] [--account <acct_id>]",
4648
+ "",
4649
+ "Status: implemented",
4650
+ "",
4651
+ "Purpose:",
4652
+ " Shortcut for `audienti motions update <motn_id> --status active`.",
4653
+ "",
4654
+ "API:",
4655
+ " PATCH /api/v1/accounts/:account_id/motions/:id.json"
4656
+ ].join("\n")],
4657
+
4658
+ ["motions pause", [
4659
+ "Usage:",
4660
+ " audienti motions pause <motn_id> [--json] [--account <acct_id>]",
4661
+ "",
4662
+ "Status: implemented",
4663
+ "",
4664
+ "Purpose:",
4665
+ " Shortcut for `audienti motions update <motn_id> --status paused`.",
4666
+ "",
4667
+ "API:",
4668
+ " PATCH /api/v1/accounts/:account_id/motions/:id.json"
4669
+ ].join("\n")],
4670
+
4671
+ ["motions archive", [
4672
+ "Usage:",
4673
+ " audienti motions archive <motn_id> [--json] [--account <acct_id>]",
4674
+ "",
4675
+ "Status: implemented",
4676
+ "",
4677
+ "Purpose:",
4678
+ " Shortcut for `audienti motions update <motn_id> --status archived`.",
4679
+ "",
4680
+ "API:",
4681
+ " PATCH /api/v1/accounts/:account_id/motions/:id.json"
4682
+ ].join("\n")],
4683
+
4684
+ ["motions delete", [
4685
+ "Usage:",
4686
+ ` ${MOTIONS_DELETE_USAGE.slice("Usage: ".length)}`,
4687
+ "",
4688
+ "Status: implemented",
4689
+ "",
4690
+ "Purpose:",
4691
+ " Delete one motion or play through the same cleanup path the app uses.",
4692
+ "",
4693
+ "Input shape:",
4694
+ " motn_id: motn_ prefix id",
4695
+ " confirm: one of yes, true, Y, y",
4696
+ "",
4697
+ "Behavior:",
4698
+ " Removes the motion, its managed custom signals, and its dedicated finder agent. Prospect records remain in the account.",
4699
+ "",
4700
+ "API:",
4701
+ " DELETE /api/v1/accounts/:account_id/motions/:id.json"
4702
+ ].join("\n")],
4703
+
4413
4704
  ["motions move-prospects", [
4414
4705
  "Usage:",
4415
4706
  ` ${MOTIONS_MOVE_PROSPECTS_USAGE.slice("Usage: ".length)}`,
@@ -5226,6 +5517,7 @@ const HELP_TOPICS = new Map([
5226
5517
  " audienti accounts list",
5227
5518
  " audienti accounts select <acct_id>",
5228
5519
  " audienti users list",
5520
+ " audienti users select me",
5229
5521
  " audienti offers list",
5230
5522
  " audienti icps list",
5231
5523
  "",
@@ -5233,6 +5525,9 @@ const HELP_TOPICS = new Map([
5233
5525
  " audienti motions create --payload <file.json>",
5234
5526
  " audienti motions clone <motn_id> --name \"New subset motion\"",
5235
5527
  " audienti motions move-prospects <source_motn_id> --target <target_motn_id> <prsp_id> [prsp_id...]",
5528
+ " audienti motions activate <motn_id>",
5529
+ " audienti motions pause <motn_id>",
5530
+ " audienti motions delete <motn_id> --confirm yes",
5236
5531
  " audienti motions status <motn_id>",
5237
5532
  "",
5238
5533
  "3. Add a new prospect from LinkedIn and poll enrichment",