create-metamynd-agent 0.10.3 → 0.10.5

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 (3) hide show
  1. package/README.md +8 -2
  2. package/index.mjs +49 -38
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -104,7 +104,11 @@ Answer a few prompts (API, owner email/password, agent name, scope, per-transact
104
104
 
105
105
  ```
106
106
  my-agent/
107
- ├─ agent.metamynd.json # portable guard config — HOLDS THE AGENT SECRET KEY (gitignored)
107
+ ├─ agent.metamynd.json # portable guard config — HOLDS THE AGENT SECRET KEY (gitignored). This
108
+ │ # is the freshly-minted key from THIS scaffold, not a re-download — the
109
+ │ # dashboard's own "Redownload config" for an EXISTING agent never re-issues
110
+ │ # the key into a downloaded file (it's excluded there by design). --byok /
111
+ │ # --daemon-socket instead keep the key off this CLI's process entirely.
108
112
  ├─ index.mjs # runnable example: signs + calls ./gateway; guardTool() here is a
109
113
  │ # fast local pre-check, NOT the enforcement boundary
110
114
  ├─ package.json # depends on @metamynd/agentsafe-guard
@@ -220,10 +224,12 @@ METAMYND_PASSWORD='…' npx create-metamynd-agent --yes …
220
224
  | Flag | Env | Default |
221
225
  |---|---|---|
222
226
  | `--harness` | — | off (no login/KYB/network at all; free local governance — see above) |
227
+ | `--gateway` | — | off — `--harness` only; ALSO scaffold a second local process (still zero network, zero account) that independently re-verifies every request via the real `@metamynd/agentsafe-mcp-guard`. Does not close nonce replay/cumulative spend — see the generated `harness-gateway/README.md#--gateway`. |
223
228
  | `--sandbox` | — | off (skips login/KYB; shared sandbox agent, still hosted) |
224
229
  | `--config <file>` | — | a JSON policy file — see [Policy config file](#policy-config-file---config) |
225
230
  | `--no-gateway` | — | off — hosted flow only; skips the default separate tool gateway (see above) |
226
- | `--gateway-port <n>` | — | `4401` — hosted flow only, the gateway process's port |
231
+ | `--gateway-port <n>` | — | `4401` — hosted flow or `--harness --gateway`, the gateway process's port |
232
+ | `--force`, `-f` | — | off — scaffold into a non-empty directory, overwriting existing files |
227
233
  | `--port <n>` | — | `4400` — `--harness` only, the local dashboard's port |
228
234
  | `--api <url>` | `METAMYND_API` | `https://metamynd.ai/api/v1` |
229
235
  | `--email <email>` | `METAMYND_EMAIL` | — (required) |
package/index.mjs CHANGED
@@ -14,7 +14,7 @@
14
14
  // npx create-metamynd-agent
15
15
  // npx create-metamynd-agent --api http://localhost:9926/api/v1 --email you@x.com \
16
16
  // --name "Support Bot" --scope flight-purchase --per-txn-max 500 --out ./support-bot --yes
17
- import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync } from 'node:fs';
17
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, chmodSync } from 'node:fs';
18
18
  import { join, resolve } from 'node:path';
19
19
  import readline from 'node:readline';
20
20
  import crypto from 'node:crypto';
@@ -71,7 +71,10 @@ const GATEWAY_PKG = '@metamynd/agentsafe-http-gateway';
71
71
  // is the actual fix: requires amount/merchant specifically, whenever the signature names a real
72
72
  // value for them. Re-tested live and closed same day; ^0.3.0 here would still resolve to the
73
73
  // broken version.
74
- const GATEWAY_VERSION = '^0.4.0';
74
+ // 0.5.0 adds the OPTIONAL Credential Vault `resolveCredential` hook on createHttpGateway (Module
75
+ // G) — additive and backward-compatible (every existing consumer sees zero behavior change), but
76
+ // the floor must still cover the real current version per this repo's own package-version check.
77
+ const GATEWAY_VERSION = '^0.5.0';
75
78
  const DEFAULT_API = 'https://metamynd.ai/api/v1';
76
79
  const DEFAULT_GATEWAY_PORT = 4401; // distinct from --harness's dashboard (4400)
77
80
 
