rentline-sandbox 0.1.2 → 0.1.3

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
@@ -20,6 +20,32 @@ Requires Node.js ≥ 18.
20
20
 
21
21
  ---
22
22
 
23
+ ## Setup
24
+
25
+ Run once after install. Saves your credentials and automatically configures your AI client:
26
+
27
+ ```bash
28
+ sandbox setup
29
+ ```
30
+
31
+ The wizard will:
32
+ 1. Ask for your API key (get one at **sandbox.rentline.xyz/cli-auth**)
33
+ 2. Verify connectivity to the API
34
+ 3. Save credentials to `~/.rentline-sandbox/credentials.json`
35
+ 4. Detect your AI client (Claude Code, Cursor, Windsurf, OpenCode) and patch its MCP config
36
+ 5. Install `SKILL.md` so your agent understands the game
37
+
38
+ **Non-interactive:**
39
+ ```bash
40
+ sandbox setup --key sb_xxx --client opencode --yes
41
+ ```
42
+
43
+ Supported clients: `claude-code`, `claude-desktop`, `cursor`, `windsurf`, `opencode`, `zed`, `cline`
44
+
45
+ After setup, **restart your AI client** to load the MCP server.
46
+
47
+ ---
48
+
23
49
  ## Authentication
24
50
 
25
51
  ### Browser login (recommended)
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ var _require = createRequire(import.meta.url);
9
9
  var { version } = _require("../package.json");
10
10
  var args = process.argv.slice(2);
11
11
  if (args[0] === "setup" || args[0] === "--setup") {
12
- const { runSetup, parseSetupArgs } = await import("./setup-JPLRGUPW.js");
12
+ const { runSetup, parseSetupArgs } = await import("./setup-IQQBGGOI.js");
13
13
  const opts = parseSetupArgs(args.filter((a) => a !== "setup" && a !== "--setup"));
14
14
  await runSetup(opts);
15
15
  process.exit(0);
@@ -31,7 +31,7 @@ if (args.length === 0 || args[0] === "server" || args[0] === "--server") {
31
31
  registerMortgage(program);
32
32
  registerAdmin(program);
33
33
  program.command("mcp-setup", { hidden: true }).allowUnknownOption().action(async () => {
34
- const { runSetup, parseSetupArgs } = await import("./setup-JPLRGUPW.js");
34
+ const { runSetup, parseSetupArgs } = await import("./setup-IQQBGGOI.js");
35
35
  const opts = parseSetupArgs(process.argv.slice(3));
36
36
  await runSetup(opts);
37
37
  });
@@ -51,7 +51,7 @@ async function runSetup(opts) {
51
51
  }
52
52
  }
53
53
  if (!apiKey) {
54
- console.error("API key is required. Get one from your sandbox-api admin.");
54
+ console.error("API key is required. Get one at: https://sandbox.rentline.xyz/cli-auth");
55
55
  process.exit(1);
56
56
  }
57
57
  const existing = loadConfig();
@@ -121,7 +121,7 @@ async function installForClient(clientName, scope, apiKey, apiUrl, displayName)
121
121
  switch (clientName) {
122
122
  case "claude-code": {
123
123
  const { execSync } = await import("child_process");
124
- const envFlags = Object.entries(entry.env ?? {}).map(([k, v]) => `-e ${k}=${v}`).join(" ");
124
+ const envFlags = Object.entries(entry.env ?? {}).map(([k, v]) => `-e ${k}="${v}"`).join(" ");
125
125
  const cmd = `claude mcp add rentline-sandbox --scope ${scope} ${envFlags} -- npx -y rentline-sandbox`;
126
126
  try {
127
127
  execSync(cmd, { stdio: "pipe" });
@@ -146,7 +146,14 @@ async function installForClient(clientName, scope, apiKey, apiUrl, displayName)
146
146
  break;
147
147
  }
148
148
  case "claude-desktop": {
149
- const file = platform() === "win32" ? join(process.env.APPDATA ?? homedir(), "Claude", "claude_desktop_config.json") : join(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
149
+ let file;
150
+ if (platform() === "win32") {
151
+ file = join(process.env.APPDATA ?? homedir(), "Claude", "claude_desktop_config.json");
152
+ } else if (platform() === "darwin") {
153
+ file = join(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
154
+ } else {
155
+ file = join(homedir(), ".config", "Claude", "claude_desktop_config.json");
156
+ }
150
157
  patchMcpJson(file, "rentline-sandbox", entry, "mcpServers");
151
158
  console.log(`Patched ${file}`);
152
159
  break;
@@ -158,14 +165,23 @@ async function installForClient(clientName, scope, apiKey, apiUrl, displayName)
158
165
  break;
159
166
  }
160
167
  case "windsurf": {
161
- const file = join(process.cwd(), ".windsurf", "mcp.json");
168
+ const file = platform() === "win32" ? join(process.env.APPDATA ?? homedir(), ".codeium", "windsurf", "mcp_config.json") : join(homedir(), ".codeium", "windsurf", "mcp_config.json");
162
169
  patchMcpJson(file, "rentline-sandbox", entry, "mcpServers");
163
170
  console.log(`Patched ${file}`);
164
171
  break;
165
172
  }
166
173
  case "opencode": {
167
174
  const file = scope === "project" ? join(process.cwd(), "opencode.json") : join(homedir(), ".config", "opencode", "config.json");
168
- patchMcpJson(file, "rentline-sandbox", entry, "mcp");
175
+ const opencodeEntry = {
176
+ type: "local",
177
+ command: ["npx", "-y", "rentline-sandbox"],
178
+ enabled: true,
179
+ environment: {
180
+ SANDBOX_API_KEY: apiKey,
181
+ SANDBOX_API_URL: apiUrl
182
+ }
183
+ };
184
+ patchMcpJson(file, "rentline-sandbox", opencodeEntry, "mcp");
169
185
  console.log(`Patched ${file}`);
170
186
  const skillSrc = join(__dirname, "../SKILL.md");
171
187
  if (existsSync(skillSrc)) {
@@ -188,9 +204,10 @@ async function installForClient(clientName, scope, apiKey, apiUrl, displayName)
188
204
  case "other":
189
205
  default: {
190
206
  console.log(`
191
- Add the following to your MCP client config:
207
+ Add the following to your MCP client config (exact key name may vary by client):
192
208
  `);
193
209
  console.log(JSON.stringify({ "rentline-sandbox": entry }, null, 2));
210
+ console.log("\nFor OpenCode specifically, use: sandbox setup --client opencode");
194
211
  break;
195
212
  }
196
213
  }
@@ -204,6 +221,9 @@ function patchMcpJson(filePath, serverName, entry, key) {
204
221
  } catch {
205
222
  }
206
223
  }
224
+ if (key === "mcp" && !config["$schema"]) {
225
+ config["$schema"] = "https://opencode.ai/config.json";
226
+ }
207
227
  const servers = config[key] ?? {};
208
228
  servers[serverName] = entry;
209
229
  config[key] = servers;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rentline-sandbox",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "CLI and MCP server for the Rentline Sandbox real estate investment simulation game",
5
5
  "type": "module",
6
6
  "bin": {