@wayai/cli 0.3.51 → 0.3.53

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/index.js CHANGED
@@ -7994,13 +7994,19 @@ function isNewerVersion(latest, current) {
7994
7994
  }
7995
7995
  return false;
7996
7996
  }
7997
- var UUID_RE, slugify;
7997
+ var UUID_RE, slugify, OWN_HELP_COMMANDS;
7998
7998
  var init_utils = __esm({
7999
7999
  "src/lib/utils.ts"() {
8000
8000
  "use strict";
8001
8001
  init_dist();
8002
8002
  UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
8003
8003
  slugify = slugifySkillName;
8004
+ OWN_HELP_COMMANDS = /* @__PURE__ */ new Set([
8005
+ "eval",
8006
+ "admin",
8007
+ "report",
8008
+ "conversations"
8009
+ ]);
8004
8010
  }
8005
8011
  });
8006
8012
 
@@ -8867,111 +8873,132 @@ var init_logout = __esm({
8867
8873
  }
8868
8874
  });
8869
8875
 
8870
- // src/lib/hub-lock.ts
8876
+ // src/lib/hub-binding.ts
8871
8877
  import { execFileSync as execFileSync2 } from "child_process";
8872
8878
  import * as fs7 from "fs";
8873
8879
  import * as path7 from "path";