@@ -438,7 +441,7 @@ async function apiPost(base, path, body, token) {
438
441
  * it — the same shape of gap --harness's README documents. See exampleIndex() below, which is
439
442
  * what the real (non-sandbox) flow scaffolds by default instead.
440
443
  */
441
- function exampleIndexNoGateway(scope, perTxnMax) {
444
+ function exampleIndexNoGateway(scope, perTxnMax, currency, merchant) {
442
445
  const under = Math.max(1, Math.round(perTxnMax * 0.5));
443
446
  const over = Math.round(perTxnMax + 100);
444
447
  return `// index.mjs — your agent, governed by MetaMynd/AgentSafe.
@@ -464,7 +467,7 @@ const gatedBookFlight = guard.guardTool(
464
467
  bookFlight,
465
468
  (a) => ({ // map tool args → gate inputs
466
469
  amount: a.amount,
467
- currency: 'USD',
470
+ currency: '${currency}',
468
471
  merchant: a.merchant,
469
472
  context: { tool: 'book-flight', riskLevel: a.riskLevel ?? 'low' },
470
473
  }),
@@ -481,7 +484,7 @@ const gatedRaiseOwnLimit = guard.guardTool(
481
484
  raiseOwnLimit,
482
485
  (a) => ({
483
486
  amount: a.amount,
484
- currency: 'USD',
487
+ currency: '${currency}',
485
488
  merchant: a.merchant,
486
489
  context: { tool: 'permissions-update' },
487
490
  }),
@@ -494,7 +497,7 @@ const rule = (n) => ' ' + '-'.repeat(n);
494
497
  // Plain-English meaning for the reason codes this demo can produce.
495
498
  const WHY = {
496
499
  AUTHORIZED: 'inside the mandate and under the SOP spend cap',
497
- SOP_SPEND_CAP: 'your SOP caps a single transaction at $${perTxnMax}',
500
+ SOP_SPEND_CAP: 'your SOP caps a single transaction at ${currency} ${perTxnMax}',
498
501
  RISK_REVIEW: 'your SOP sends high-risk actions to a human first',
499
502
  MERCHANT_NOT_ALLOWED: 'the mandate lists which merchants this agent may pay',
500
503
  // Both say the same thing from where you are standing: the mandate does not cover that
@@ -525,7 +528,7 @@ console.log(dim(' 4. each attempt is signed here, then decided by MetaMynd rem
525
528
  console.log(dim(' 5. your tool runs ONLY if that decision is ALLOW'));
526
529
  console.log('');
527
530
  console.log(dim(' scope ${scope}'));
528
- console.log(dim(' cap $${perTxnMax} per transaction, set by your SOP'));
531
+ console.log(dim(' cap ${currency} ${perTxnMax} per transaction, set by your SOP'));
529
532
 
530
533
  // ---------------------------------------------------------------- 3. THE STEPS
531
534
  async function attempt(n, intent, args, tool = gatedBookFlight) {
@@ -553,13 +556,13 @@ async function attempt(n, intent, args, tool = gatedBookFlight) {
553
556
 
554
557
  console.log('');
555
558
  console.log(rule(66));
556
- await attempt(1, 'a $${under} booking, low risk. Expected to pass.', { amount: ${under}, merchant: 'skyward-air', riskLevel: 'low' });
557
- await attempt(2, 'a $${over} booking, deliberately over the cap.', { amount: ${over}, merchant: 'skyward-air', riskLevel: 'low' });
558
- await attempt(3, 'a $${under} booking, but flagged high risk.', { amount: ${under}, merchant: 'skyward-air', riskLevel: 'high' });
559
+ await attempt(1, 'a ${currency} ${under} booking, low risk. Expected to pass.', { amount: ${under}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'low' });
560
+ await attempt(2, 'a ${currency} ${over} booking, deliberately over the cap.', { amount: ${over}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'low' });
561
+ await attempt(3, 'a ${currency} ${under} booking, but flagged high risk.', { amount: ${under}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'high' });
559
562
  await attempt(
560
563
  4,
561
564
  'the agent stops booking flights and asks to raise its OWN limit.',
562
- { amount: 100000, merchant: 'skyward-air' },
565
+ { amount: 100000, currency: '${currency}', merchant: '${merchant}' },
563
566
  gatedRaiseOwnLimit,
564
567
  );
565
568
  console.log('');
@@ -595,7 +598,7 @@ console.log('');
595
598
  * directly: it only exists in ./gateway, which independently re-verifies every request against
596
599
  * this agent's own policy bundle before it runs, and holds any real credentials the tool needs.
597
600
  */
598
- function exampleIndex(scope, perTxnMax, gatewayPort) {
601
+ function exampleIndex(scope, perTxnMax, gatewayPort, currency, merchant) {
599
602
  const under = Math.max(1, Math.round(perTxnMax * 0.5));
600
603
  const over = Math.round(perTxnMax + 100);
601
604
  return `// index.mjs — your agent, governed by MetaMynd/AgentSafe.
@@ -620,7 +623,7 @@ async function bookFlightViaGateway(args, decision) {
620
623
  const signed = await guard.buildSignedRequest({
621
624
  action: '${scope}',
622
625
  amount: args.amount,
623
- currency: 'USD',
626
+ currency: args.currency ?? '${currency}',
624
627
  merchant: args.merchant,
625
628
  context: { tool: 'book-flight', riskLevel: args.riskLevel ?? 'low' },
626
629
  });
@@ -647,7 +650,7 @@ const gatedBookFlight = guard.guardTool(
647
650
  bookFlightViaGateway,
648
651
  (a) => ({ // map tool args → gate inputs
649
652
  amount: a.amount,
650
- currency: 'USD',
653
+ currency: a.currency ?? '${currency}',
651
654
  merchant: a.merchant,
652
655
  context: { tool: 'book-flight', riskLevel: a.riskLevel ?? 'low' },
653
656
  }),
@@ -664,7 +667,7 @@ const gatedRaiseOwnLimit = guard.guardTool(
664
667
  raiseOwnLimit,
665
668
  (a) => ({
666
669
  amount: a.amount,
667
- currency: 'USD',
670
+ currency: a.currency ?? '${currency}',
668
671
  merchant: a.merchant,
669
672
  context: { tool: 'permissions-update' },
670
673
  }),
@@ -711,7 +714,7 @@ console.log(dim(' 5. the gateway independently re-verifies before your tool ru
711
714
  console.log(dim(' 6. there is no local bookFlight() to call directly - only the gateway has it'));
712
715
  console.log('');
713
716
  console.log(dim(' scope ${scope}'));
714
- console.log(dim(' cap $${perTxnMax} per transaction, set by your SOP'));
717
+ console.log(dim(' cap ${currency} ${perTxnMax} per transaction, set by your SOP'));
715
718
  console.log(dim(' gateway ' + GATEWAY + ' (run it in a separate terminal - see ./gateway)'));
716
719
 
717
720
  // ---------------------------------------------------------------- 3. THE STEPS
@@ -740,13 +743,13 @@ async function attempt(n, intent, args, tool = gatedBookFlight) {
740
743
 
741
744
  console.log('');
742
745
  console.log(rule(66));
743
- await attempt(1, 'a $${under} booking, low risk. Expected to pass.', { amount: ${under}, merchant: 'skyward-air', riskLevel: 'low' });
744
- await attempt(2, 'a $${over} booking, deliberately over the cap.', { amount: ${over}, merchant: 'skyward-air', riskLevel: 'low' });
745
- await attempt(3, 'a $${under} booking, but flagged high risk.', { amount: ${under}, merchant: 'skyward-air', riskLevel: 'high' });
746
+ await attempt(1, 'a ${currency} ${under} booking, low risk. Expected to pass.', { amount: ${under}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'low' });
747
+ await attempt(2, 'a ${currency} ${over} booking, deliberately over the cap.', { amount: ${over}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'low' });
748
+ await attempt(3, 'a ${currency} ${under} booking, but flagged high risk.', { amount: ${under}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'high' });
746
749
  await attempt(
747
750
  4,
748
751
  'the agent stops booking flights and asks to raise its OWN limit.',
749
- { amount: 100000, merchant: 'skyward-air' },
752
+ { amount: 100000, currency: '${currency}', merchant: '${merchant}' },
750
753
  gatedRaiseOwnLimit,
751
754
  );
752
755
  console.log('');
@@ -1108,11 +1111,16 @@ and \`demo/duffel-mcp-gateway\` in the AgentSafe repo for the fuller pattern thi
1108
1111
  `;
1109
1112
  }
1110
1113
 
1111
- function writeFileSafe(dir, name, content, force = false) {
1114
+ function writeFileSafe(dir, name, content, force = false, mode) {
1112
1115
  const p = join(dir, name);
1113
1116
  const exists = existsSync(p);
1114
1117
  if (exists && !force) { console.log(` ${c.yellow('skip')} ${name} ${c.dim('(exists)')}`); return; }
1115
- writeFileSync(p, content);
1118
+ // `mode` (e.g. 0o600 for a private-key-bearing file) only narrows perms at CREATE time —
1119
+ // writeFileSync ignores its own `mode` option on an existing file, so an --force overwrite
1120
+ // needs an explicit chmod or a stale world-readable mode from the file's first creation
1121
+ // would otherwise survive untouched.
1122
+ writeFileSync(p, content, mode !== undefined ? { mode } : undefined);
1123
+ if (mode !== undefined) chmodSync(p, mode);
1116
1124
  console.log(` ${exists ? c.yellow('overwrite') : c.green('create')} ${name}`);
1117
1125
  }
1118
1126
 
@@ -1146,12 +1154,12 @@ function assertScaffoldTarget(outDir, force) {
1146
1154
  * enforcement boundary. Off for --sandbox (shared demo identity, never real credentials
1147
1155
  * anyway) and --no-gateway (opt out, e.g. you're already running your own separate gateway).
1148
1156
  */
1149
- function scaffoldProject({ outDir, config, slug, scope, perTxnMax, sandbox, withGateway, gatewayPort = DEFAULT_GATEWAY_PORT, force = false }) {
1157
+ function scaffoldProject({ outDir, config, slug, scope, perTxnMax, currency = 'USD', merchant = 'skyward-air', sandbox, withGateway, gatewayPort = DEFAULT_GATEWAY_PORT, force = false }) {
1150
1158
  assertScaffoldTarget(outDir, force);
1151
1159
  console.log(`\n ${c.b('Scaffolding')} ${c.dim(outDir)}`);
1152
1160
  if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
1153
- writeFileSafe(outDir, 'agent.metamynd.json', JSON.stringify(config, null, 2) + '\n', force);
1154
- writeFileSafe(outDir, 'index.mjs', withGateway ? exampleIndex(scope, perTxnMax, gatewayPort) : exampleIndexNoGateway(scope, perTxnMax), force);
1161
+ writeFileSafe(outDir, 'agent.metamynd.json', JSON.stringify(config, null, 2) + '\n', force, 0o600);
1162
+ writeFileSafe(outDir, 'index.mjs', withGateway ? exampleIndex(scope, perTxnMax, gatewayPort, currency, merchant) : exampleIndexNoGateway(scope, perTxnMax, currency, merchant), force);
1155
1163
  writeFileSafe(outDir, 'package.json', examplePackageJson(slug), force);
1156
1164
  writeFileSafe(outDir, '.gitignore', gitignore(), force);
1157
1165
  writeFileSafe(outDir, 'README.md', exampleReadme(slug, scope, withGateway, gatewayPort, config.keyProvider === 'daemon'), force);
@@ -1792,7 +1800,7 @@ setInterval(refresh, 3000);
1792
1800
  `;
1793
1801
  }
1794
1802
 
1795
- function harnessIndexFile(scope, perTxnMax, port, withGateway, gatewayPort) {
1803
+ function harnessIndexFile(scope, perTxnMax, port, withGateway, gatewayPort, currency, merchant) {
1796
1804
  const under = Math.max(1, Math.round(perTxnMax * 0.5));
1797
1805
  const over = Math.round(perTxnMax + 100);
1798
1806
  return `// index.mjs — your agent, governed entirely on this machine. No account, no network call
@@ -1831,7 +1839,7 @@ const GATEWAY = process.env.HARNESS_GATEWAY_URL || 'http://localhost:${gatewayPo
1831
1839
  // issuer): it builds and signs the same canonical message a real gate would verify, entirely
1832
1840
  // offline, using this agent's own did:key — the gateway verifies that signature for itself.
1833
1841
  async function callGateway(path, action, args) {
1834
- const signed = await guard.buildSignedRequest({ action, amount: args.amount, currency: 'USD', merchant: args.merchant, context: { tool: '${scope}', riskLevel: args.riskLevel ?? 'low' } });
1842
+ const signed = await guard.buildSignedRequest({ action, amount: args.amount, currency: args.currency ?? '${currency}', merchant: args.merchant, context: { tool: '${scope}', riskLevel: args.riskLevel ?? 'low' } });
1835
1843
  const res = await fetch(GATEWAY + path, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ signed, args }) });
1836
1844
  const body = await res.json().catch(() => null);
1837
1845
  if (!res.ok) {
@@ -1854,6 +1862,7 @@ const gatedBookFlight = guard.guardToolLocal(
1854
1862
  ${withGateway ? `(args) => callGateway('/book-flight', '${scope}', args)` : 'bookFlight'},
1855
1863
  (a) => ({ // map tool args → gate inputs
1856
1864
  amount: a.amount,
1865
+ currency: a.currency ?? '${currency}',
1857
1866
  merchant: a.merchant,
1858
1867
  context: { tool: 'book-flight', riskLevel: a.riskLevel ?? 'low' },
1859
1868
  }),
@@ -1869,7 +1878,7 @@ async function raiseOwnLimit(args) {
1869
1878
  const gatedRaiseOwnLimit = guard.guardToolLocal(
1870
1879
  'permissions.update', // an action NOT in the mandate
1871
1880
  ${withGateway ? `(args) => callGateway('/raise-limit', 'permissions.update', args)` : 'raiseOwnLimit'},
1872
- (a) => ({ amount: a.amount, merchant: a.merchant, context: { tool: 'permissions-update' } }),
1881
+ (a) => ({ amount: a.amount, currency: a.currency ?? '${currency}', merchant: a.merchant, context: { tool: 'permissions-update' } }),
1873
1882
  getBundle,
1874
1883
  );
1875
1884
 
@@ -1879,7 +1888,7 @@ const rule = (n) => ' ' + '-'.repeat(n);
1879
1888
 
1880
1889
  const WHY = {
1881
1890
  AUTHORIZED: 'inside the mandate and under the SOP spend cap',
1882
- SOP_SPEND_CAP: 'your SOP caps a single transaction at $${perTxnMax}',
1891
+ SOP_SPEND_CAP: 'your SOP caps a single transaction at ${currency} ${perTxnMax}',
1883
1892
  RISK_REVIEW: 'your SOP sends high-risk actions to a human first',
1884
1893
  MERCHANT_NOT_ALLOWED: 'the mandate lists which merchants this agent may pay',
1885
1894
  NO_PERMISSION_FOR_ACTION: 'the mandate never granted this action - at any amount',
@@ -1925,14 +1934,14 @@ console.log(' for something never granted at all - the one a prompt could not h
1925
1934
  console.log(' because the decision is not made inside your program, and not on a server either.');
1926
1935
  console.log('');
1927
1936
  console.log(dim(' scope ${scope}'));
1928
- console.log(dim(' cap $${perTxnMax} per transaction, from ./metamynd-rules.json'));
1937
+ console.log(dim(' cap ${currency} ${perTxnMax} per transaction, from ./metamynd-rules.json'));
1929
1938
 
1930
1939
  console.log('');
1931
1940
  console.log(rule(66));
1932
- await attempt(1, 'a $${under} booking, low risk. Expected to pass.', '${scope}', { amount: ${under}, merchant: 'skyward-air', riskLevel: 'low' });
1933
- await attempt(2, 'a $${over} booking, deliberately over the cap.', '${scope}', { amount: ${over}, merchant: 'skyward-air', riskLevel: 'low' });
1934
- await attempt(3, 'a $${under} booking, but flagged high risk.', '${scope}', { amount: ${under}, merchant: 'skyward-air', riskLevel: 'high' });
1935
- await attempt(4, 'the agent stops booking flights and asks to raise its OWN limit.', 'permissions.update', { amount: 100000, merchant: 'skyward-air' }, gatedRaiseOwnLimit);
1941
+ await attempt(1, 'a ${currency} ${under} booking, low risk. Expected to pass.', '${scope}', { amount: ${under}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'low' });
1942
+ await attempt(2, 'a ${currency} ${over} booking, deliberately over the cap.', '${scope}', { amount: ${over}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'low' });
1943
+ await attempt(3, 'a ${currency} ${under} booking, but flagged high risk.', '${scope}', { amount: ${under}, currency: '${currency}', merchant: '${merchant}', riskLevel: 'high' });
1944
+ await attempt(4, 'the agent stops booking flights and asks to raise its OWN limit.', 'permissions.update', { amount: 100000, currency: '${currency}', merchant: '${merchant}' }, gatedRaiseOwnLimit);
1936
1945
  console.log('');
1937
1946
  console.log(rule(66));
1938
1947
 
@@ -2109,10 +2118,10 @@ async function runHarness(args) {
2109
2118
 
2110
2119
  console.log(`\n ${c.b('Scaffolding')} ${c.dim(outDir)}`);
2111
2120
  if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
2112
- writeFileSafe(outDir, 'agent.metamynd.json', JSON.stringify({ agentDid, agentKey: privateKeyHex, mode: 'harness' }, null, 2) + '\n', !!args.force);
2121
+ writeFileSafe(outDir, 'agent.metamynd.json', JSON.stringify({ agentDid, agentKey: privateKeyHex, mode: 'harness' }, null, 2) + '\n', !!args.force, 0o600);
2113
2122
  writeFileSafe(outDir, 'metamynd-rules.json', harnessRulesFile(mandate, sopDocument), !!args.force);
2114
2123
  writeFileSafe(outDir, 'harness-server.mjs', harnessServerFile(), !!args.force);
2115
- writeFileSafe(outDir, 'index.mjs', harnessIndexFile(scope, perTxnMax, port, withGateway, gatewayPort), !!args.force);
2124
+ writeFileSafe(outDir, 'index.mjs', harnessIndexFile(scope, perTxnMax, port, withGateway, gatewayPort, currency, merchants[0] || 'demo-merchant'), !!args.force);
2116
2125
  writeFileSafe(outDir, 'package.json', harnessPackageJson(slug), !!args.force);
2117
2126
  writeFileSafe(outDir, '.gitignore', gitignore(), !!args.force);
2118
2127
  writeFileSafe(outDir, 'README.md', harnessReadme(slug, scope, port, withGateway, gatewayPort), !!args.force);
@@ -2204,7 +2213,9 @@ async function runRequest(args) {
2204
2213
  const d = res.data;
2205
2214
  const state = { api: base, requestId: d.requestId, claimToken: d.claimToken, byok: !!generated, privateKey: generated?.privateKeyHex ?? null, name, scope, perTxnMax };
2206
2215
  const file = resolve(String(args.out || '.'), REQUEST_STATE_FILE);
2207
- writeFileSync(file, JSON.stringify(state, null, 2) + '\n');
2216
+ // May carry a BYOK private key (state.privateKey) same 0600 treatment as agent.metamynd.json.
2217
+ writeFileSync(file, JSON.stringify(state, null, 2) + '\n', { mode: 0o600 });
2218
+ if (existsSync(file)) chmodSync(file, 0o600);
2208
2219
 
2209
2220
  console.log(` ${c.green('✓')} request ${c.b(d.requestId)} submitted — awaiting ${owner}'s approval`);
2210
2221
  console.log(` ${c.yellow('⚠ saved the one-time claim token to')} ${file.replace(resolve('.'), '.').replace(/\\/g, '/')} ${c.dim('(secret — do not commit)')}\n`);
@@ -2413,7 +2424,7 @@ async function main() {
2413
2424
  }
2414
2425
 
2415
2426
  // 4. Scaffold + next steps
2416
- scaffoldProject({ outDir, config, slug, scope, perTxnMax, sandbox: false, withGateway: !args['no-gateway'], gatewayPort: Number(args['gateway-port']) || DEFAULT_GATEWAY_PORT, force: !!args.force });
2427
+ scaffoldProject({ outDir, config, slug, scope, perTxnMax, currency, merchant: merchants[0] || 'demo-merchant', sandbox: false, withGateway: !args['no-gateway'], gatewayPort: Number(args['gateway-port']) || DEFAULT_GATEWAY_PORT, force: !!args.force });
2417
2428
  }
2418
2429
 
2419
2430
  main().catch((e) => fail(e?.stack || e?.message || String(e)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-metamynd-agent",
3
- "version": "0.10.3",
3
+ "version": "0.10.5",
4
4
  "description": "Scaffold a MetaMynd/AgentSafe-governed AI agent in one command — logs in, provisions the agent (identity + mandate + SOP + Standards) in a single call, writes agent.metamynd.json plus a runnable agent + separate tool-gateway process that closes direct-call, confused-deputy, replay, and cumulative-spend bypasses. --harness scaffolds a free, local, zero-network governance harness instead.",
5
5
  "type": "module",
6
6
  "bin": {