@phnx-labs/agents-cli 1.22.84 → 1.22.85

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.
Files changed (257) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +80 -53
  3. package/dist/bootstrap.d.ts +7 -6
  4. package/dist/bootstrap.js +20 -27
  5. package/dist/cli/command-registry.js +5 -1
  6. package/dist/commands/accounts.d.ts +6 -13
  7. package/dist/commands/accounts.js +330 -143
  8. package/dist/commands/apply.js +1 -1
  9. package/dist/commands/auth-mint.d.ts +7 -3
  10. package/dist/commands/auth-mint.js +21 -9
  11. package/dist/commands/auth.js +2 -3
  12. package/dist/commands/browser.js +10 -10
  13. package/dist/commands/daemon.d.ts +7 -3
  14. package/dist/commands/daemon.js +40 -25
  15. package/dist/commands/doctor.js +28 -2
  16. package/dist/commands/exec.js +87 -39
  17. package/dist/commands/fleet-capture.js +21 -2
  18. package/dist/commands/harness-wizard.js +2 -2
  19. package/dist/commands/lease.js +7 -12
  20. package/dist/commands/profiles.d.ts +2 -2
  21. package/dist/commands/profiles.js +20 -13
  22. package/dist/commands/repo.js +3 -3
  23. package/dist/commands/run-account-picker.d.ts +3 -3
  24. package/dist/commands/run-account-picker.js +29 -30
  25. package/dist/commands/secrets-passthrough.d.ts +20 -0
  26. package/dist/commands/secrets-passthrough.js +43 -0
  27. package/dist/commands/setup-accounts.d.ts +3 -2
  28. package/dist/commands/setup-accounts.js +4 -4
  29. package/dist/commands/setup-secrets.d.ts +16 -21
  30. package/dist/commands/setup-secrets.js +43 -224
  31. package/dist/commands/ssh.js +2 -2
  32. package/dist/commands/sync.js +1 -1
  33. package/dist/commands/update.d.ts +10 -0
  34. package/dist/commands/update.js +43 -40
  35. package/dist/commands/versions.d.ts +11 -11
  36. package/dist/commands/versions.js +131 -83
  37. package/dist/commands/view.d.ts +1 -9
  38. package/dist/commands/view.js +41 -55
  39. package/dist/commands/webhook.js +5 -5
  40. package/dist/commands/workflows.js +2 -1
  41. package/dist/index.d.ts +12 -12
  42. package/dist/index.js +13 -42
  43. package/dist/lib/account-capabilities.d.ts +1 -1
  44. package/dist/lib/account-capabilities.js +1 -1
  45. package/dist/lib/account-catalog.d.ts +121 -6
  46. package/dist/lib/account-catalog.js +421 -7
  47. package/dist/lib/account-registry.d.ts +8 -30
  48. package/dist/lib/account-registry.js +36 -79
  49. package/dist/lib/account-schema.d.ts +1 -1
  50. package/dist/lib/account-schema.js +1 -1
  51. package/dist/lib/accounting/account-pool-collect.js +16 -4
  52. package/dist/lib/accounting/rotate.d.ts +20 -7
  53. package/dist/lib/accounting/rotate.js +89 -13
  54. package/dist/lib/accounting/usage.js +11 -16
  55. package/dist/lib/accounts/add.d.ts +138 -0
  56. package/dist/lib/accounts/add.js +651 -0
  57. package/dist/lib/accounts/migrate.d.ts +117 -0
  58. package/dist/lib/accounts/migrate.js +536 -0
  59. package/dist/lib/accounts/slots.d.ts +13 -0
  60. package/dist/lib/accounts/slots.js +100 -0
  61. package/dist/lib/agent-spec/agents.d.ts +16 -0
  62. package/dist/lib/agent-spec/agents.js +32 -4
  63. package/dist/lib/app-bundle-install.js +5 -4
  64. package/dist/lib/auth-health.d.ts +3 -0
  65. package/dist/lib/auth-health.js +11 -0
  66. package/dist/lib/auth-mint.d.ts +52 -16
  67. package/dist/lib/auth-mint.js +117 -39
  68. package/dist/lib/browser/chrome.d.ts +1 -1
  69. package/dist/lib/browser/chrome.js +5 -5
  70. package/dist/lib/byok-usage.js +3 -3
  71. package/dist/lib/claude-account-token.d.ts +47 -3
  72. package/dist/lib/claude-account-token.js +172 -50
  73. package/dist/lib/cloud/antigravity.js +4 -4
  74. package/dist/lib/cloud/cursor.js +4 -4
  75. package/dist/lib/crabbox/cli.d.ts +1 -1
  76. package/dist/lib/crabbox/cli.js +6 -6
  77. package/dist/lib/crabbox/runtimes.d.ts +3 -3
  78. package/dist/lib/crabbox/runtimes.js +5 -5
  79. package/dist/lib/daemon/account-state-daemon-service.d.ts +37 -1
  80. package/dist/lib/daemon/account-state-daemon-service.js +199 -3
  81. package/dist/lib/daemon/auth-sync-service.js +28 -1
  82. package/dist/lib/daemon/daemon.d.ts +6 -16
  83. package/dist/lib/daemon/daemon.js +52 -97
  84. package/dist/lib/daemon/daemon.test-fixture.d.ts +7 -9
  85. package/dist/lib/daemon/daemon.test-fixture.js +22 -40
  86. package/dist/lib/daemon/harness-update-service.d.ts +1 -1
  87. package/dist/lib/daemon/harness-update-service.js +1 -1
  88. package/dist/lib/daemon/runner.d.ts +15 -3
  89. package/dist/lib/daemon/runner.js +49 -24
  90. package/dist/lib/daemon-health.d.ts +1 -2
  91. package/dist/lib/daemon-health.js +7 -6
  92. package/dist/lib/daemon-services.d.ts +1 -1
  93. package/dist/lib/daemon-services.js +1 -11
  94. package/dist/lib/daemon-webhooks.d.ts +8 -7
  95. package/dist/lib/daemon-webhooks.js +10 -9
  96. package/dist/lib/device-config.js +1 -1
  97. package/dist/lib/devices/doctor-findings.d.ts +1 -1
  98. package/dist/lib/devices/harness-inventory.d.ts +39 -0
  99. package/dist/lib/devices/harness-inventory.js +126 -4
  100. package/dist/lib/doctor-diff.js +2 -1
  101. package/dist/lib/exec-account-home.d.ts +38 -0
  102. package/dist/lib/exec-account-home.js +164 -0
  103. package/dist/lib/exec.d.ts +30 -0
  104. package/dist/lib/exec.js +101 -31
  105. package/dist/lib/fleet/apply.d.ts +2 -2
  106. package/dist/lib/fleet/apply.js +4 -4
  107. package/dist/lib/fleet/auth-sync.js +4 -3
  108. package/dist/lib/fleet-shared-repo-sync.js +6 -9
  109. package/dist/lib/harness/adapter.d.ts +7 -7
  110. package/dist/lib/harness/adapter.js +10 -6
  111. package/dist/lib/harness/adapters/grok.js +8 -3
  112. package/dist/lib/harness/adapters/muse.js +1 -1
  113. package/dist/lib/harness/adapters/opencode.js +12 -3
  114. package/dist/lib/harness-auth-capabilities.d.ts +61 -0
  115. package/dist/lib/harness-auth-capabilities.js +52 -0
  116. package/dist/lib/helper-versions.d.ts +6 -4
  117. package/dist/lib/helper-versions.js +5 -4
  118. package/dist/lib/hosts/credential-transport.d.ts +10 -0
  119. package/dist/lib/hosts/credential-transport.js +37 -0
  120. package/dist/lib/hosts/dispatch.d.ts +7 -0
  121. package/dist/lib/hosts/dispatch.js +13 -6
  122. package/dist/lib/identity/client.d.ts +3 -3
  123. package/dist/lib/identity/client.js +3 -3
  124. package/dist/lib/installations/index.d.ts +1 -1
  125. package/dist/lib/installations/index.js +1 -1
  126. package/dist/lib/installations/migrate.js +9 -0
  127. package/dist/lib/installations/resolve.js +1 -1
  128. package/dist/lib/installations/shims.d.ts +15 -0
  129. package/dist/lib/installations/shims.js +69 -0
  130. package/dist/lib/installations/store.d.ts +43 -0
  131. package/dist/lib/installations/store.js +75 -7
  132. package/dist/lib/installations/versions.js +1 -1
  133. package/dist/lib/menubar/install-menubar.d.ts +3 -3
  134. package/dist/lib/menubar/install-menubar.js +3 -3
  135. package/dist/lib/native-accounts.d.ts +35 -0
  136. package/dist/lib/native-accounts.js +41 -0
  137. package/dist/lib/net-close.d.ts +11 -0
  138. package/dist/lib/net-close.js +25 -0
  139. package/dist/lib/openclaw-keychain.js +27 -1
  140. package/dist/lib/profiles.js +22 -9
  141. package/dist/lib/project-resources.js +1 -1
  142. package/dist/lib/reserved-stores.d.ts +53 -0
  143. package/dist/lib/reserved-stores.js +120 -0
  144. package/dist/lib/secrets-client.d.ts +191 -0
  145. package/dist/lib/secrets-client.js +710 -0
  146. package/dist/lib/secrets-policy.d.ts +222 -0
  147. package/dist/lib/secrets-policy.js +483 -0
  148. package/dist/lib/secrets-types.d.ts +188 -0
  149. package/dist/lib/secrets-types.js +24 -0
  150. package/dist/lib/service-manifest.js +3 -4
  151. package/dist/lib/session/db.d.ts +18 -0
  152. package/dist/lib/session/db.js +47 -14
  153. package/dist/lib/session/sync/config.js +2 -2
  154. package/dist/lib/sha256-asset.d.ts +11 -16
  155. package/dist/lib/sha256-asset.js +11 -16
  156. package/dist/lib/share/config.js +14 -5
  157. package/dist/lib/signin-badge.d.ts +26 -0
  158. package/dist/lib/signin-badge.js +42 -0
  159. package/dist/lib/staleness/detectors/workflows.js +3 -105
  160. package/dist/lib/staleness/writers/workflows.js +2 -1
  161. package/dist/lib/state.d.ts +7 -4
  162. package/dist/lib/state.js +18 -7
  163. package/dist/lib/sync-umbrella.js +2 -2
  164. package/dist/lib/teams/agents.js +1 -1
  165. package/dist/lib/types.d.ts +74 -33
  166. package/dist/lib/view-types.d.ts +6 -3
  167. package/dist/lib/workflows-registry.d.ts +71 -0
  168. package/dist/lib/workflows-registry.js +280 -0
  169. package/dist/lib/workflows.d.ts +21 -21
  170. package/dist/lib/workflows.js +12 -327
  171. package/package.json +2 -3
  172. package/scripts/postinstall.js +4 -29
  173. package/dist/commands/secrets-import.d.ts +0 -18
  174. package/dist/commands/secrets-import.js +0 -74
  175. package/dist/commands/secrets-migrate.d.ts +0 -25
  176. package/dist/commands/secrets-migrate.js +0 -334
  177. package/dist/commands/secrets-rotate-passphrase.d.ts +0 -17
  178. package/dist/commands/secrets-rotate-passphrase.js +0 -96
  179. package/dist/commands/secrets-sync.d.ts +0 -11
  180. package/dist/commands/secrets-sync.js +0 -153
  181. package/dist/commands/secrets-vault.d.ts +0 -10
  182. package/dist/commands/secrets-vault.js +0 -130
  183. package/dist/commands/secrets.d.ts +0 -212
  184. package/dist/commands/secrets.js +0 -3030
  185. package/dist/lib/accounts/connect.d.ts +0 -176
  186. package/dist/lib/accounts/connect.js +0 -453
  187. package/dist/lib/daemon/keychain-reap-service.d.ts +0 -17
  188. package/dist/lib/daemon/keychain-reap-service.js +0 -32
  189. package/dist/lib/daemon/secrets-broker-service.d.ts +0 -21
  190. package/dist/lib/daemon/secrets-broker-service.js +0 -51
  191. package/dist/lib/secrets/agent.d.ts +0 -358
  192. package/dist/lib/secrets/agent.js +0 -1291
  193. package/dist/lib/secrets/audit.d.ts +0 -46
  194. package/dist/lib/secrets/audit.js +0 -101
  195. package/dist/lib/secrets/bundles.d.ts +0 -290
  196. package/dist/lib/secrets/bundles.js +0 -1547
  197. package/dist/lib/secrets/download-keychain.d.ts +0 -47
  198. package/dist/lib/secrets/download-keychain.js +0 -70
  199. package/dist/lib/secrets/drivers/rush.d.ts +0 -14
  200. package/dist/lib/secrets/drivers/rush.js +0 -90
  201. package/dist/lib/secrets/fallback.d.ts +0 -48
  202. package/dist/lib/secrets/fallback.js +0 -48
  203. package/dist/lib/secrets/filestore.d.ts +0 -222
  204. package/dist/lib/secrets/filestore.js +0 -1099
  205. package/dist/lib/secrets/headless.d.ts +0 -43
  206. package/dist/lib/secrets/headless.js +0 -56
  207. package/dist/lib/secrets/icloud-import.d.ts +0 -79
  208. package/dist/lib/secrets/icloud-import.js +0 -206
  209. package/dist/lib/secrets/index.d.ts +0 -451
  210. package/dist/lib/secrets/index.js +0 -1568
  211. package/dist/lib/secrets/install-helper.d.ts +0 -72
  212. package/dist/lib/secrets/install-helper.js +0 -245
  213. package/dist/lib/secrets/lease.d.ts +0 -25
  214. package/dist/lib/secrets/lease.js +0 -44
  215. package/dist/lib/secrets/linux.d.ts +0 -77
  216. package/dist/lib/secrets/linux.js +0 -393
  217. package/dist/lib/secrets/list-filter.d.ts +0 -109
  218. package/dist/lib/secrets/list-filter.js +0 -261
  219. package/dist/lib/secrets/mcp.d.ts +0 -93
  220. package/dist/lib/secrets/mcp.js +0 -211
  221. package/dist/lib/secrets/profiles.d.ts +0 -10
  222. package/dist/lib/secrets/profiles.js +0 -13
  223. package/dist/lib/secrets/push.d.ts +0 -133
  224. package/dist/lib/secrets/push.js +0 -273
  225. package/dist/lib/secrets/rc-hygiene.d.ts +0 -63
  226. package/dist/lib/secrets/rc-hygiene.js +0 -143
  227. package/dist/lib/secrets/read-backoff.d.ts +0 -27
  228. package/dist/lib/secrets/read-backoff.js +0 -64
  229. package/dist/lib/secrets/reaper.d.ts +0 -90
  230. package/dist/lib/secrets/reaper.js +0 -243
  231. package/dist/lib/secrets/remote.d.ts +0 -152
  232. package/dist/lib/secrets/remote.js +0 -344
  233. package/dist/lib/secrets/reserved-sync.d.ts +0 -66
  234. package/dist/lib/secrets/reserved-sync.js +0 -147
  235. package/dist/lib/secrets/scope.d.ts +0 -26
  236. package/dist/lib/secrets/scope.js +0 -29
  237. package/dist/lib/secrets/session-store.d.ts +0 -107
  238. package/dist/lib/secrets/session-store.js +0 -342
  239. package/dist/lib/secrets/sync-backend.d.ts +0 -48
  240. package/dist/lib/secrets/sync-backend.js +0 -13
  241. package/dist/lib/secrets/sync-commands.d.ts +0 -21
  242. package/dist/lib/secrets/sync-commands.js +0 -21
  243. package/dist/lib/secrets/sync.d.ts +0 -48
  244. package/dist/lib/secrets/sync.js +0 -237
  245. package/dist/lib/secrets/unlock-hints.d.ts +0 -27
  246. package/dist/lib/secrets/unlock-hints.js +0 -36
  247. package/dist/lib/secrets/usage-db.d.ts +0 -46
  248. package/dist/lib/secrets/usage-db.js +0 -96
  249. package/dist/lib/secrets/vault-age-helper.d.ts +0 -1
  250. package/dist/lib/secrets/vault-age-helper.js +0 -34
  251. package/dist/lib/secrets/vault.d.ts +0 -49
  252. package/dist/lib/secrets/vault.js +0 -399
  253. package/dist/lib/secrets/windows.d.ts +0 -81
  254. package/dist/lib/secrets/windows.js +0 -556
  255. package/scripts/install-helper.js +0 -97
  256. /package/dist/lib/{secrets/sync-passphrase.d.ts → sync-passphrase.d.ts} +0 -0
  257. /package/dist/lib/{secrets/sync-passphrase.js → sync-passphrase.js} +0 -0
