@boole-digital/cli 0.1.0 → 0.1.1

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 (2) hide show
  1. package/dist/index.js +104 -78
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -372,6 +372,22 @@ function onboardingNotice() {
372
372
  log(` Deploy your first trading computer there, then come back and run ${c.cyan("boole connect")}.`);
373
373
  log("");
374
374
  }
375
+ function operatingBrief() {
376
+ log("");
377
+ log(c.bold("How to operate this computer"));
378
+ log(" Trades and strategies go through the gateway gate \u2014 automatically tracked on your dashboard.");
379
+ log("");
380
+ log(` ${c.dim("# buy $100 of BTC (market)")}`);
381
+ log(c.cyan(" boole strategy spawn --template order_template.js --name btc-buy \\"));
382
+ log(c.cyan(" --param EXCHANGE=hyperliquid --param MARKET=BTC --param SIDE=buy \\"));
383
+ log(c.cyan(" --param ORDER_TYPE=market --param TOTAL_USD=100 --param LIMIT_PRICE=0"));
384
+ log("");
385
+ log(` Sell with ${c.dim("SIDE=sell")}. Other templates: ${c.dim("grid, twap, scale, stop, loop")}.`);
386
+ log(` Inspect: ${c.cyan("boole balances")} \xB7 ${c.cyan("boole strategy ls")} \xB7 ${c.cyan("boole logs <name>")} \xB7 ${c.cyan('boole ssh "<read cmd>"')}`);
387
+ log(` ${c.yellow("Never")} write files or run pm2 by hand \u2014 always use the gate (that is what keeps tracking correct).`);
388
+ log(` Drop the full rules into your coding agent: ${c.cyan("boole init")} ${c.dim("\u2192 CLAUDE.md / AGENTS.md / GEMINI.md")}`);
389
+ log("");
390
+ }
375
391
  function printAgents(droplets) {
376
392
  if (!droplets.length) {
377
393
  onboardingNotice();
@@ -414,13 +430,27 @@ async function summary() {
414
430
  ok(`Logged in as ${c.bold(creds.user.email || creds.user.id)}${creds.user.role ? c.dim(` \xB7 ${creds.user.role}`) : ""}`);
415
431
  const api = new BooleApi();
416
432
  let droplets = [];
433
+ let listErr = "";
417
434
  try {
418
435
  droplets = await api.listDroplets();
419
436
  } catch (e) {
420
- warn(`Could not list trading computers: ${e.message}`);
421
- return;
437
+ listErr = e?.message || String(e);
422
438
  }
423
439
  if (!droplets.length) {
440
+ const sess = loadSession();
441
+ if (sess?.ip) {
442
+ log("");
443
+ ok(`Connected to ${c.bold(sess.agent || sess.ip)} ${c.dim(`(${sess.ip})`)} ${c.dim("\xB7 cached session")}`);
444
+ if (listErr) log(c.dim(` (couldn't reach the account API: ${listErr})`));
445
+ else log(c.dim(` This account has no computer on file, but \`boole ssh\` + \`boole strategy \u2026\` work against the connected box.`));
446
+ log(c.dim(` If you expected a computer here, you may be logged in as a different account than the one that owns it.`));
447
+ operatingBrief();
448
+ return;
449
+ }
450
+ if (listErr) {
451
+ warn(`Could not list trading computers: ${listErr}`);
452
+ return;
453
+ }
424
454
  onboardingNotice();
425
455
  return;
426
456
  }
@@ -428,17 +458,18 @@ async function summary() {
428
458
  log(c.bold(`Trading computers (${droplets.length})`));
429
459
  printAgents(droplets);
430
460
  const pick = pickAgentId(droplets);
431
- if (!pick) return;
432
- log("");
433
- log(c.bold(`Snapshot \u2014 ${pick.name}`));
434
- try {
435
- const health = await api.getHealth(pick.id);
436
- ok(`online${health.defaultModel ? c.dim(` \xB7 model ${health.defaultModel}`) : ""}`);
437
- } catch {
438
- warn("trading computer unreachable (tunnel may be waking up \u2014 retry in a moment)");
439
- return;
461
+ if (pick) {
462
+ log("");
463
+ log(c.bold(`Snapshot \u2014 ${pick.name}`));
464
+ try {
465
+ const health = await api.getHealth(pick.id);
466
+ ok(`online${health.defaultModel ? c.dim(` \xB7 model ${health.defaultModel}`) : ""}`);
467
+ await printBalances(api, pick.id, "hyperliquid");
468
+ } catch {
469
+ warn("trading computer unreachable (tunnel may be waking up \u2014 retry in a moment)");
470
+ }
440
471
  }
441
- await printBalances(api, pick.id, "hyperliquid");
472
+ operatingBrief();
442
473
  }
443
474
  async function printBalances(api, id, exchange) {
444
475
  try {
@@ -718,80 +749,75 @@ async function strategyDoctor(name) {
718
749
  // src/rules.ts
719
750
  import { writeFileSync as writeFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "node:fs";
720
751
  import { join as join2, resolve } from "node:path";
721
- var OPERATING_RULES = `# Boole Trading Computer \u2014 Operating Rules (READ FIRST, IN FULL)
722
-
723
- You operate a customer's **live** crypto trading computer through the \`boole\` CLI.
724
- **Real money is at risk.** These are STRICT, NON-NEGOTIABLE rules.
725
-
726
- > Why they matter: Boole tracks and controls every strategy by HOW it was created.
727
- > If you create one any other way \u2014 writing files over SSH, starting processes
728
- > yourself \u2014 it **silently fails**: it won't register, won't appear on the
729
- > dashboard, can't be controlled, and may mismanage live positions. There is no
730
- > error message. When in doubt, STOP and ask the user.
731
-
732
- ## Boot sequence \u2014 every session, before anything else
733
- 1. \`boole status\` \u2014 confirm you are logged in and a trading computer is connected.
734
- If not, STOP and tell the user to run \`boole login\` then \`boole connect\`.
735
- 2. Read this entire file.
736
- 3. \`boole strategy ls\` \u2014 see what is already running.
737
-
738
- ## The one rule: THINK locally, COMMIT through \`boole\`
739
- - THINK \u2014 research, analyze data, design, draft code \u2014 freely on this machine. No limits.
740
- - COMMIT \u2014 anything that changes the trading computer \u2014 ONLY through \`boole\` commands.
741
-
742
- ## Creating / running a strategy \u2014 the ONLY sanctioned path
743
- Spawn from a known-good template through the gateway gate:
744
-
745
- boole strategy spawn --template <template.js> --name <name> \\
746
- --param KEY=VALUE --param KEY=VALUE ...
747
-
748
- - This registers the run and starts it tracked, so it appears on the dashboard.
749
- - \`--name\`: lowercase letters, digits, "-" or "_" (e.g. btc-grid).
750
- - \`--param\`: pass raw values (EXCHANGE=hyperliquid, TOTAL_USD=50). The CLI quotes them.
751
- - Verify: \`boole strategy doctor <name>\` \u2192 should report online and tracked.
752
-
753
- ### Templates (required params)
752
+ var OPERATING_RULES = `# Boole Trading Computer \u2014 Operating Rules (READ FIRST)
753
+
754
+ You operate the customer's **live** crypto trading computer by working ON the box
755
+ (over \`boole ssh\`) and using its on-box **harness** \u2014 the gateway's spawn GATE,
756
+ which places and TRACKS every order and strategy on the dashboard. Real money is
757
+ at risk, so be deliberate \u2014 but the user asked you to operate their computer, so
758
+ OPERATE IT. Place the trades they ask for; don't refuse or interrogate over
759
+ routine orders.
760
+
761
+ ## What "the harness" is (and why you go through it)
762
+ The box runs a gateway that exposes a spawn GATE. You place trades and run
763
+ strategies by spawning a known-good TEMPLATE through that gate \u2014 NEVER by writing
764
+ files or starting processes yourself. The gate registers the run, wires up
765
+ tracking, sets STRATEGY_NAME/RUN_ID, and starts it, so it always shows on the
766
+ dashboard with accounting. \`boole strategy spawn\` is simply how you call that
767
+ gate over SSH. Going around it (hand-writing a file, raw \`pm2 start\`) makes the
768
+ order **silently** untracked \u2014 that is the one thing you must never do.
769
+
770
+ ## Boot (every session)
771
+ 1. \`boole status\` \u2014 see who you're logged in as.
772
+ 2. \`boole ssh "whoami"\` \u2014 if it connects, you HAVE a usable box; proceed. A
773
+ connected session is enough. Do NOT refuse to work just because \`status\`
774
+ doesn't list a computer for this account \u2014 that only means the web API has
775
+ none on file, not that you can't operate the connected box. If \`boole ssh\`
776
+ fails, tell the user to run \`boole connect\`.
777
+
778
+ ## Placing a trade \u2014 just do it
779
+ "buy/sell $X of <coin>" is one market order. Place it through the gate with
780
+ order_template. Do NOT quiz the user about venue/leverage for a routine order \u2014
781
+ use the defaults and report the fill:
782
+
783
+ boole strategy spawn --template order_template.js --name <coin>-buy \\
784
+ --param EXCHANGE=hyperliquid --param MARKET=<COIN> --param SIDE=buy \\
785
+ --param ORDER_TYPE=market --param TOTAL_USD=<X> --param LIMIT_PRICE=0
786
+
787
+ Defaults when unspecified: EXCHANGE=hyperliquid, ORDER_TYPE=market, LIMIT_PRICE=0,
788
+ no leverage. Sell with SIDE=sell. Limit order: ORDER_TYPE=limit + LIMIT_PRICE=<p>.
789
+ Pick a unique --name (if the gate says it exists, add a suffix). After it returns,
790
+ tell the user what filled. Ask FIRST only if genuinely ambiguous (which coin? which
791
+ account has funds?) or clearly risky (size far beyond their balance, leverage they
792
+ didn't request) \u2014 a plain market buy the user requested is NOT one of those.
793
+
794
+ ## Running a strategy \u2014 same gate, different template
795
+ boole strategy spawn --template <template.js> --name <name> --param KEY=VALUE ...
796
+
797
+ Templates (required params):
754
798
  - order_template.js \u2014 single order: EXCHANGE, MARKET, SIDE(buy|sell), ORDER_TYPE(market|limit), TOTAL_USD, LIMIT_PRICE(0 for market)
755
799
  - grid_template.js \u2014 grid: EXCHANGE, SYMBOL, LEVELS_PER_SIDE, ORDER_SIZE_USD, LEVERAGE, MAX_EXPOSURE_USD
756
800
  - twap_template.js \u2014 TWAP: EXCHANGE, MARKET, SIDE, TOTAL_USD, DURATION_MIN, SLICES
757
801
  - scale_template.js \u2014 ladder: EXCHANGE, MARKET, SIDE, TOTAL_USD, PRICE_LOW, PRICE_HIGH, LEVELS
758
802
  - stop_template.js \u2014 conditional (no position yet): EXCHANGE, MARKET, SIDE, STOP_KIND(stop_market|stop_limit|tp_market|tp_limit), TOTAL_USD, TRIGGER_PRICE, LIMIT_PRICE(0 for *_market)
759
- - loop_template.js \u2014 generic poll loop / price watcher: EXCHANGE, MARKET, POLL_SEC
760
-
761
- Example:
762
-
763
- boole strategy spawn --template loop_template.js --name btc-watch \\
764
- --param EXCHANGE=hyperliquid --param MARKET=BTC --param POLL_SEC=10
803
+ - loop_template.js \u2014 poll loop / price watcher: EXCHANGE, MARKET, POLL_SEC
765
804
 
766
- If you omit a required param, the gate returns an error naming it \u2014 fix and retry.
767
- If the gate says a template is not found, it is not installed on this box \u2014 pick
768
- another from the list or ask the user.
769
- Only use a template above. Do NOT hand-roll custom strategy files. If you need
770
- something no template covers, STOP and ask the user.
805
+ If the gate names a missing param, add it and retry. If it says a template is not
806
+ found, that one isn't installed on this box \u2014 pick another or ask.
771
807
 
772
- ## Allowed \u2014 read-only inspection
808
+ ## Inspect (read-only) anytime
773
809
  - \`boole status\` / \`boole balances [--venue <v>]\` \u2014 identity, equity, positions
774
- - \`boole strategy ls\` \u2014 running strategies
775
- - \`boole strategy doctor <name>\` \u2014 health + tracking check
810
+ - \`boole strategy ls\` / \`boole strategy doctor <name>\` \u2014 running strategies + tracking
776
811
  - \`boole logs <name>\` \u2014 tail a strategy's logs
777
- - \`boole ssh "<read-only command>"\` \u2014 inspect only (cat, ls, pm2 list, curl localhost:3000/health)
778
-
779
- ## Forbidden
780
- - Do NOT write strategy or interface files over SSH.
781
- - Do NOT \`pm2 start/restart/stop/delete\` by hand.
782
- - Do NOT edit gateway files directly.
783
- - \`boole ssh\` is for READ-ONLY inspection. To change the box, use a \`boole\` verb.
784
- - If there is no verb for a change you need, STOP and ask. A missing verb is not permission to freelance.
785
-
786
- ## Safety (real money)
787
- - Trading is live. Prefer capital preservation. Confirm exchange state before acting.
788
- - Never print or exfiltrate .env, API keys, or credentials.
789
- - Never restart the gateway.
790
- - Ask the user before destructive actions (closing positions, stopping strategies).
791
-
792
- ## Notes
793
- - Some gateway internals are intentionally not readable from your account \u2014 by design. Use the \`boole\` verbs; you don't need them.
794
- - A commit is not done until \`boole strategy doctor\` confirms it. If it did not register, fix it before moving on.
812
+ - \`boole ssh "<read-only cmd>"\` \u2014 cat / ls / pm2 list / curl localhost:3000/health
813
+
814
+ ## The hard lines (protect real money + tracking)
815
+ - Place trades + strategies ONLY through the gate (\`boole strategy spawn\`). NEVER
816
+ write strategy files over SSH or \`pm2 start\` by hand \u2014 that bypasses tracking and
817
+ the order won't appear on the dashboard.
818
+ - Never print or exfiltrate .env, keys, or credentials. Never restart the gateway.
819
+ - Ask before genuinely destructive actions (closing positions, stopping a running
820
+ strategy). A plain market buy the user asked for is NOT destructive \u2014 place it.
795
821
  `;
796
822
  var FILES = ["CLAUDE.md", "AGENTS.md", "GEMINI.md"];
797
823
  function init(opts = {}) {
@@ -818,7 +844,7 @@ function init(opts = {}) {
818
844
  }
819
845
 
820
846
  // src/index.ts
821
- var VERSION = "0.1.0";
847
+ var VERSION = "0.1.1";
822
848
  function parse(argv) {
823
849
  const _ = [];
824
850
  const flags = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boole-digital/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Boole — install, sign in, and operate your trading computer from the terminal (Claude Code, Codex, Gemini).",
5
5
  "type": "module",
6
6
  "bin": { "boole": "dist/index.js" },
@@ -8,7 +8,7 @@
8
8
  "files": ["dist/index.js", "README.md", "LICENSE"],
9
9
  "license": "SEE LICENSE IN LICENSE",
10
10
  "engines": { "node": ">=18" },
11
- "repository": { "type": "git", "url": "github:Boole-Digital/portara-desktop" },
11
+ "repository": { "type": "git", "url": "git+https://github.com/Boole-Digital/portara-desktop.git" },
12
12
  "homepage": "https://trade.boole.markets",
13
13
  "publishConfig": { "access": "public" },
14
14
  "keywords": ["boole", "trading", "cli", "claude-code", "codex", "gemini"],