@buoy-gg/mcp 7.0.72 → 7.0.74

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/README.md CHANGED
@@ -54,13 +54,13 @@ Pass `real: true` to make each tap a real touch.
54
54
 
55
55
  ## Many sims at once
56
56
 
57
- The `sim_farm_*` tools run many slim iOS sims on one Mac. They make Buoy Optimize faster. Ask your agent:
57
+ The `sim_farm_*` tools run many slim iOS sims and Android phones on one Mac. They make Buoy Optimize faster. Ask your agent:
58
58
 
59
59
  ```text
60
60
  Use buoy optimize and the sim farm on our slow feed screen.
61
61
  ```
62
62
 
63
- The agent finds as many ideas as it can and tests them all. Each idea gets its own sim. The agent checks how each one looks and how much memory it uses. Each app acts like a real iPhone SE, so an idea that uses too much memory is out. Then the best ideas are timed on one quiet sim. You can run the farm yourself too:
63
+ The agent finds as many ideas as it can and tests them all. Each idea gets its own sim. The agent checks how each one looks and how much memory it uses. Each app acts like a real phone (an iPhone SE, or a 3 GB Android phone), so an idea that uses too much memory is out. Then the best ideas are timed on one quiet sim. You can run the farm yourself too:
64
64
 
65
65
  ```bash
66
66
  npx -y @buoy-gg/mcp@latest farm status
@@ -69,6 +69,17 @@ npx -y @buoy-gg/mcp@latest farm phone use off
69
69
 
70
70
  See the [Sim Farm guide](https://buoy.gg/buoy/latest/docs/tools/sim-farm).
71
71
 
72
+ ## Many Chromes at once
73
+
74
+ The `chrome_farm_*` tools run many slim Chromes on one computer. Each one runs your web app with its own storage and its own debugging address. Your tests and your agent can drive them all at once:
75
+
76
+ ```bash
77
+ npx -y @buoy-gg/mcp@latest farm chrome up 8 --url http://localhost:3000
78
+ npx -y @buoy-gg/mcp@latest farm chrome run 8 --url http://localhost:3000 -- node my-test.mjs
79
+ ```
80
+
81
+ See the [Chrome Farm guide](https://buoy.gg/buoy/latest/docs/tools/chrome-farm).
82
+
72
83
  ---
73
84
 
74
85
  <sub>Part of <a href="https://buoy.gg">Buoy</a>, developer tools that live inside your app. Proprietary software. © Buoy LLC. <a href="https://buoy.gg/terms">Terms</a></sub>
@@ -1 +1 @@
1
- import{createRequire as e}from"module";const c=e(import.meta.url);import{cliPath as r,describeDevices as t,describeDiagnosis as i,describeInputs as o,entitlementHasPro as s,proRequired as m,readEntitlement as n,run as a,setEntitlementFileForTests as p}from"./chunk-OUCB2Y5J.mjs";import"./chunk-FOMLVT7K.mjs";import"./chunk-MTTWR4T7.mjs";export{r as cliPath,t as describeDevices,i as describeDiagnosis,o as describeInputs,s as entitlementHasPro,m as proRequired,n as readEntitlement,a as run,p as setEntitlementFileForTests};
1
+ import{createRequire as e}from"module";const c=e(import.meta.url);import{cliPath as r,describeDevices as t,describeDiagnosis as i,describeInputs as o,entitlementHasPro as s,proRequired as m,readEntitlement as n,run as a,setEntitlementFileForTests as p}from"./chunk-FRGTROJC.mjs";import"./chunk-PAOWVPJM.mjs";import"./chunk-MTTWR4T7.mjs";export{r as cliPath,t as describeDevices,i as describeDiagnosis,o as describeInputs,s as entitlementHasPro,m as proRequired,n as readEntitlement,a as run,p as setEntitlementFileForTests};
@@ -1,4 +1,4 @@
1
- import{createRequire as p}from"module";const D=p(import.meta.url);import{weekendNow as h}from"./chunk-FOMLVT7K.mjs";import{execFile as f}from"child_process";import{promisify as y}from"util";import{existsSync as c,readFileSync as g}from"fs";import u from"os";import a from"path";var b=y(f);function k(){const n=process.env.BUOY_SIMCAM_DIR;const t=[...n?[a.join(n,"buoycam")]:[],"/Applications/Buoy.app/Contents/Resources/simcam/buoycam",a.join(u.homedir(),"Applications/Buoy.app/Contents/Resources/simcam/buoycam")];let e=__dirname;for(let o=0;o<8;o++){t.push(a.join(e,"apps/desktop/resources/simcam/buoycam"));const i=a.dirname(e);if(i===e)break;e=i}return t}var s=null;function m(){if(s)return s;s=k().find(n=>c(n))??null;return s}async function _(n){const t=m();if(!t){return{ok:false,error:"The simulator camera components were not found. They ship with the Buoy desktop app \u2014 install it, or set BUOY_SIMCAM_DIR to the directory holding `buoycam`."}}try{const{stdout:e}=await b(t,[...n,"--json"],{timeout:3e4});return{ok:true,data:JSON.parse(e)}}catch(e){const o=e.stdout??"";try{return{ok:false,data:JSON.parse(o)}}catch{return{ok:false,error:e.message||"the simulator camera CLI failed"}}}}function $(n){const t=n.filter(r=>r.level==="fail");const e=n.filter(r=>r.level==="warn");if(t.length===0&&e.length===0){return"The simulator camera is healthy \u2014 every check passed."}const o=[];for(const r of[...t,...e]){o.push(`- **${r.name}** (${r.level}): ${r.detail}`);if(r.fix)o.push(` ${r.fix}`)}const i=t.length>0?`${t.length} problem${t.length===1?"":"s"} found.`:`No hard failures, but ${e.length} thing${e.length===1?"":"s"} worth knowing.`;return[i,"",...o].join("\n")}function S(n,t){if(n.length===0){return"No booted simulators.\n\n_Boot one first \u2014 `xcrun simctl boot <udid>`, or open Simulator.app. The camera attaches to a simulator, so nothing else here works until one is running._"}const e=[n.length===1?"1 booted simulator:":`${n.length} booted simulators:`,...n.map(o=>`- **${o.name}** (${o.runtime}) \u2014 \`${o.udid}\``)];if(n.length>1&&t===null){e.push("","_More than one is booted, so pass `udid` to list a specific one's apps \u2014 and to every other camera tool that takes one._");return e.join("\n")}if(t===null){e.push("","_Could not read the installed apps._");return e.join("\n")}if(t.length===0){e.push("","No apps installed on it.");return e.join("\n")}e.push("",`${t.length} installed app${t.length===1?"":"s"}:`,...t.map(o=>`- ${o.name} \u2014 \`${o.bundleId}\``),"","_Pass one of these bundle ids to `camera_launch` to relaunch it with the camera attached._");return e.join("\n")}function w(n,t){const e=[];e.push(n.length?'**Mac cameras** (for `kind: "camera"`):':"**Mac cameras**: none found.");if(n.length){e.push(...n.map(o=>`- ${o.name} \u2014 \`${o.uniqueId}\``))}else{e.push("_If this Mac has a webcam, Buoy has not been granted Camera permission (System Settings \u2192 Privacy & Security \u2192 Camera)._")}e.push("");e.push(t.length?'**Capturable windows** (for `kind: "screen"`, `value: "window:<id>"`):':"**Capturable windows**: none found.");if(t.length){e.push(...t.map(o=>`- ${o.app}${o.title?` \u2014 ${o.title}`:""} \u2014 \`window:${o.id}\``))}else{e.push("_Screen Recording permission is almost certainly missing (System Settings \u2192 Privacy & Security \u2192 Screen & System Audio Recording)._")}return e.join("\n")}var l=null;function v(n){l=n}function j(){if(l)return[l];return[a.join(u.homedir(),"Library/Application Support/Buoy/entitlement.json"),a.join(u.homedir(),"Library/Application Support/buoy-desktop/entitlement.json")]}function d(){for(const n of j()){try{if(!c(n))continue;const t=JSON.parse(g(n,"utf8"));const e=t.tier==="pro"||t.tier==="free"?t.tier:"locked";const o=t.hasDesktopAccess===true&&typeof t.validUntil==="number"&&Number.isFinite(t.validUntil)&&Date.now()<t.validUntil;const i=o&&t.isPro===true&&typeof t.proValidUntil==="number"&&Number.isFinite(t.proValidUntil)&&Date.now()<t.proValidUntil;return{tier:e,isPro:i,admitted:i||o&&e!=="locked"}}catch{}}return{tier:"locked",isPro:false,admitted:false}}function P(n=d()){return n.isPro||n.admitted===true&&h()}function C(n){return`\`${n}\` is a Buoy Pro feature.
1
+ import{createRequire as p}from"module";const D=p(import.meta.url);import{weekendNow as h}from"./chunk-PAOWVPJM.mjs";import{execFile as f}from"child_process";import{promisify as y}from"util";import{existsSync as c,readFileSync as g}from"fs";import u from"os";import a from"path";var b=y(f);function k(){const n=process.env.BUOY_SIMCAM_DIR;const t=[...n?[a.join(n,"buoycam")]:[],"/Applications/Buoy.app/Contents/Resources/simcam/buoycam",a.join(u.homedir(),"Applications/Buoy.app/Contents/Resources/simcam/buoycam")];let e=__dirname;for(let o=0;o<8;o++){t.push(a.join(e,"apps/desktop/resources/simcam/buoycam"));const i=a.dirname(e);if(i===e)break;e=i}return t}var s=null;function m(){if(s)return s;s=k().find(n=>c(n))??null;return s}async function _(n){const t=m();if(!t){return{ok:false,error:"The simulator camera components were not found. They ship with the Buoy desktop app \u2014 install it, or set BUOY_SIMCAM_DIR to the directory holding `buoycam`."}}try{const{stdout:e}=await b(t,[...n,"--json"],{timeout:3e4});return{ok:true,data:JSON.parse(e)}}catch(e){const o=e.stdout??"";try{return{ok:false,data:JSON.parse(o)}}catch{return{ok:false,error:e.message||"the simulator camera CLI failed"}}}}function $(n){const t=n.filter(r=>r.level==="fail");const e=n.filter(r=>r.level==="warn");if(t.length===0&&e.length===0){return"The simulator camera is healthy \u2014 every check passed."}const o=[];for(const r of[...t,...e]){o.push(`- **${r.name}** (${r.level}): ${r.detail}`);if(r.fix)o.push(` ${r.fix}`)}const i=t.length>0?`${t.length} problem${t.length===1?"":"s"} found.`:`No hard failures, but ${e.length} thing${e.length===1?"":"s"} worth knowing.`;return[i,"",...o].join("\n")}function S(n,t){if(n.length===0){return"No booted simulators.\n\n_Boot one first \u2014 `xcrun simctl boot <udid>`, or open Simulator.app. The camera attaches to a simulator, so nothing else here works until one is running._"}const e=[n.length===1?"1 booted simulator:":`${n.length} booted simulators:`,...n.map(o=>`- **${o.name}** (${o.runtime}) \u2014 \`${o.udid}\``)];if(n.length>1&&t===null){e.push("","_More than one is booted, so pass `udid` to list a specific one's apps \u2014 and to every other camera tool that takes one._");return e.join("\n")}if(t===null){e.push("","_Could not read the installed apps._");return e.join("\n")}if(t.length===0){e.push("","No apps installed on it.");return e.join("\n")}e.push("",`${t.length} installed app${t.length===1?"":"s"}:`,...t.map(o=>`- ${o.name} \u2014 \`${o.bundleId}\``),"","_Pass one of these bundle ids to `camera_launch` to relaunch it with the camera attached._");return e.join("\n")}function w(n,t){const e=[];e.push(n.length?'**Mac cameras** (for `kind: "camera"`):':"**Mac cameras**: none found.");if(n.length){e.push(...n.map(o=>`- ${o.name} \u2014 \`${o.uniqueId}\``))}else{e.push("_If this Mac has a webcam, Buoy has not been granted Camera permission (System Settings \u2192 Privacy & Security \u2192 Camera)._")}e.push("");e.push(t.length?'**Capturable windows** (for `kind: "screen"`, `value: "window:<id>"`):':"**Capturable windows**: none found.");if(t.length){e.push(...t.map(o=>`- ${o.app}${o.title?` \u2014 ${o.title}`:""} \u2014 \`window:${o.id}\``))}else{e.push("_Screen Recording permission is almost certainly missing (System Settings \u2192 Privacy & Security \u2192 Screen & System Audio Recording)._")}return e.join("\n")}var l=null;function v(n){l=n}function j(){if(l)return[l];return[a.join(u.homedir(),"Library/Application Support/Buoy/entitlement.json"),a.join(u.homedir(),"Library/Application Support/buoy-desktop/entitlement.json")]}function d(){for(const n of j()){try{if(!c(n))continue;const t=JSON.parse(g(n,"utf8"));const e=t.tier==="pro"||t.tier==="free"?t.tier:"locked";const o=t.hasDesktopAccess===true&&typeof t.validUntil==="number"&&Number.isFinite(t.validUntil)&&Date.now()<t.validUntil;const i=o&&t.isPro===true&&typeof t.proValidUntil==="number"&&Number.isFinite(t.proValidUntil)&&Date.now()<t.proValidUntil;return{tier:e,isPro:i,admitted:i||o&&e!=="locked"}}catch{}}return{tier:"locked",isPro:false,admitted:false}}function P(n=d()){return n.isPro||n.admitted===true&&h()}function C(n){return`\`${n}\` is a Buoy Pro feature.
2
2
 
3
3
  The simulator camera itself is free \u2014 the Mac camera, image, video, test-pattern and QR sources all work in the Buoy desktop panel with a Free account. Pro adds the screen region, the non-QR symbologies (PDF417, Aztec, DataMatrix, Code 128), and driving any of it from an agent.
4
4
 
@@ -1,4 +1,4 @@
1
- import{createRequire as A}from"module";const G=A(import.meta.url);import{PACKAGE_NAME as l,VERSION as b}from"./chunk-FJI4FST7.mjs";import{spawnSync as m}from"child_process";import s from"fs";import E from"os";import c from"path";function g(){return{BUOY_VERIFY:"auto"}}var w="https://registry.npmjs.org";var f=3e3;function C(e={}){const t=e.cwd??process.cwd();const r=e.skillSrcDir??c.resolve(__dirname,"../skill");const n=e.log??(a=>process.stdout.write(a+"\n"));const o=k(e,n);const i=[];d(c.join(t,".mcp.json"),"mcpServers",o,t,i);s.mkdirSync(c.join(t,".cursor"),{recursive:true});d(c.join(t,".cursor","mcp.json"),"mcpServers",o,t,i);if(s.existsSync(c.join(t,".vscode"))){d(c.join(t,".vscode","mcp.json"),"servers",o,t,i)}D(r,t,i);x(c.join(t,"CLAUDE.md"),t,i);x(c.join(t,"AGENTS.md"),t,i);n("Buoy MCP configuration written:");for(const a of i)n(" \u2022 "+a);n("");n("Next steps:");n(" 1. Restart your editor (or reconnect the MCP server) to load `buoy`.");n(" 2. Complete account setup, then open an app with the required Buoy tools and sync integration.");n(" 3. Confirm the device and tools are available. Free accounts get the basic MCP tools; Pro adds the rest.");n("");n(`Want your AI to use the web too? Run \`npx -y ${l}@latest init --web\` for Buoy Web (free, no account).`);if(o.command==="npx"){n("");n(`The editor launches the server with \`npx -y ${l}@latest\`, so it stays`);n(`Registry access may be needed. Re-run \`npx -y ${l}@latest init\` to refresh configuration.`)}else if(!e.cliPath){n("");n(`This uses a pinned local install (no network on startup). To update it later,`);n(`To update the local package, run: npx -y ${o.args[0]?.replace(/dist[/\\]cli\.js$/,"")??""}@latest init --local`)}}function k(e,t){if(e.cliPath){return{type:"stdio",command:"node",args:[e.cliPath],env:g()}}const r=e.mode??"auto";if(r==="npx"){return y()}if(r==="local"){return $(e,t)}const n=I();if(n.reachable){return y()}t(`\u26A0 npm registry ${n.registry?`(${n.registry}) `:""}looks unreachable \u2014 \`npx @latest\` would hang your editor at startup. Falling back to a pinned local install.`);return $(e,t)}function y(){return{type:"stdio",command:"npx",args:["-y",`${l}@latest`],env:g()}}function $(e,t){const r=e.installDir??process.env.BUOY_MCP_HOME??c.join(E.homedir(),".buoy-mcp");const n=e.registry??w;const o=R(r,n,t);if(o){return{type:"stdio",command:"node",args:[o],env:g()}}t("\u26A0 local install failed \u2014 writing the npx entry instead (see the error above).");return y()}function R(e,t,r){const n=`${l}@${b==="0.0.0-dev"?"latest":b}`;s.mkdirSync(e,{recursive:true});const o=process.platform==="win32"?"npm.cmd":"npm";r(`Installing ${n} into ${e} from ${t} \u2026`);const i=m(o,["install",n,"--prefix",e,"--registry",t,`--@buoy-gg:registry=${t}`,"--no-audit","--no-fund","--loglevel=error"],{stdio:["ignore","ignore","inherit"],encoding:"utf8"});if(i.status!==0){r(`\u26A0 npm install exited with code ${i.status??"?"}${i.error?` (${i.error.message})`:""}.`);return null}const a=c.join(e,"node_modules",l,"dist","cli.js");if(!s.existsSync(a)){r(`\u26A0 install finished but ${a} is missing.`);return null}return a}function I(){const e=P();if(!e)return{reachable:false,registry:null};if(/^https?:\/\/registry\.npmjs\.org\/?$/i.test(e)){return{reachable:true,registry:e}}return{reachable:T(e),registry:e}}function P(){const e=S("@buoy-gg:registry");if(e)return e;const t=S("registry");return t??w}function S(e){const t=process.platform==="win32"?"npm.cmd":"npm";const r=m(t,["config","get",e],{encoding:"utf8",timeout:f});if(r.status!==0||typeof r.stdout!=="string")return null;const n=r.stdout.trim();if(!n||n==="undefined"||n==="null")return null;return n}function T(e){const t=m(process.execPath,["-e",F,e,String(f)],{encoding:"utf8",timeout:f+2e3});return t.status===0}var F=`
1
+ import{createRequire as A}from"module";const G=A(import.meta.url);import{PACKAGE_NAME as l,VERSION as b}from"./chunk-ZHEXLBAX.mjs";import{spawnSync as m}from"child_process";import s from"fs";import E from"os";import c from"path";function g(){return{BUOY_VERIFY:"auto"}}var w="https://registry.npmjs.org";var f=3e3;function C(e={}){const t=e.cwd??process.cwd();const r=e.skillSrcDir??c.resolve(__dirname,"../skill");const n=e.log??(a=>process.stdout.write(a+"\n"));const o=k(e,n);const i=[];d(c.join(t,".mcp.json"),"mcpServers",o,t,i);s.mkdirSync(c.join(t,".cursor"),{recursive:true});d(c.join(t,".cursor","mcp.json"),"mcpServers",o,t,i);if(s.existsSync(c.join(t,".vscode"))){d(c.join(t,".vscode","mcp.json"),"servers",o,t,i)}D(r,t,i);x(c.join(t,"CLAUDE.md"),t,i);x(c.join(t,"AGENTS.md"),t,i);n("Buoy MCP configuration written:");for(const a of i)n(" \u2022 "+a);n("");n("Next steps:");n(" 1. Restart your editor (or reconnect the MCP server) to load `buoy`.");n(" 2. Complete account setup, then open an app with the required Buoy tools and sync integration.");n(" 3. Confirm the device and tools are available. Free accounts get the basic MCP tools; Pro adds the rest.");n("");n(`Want your AI to use the web too? Run \`npx -y ${l}@latest init --web\` for Buoy Web (free, no account).`);if(o.command==="npx"){n("");n(`The editor launches the server with \`npx -y ${l}@latest\`, so it stays`);n(`Registry access may be needed. Re-run \`npx -y ${l}@latest init\` to refresh configuration.`)}else if(!e.cliPath){n("");n(`This uses a pinned local install (no network on startup). To update it later,`);n(`To update the local package, run: npx -y ${o.args[0]?.replace(/dist[/\\]cli\.js$/,"")??""}@latest init --local`)}}function k(e,t){if(e.cliPath){return{type:"stdio",command:"node",args:[e.cliPath],env:g()}}const r=e.mode??"auto";if(r==="npx"){return y()}if(r==="local"){return $(e,t)}const n=I();if(n.reachable){return y()}t(`\u26A0 npm registry ${n.registry?`(${n.registry}) `:""}looks unreachable \u2014 \`npx @latest\` would hang your editor at startup. Falling back to a pinned local install.`);return $(e,t)}function y(){return{type:"stdio",command:"npx",args:["-y",`${l}@latest`],env:g()}}function $(e,t){const r=e.installDir??process.env.BUOY_MCP_HOME??c.join(E.homedir(),".buoy-mcp");const n=e.registry??w;const o=R(r,n,t);if(o){return{type:"stdio",command:"node",args:[o],env:g()}}t("\u26A0 local install failed \u2014 writing the npx entry instead (see the error above).");return y()}function R(e,t,r){const n=`${l}@${b==="0.0.0-dev"?"latest":b}`;s.mkdirSync(e,{recursive:true});const o=process.platform==="win32"?"npm.cmd":"npm";r(`Installing ${n} into ${e} from ${t} \u2026`);const i=m(o,["install",n,"--prefix",e,"--registry",t,`--@buoy-gg:registry=${t}`,"--no-audit","--no-fund","--loglevel=error"],{stdio:["ignore","ignore","inherit"],encoding:"utf8"});if(i.status!==0){r(`\u26A0 npm install exited with code ${i.status??"?"}${i.error?` (${i.error.message})`:""}.`);return null}const a=c.join(e,"node_modules",l,"dist","cli.js");if(!s.existsSync(a)){r(`\u26A0 install finished but ${a} is missing.`);return null}return a}function I(){const e=P();if(!e)return{reachable:false,registry:null};if(/^https?:\/\/registry\.npmjs\.org\/?$/i.test(e)){return{reachable:true,registry:e}}return{reachable:T(e),registry:e}}function P(){const e=S("@buoy-gg:registry");if(e)return e;const t=S("registry");return t??w}function S(e){const t=process.platform==="win32"?"npm.cmd":"npm";const r=m(t,["config","get",e],{encoding:"utf8",timeout:f});if(r.status!==0||typeof r.stdout!=="string")return null;const n=r.stdout.trim();if(!n||n==="undefined"||n==="null")return null;return n}function T(e){const t=m(process.execPath,["-e",F,e,String(f)],{encoding:"utf8",timeout:f+2e3});return t.status===0}var F=`
2
2
  const url = process.argv[1];
3
3
  const ms = Number(process.argv[2]) || 3000;
4
4
  const c = new AbortController();