@@ -11,8 +11,7 @@ import * as path from 'path';
11
11
  import * as yaml from 'yaml';
12
12
  import { capableAgents, supports } from './capabilities.js';
13
13
  import { getProjectAgentsDir, getSystemWorkflowsDir, getUserWorkflowsDir, getTrashWorkflowsDir, getEnabledExtraRepos, getPluginsDir, getSystemPluginsDir, getProjectPluginsDir, } from './state.js';
14
- import { listInstalledVersions, getVersionHomePath } from './installations/versions.js';
15
- import { dirsContentMatch, normalizeResourceContent } from './resource-content-diff.js';
14
+ import { listInstalledVersions } from './installations/versions.js';
16
15
  /**
17
16
  * Hard upper bound on items a single `for_each` expands, absent an explicit
18
17
  * `max_items`. A guard against a runaway producer spawning unbounded teammates
@@ -798,98 +797,9 @@ export function removeWorkflow(name) {
798
797
  * intentionally ignored. (Verified via strace of `agy`: it opens
799
798
  * `$HOME/.gemini/config/global_workflows/<name>.md` and never the version home.)
800
799
  */
801
- function antigravityWorkflowsDir() {
800
+ export function antigravityWorkflowsDir() {
802
801
  return path.join(process.env.HOME ?? os.homedir(), '.gemini', 'config', 'global_workflows');
803
802
  }
804
- function workflowTargetRoot(agent, versionHome) {
805
- if (agent === 'kimi')
806
- return path.join(versionHome, '.kimi-code', 'skills');
807
- if (agent === 'antigravity')
808
- return antigravityWorkflowsDir();
809
- if (agent === 'openclaw')
810
- return path.join(versionHome, '.openclaw', 'workflows');
811
- if (agent === 'grok')
812
- return path.join(versionHome, '.grok', 'workflows');
813
- return path.join(versionHome, 'workflows');
814
- }
815
- /** List workflow names synced into a specific agent version home. */
816
- export function listWorkflowsForAgent(agent, versionHome) {
817
- if (agent === 'kimi') {
818
- const skillsDir = workflowTargetRoot(agent, versionHome);
819
- if (!fs.existsSync(skillsDir))
820
- return [];
821
- return fs.readdirSync(skillsDir, { withFileTypes: true })
822
- .filter(d => d.isDirectory() && fs.existsSync(path.join(skillsDir, d.name, 'SKILL.md')))
823
- .filter(d => kimiWorkflowMarker(path.join(skillsDir, d.name, 'SKILL.md')) === d.name)
824
- .map(d => d.name);
825
- }
826
- if (agent === 'antigravity') {
827
- const dir = workflowTargetRoot(agent, versionHome);
828
- if (!fs.existsSync(dir))
829
- return [];
830
- try {
831
- return fs.readdirSync(dir, { withFileTypes: true })
832
- .filter(d => d.isFile() && d.name.endsWith('.md') && !d.name.startsWith('.'))
833
- .map(d => d.name.slice(0, -'.md'.length))
834
- .filter(base => antigravityWorkflowMarker(path.join(dir, `${base}.md`)) === base);
835
- }
836
- catch {
837
- return [];
838
- }
839
- }
840
- if (agent === 'goose') {
841
- const recipesDir = path.join(versionHome, '.config', 'goose', 'recipes');
842
- if (!fs.existsSync(recipesDir))
843
- return [];
844
- try {
845
- return fs.readdirSync(recipesDir, { withFileTypes: true })
846
- .filter(d => d.isFile() && d.name.endsWith('.yaml') && !d.name.startsWith('.'))
847
- .map(d => d.name.slice(0, -'.yaml'.length));
848
- }
849
- catch {
850
- return [];
851
- }
852
- }
853
- if (agent === 'openclaw') {
854
- const dir = workflowTargetRoot(agent, versionHome);
855
- if (!fs.existsSync(dir))
856
- return [];
857
- try {
858
- return fs.readdirSync(dir, { withFileTypes: true })
859
- .filter(d => d.isFile() && d.name.endsWith('.lobster') && !d.name.startsWith('.'))
860
- .map(d => d.name.slice(0, -'.lobster'.length))
861
- .filter(base => openclawWorkflowMarker(path.join(dir, `${base}.lobster`)) === base);
862
- }
863
- catch {
864
- return [];
865
- }
866
- }
867
- if (agent === 'grok') {
868
- const dir = workflowTargetRoot(agent, versionHome);
869
- if (!fs.existsSync(dir))
870
- return [];
871
- try {
872
- return fs.readdirSync(dir, { withFileTypes: true })
873
- .filter(d => d.isFile() && d.name.endsWith('.rhai') && !d.name.startsWith('.'))
874
- .map(d => d.name.slice(0, -'.rhai'.length))
875
- .filter(base => grokWorkflowMarker(path.join(dir, `${base}.rhai`)) === base);
876
- }
877
- catch {
878
- return [];
879
- }
880
- }
881
- const workflowsDir = workflowTargetRoot(agent, versionHome);
882
- if (!fs.existsSync(workflowsDir))
883
- return [];
884
- try {
885
- return fs.readdirSync(workflowsDir, { withFileTypes: true })
886
- .filter(d => d.isDirectory() && fs.existsSync(path.join(workflowsDir, d.name, 'WORKFLOW.md')))
887
- .map(d => d.name);
888
- }
889
- catch {
890
- return [];
891
- }
892
- }
893
803
  function parseSubrecipeFrontmatter(filePath) {
894
804
  const content = fs.readFileSync(filePath, 'utf-8');
895
805
  const lines = content.split('\n');
@@ -913,7 +823,7 @@ function parseSubrecipeFrontmatter(filePath) {
913
823
  body: lines.slice(endIndex + 2).join('\n').trim(),
914
824
  };
915
825
  }
916
- function selectedWorkflowSubagents(workflowPath, allowedAgents) {
826
+ export function selectedWorkflowSubagents(workflowPath, allowedAgents) {
917
827
  const subagentsDir = path.join(workflowPath, 'subagents');
918
828
  if (!fs.existsSync(subagentsDir))
919
829
  return [];
@@ -924,7 +834,7 @@ function selectedWorkflowSubagents(workflowPath, allowedAgents) {
924
834
  .filter(name => !allowed || allowed.has(name))
925
835
  .sort();
926
836
  }
927
- function writeGooseSubrecipe(workflowPath, subrecipeName, destDir) {
837
+ export function writeGooseSubrecipe(workflowPath, subrecipeName, destDir) {
928
838
  const sourcePath = path.join(workflowPath, 'subagents', `${subrecipeName}.md`);
929
839
  const parsed = parseSubrecipeFrontmatter(sourcePath);
930
840
  const body = parsed.body || parsed.description || subrecipeName;
@@ -939,12 +849,12 @@ function writeGooseSubrecipe(workflowPath, subrecipeName, destDir) {
939
849
  fs.writeFileSync(path.join(destDir, `${subrecipeName}.yaml`), yaml.stringify(recipe), 'utf-8');
940
850
  }
941
851
  /**
942
- * Render the main Goose recipe YAML for a workflow — the exact bytes
943
- * `syncWorkflowToGooseRecipe` writes to `<name>.yaml`. Extracted so the sync
944
- * writer and the doctor content-drift check (`workflowContentMatches`) render
945
- * from ONE source and can never disagree. Returns null on invalid frontmatter.
852
+ * Render the main Goose recipe YAML for a workflow — the exact bytes the Goose
853
+ * `WORKFLOW_TARGETS` entry writes to `<name>.yaml`. Extracted so the writer and
854
+ * the doctor content-drift check (`matches`) render from ONE source and can
855
+ * never disagree. Returns null on invalid frontmatter.
946
856
  */
947
- function renderGooseRecipeYaml(workflowPath, name) {
857
+ export function renderGooseRecipeYaml(workflowPath, name) {
948
858
  const frontmatter = parseWorkflowFrontmatter(workflowPath);
949
859
  if (!frontmatter)
950
860
  return null;
@@ -969,231 +879,6 @@ function renderGooseRecipeYaml(workflowPath, name) {
969
879
  }
970
880
  return yaml.stringify(recipe);
971
881
  }
972
- function syncWorkflowToGooseRecipe(workflowPath, name, versionHome) {
973
- const frontmatter = parseWorkflowFrontmatter(workflowPath);
974
- if (!frontmatter) {
975
- return { success: false, error: `Workflow '${name}' has invalid WORKFLOW.md frontmatter` };
976
- }
977
- const recipesDir = path.join(versionHome, '.config', 'goose', 'recipes');
978
- const recipePath = path.join(recipesDir, `${name}.yaml`);
979
- const subrecipesDir = path.join(recipesDir, `${name}.subrecipes`);
980
- const subagents = selectedWorkflowSubagents(workflowPath, frontmatter.allowedAgents);
981
- const recipeYaml = renderGooseRecipeYaml(workflowPath, name);
982
- if (recipeYaml == null) {
983
- return { success: false, error: `Workflow '${name}' has invalid WORKFLOW.md frontmatter` };
984
- }
985
- try {
986
- fs.mkdirSync(recipesDir, { recursive: true });
987
- if (fs.existsSync(subrecipesDir)) {
988
- fs.rmSync(subrecipesDir, { recursive: true, force: true });
989
- }
990
- for (const subagentName of subagents) {
991
- writeGooseSubrecipe(workflowPath, subagentName, subrecipesDir);
992
- }
993
- fs.writeFileSync(recipePath, recipeYaml, 'utf-8');
994
- return { success: true };
995
- }
996
- catch (err) {
997
- return { success: false, error: err.message };
998
- }
999
- }
1000
- /**
1001
- * True when workflow `name` materialized in `agent`'s version home byte-matches
1002
- * what the writer would produce NOW from `sourcePath` — the content-drift
1003
- * predicate `agents doctor` uses. Layout-aware per the same per-harness map the
1004
- * writer (`syncWorkflowToVersion`) and detector use: Claude/default copy the
1005
- * whole WORKFLOW.md tree (recursive dir compare); Kimi/Antigravity/OpenClaw/Grok
1006
- * render one transformed file; Goose renders a recipe YAML. Antigravity's target
1007
- * is the shared HOME-global dir, not a per-version path. Returns false when the
1008
- * home copy is absent (surfaced as `missing` at the name level, not here).
1009
- */
1010
- export function workflowContentMatches(agent, versionHome, name, sourcePath) {
1011
- const root = workflowTargetRoot(agent, versionHome);
1012
- const renderedMatches = (homePath, expected) => {
1013
- let actual;
1014
- try {
1015
- actual = fs.readFileSync(homePath, 'utf-8');
1016
- }
1017
- catch {
1018
- return false;
1019
- }
1020
- return normalizeResourceContent(actual) === normalizeResourceContent(expected);
1021
- };
1022
- switch (agent) {
1023
- case 'kimi':
1024
- return renderedMatches(path.join(root, name, 'SKILL.md'), transformWorkflowForKimi(sourcePath, name));
1025
- case 'antigravity':
1026
- return renderedMatches(path.join(root, `${name}.md`), transformWorkflowForAntigravity(sourcePath, name));
1027
- case 'openclaw':
1028
- return renderedMatches(path.join(root, `${name}.lobster`), transformWorkflowForOpenClaw(sourcePath, name));
1029
- case 'grok':
1030
- return renderedMatches(path.join(root, `${name}.rhai`), transformWorkflowForGrok(sourcePath, name));
1031
- case 'goose': {
1032
- const expected = renderGooseRecipeYaml(sourcePath, name);
1033
- if (expected == null)
1034
- return false;
1035
- return renderedMatches(path.join(versionHome, '.config', 'goose', 'recipes', `${name}.yaml`), expected);
1036
- }
1037
- default:
1038
- return dirsContentMatch(sourcePath, path.join(root, name));
1039
- }
1040
- }
1041
- /** Copy a workflow directory into a version home at {versionHome}/workflows/<name>/. */
1042
- export function syncWorkflowToVersion(workflowPath, name, agent, versionHome) {
1043
- if (agent === 'goose') {
1044
- return syncWorkflowToGooseRecipe(workflowPath, name, versionHome);
1045
- }
1046
- try {
1047
- if (agent === 'kimi') {
1048
- const targetDir = path.join(workflowTargetRoot(agent, versionHome), name);
1049
- const targetFile = path.join(targetDir, 'SKILL.md');
1050
- if (fs.existsSync(targetFile)) {
1051
- const marker = kimiWorkflowMarker(targetFile);
1052
- if (marker !== name) {
1053
- return { success: false, error: `Kimi skill '${name}' already exists and is not managed by agents-cli` };
1054
- }
1055
- }
1056
- fs.mkdirSync(targetDir, { recursive: true });
1057
- fs.writeFileSync(targetFile, transformWorkflowForKimi(workflowPath, name), 'utf-8');
1058
- return { success: true };
1059
- }
1060
- if (agent === 'antigravity') {
1061
- const targetDir = workflowTargetRoot(agent, versionHome);
1062
- const targetFile = path.join(targetDir, `${name}.md`);
1063
- if (fs.existsSync(targetFile)) {
1064
- const marker = antigravityWorkflowMarker(targetFile);
1065
- if (marker !== name) {
1066
- return { success: false, error: `Antigravity workflow '${name}' already exists and is not managed by agents-cli` };
1067
- }
1068
- }
1069
- fs.mkdirSync(targetDir, { recursive: true });
1070
- fs.writeFileSync(targetFile, transformWorkflowForAntigravity(workflowPath, name), 'utf-8');
1071
- return { success: true };
1072
- }
1073
- if (agent === 'openclaw') {
1074
- const targetDir = workflowTargetRoot(agent, versionHome);
1075
- const targetFile = path.join(targetDir, `${name}.lobster`);
1076
- if (fs.existsSync(targetFile)) {
1077
- const marker = openclawWorkflowMarker(targetFile);
1078
- if (marker !== name) {
1079
- return { success: false, error: `OpenClaw workflow '${name}' already exists and is not managed by agents-cli` };
1080
- }
1081
- }
1082
- fs.mkdirSync(targetDir, { recursive: true });
1083
- fs.writeFileSync(targetFile, transformWorkflowForOpenClaw(workflowPath, name), 'utf-8');
1084
- return { success: true };
1085
- }
1086
- if (agent === 'grok') {
1087
- const targetDir = workflowTargetRoot(agent, versionHome);
1088
- const targetFile = path.join(targetDir, `${name}.rhai`);
1089
- if (fs.existsSync(targetFile)) {
1090
- const marker = grokWorkflowMarker(targetFile);
1091
- if (marker !== name) {
1092
- return { success: false, error: `Grok workflow '${name}' already exists and is not managed by agents-cli` };
1093
- }
1094
- }
1095
- fs.mkdirSync(targetDir, { recursive: true });
1096
- fs.writeFileSync(targetFile, transformWorkflowForGrok(workflowPath, name), 'utf-8');
1097
- return { success: true };
1098
- }
1099
- const targetDir = path.join(workflowTargetRoot(agent, versionHome), name);
1100
- fs.mkdirSync(workflowTargetRoot(agent, versionHome), { recursive: true });
1101
- if (fs.existsSync(targetDir)) {
1102
- fs.rmSync(targetDir, { recursive: true, force: true });
1103
- }
1104
- fs.cpSync(workflowPath, targetDir, { recursive: true });
1105
- return { success: true };
1106
- }
1107
- catch (err) {
1108
- return { success: false, error: err.message };
1109
- }
1110
- }
1111
- /** Remove a workflow from a specific agent version home. */
1112
- export function removeWorkflowFromVersion(agent, version, name) {
1113
- const versionHome = getVersionHomePath(agent, version);
1114
- if (agent === 'antigravity') {
1115
- const targetFile = path.join(workflowTargetRoot(agent, versionHome), `${name}.md`);
1116
- if (!fs.existsSync(targetFile)) {
1117
- return { success: false, error: `Workflow '${name}' not synced to ${agent}@${version}` };
1118
- }
1119
- if (antigravityWorkflowMarker(targetFile) !== name) {
1120
- return { success: false, error: `Antigravity workflow '${name}' is not managed by agents-cli` };
1121
- }
1122
- try {
1123
- fs.rmSync(targetFile, { force: true });
1124
- return { success: true };
1125
- }
1126
- catch (err) {
1127
- return { success: false, error: err.message };
1128
- }
1129
- }
1130
- if (agent === 'goose') {
1131
- const recipePath = path.join(versionHome, '.config', 'goose', 'recipes', `${name}.yaml`);
1132
- const subrecipesDir = path.join(versionHome, '.config', 'goose', 'recipes', `${name}.subrecipes`);
1133
- if (!fs.existsSync(recipePath) && !fs.existsSync(subrecipesDir)) {
1134
- return { success: false, error: `Workflow '${name}' not synced to ${agent}@${version}` };
1135
- }
1136
- try {
1137
- if (fs.existsSync(recipePath))
1138
- fs.rmSync(recipePath, { force: true });
1139
- if (fs.existsSync(subrecipesDir))
1140
- fs.rmSync(subrecipesDir, { recursive: true, force: true });
1141
- return { success: true };
1142
- }
1143
- catch (err) {
1144
- return { success: false, error: err.message };
1145
- }
1146
- }
1147
- if (agent === 'openclaw') {
1148
- const targetFile = path.join(workflowTargetRoot(agent, versionHome), `${name}.lobster`);
1149
- if (!fs.existsSync(targetFile)) {
1150
- return { success: false, error: `Workflow '${name}' not synced to ${agent}@${version}` };
1151
- }
1152
- if (openclawWorkflowMarker(targetFile) !== name) {
1153
- return { success: false, error: `OpenClaw workflow '${name}' is not managed by agents-cli` };
1154
- }
1155
- try {
1156
- fs.rmSync(targetFile, { force: true });
1157
- return { success: true };
1158
- }
1159
- catch (err) {
1160
- return { success: false, error: err.message };
1161
- }
1162
- }
1163
- if (agent === 'grok') {
1164
- const targetFile = path.join(workflowTargetRoot(agent, versionHome), `${name}.rhai`);
1165
- if (!fs.existsSync(targetFile)) {
1166
- return { success: false, error: `Workflow '${name}' not synced to ${agent}@${version}` };
1167
- }
1168
- if (grokWorkflowMarker(targetFile) !== name) {
1169
- return { success: false, error: `Grok workflow '${name}' is not managed by agents-cli` };
1170
- }
1171
- try {
1172
- fs.rmSync(targetFile, { force: true });
1173
- return { success: true };
1174
- }
1175
- catch (err) {
1176
- return { success: false, error: err.message };
1177
- }
1178
- }
1179
- const targetPath = path.join(workflowTargetRoot(agent, versionHome), name);
1180
- if (!fs.existsSync(targetPath)) {
1181
- return { success: false, error: `Workflow '${name}' not synced to ${agent}@${version}` };
1182
- }
1183
- try {
1184
- if (agent === 'kimi') {
1185
- const targetFile = path.join(targetPath, 'SKILL.md');
1186
- if (kimiWorkflowMarker(targetFile) !== name) {
1187
- return { success: false, error: `Kimi skill '${name}' is not managed by agents-cli` };
1188
- }
1189
- }
1190
- fs.rmSync(targetPath, { recursive: true, force: true });
1191
- return { success: true };
1192
- }
1193
- catch (err) {
1194
- return { success: false, error: err.message };
1195
- }
1196
- }
1197
882
  function parseSkillFrontmatter(filePath) {
1198
883
  const content = fs.readFileSync(filePath, 'utf-8');
1199
884
  const lines = content.split('\n');
@@ -1206,7 +891,7 @@ function parseSkillFrontmatter(filePath) {
1206
891
  const parsed = yaml.parse(frontmatter);
1207
892
  return parsed && typeof parsed === 'object' ? parsed : null;
1208
893
  }
1209
- function kimiWorkflowMarker(filePath) {
894
+ export function kimiWorkflowMarker(filePath) {
1210
895
  try {
1211
896
  const fm = parseSkillFrontmatter(filePath);
1212
897
  return fm?.type === 'flow' && typeof fm.agents_workflow === 'string' ? fm.agents_workflow : null;
@@ -1215,7 +900,7 @@ function kimiWorkflowMarker(filePath) {
1215
900
  return null;
1216
901
  }
1217
902
  }
1218
- function antigravityWorkflowMarker(filePath) {
903
+ export function antigravityWorkflowMarker(filePath) {
1219
904
  try {
1220
905
  const fm = parseSkillFrontmatter(filePath);
1221
906
  return typeof fm?.agents_workflow === 'string' ? fm.agents_workflow : null;
@@ -1224,7 +909,7 @@ function antigravityWorkflowMarker(filePath) {
1224
909
  return null;
1225
910
  }
1226
911
  }
1227
- function openclawWorkflowMarker(filePath) {
912
+ export function openclawWorkflowMarker(filePath) {
1228
913
  try {
1229
914
  const parsed = yaml.parse(fs.readFileSync(filePath, 'utf-8'));
1230
915
  if (!parsed || typeof parsed !== 'object' || !parsed.env || typeof parsed.env !== 'object' || Array.isArray(parsed.env)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phnx-labs/agents-cli",
3
- "version": "1.22.84",
3
+ "version": "1.22.85",
4
4
  "description": "One CLI for all your AI coding agents - versions, config, cloud dispatch, sessions, and teams (now with first-class Grok Build CLI support)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -43,7 +43,7 @@
43
43
  "url": "https://github.com/phnx-labs/agi-cli/issues"
44
44
  },
45
45
  "scripts": {
46
- "build": "tsc && rm -rf 'dist/lib/secrets/AgentsKeychain.app' 'dist/lib/secrets/Agents CLI.app' 'dist/lib/menubar/MenubarHelper.app' && ([ -f 'bin/agents-macos' ] && mkdir -p dist/bin && cp -f 'bin/agents-macos' 'dist/bin/agents' && chmod 755 'dist/bin/agents' || true)",
46
+ "build": "tsc && rm -rf 'dist/lib/menubar/MenubarHelper.app' && ([ -f 'bin/agents-macos' ] && mkdir -p dist/bin && cp -f 'bin/agents-macos' 'dist/bin/agents' && chmod 755 'dist/bin/agents' || true)",
47
47
  "build:bin": "scripts/build-bin.sh",
48
48
  "prepare": "npm run build",
49
49
  "prepack": "cp ../README.md README.md",
@@ -95,7 +95,6 @@
95
95
  "@xterm/headless": "6.0.0",
96
96
  "@zed-industries/agent-client-protocol": "0.4.5",
97
97
  "acorn": "8.18.0",
98
- "age-encryption": "0.3.0",
99
98
  "aws4fetch": "1.0.20",
100
99
  "chalk": "5.6.2",
101
100
  "commander": "15.0.0",
@@ -22,7 +22,6 @@ const AGENTS_JS_ENTRYPOINT = fileURLToPath(new URL('../dist/index.js', import.me
22
22
  // is what EDR (CrowdStrike Falcon) flags when an editor child spawns it (#315).
23
23
  const AGENTS_NATIVE_MACOS_BIN = fileURLToPath(new URL('../dist/bin/agents', import.meta.url));
24
24
  const AGENTS_BIN = resolveAgentsBin();
25
- const INSTALL_HELPER_SCRIPT = fileURLToPath(new URL('./install-helper.js', import.meta.url));
26
25
 
27
26
  function resolveAgentsBin() {
28
27
  if (process.platform !== 'darwin') return AGENTS_JS_ENTRYPOINT;
@@ -46,15 +45,6 @@ function resolveAgentsBin() {
46
45
  return AGENTS_JS_ENTRYPOINT;
47
46
  }
48
47
 
49
- function installKeychainHelper() {
50
- if (process.platform !== 'darwin') return;
51
- if (!fs.existsSync(INSTALL_HELPER_SCRIPT)) return;
52
- // Sub-process so a hard failure (codesign / spctl missing on a weird host)
53
- // can't take down the rest of postinstall. install-helper.js stays silent
54
- // on no-op and emits one stdout line on success.
55
- spawnSync(process.execPath, [INSTALL_HELPER_SCRIPT], { stdio: 'inherit' });
56
- }
57
-
58
48
  function shellQuote(value) {
59
49
  return `'${value.replace(/'/g, `'\\''`)}'`;
60
50
  }
@@ -93,7 +83,6 @@ const isGlobalInstall = process.env.npm_config_global || process.argv.includes('
93
83
  if (!isGlobalInstall) {
94
84
  // Still create user directories for local installs
95
85
  fs.mkdirSync(USER_DIR, { recursive: true, mode: 0o700 });
96
- installKeychainHelper();
97
86
  console.log(`
98
87
  agents-cli installed locally.
99
88
  To complete setup, run: npx agents setup
@@ -115,10 +104,6 @@ To complete setup, run: npx agents setup
115
104
  fs.mkdirSync(USER_DIR, { recursive: true, mode: 0o700 });
116
105
  fs.mkdirSync(SHIMS_DIR, { recursive: true });
117
106
 
118
- // Copy the signed macOS Keychain helper to a stable user path so its trusted-app
119
- // ACLs survive future npm publishes (which re-sign the bundle).
120
- installKeychainHelper();
121
-
122
107
  const shellName = path.basename(process.env.SHELL || '/bin/bash');
123
108
 
124
109
  function getShellRc() {
@@ -377,10 +362,12 @@ function retargetManagedLinksToNativeBin() {
377
362
  /**
378
363
  * Self-heal long-running processes onto the just-installed code (darwin + linux).
379
364
  *
380
- * The root cause behind stale-behavior bugs is a daemon/broker that keeps
365
+ * The root cause behind stale-behavior bugs is a daemon that keeps
381
366
  * running pre-upgrade code for days. An in-place `npm i -g` swaps the files but
382
367
  * not the running processes — so we bounce them here, the one moment we know the
383
- * code just changed. Always start (or restart) the supervised daemon so a fresh
368
+ * code just changed. (The secrets broker is not one of them — the standalone
369
+ * `secrets` CLI owns its own broker lifecycle, PHNX-3989.) Always start (or
370
+ * restart) the supervised daemon so a fresh
384
371
  * install gets launchd/systemd KeepAlive without waiting for routines add.
385
372
  * Best-effort and non-fatal: a failure must never break the install. Skipped in
386
373
  * CI and when AGENTS_NO_HEAL=1. Windows is out of scope (detached-only, no KeepAlive).
@@ -389,18 +376,6 @@ async function healLongRunningProcesses() {
389
376
  if (process.platform !== 'darwin' && process.platform !== 'linux') return;
390
377
  if (process.env.CI || process.env.AGENTS_NO_HEAL === '1') return;
391
378
 
392
- // Retire the legacy standalone secrets-agent service FIRST (#416 step 2) so
393
- // that when the daemon (re)starts below its coexistence guard sees no
394
- // standalone broker and hosts the broker socket itself. No-op if no legacy
395
- // plist is present; never blocks. Darwin-only in practice (launchd service).
396
- try {
397
- const a = await import('../dist/lib/secrets/agent.js');
398
- if (a.secretsAgentServiceInstalled?.()) {
399
- a.retireLegacySecretsAgentService?.();
400
- console.log(' Retired the standalone secrets-agent service — the daemon now hosts the broker.');
401
- }
402
- } catch { /* best effort */ }
403
-
404
379
  // Always (re)start so first install writes the LaunchAgent/systemd unit and
405
380
  // upgrades bounce onto the new binary — but honor daemon.enabled for cold
406
381
  // starts (SING-4a). If it was already running under a disable, stop and leave
@@ -1,18 +0,0 @@
1
- /**
2
- * `agents secrets import-keyring` — migrate agents-cli secrets out of the native
3
- * credential store (GNOME Keyring / Windows Credential Manager) and into the
4
- * encrypted file store.
5
- *
6
- * Why: on headless Linux/Windows the file store is the durable, passwordless
7
- * backend, but secrets written earlier (e.g. while a desktop keyring was
8
- * unlocked) can linger in the native store where a headless session can't reach
9
- * them. This is the Linux/Windows analogue of the macOS `migrate-acl` /
10
- * orphan sweep. Dry-run by default; `--commit` performs the copy.
11
- *
12
- * Requires the native store to be reachable/unlocked — a locked keyring can't be
13
- * read, so unlock it first (or the values are already only in the file store and
14
- * there is nothing to do).
15
- */
16
- import type { Command } from 'commander';
17
- /** Register `agents secrets import-keyring` on the parent secrets Command. */
18
- export declare function registerSecretsImportKeyringCommand(secrets: Command): void;
@@ -1,74 +0,0 @@
1
- /**
2
- * `agents secrets import-keyring` — migrate agents-cli secrets out of the native
3
- * credential store (GNOME Keyring / Windows Credential Manager) and into the
4
- * encrypted file store.
5
- *
6
- * Why: on headless Linux/Windows the file store is the durable, passwordless
7
- * backend, but secrets written earlier (e.g. while a desktop keyring was
8
- * unlocked) can linger in the native store where a headless session can't reach
9
- * them. This is the Linux/Windows analogue of the macOS `migrate-acl` /
10
- * orphan sweep. Dry-run by default; `--commit` performs the copy.
11
- *
12
- * Requires the native store to be reachable/unlocked — a locked keyring can't be
13
- * read, so unlock it first (or the values are already only in the file store and
14
- * there is nothing to do).
15
- */
16
- import chalk from 'chalk';
17
- import { importNativeItems } from '../lib/secrets/index.js';
18
- /** Register `agents secrets import-keyring` on the parent secrets Command. */
19
- export function registerSecretsImportKeyringCommand(secrets) {
20
- secrets
21
- .command('import-keyring')
22
- .description('Migrate agents-cli secrets from the OS keyring / Credential Manager into the encrypted file store (headless-safe). Dry-run by default.')
23
- .option('--commit', 'Perform the import (default is dry-run reporting only)')
24
- .option('--prefix <p>', 'Only import items beginning with PREFIX (default: all agents-cli items)')
25
- .action((opts) => {
26
- try {
27
- if (process.platform === 'darwin') {
28
- throw new Error('import-keyring is for the Linux/Windows file-store fallback. On macOS use `agents secrets migrate-acl`.');
29
- }
30
- const commit = !!opts.commit;
31
- const report = importNativeItems(opts.prefix ?? '', commit);
32
- if (!report.available) {
33
- console.log(chalk.gray('No native credential tooling found (secret-tool / PowerShell) — nothing to import.'));
34
- return;
35
- }
36
- if (report.locked) {
37
- console.error(chalk.yellow('The native credential store is locked/unreachable, so its secrets can\'t be read. ' +
38
- 'Unlock it and retry (a locked store can\'t be migrated).'));
39
- process.exit(1);
40
- }
41
- if (report.results.length === 0) {
42
- console.log(chalk.green('Nothing to import — no native secrets outside the file store.'));
43
- return;
44
- }
45
- const imported = report.results.filter((r) => r.status === 'imported' || r.status === 'would-import');
46
- const existing = report.results.filter((r) => r.status === 'exists');
47
- const failed = report.results.filter((r) => r.status === 'failed');
48
- for (const r of report.results) {
49
- if (r.status === 'imported')
50
- console.log(` ${chalk.green('imported')} ${r.item}`);
51
- else if (r.status === 'would-import')
52
- console.log(` ${chalk.cyan('would import')} ${r.item}`);
53
- else if (r.status === 'exists')
54
- console.log(` ${chalk.gray('exists')} ${r.item} ${chalk.gray('(already in file store)')}`);
55
- else
56
- console.log(` ${chalk.red('failed')} ${r.item} ${chalk.gray(r.detail ?? '')}`);
57
- }
58
- console.log();
59
- if (!commit) {
60
- console.log(chalk.gray(`Dry-run: ${imported.length} would be imported, ${existing.length} already present, ${failed.length} unreadable. Pass --commit to write.`));
61
- return;
62
- }
63
- if (failed.length > 0) {
64
- console.error(chalk.yellow(`Imported ${imported.length}; ${existing.length} already present; ${failed.length} failed.`));
65
- process.exit(1);
66
- }
67
- console.log(chalk.green(`Imported ${imported.length} secret(s) into the file store (${existing.length} already present).`));
68
- }
69
- catch (err) {
70
- console.error(chalk.red(err.message));
71
- process.exit(1);
72
- }
73
- });
74
- }
@@ -1,25 +0,0 @@
1
- /**
2
- * `agents secrets migrate-acl` — refresh existing keychain items so they pick
3
- * up the new SecAccess ACL written by the signed Agents CLI.app helper.
4
- *
5
- * Items created before 1.19.2 (or by `security add-generic-password` directly)
6
- * may carry the legacy "this-app-only" ACL that prompts the user for a
7
- * password on every read. Re-writing them through the helper bakes in the
8
- * empty trusted-app ACL that suppresses the prompt and lets the helper read
9
- * them under LocalAuthentication instead.
10
- *
11
- * Sequence per item:
12
- * 1. Read the current value (no auth prompt path — uses the unauthenticated
13
- * `security` CLI for non-sync items, helper `get` for sync items).
14
- * 2. Append (item, value, sync) to an encrypted backup before any writes.
15
- * 3. Delete + rewrite via the helper so macOS hands us a fresh ACL on the
16
- * new item.
17
- * 4. Read back via the helper to verify the value round-trips.
18
- *
19
- * `--dry-run` (default) reports the planned actions. `--commit` performs the
20
- * writes and produces the backup.
21
- */
22
- import type { Command } from 'commander';
23
- /** Register the keychain-migration commands (`migrate-acl`, `rekey`) on the
24
- * parent secrets Command. */
25
- export declare function registerSecretsMigrateAclCommand(secrets: Command): void;