8874
- function getLockPath() {
8880
+ function resolveGitDir() {
8875
8881
  const cwd = process.cwd();
8876
- if (_lockPathCache && _lockPathCache.cwd === cwd) return _lockPathCache.lockPath;
8882
+ if (_gitDirCache && _gitDirCache.cwd === cwd) return _gitDirCache.gitDir;
8877
8883
  let gitDir;
8878
8884
  try {
8879
- gitDir = execFileSync2("git", ["rev-parse", "--git-dir"], {
8885
+ const raw = execFileSync2("git", ["rev-parse", "--git-dir"], {
8880
8886
  cwd,
8881
8887
  encoding: "utf-8",
8882
8888
  stdio: ["pipe", "pipe", "pipe"]
8883
8889
  }).trim();
8890
+ gitDir = raw ? path7.resolve(cwd, raw) : null;
8884
8891
  } catch {
8885
- _lockPathCache = { cwd, lockPath: null };
8886
- return null;
8892
+ gitDir = null;
8887
8893
  }
8888
- const lockPath = gitDir ? path7.resolve(cwd, gitDir, LOCK_FILENAME) : null;
8889
- _lockPathCache = { cwd, lockPath };
8890
- return lockPath;
8894
+ _gitDirCache = { cwd, gitDir };
8895
+ return gitDir;
8891
8896
  }
8892
- function readLock() {
8893
- const lockPath = getLockPath();
8894
- if (!lockPath) return null;
8895
- let raw;
8896
- try {
8897
- raw = fs7.readFileSync(lockPath, "utf-8");
8898
- } catch (err) {
8899
- if (err.code === "ENOENT") return null;
8900
- throw err;
8897
+ function getBindingPath() {
8898
+ const gitDir = resolveGitDir();
8899
+ return gitDir ? path7.join(gitDir, BINDING_FILENAME) : null;
8900
+ }
8901
+ function getLegacyBindingPath() {
8902
+ const gitDir = resolveGitDir();
8903
+ return gitDir ? path7.join(gitDir, LEGACY_BINDING_FILENAME) : null;
8904
+ }
8905
+ function readBinding() {
8906
+ for (const bindingPath of [getBindingPath(), getLegacyBindingPath()]) {
8907
+ if (!bindingPath) continue;
8908
+ let raw;
8909
+ try {
8910
+ raw = fs7.readFileSync(bindingPath, "utf-8");
8911
+ } catch (err) {
8912
+ if (err.code === "ENOENT") continue;
8913
+ throw err;
8914
+ }
8915
+ const trimmed = raw.trim();
8916
+ return UUID_RE.test(trimmed) ? trimmed : null;
8901
8917
  }
8902
- const trimmed = raw.trim();
8903
- return UUID_RE.test(trimmed) ? trimmed : null;
8918
+ return null;
8904
8919
  }
8905
- function writeLock(hubId) {
8920
+ function writeBinding(hubId) {
8906
8921
  if (!UUID_RE.test(hubId)) {
8907
8922
  throw new Error(`Invalid hub_id (must be a UUID): ${hubId}`);
8908
8923
  }
8909
- const lockPath = getLockPath();
8910
- if (!lockPath) {
8911
- throw new Error("Not inside a git repository \u2014 cannot write hub lock.");
8924
+ const bindingPath = getBindingPath();
8925
+ if (!bindingPath) {
8926
+ throw new Error("Not inside a git repository \u2014 cannot write hub binding.");
8912
8927
  }
8913
- fs7.writeFileSync(lockPath, `${hubId}
8928
+ fs7.writeFileSync(bindingPath, `${hubId}
8914
8929
  `, "utf-8");
8930
+ removeLegacyBinding();
8915
8931
  }
8916
- function clearLock() {
8917
- const lockPath = getLockPath();
8918
- if (!lockPath) return false;
8932
+ function removeLegacyBinding() {
8933
+ const legacyPath = getLegacyBindingPath();
8934
+ if (!legacyPath) return;
8919
8935
  try {
8920
- fs7.unlinkSync(lockPath);
8921
- return true;
8922
- } catch (err) {
8923
- if (err.code === "ENOENT") return false;
8924
- throw err;
8936
+ fs7.unlinkSync(legacyPath);
8937
+ } catch {
8938
+ }
8939
+ }
8940
+ function clearBinding() {
8941
+ let removed = false;
8942
+ for (const bindingPath of [getBindingPath(), getLegacyBindingPath()]) {
8943
+ if (!bindingPath) continue;
8944
+ try {
8945
+ fs7.unlinkSync(bindingPath);
8946
+ removed = true;
8947
+ } catch (err) {
8948
+ if (err.code !== "ENOENT") throw err;
8949
+ }
8925
8950
  }
8951
+ return removed;
8926
8952
  }
8927
- function assertHubMatchesLock(resolvedHubId, hubLabel) {
8928
- const locked = readLock();
8929
- if (!locked) return;
8930
- if (locked === resolvedHubId) return;
8953
+ function assertHubMatchesBinding(resolvedHubId, hubLabel) {
8954
+ const bound = readBinding();
8955
+ if (!bound) return;
8956
+ if (bound === resolvedHubId) return;
8931
8957
  const target = hubLabel ? `${hubLabel} (${resolvedHubId})` : resolvedHubId;
8932
8958
  console.error(
8933
8959
  [
8934
- `This worktree is locked to hub ${locked}, but the command resolved to ${target}.`,
8960
+ `This worktree is bound to hub ${bound}, but the command resolved to ${target}.`,
8935
8961
  "",
8936
8962
  "This usually means a prompt was routed to the wrong worktree.",
8937
- "Confirm with the user before unlocking. To override:",
8938
- " wayai unlock # clear the lock for this worktree",
8963
+ "Confirm with the user before unbinding. To override:",
8964
+ " wayai unbind # clear the binding for this worktree",
8939
8965
  ` wayai use ${resolvedHubId} # rebind this worktree to the new hub`
8940
8966
  ].join("\n")
8941
8967
  );
8942
8968
  process.exit(1);
8943
8969
  }
8944
- function autoLockIfUnlocked(hubId) {
8970
+ function autoBindIfUnbound(hubId) {
8945
8971
  try {
8946
- if (readLock()) return false;
8947
- writeLock(hubId);
8948
- console.log(`Worktree locked to hub ${hubId} (run \`wayai unlock\` to clear).`);
8972
+ if (readBinding()) return false;
8973
+ writeBinding(hubId);
8974
+ console.log(`Worktree bound to hub ${hubId} (run \`wayai unbind\` to clear).`);
8949
8975
  return true;
8950
8976
  } catch (err) {
8951
- console.warn(` Warning: could not auto-lock worktree (${err instanceof Error ? err.message : String(err)})`);
8977
+ console.warn(` Warning: could not auto-bind worktree (${err instanceof Error ? err.message : String(err)})`);
8952
8978
  return false;
8953
8979
  }
8954
8980
  }
8955
- function assertNoLockBlocksHubCreation(newHubName) {
8956
- const locked = readLock();
8957
- if (!locked) return;
8981
+ function assertNoBindingBlocksHubCreation(newHubName) {
8982
+ const bound = readBinding();
8983
+ if (!bound) return;
8958
8984
  console.error(
8959
8985
  [
8960
- `This worktree is locked to hub ${locked}, but you're about to create a new hub "${newHubName}" here.`,
8986
+ `This worktree is bound to hub ${bound}, but you're about to create a new hub "${newHubName}" here.`,
8961
8987
  "",
8962
8988
  "This usually means a prompt was routed to the wrong worktree.",
8963
- "Confirm with the user before unlocking. To override:",
8964
- " wayai unlock # clear the lock for this worktree"
8989
+ "Confirm with the user before unbinding. To override:",
8990
+ " wayai unbind # clear the binding for this worktree"
8965
8991
  ].join("\n")
8966
8992
  );
8967
8993
  process.exit(1);
8968
8994
  }
8969
- var LOCK_FILENAME, _lockPathCache;
8970
- var init_hub_lock = __esm({
8971
- "src/lib/hub-lock.ts"() {
8995
+ var BINDING_FILENAME, LEGACY_BINDING_FILENAME, _gitDirCache;
8996
+ var init_hub_binding = __esm({
8997
+ "src/lib/hub-binding.ts"() {
8972
8998
  "use strict";
8973
8999
  init_utils();
8974
- LOCK_FILENAME = "wayai-lock";
9000
+ BINDING_FILENAME = "wayai-binding";
9001
+ LEGACY_BINDING_FILENAME = "wayai-lock";
8975
9002
  }
8976
9003
  });
8977
9004
 
@@ -9017,11 +9044,11 @@ async function statusCommand(args2, pkg2) {
9017
9044
  const cachedCliLatest = readCachedLatest(CLI_CACHE_FILE);
9018
9045
  const cliLatest = cachedCliLatest && isNewerVersion(cachedCliLatest, pkg2.version) ? cachedCliLatest : null;
9019
9046
  const skill = buildSkillState();
9020
- let lockedHubId = null;
9047
+ let boundHubId = null;
9021
9048
  try {
9022
- lockedHubId = readLock();
9049
+ boundHubId = readBinding();
9023
9050
  } catch {
9024
- lockedHubId = null;
9051
+ boundHubId = null;
9025
9052
  }
9026
9053
  if (!config) {
9027
9054
  const snapshot2 = {
@@ -9035,7 +9062,8 @@ async function statusCommand(args2, pkg2) {
9035
9062
  orgs: [],
9036
9063
  active_org: null,
9037
9064
  workspace,
9038
- worktree_lock: { hub_id: lockedHubId }
9065
+ worktree_binding: { hub_id: boundHubId },
9066
+ worktree_lock: { hub_id: boundHubId }
9039
9067
  };
9040
9068
  if (json) {
9041
9069
  console.log(JSON.stringify(snapshot2, null, 2));
@@ -9089,7 +9117,8 @@ async function statusCommand(args2, pkg2) {
9089
9117
  orgs,
9090
9118
  active_org: activeOrg,
9091
9119
  workspace,
9092
- worktree_lock: { hub_id: lockedHubId }
9120
+ worktree_binding: { hub_id: boundHubId },
9121
+ worktree_lock: { hub_id: boundHubId }
9093
9122
  };
9094
9123
  if (json) {
9095
9124
  console.log(JSON.stringify(snapshot, null, 2));
@@ -9119,8 +9148,8 @@ async function statusCommand(args2, pkg2) {
9119
9148
  } else {
9120
9149
  console.log("No .wayai.yaml found \u2014 run `wayai init` to scope this repo to an organization.");
9121
9150
  }
9122
- if (lockedHubId) {
9123
- console.log(`Worktree lock: ${lockedHubId} (run \`wayai unlock\` to clear)`);
9151
+ if (boundHubId) {
9152
+ console.log(`Worktree binding: ${boundHubId} (run \`wayai unbind\` to clear)`);
9124
9153
  }
9125
9154
  if (tokenValid === true && accessToken) {
9126
9155
  await nudgeReportActions(config.api_url, accessToken);
@@ -9133,7 +9162,7 @@ var init_status = __esm({
9133
9162
  init_auth();
9134
9163
  init_repo_config();
9135
9164
  init_workspace();
9136
- init_hub_lock();
9165
+ init_hub_binding();
9137
9166
  init_api_client();
9138
9167
  init_version_cache();
9139
9168
  init_skill_version();
@@ -10243,7 +10272,7 @@ async function pullCommand(args2) {
10243
10272
  }
10244
10273
  if (gitRoot) warnLayoutOnce(gitRoot);
10245
10274
  const { hubId, hubFolder: existingFolder } = resolveHubTarget(workspaceDir, hubSelector);
10246
- assertHubMatchesLock(hubId);
10275
+ assertHubMatchesBinding(hubId);
10247
10276
  console.log("Fetching hub configuration...");
10248
10277
  const payload = await client.pull(hubId, organizationId);
10249
10278
  if (payload.hub_environment === "production") {
@@ -10315,7 +10344,7 @@ async function pullCommand(args2) {
10315
10344
  }
10316
10345
  if (cancelled) return;
10317
10346
  }
10318
- if (wroteFiles) autoLockIfUnlocked(hubId);
10347
+ if (wroteFiles) autoBindIfUnbound(hubId);
10319
10348
  }
10320
10349
  async function downloadBinaryResourceFiles(hubFolder, payload) {
10321
10350
  const resources = payload.resources || [];
@@ -10355,7 +10384,7 @@ var init_pull = __esm({
10355
10384
  init_workspace();
10356
10385
  init_layout();
10357
10386
  init_repo_config();
10358
- init_hub_lock();
10387
+ init_hub_binding();
10359
10388
  }
10360
10389
  });
10361
10390
 
@@ -10602,7 +10631,7 @@ async function pushSingleHub(client, hubId, hubFolder, autoConfirm, organization
10602
10631
  } else {
10603
10632
  console.log("No changes to push; folder renamed.");
10604
10633
  }
10605
- autoLockIfUnlocked(hubId);
10634
+ autoBindIfUnbound(hubId);
10606
10635
  return true;
10607
10636
  }
10608
10637
  console.log("\nChanges to push:");
@@ -10618,7 +10647,7 @@ async function pushSingleHub(client, hubId, hubFolder, autoConfirm, organization
10618
10647
  const result = await client.push(hubId, localConfig, organizationId);
10619
10648
  printSyncResult(result);
10620
10649
  await syncAfterPush(client, hubId, hubFolder, organizationId);
10621
- autoLockIfUnlocked(hubId);
10650
+ autoBindIfUnbound(hubId);
10622
10651
  return true;
10623
10652
  }
10624
10653
  function resolveWorkspaceDir() {
@@ -10677,7 +10706,7 @@ async function pushCommand(args2) {
10677
10706
  const newHubs = scanNewHubs(workspaceDir);
10678
10707
  const existing = selectExistingHub(workspaceDir, existingHubs, hubSelector, wsLabel);
10679
10708
  if (existing) {
10680
- assertHubMatchesLock(existing.hubId, path14.basename(existing.hubFolder));
10709
+ assertHubMatchesBinding(existing.hubId, path14.basename(existing.hubFolder));
10681
10710
  await pushSingleHub(client, existing.hubId, existing.hubFolder, autoConfirm, organizationId);
10682
10711
  return;
10683
10712
  }
@@ -10696,7 +10725,7 @@ async function pushCommand(args2) {
10696
10725
  }
10697
10726
  process.exit(1);
10698
10727
  }
10699
- assertNoLockBlocksHubCreation(newHub.hubName);
10728
+ assertNoBindingBlocksHubCreation(newHub.hubName);
10700
10729
  const hubType = newHub.hubType || "chat";
10701
10730
  console.log(`
10702
10731
  New hub detected: "${newHub.hubName}" (${hubType})`);
@@ -10738,7 +10767,7 @@ hub_environment: preview
10738
10767
  ${content}`;
10739
10768
  }
10740
10769
  fs12.writeFileSync(hubYamlPath, updated, "utf-8");
10741
- autoLockIfUnlocked(hubId);
10770
+ autoBindIfUnbound(hubId);
10742
10771
  await pushSingleHub(client, hubId, newHub.hubFolder, autoConfirm, organizationId, { skipAgentRename: true });
10743
10772
  }
10744
10773
  var init_push = __esm({
@@ -10754,7 +10783,7 @@ var init_push = __esm({
10754
10783
  init_workspace();
10755
10784
  init_layout();
10756
10785
  init_repo_config();
10757
- init_hub_lock();
10786
+ init_hub_binding();
10758
10787
  }
10759
10788
  });
10760
10789
 
@@ -10792,13 +10821,13 @@ async function useCommand(args2) {
10792
10821
  }
10793
10822
  hubId = match.hubId;
10794
10823
  }
10795
- const previous = readLock();
10824
+ const previous = readBinding();
10796
10825
  if (previous === hubId) {
10797
- console.log(`Worktree already locked to ${hubId}.`);
10826
+ console.log(`Worktree already bound to ${hubId}.`);
10798
10827
  return;
10799
10828
  }
10800
10829
  try {
10801
- writeLock(hubId);
10830
+ writeBinding(hubId);
10802
10831
  } catch (err) {
10803
10832
  console.error(err instanceof Error ? err.message : String(err));
10804
10833
  process.exit(1);
@@ -10806,13 +10835,13 @@ async function useCommand(args2) {
10806
10835
  if (previous) {
10807
10836
  console.log(`Worktree rebound: ${previous} \u2192 ${hubId}`);
10808
10837
  } else {
10809
- console.log(`Worktree locked to hub ${hubId}.`);
10838
+ console.log(`Worktree bound to hub ${hubId}.`);
10810
10839
  }
10811
10840
  }
10812
10841
  var init_use = __esm({
10813
10842
  "src/commands/use.ts"() {
10814
10843
  "use strict";
10815
- init_hub_lock();
10844
+ init_hub_binding();
10816
10845
  init_workspace();
10817
10846
  init_layout();
10818
10847
  init_utils();
@@ -10912,24 +10941,24 @@ var init_migrate = __esm({
10912
10941
  }
10913
10942
  });
10914
10943
 
10915
- // src/commands/unlock.ts
10916
- var unlock_exports = {};
10917
- __export(unlock_exports, {
10918
- unlockCommand: () => unlockCommand
10944
+ // src/commands/unbind.ts
10945
+ var unbind_exports = {};
10946
+ __export(unbind_exports, {
10947
+ unbindCommand: () => unbindCommand
10919
10948
  });
10920
- async function unlockCommand(_args) {
10921
- const previous = readLock();
10949
+ async function unbindCommand(_args) {
10950
+ const previous = readBinding();
10922
10951
  if (!previous) {
10923
- console.log("No worktree lock to clear.");
10952
+ console.log("No worktree binding to clear.");
10924
10953
  return;
10925
10954
  }
10926
- clearLock();
10927
- console.log(`Worktree unlocked (was: ${previous}).`);
10955
+ clearBinding();
10956
+ console.log(`Worktree unbound (was: ${previous}).`);
10928
10957
  }
10929
- var init_unlock = __esm({
10930
- "src/commands/unlock.ts"() {
10958
+ var init_unbind = __esm({
10959
+ "src/commands/unbind.ts"() {
10931
10960
  "use strict";
10932
- init_hub_lock();
10961
+ init_hub_binding();
10933
10962
  }
10934
10963
  });
10935
10964
 
@@ -11115,7 +11144,41 @@ var conversations_exports = {};
11115
11144
  __export(conversations_exports, {
11116
11145
  conversationsCommand: () => conversationsCommand
11117
11146
  });
11147
+ function printConversationsHelp() {
11148
+ console.error(`
11149
+ wayai conversations \u2014 list conversations or inspect what an agent received
11150
+
11151
+ Usage:
11152
+ wayai conversations List conversations
11153
+ wayai conversations --status <agent|team|ended> Filter by status
11154
+ wayai conversations --period 7d Analytics-powered list
11155
+ wayai conversations --from <date> --to <date> List within a date range
11156
+ wayai conversations <conversation_id> Show detail + messages
11157
+ wayai conversations <conversation_id> observability List the LLM turns (per-message id, latency, tool_calls)
11158
+ wayai conversations <conversation_id> observability --message-id <id>
11159
+ Full record for one turn:
11160
+ resolved system prompt, the exact
11161
+ messages the model saw (rendered
11162
+ additional_context, injected
11163
+ timestamps, replayed history),
11164
+ completion, tool calls, tokens
11165
+
11166
+ Options:
11167
+ --message-id <id> Expand one turn (only with the \`observability\` subcommand)
11168
+ --limit <n> Max rows (list view)
11169
+ --offset <n> Skip rows (list view)
11170
+ --json Raw JSON output
11171
+
11172
+ The default text list omits message ids \u2014 use \`--json\` or the \`observability\`
11173
+ subcommand to discover them. \`observability\` is the answer to "the agent did X \u2014
11174
+ what did it ACTUALLY see?".
11175
+ `.trim());
11176
+ }
11118
11177
  async function conversationsCommand(args2) {
11178
+ if (wantsHelp(args2)) {
11179
+ printConversationsHelp();
11180
+ return;
11181
+ }
11119
11182
  const hubId = resolveActiveHubId(args2);
11120
11183
  const { config, accessToken } = await requireAuth();
11121
11184
  requireRepoConfig();
@@ -17027,11 +17090,11 @@ var init_admin = __esm({
17027
17090
 
17028
17091
  // src/commands/report-create.ts
17029
17092
  import { readFileSync as readFileSync14 } from "fs";
17030
- import { dirname as dirname7, join as join19 } from "path";
17093
+ import { dirname as dirname7, join as join20 } from "path";
17031
17094
  import { fileURLToPath as fileURLToPath2 } from "url";
17032
17095
  function getCliVersion() {
17033
17096
  try {
17034
- const pkg2 = JSON.parse(readFileSync14(join19(__dirname, "..", "..", "package.json"), "utf-8"));
17097
+ const pkg2 = JSON.parse(readFileSync14(join20(__dirname, "..", "..", "package.json"), "utf-8"));
17035
17098
  return `cli@${pkg2.version}`;
17036
17099
  } catch {
17037
17100
  return "cli@unknown";
@@ -17415,7 +17478,7 @@ var init_update = __esm({
17415
17478
  init_sentry();
17416
17479
  import { readFileSync as readFileSync15 } from "fs";
17417
17480
  import { fileURLToPath as fileURLToPath3 } from "url";
17418
- import { dirname as dirname8, join as join20 } from "path";
17481
+ import { dirname as dirname8, join as join21 } from "path";
17419
17482
 
17420
17483
  // src/lib/errors.ts
17421
17484
  init_api_client();
@@ -17544,10 +17607,9 @@ Run \`npx skills add wayai-pro/wayai-skill -y\` to update.`);
17544
17607
 
17545
17608
  // src/index.ts
17546
17609
  var __dirname2 = dirname8(fileURLToPath3(import.meta.url));
17547
- var pkg = JSON.parse(readFileSync15(join20(__dirname2, "..", "package.json"), "utf-8"));
17610
+ var pkg = JSON.parse(readFileSync15(join21(__dirname2, "..", "package.json"), "utf-8"));
17548
17611
  var [, , command, ...args] = process.argv;
17549
17612
  var isBackgroundRefresh = command === REFRESH_COMMAND;
17550
- var OWN_HELP_COMMANDS = /* @__PURE__ */ new Set(["eval", "admin", "report"]);
17551
17613
  if (!isBackgroundRefresh) initSentry(command);
17552
17614
  async function main() {
17553
17615
  if (shouldInterceptHelp(command, args, OWN_HELP_COMMANDS)) {
@@ -17600,9 +17662,11 @@ async function main() {
17600
17662
  await migrateCommand2(args);
17601
17663
  break;
17602
17664
  }
17665
+ // `unlock` is the deprecated pre-rename alias for `unbind` (kept for back-compat).
17666
+ case "unbind":
17603
17667
  case "unlock": {
17604
- const { unlockCommand: unlockCommand2 } = await Promise.resolve().then(() => (init_unlock(), unlock_exports));
17605
- await unlockCommand2(args);
17668
+ const { unbindCommand: unbindCommand2 } = await Promise.resolve().then(() => (init_unbind(), unbind_exports));
17669
+ await unbindCommand2(args);
17606
17670
  break;
17607
17671
  }
17608
17672
  case "send-message": {
@@ -17726,9 +17790,9 @@ Commands:
17726
17790
  push Parse local files, show diff, sync to preview (creates hub if new)
17727
17791
  org create Create a new organization (you become its owner)
17728
17792
  org <pull|push|diff> Sync org-scoped resources as code (wayai-ws/org/)
17729
- use <hub> Lock this worktree to a specific hub (UUID or folder name)
17793
+ use <hub> Bind this worktree to a specific hub (UUID or folder name)
17730
17794
  migrate Move a legacy repo to the wayai-ws/{hubs,org} layout
17731
- unlock Clear the worktree hub lock
17795
+ unbind Clear the worktree hub binding
17732
17796
  send-message Send a test message to a preview hub
17733
17797
  conversations List or inspect conversations
17734
17798
  analytics Show analytics summary and metrics (use \`analytics query\` for structured ClickHouse queries)
@@ -17786,12 +17850,12 @@ Org-scoped mode:
17786
17850
  pull/push operate on the single hub in the workspace, or pass
17787
17851
  \`--hub <uuid|name>\` to disambiguate when multiple hubs exist.
17788
17852
 
17789
- Worktree hub lock:
17790
- Each git checkout (main or linked worktree) can be locked to a single hub.
17791
- push/pull refuse to run against a different hub once locked. The lock is
17792
- auto-set on first successful pull (or new-hub creation) into an unlocked
17793
- checkout. Use \`wayai use <hub>\` to bind manually and \`wayai unlock\` to clear.
17794
- The lock lives at \`<git-dir>/wayai-lock\` and is naturally per-checkout.
17853
+ Worktree hub binding:
17854
+ Each git checkout (main or linked worktree) can be bound to a single hub.
17855
+ push/pull refuse to run against a different hub once bound. The binding is
17856
+ auto-set on first successful pull (or new-hub creation) into an unbound
17857
+ checkout. Use \`wayai use <hub>\` to bind manually and \`wayai unbind\` to clear.
17858
+ The binding lives at \`<git-dir>/wayai-binding\` and is naturally per-checkout.
17795
17859
 
17796
17860
  Examples:
17797
17861
  wayai login