trymeanwhile 1.1.0 → 1.2.0

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/bin/meanwhile.js +50 -0
  2. package/package.json +1 -1
package/bin/meanwhile.js CHANGED
@@ -69,7 +69,57 @@ function wireSettings(settingsPath, python, scriptPath) {
69
69
  log(`wired into ${settingsPath}`);
70
70
  }
71
71
 
72
+ // Wraps any long-running shell command (npm install, docker build, terraform
73
+ // apply, ...) and shows the same disclosed line the Claude Code/Copilot
74
+ // status lines show -- reusing the exact same /line endpoint and billing
75
+ // mechanism, just from a different trigger than an editor hook. The server
76
+ // only bills a line if it stayed on screen >= BILLABLE_THRESHOLD (10s), so
77
+ // this polls every 15s -- fast enough to feel alive, slow enough that real
78
+ // polls actually bill instead of always resetting the timer on each other.
79
+ async function wrapCommand(args) {
80
+ const cmdArgs = args[0] === "--" ? args.slice(1) : args;
81
+ if (cmdArgs.length === 0) {
82
+ log("usage: npx trymeanwhile wrap -- <command> [args...]");
83
+ log("example: npx trymeanwhile wrap -- npm install");
84
+ process.exit(1);
85
+ }
86
+
87
+ fs.mkdirSync(STATE_DIR, { recursive: true });
88
+ const idPath = path.join(STATE_DIR, "install_id");
89
+ if (!fs.existsSync(idPath)) {
90
+ fs.writeFileSync(idPath, crypto.randomUUID(), { mode: 0o600 });
91
+ }
92
+ const installId = fs.readFileSync(idPath, "utf8").trim();
93
+
94
+ const { spawn } = require("child_process");
95
+ const child = spawn(cmdArgs[0], cmdArgs.slice(1), { stdio: "inherit", shell: process.platform === "win32" });
96
+
97
+ let stopped = false;
98
+ (async function pollLoop() {
99
+ while (!stopped) {
100
+ try {
101
+ const res = await fetch(`${SERVER}/line?id=${installId}&event=cli_wrap`);
102
+ if (res.ok) {
103
+ const data = await res.json();
104
+ process.stderr.write(`\nmeanwhile: ${data.line}\n`);
105
+ }
106
+ } catch (e) {}
107
+ await new Promise((r) => setTimeout(r, 15000));
108
+ }
109
+ })();
110
+
111
+ child.on("exit", (code) => {
112
+ stopped = true;
113
+ process.exit(code === null ? 1 : code);
114
+ });
115
+ }
116
+
72
117
  async function main() {
118
+ if (process.argv[2] === "wrap") {
119
+ await wrapCommand(process.argv.slice(3));
120
+ return;
121
+ }
122
+
73
123
  log(`installing to ${INSTALL_DIR}`);
74
124
  fs.mkdirSync(INSTALL_DIR, { recursive: true });
75
125
  fs.mkdirSync(STATE_DIR, { recursive: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trymeanwhile",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Get paid while your AI coding agent thinks. Wires a disclosed status line into Claude Code / Copilot CLI.",
5
5
  "bin": {
6
6
  "meanwhile": "bin/meanwhile.js"