happy-coder 0.3.1-beta.1 → 0.4.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 (49) hide show
  1. package/dist/index.cjs +76 -27
  2. package/dist/index.mjs +76 -27
  3. package/dist/lib.cjs +1 -1
  4. package/dist/lib.d.cts +1 -0
  5. package/dist/lib.d.mts +1 -0
  6. package/dist/lib.mjs +1 -1
  7. package/dist/{types-CzYKFAYa.mjs → types-VkaGP8up.mjs} +1 -1
  8. package/dist/{types-D7u2DxfV.cjs → types-eN-YHsuj.cjs} +1 -0
  9. package/package.json +8 -6
  10. package/dist/index-B2GqfEZV.cjs +0 -1564
  11. package/dist/index-QItBXhux.mjs +0 -1540
  12. package/dist/install-B0DnBGS_.mjs +0 -29
  13. package/dist/install-B2r_gX72.cjs +0 -109
  14. package/dist/install-C809w0Cj.cjs +0 -31
  15. package/dist/install-DEPy62QN.mjs +0 -97
  16. package/dist/install-GZIzyuIE.cjs +0 -99
  17. package/dist/install-HKe7dyS4.mjs +0 -107
  18. package/dist/run-BmEaINbl.cjs +0 -250
  19. package/dist/run-DMbKhYfb.mjs +0 -247
  20. package/dist/run-FBXkmmN7.mjs +0 -32
  21. package/dist/run-q2To6b-c.cjs +0 -34
  22. package/dist/types-BG9AgCI4.mjs +0 -875
  23. package/dist/types-BRICSarm.mjs +0 -870
  24. package/dist/types-BTQRfIr3.cjs +0 -892
  25. package/dist/types-BX4xv8Ty.mjs +0 -881
  26. package/dist/types-BeUppqJU.cjs +0 -886
  27. package/dist/types-C6Wx_bRW.cjs +0 -886
  28. package/dist/types-CEvzGLMI.cjs +0 -882
  29. package/dist/types-CKUdOV6c.mjs +0 -875
  30. package/dist/types-CNuBtNA5.cjs +0 -884
  31. package/dist/types-Cg4664gs.cjs +0 -879
  32. package/dist/types-CkPUFpfr.cjs +0 -885
  33. package/dist/types-D39L8JSd.mjs +0 -850
  34. package/dist/types-DD9P_5rj.mjs +0 -868
  35. package/dist/types-DNu8okOb.mjs +0 -874
  36. package/dist/types-DXK5YldG.cjs +0 -892
  37. package/dist/types-DYBiuNUQ.cjs +0 -883
  38. package/dist/types-Df5dlWLV.mjs +0 -871
  39. package/dist/types-fXgEaaqP.mjs +0 -861
  40. package/dist/types-hotUTaWz.cjs +0 -863
  41. package/dist/types-ikrrEcJm.mjs +0 -873
  42. package/dist/types-mykDX2xe.cjs +0 -872
  43. package/dist/types-tLWMaptR.mjs +0 -879
  44. package/dist/uninstall-BGgl5V8F.mjs +0 -29
  45. package/dist/uninstall-BWHglipH.mjs +0 -40
  46. package/dist/uninstall-C42CoSCI.cjs +0 -53
  47. package/dist/uninstall-CLkTtlMv.mjs +0 -51
  48. package/dist/uninstall-CdHMb6wi.cjs +0 -31
  49. package/dist/uninstall-FXyyAuGU.cjs +0 -42
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var chalk = require('chalk');
4
- var types$1 = require('./types-DXK5YldG.cjs');
4
+ var types$1 = require('./types-eN-YHsuj.cjs');
5
5
  var node_crypto = require('node:crypto');
6
6
  var node_child_process = require('node:child_process');
7
7
  var node_path = require('node:path');
@@ -2248,7 +2248,7 @@ async function loop(opts) {
2248
2248
  }
2249
2249
 
2250
2250
  var name = "happy-coder";
2251
- var version = "0.3.1-beta.1";
2251
+ var version = "0.4.0";
2252
2252
  var description = "Claude Code session sharing CLI";
2253
2253
  var author = "Kirill Dubovitskiy";
2254
2254
  var license = "MIT";
@@ -2294,15 +2294,16 @@ var files = [
2294
2294
  var scripts = {
2295
2295
  test: "vitest run",
2296
2296
  "test:watch": "vitest",
2297
- build: "tsc --noEmit && pkgroll",
2297
+ build: "shx rm -rf dist && tsc --noEmit && pkgroll",
2298
2298
  prepublishOnly: "yarn build && yarn test",
2299
2299
  typecheck: "tsc --noEmit",
2300
- dev: "npx tsx --env-file .env.sample src/index.ts",
2301
- "dev:local-server": "HANDY_SERVER_URL=http://localhost:3005 npx tsx --env-file .env.sample src/index.ts",
2302
- prerelease: "npm version prerelease --preid=beta"
2300
+ dev: "yarn build && npx tsx --env-file .env.sample src/index.ts",
2301
+ "dev:local-server": "yarn build && cross-env HANDY_SERVER_URL=http://localhost:3005 tsx --env-file .env.sample src/index.ts",
2302
+ "version:prerelease": "npm version prerelease --preid=beta",
2303
+ "publish:prerelease": "npm publish --tag beta"
2303
2304
  };
2304
2305
  var dependencies = {
2305
- "@anthropic-ai/claude-code": "^1.0.72",
2306
+ "@anthropic-ai/claude-code": "^1.0.73",
2306
2307
  "@anthropic-ai/sdk": "^0.56.0",
2307
2308
  "@modelcontextprotocol/sdk": "^1.15.1",
2308
2309
  "@stablelib/base64": "^2.0.1",
@@ -2325,6 +2326,7 @@ var dependencies = {
2325
2326
  var devDependencies = {
2326
2327
  "@eslint/compat": "^1",
2327
2328
  "@types/node": ">=18",
2329
+ "cross-env": "^10.0.0",
2328
2330
  eslint: "^9",
2329
2331
  "eslint-config-prettier": "^10",
2330
2332
  pkgroll: "^2.14.2",
@@ -2960,7 +2962,8 @@ async function start(credentials, options = {}) {
2960
2962
  host: os.hostname(),
2961
2963
  version: packageJson.version,
2962
2964
  os: os.platform(),
2963
- machineId: settings.machineId
2965
+ machineId: settings.machineId,
2966
+ homeDir: os.homedir()
2964
2967
  };
2965
2968
  const response = await api.getOrCreateSession({ tag: sessionTag, metadata, state });
2966
2969
  types$1.logger.debug(`Session created: ${response.id}`);
@@ -3114,6 +3117,7 @@ class ApiDaemonSession extends node_events.EventEmitter {
3114
3117
  token;
3115
3118
  secret;
3116
3119
  spawnedProcesses = /* @__PURE__ */ new Set();
3120
+ machineRegistered = false;
3117
3121
  constructor(token, secret, machineIdentity) {
3118
3122
  super();
3119
3123
  this.token = token;
@@ -3135,9 +3139,12 @@ class ApiDaemonSession extends node_events.EventEmitter {
3135
3139
  withCredentials: true,
3136
3140
  autoConnect: false
3137
3141
  });
3138
- socket.on("connect", () => {
3142
+ socket.on("connect", async () => {
3139
3143
  types$1.logger.debug("[DAEMON SESSION] Socket connected");
3140
3144
  types$1.logger.debug(`[DAEMON SESSION] Connected with auth - token: ${this.token.substring(0, 10)}..., machineId: ${this.machineIdentity.machineId}`);
3145
+ if (!this.machineRegistered) {
3146
+ await this.registerMachine();
3147
+ }
3141
3148
  const rpcMethod = `${this.machineIdentity.machineId}:spawn-happy-session`;
3142
3149
  socket.emit("rpc-register", { method: rpcMethod });
3143
3150
  types$1.logger.debug(`[DAEMON SESSION] Emitted RPC registration: ${rpcMethod}`);
@@ -3164,16 +3171,11 @@ class ApiDaemonSession extends node_events.EventEmitter {
3164
3171
  args.push("--local");
3165
3172
  }
3166
3173
  types$1.logger.debug(`[DAEMON SESSION] Spawning happy in directory: ${directory} with args: ${args.join(" ")}`);
3167
- const happyPath = process.argv[1];
3168
- const runningFromBuiltBinary = happyPath.endsWith("happy") || happyPath.endsWith("happy.cmd");
3169
- let executable, spawnArgs;
3170
- if (runningFromBuiltBinary) {
3171
- executable = happyPath;
3172
- spawnArgs = args;
3173
- } else {
3174
- executable = "npx";
3175
- spawnArgs = ["tsx", happyPath, ...args];
3176
- }
3174
+ const happyBinPath = path.join(projectPath(), "bin", "happy.mjs");
3175
+ types$1.logger.debug(`[DAEMON SESSION] Using happy binary at: ${happyBinPath}`);
3176
+ const executable = happyBinPath;
3177
+ const spawnArgs = args;
3178
+ types$1.logger.debug(`[DAEMON SESSION] Spawn: executable=${executable}, args=${JSON.stringify(spawnArgs)}, cwd=${directory}`);
3177
3179
  const happyProcess = child_process.spawn(executable, spawnArgs, {
3178
3180
  cwd: directory,
3179
3181
  detached: true,
@@ -3266,7 +3268,7 @@ class ApiDaemonSession extends node_events.EventEmitter {
3266
3268
  types$1.logger.debug(`[DAEMON SESSION] RPC error: ${JSON.stringify(data)}`);
3267
3269
  });
3268
3270
  socket.onAny((event, ...args) => {
3269
- if (!event.startsWith("machine-alive")) {
3271
+ if (!event.startsWith("session-alive") && event !== "ephemeral") {
3270
3272
  types$1.logger.debug(`[DAEMON SESSION] Socket event: ${event}, args: ${JSON.stringify(args)}`);
3271
3273
  }
3272
3274
  });
@@ -3289,12 +3291,47 @@ class ApiDaemonSession extends node_events.EventEmitter {
3289
3291
  });
3290
3292
  this.socket = socket;
3291
3293
  }
3294
+ async registerMachine() {
3295
+ try {
3296
+ const metadata = {
3297
+ host: this.machineIdentity.machineHost,
3298
+ platform: this.machineIdentity.platform,
3299
+ happyCliVersion: this.machineIdentity.happyCliVersion,
3300
+ happyHomeDirectory: this.machineIdentity.happyHomeDirectory
3301
+ };
3302
+ const encrypted = types$1.encrypt(JSON.stringify(metadata), this.secret);
3303
+ const encryptedMetadata = types$1.encodeBase64(encrypted);
3304
+ const response = await fetch(`${types$1.configuration.serverUrl}/v1/machines`, {
3305
+ method: "POST",
3306
+ headers: {
3307
+ "Authorization": `Bearer ${this.token}`,
3308
+ "Content-Type": "application/json"
3309
+ },
3310
+ body: JSON.stringify({
3311
+ id: this.machineIdentity.machineId,
3312
+ metadata: encryptedMetadata
3313
+ })
3314
+ });
3315
+ if (response.ok) {
3316
+ types$1.logger.debug("[DAEMON SESSION] Machine registered/updated successfully");
3317
+ this.machineRegistered = true;
3318
+ } else {
3319
+ types$1.logger.debug(`[DAEMON SESSION] Failed to register machine: ${response.status}`);
3320
+ }
3321
+ } catch (error) {
3322
+ types$1.logger.debug("[DAEMON SESSION] Failed to register machine:", error);
3323
+ }
3324
+ }
3292
3325
  startKeepAlive() {
3293
3326
  this.stopKeepAlive();
3294
3327
  this.keepAliveInterval = setInterval(() => {
3295
- this.socket.volatile.emit("machine-alive", {
3328
+ const payload = {
3329
+ type: "machine-scoped",
3330
+ machineId: this.machineIdentity.machineId,
3296
3331
  time: Date.now()
3297
- });
3332
+ };
3333
+ types$1.logger.debugLargeJson(`[DAEMON SESSION] Emitting session-alive`, payload);
3334
+ this.socket.emit("session-alive", payload);
3298
3335
  }, 2e4);
3299
3336
  }
3300
3337
  stopKeepAlive() {
@@ -3319,15 +3356,26 @@ class ApiDaemonSession extends node_events.EventEmitter {
3319
3356
  connect() {
3320
3357
  this.socket.connect();
3321
3358
  }
3359
+ updateMetadata(updates) {
3360
+ const metadata = {
3361
+ host: this.machineIdentity.machineHost,
3362
+ platform: this.machineIdentity.platform,
3363
+ happyCliVersion: updates.happyCliVersion || this.machineIdentity.happyCliVersion,
3364
+ happyHomeDirectory: updates.happyHomeDirectory || this.machineIdentity.happyHomeDirectory
3365
+ };
3366
+ const encrypted = types$1.encrypt(JSON.stringify(metadata), this.secret);
3367
+ const encryptedMetadata = types$1.encodeBase64(encrypted);
3368
+ this.socket.emit("update-machine-metadata", { metadata: encryptedMetadata });
3369
+ }
3322
3370
  shutdown() {
3323
3371
  types$1.logger.debug(`[DAEMON SESSION] Shutting down daemon, killing ${this.spawnedProcesses.size} spawned processes`);
3324
- for (const process2 of this.spawnedProcesses) {
3372
+ for (const process of this.spawnedProcesses) {
3325
3373
  try {
3326
- types$1.logger.debug(`[DAEMON SESSION] Killing spawned process with PID: ${process2.pid}`);
3327
- process2.kill("SIGTERM");
3374
+ types$1.logger.debug(`[DAEMON SESSION] Killing spawned process with PID: ${process.pid}`);
3375
+ process.kill("SIGTERM");
3328
3376
  setTimeout(() => {
3329
3377
  try {
3330
- process2.kill("SIGKILL");
3378
+ process.kill("SIGKILL");
3331
3379
  } catch (e) {
3332
3380
  }
3333
3381
  }, 1e3);
@@ -3403,7 +3451,8 @@ async function startDaemon() {
3403
3451
  machineId: settings.machineId,
3404
3452
  machineHost: settings.machineHost || os$1.hostname(),
3405
3453
  platform: process.platform,
3406
- version: packageJson.version
3454
+ happyCliVersion: packageJson.version,
3455
+ happyHomeDirectory: process.cwd()
3407
3456
  };
3408
3457
  let credentials = await readCredentials();
3409
3458
  if (!credentials) {
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { l as logger, d as backoff, e as delay, R as RawJSONLinesSchema, c as configuration, f as encodeBase64, A as ApiClient, g as encodeBase64Url, h as decodeBase64, b as initializeConfiguration, i as initLoggerWithGlobalConfiguration } from './types-BX4xv8Ty.mjs';
2
+ import { l as logger, d as backoff, e as delay, R as RawJSONLinesSchema, c as configuration, f as encodeBase64, A as ApiClient, g as encodeBase64Url, h as decodeBase64, j as encrypt, b as initializeConfiguration, i as initLoggerWithGlobalConfiguration } from './types-VkaGP8up.mjs';
3
3
  import { randomUUID, randomBytes } from 'node:crypto';
4
4
  import { spawn, execSync } from 'node:child_process';
5
5
  import { resolve, join, dirname as dirname$1 } from 'node:path';
@@ -2227,7 +2227,7 @@ async function loop(opts) {
2227
2227
  }
2228
2228
 
2229
2229
  var name = "happy-coder";
2230
- var version = "0.3.1-beta.1";
2230
+ var version = "0.4.0";
2231
2231
  var description = "Claude Code session sharing CLI";
2232
2232
  var author = "Kirill Dubovitskiy";
2233
2233
  var license = "MIT";
@@ -2273,15 +2273,16 @@ var files = [
2273
2273
  var scripts = {
2274
2274
  test: "vitest run",
2275
2275
  "test:watch": "vitest",
2276
- build: "tsc --noEmit && pkgroll",
2276
+ build: "shx rm -rf dist && tsc --noEmit && pkgroll",
2277
2277
  prepublishOnly: "yarn build && yarn test",
2278
2278
  typecheck: "tsc --noEmit",
2279
- dev: "npx tsx --env-file .env.sample src/index.ts",
2280
- "dev:local-server": "HANDY_SERVER_URL=http://localhost:3005 npx tsx --env-file .env.sample src/index.ts",
2281
- prerelease: "npm version prerelease --preid=beta"
2279
+ dev: "yarn build && npx tsx --env-file .env.sample src/index.ts",
2280
+ "dev:local-server": "yarn build && cross-env HANDY_SERVER_URL=http://localhost:3005 tsx --env-file .env.sample src/index.ts",
2281
+ "version:prerelease": "npm version prerelease --preid=beta",
2282
+ "publish:prerelease": "npm publish --tag beta"
2282
2283
  };
2283
2284
  var dependencies = {
2284
- "@anthropic-ai/claude-code": "^1.0.72",
2285
+ "@anthropic-ai/claude-code": "^1.0.73",
2285
2286
  "@anthropic-ai/sdk": "^0.56.0",
2286
2287
  "@modelcontextprotocol/sdk": "^1.15.1",
2287
2288
  "@stablelib/base64": "^2.0.1",
@@ -2304,6 +2305,7 @@ var dependencies = {
2304
2305
  var devDependencies = {
2305
2306
  "@eslint/compat": "^1",
2306
2307
  "@types/node": ">=18",
2308
+ "cross-env": "^10.0.0",
2307
2309
  eslint: "^9",
2308
2310
  "eslint-config-prettier": "^10",
2309
2311
  pkgroll: "^2.14.2",
@@ -2939,7 +2941,8 @@ async function start(credentials, options = {}) {
2939
2941
  host: os.hostname(),
2940
2942
  version: packageJson.version,
2941
2943
  os: os.platform(),
2942
- machineId: settings.machineId
2944
+ machineId: settings.machineId,
2945
+ homeDir: os.homedir()
2943
2946
  };
2944
2947
  const response = await api.getOrCreateSession({ tag: sessionTag, metadata, state });
2945
2948
  logger.debug(`Session created: ${response.id}`);
@@ -3093,6 +3096,7 @@ class ApiDaemonSession extends EventEmitter {
3093
3096
  token;
3094
3097
  secret;
3095
3098
  spawnedProcesses = /* @__PURE__ */ new Set();
3099
+ machineRegistered = false;
3096
3100
  constructor(token, secret, machineIdentity) {
3097
3101
  super();
3098
3102
  this.token = token;
@@ -3114,9 +3118,12 @@ class ApiDaemonSession extends EventEmitter {
3114
3118
  withCredentials: true,
3115
3119
  autoConnect: false
3116
3120
  });
3117
- socket.on("connect", () => {
3121
+ socket.on("connect", async () => {
3118
3122
  logger.debug("[DAEMON SESSION] Socket connected");
3119
3123
  logger.debug(`[DAEMON SESSION] Connected with auth - token: ${this.token.substring(0, 10)}..., machineId: ${this.machineIdentity.machineId}`);
3124
+ if (!this.machineRegistered) {
3125
+ await this.registerMachine();
3126
+ }
3120
3127
  const rpcMethod = `${this.machineIdentity.machineId}:spawn-happy-session`;
3121
3128
  socket.emit("rpc-register", { method: rpcMethod });
3122
3129
  logger.debug(`[DAEMON SESSION] Emitted RPC registration: ${rpcMethod}`);
@@ -3143,16 +3150,11 @@ class ApiDaemonSession extends EventEmitter {
3143
3150
  args.push("--local");
3144
3151
  }
3145
3152
  logger.debug(`[DAEMON SESSION] Spawning happy in directory: ${directory} with args: ${args.join(" ")}`);
3146
- const happyPath = process.argv[1];
3147
- const runningFromBuiltBinary = happyPath.endsWith("happy") || happyPath.endsWith("happy.cmd");
3148
- let executable, spawnArgs;
3149
- if (runningFromBuiltBinary) {
3150
- executable = happyPath;
3151
- spawnArgs = args;
3152
- } else {
3153
- executable = "npx";
3154
- spawnArgs = ["tsx", happyPath, ...args];
3155
- }
3153
+ const happyBinPath = join$1(projectPath(), "bin", "happy.mjs");
3154
+ logger.debug(`[DAEMON SESSION] Using happy binary at: ${happyBinPath}`);
3155
+ const executable = happyBinPath;
3156
+ const spawnArgs = args;
3157
+ logger.debug(`[DAEMON SESSION] Spawn: executable=${executable}, args=${JSON.stringify(spawnArgs)}, cwd=${directory}`);
3156
3158
  const happyProcess = spawn$1(executable, spawnArgs, {
3157
3159
  cwd: directory,
3158
3160
  detached: true,
@@ -3245,7 +3247,7 @@ class ApiDaemonSession extends EventEmitter {
3245
3247
  logger.debug(`[DAEMON SESSION] RPC error: ${JSON.stringify(data)}`);
3246
3248
  });
3247
3249
  socket.onAny((event, ...args) => {
3248
- if (!event.startsWith("machine-alive")) {
3250
+ if (!event.startsWith("session-alive") && event !== "ephemeral") {
3249
3251
  logger.debug(`[DAEMON SESSION] Socket event: ${event}, args: ${JSON.stringify(args)}`);
3250
3252
  }
3251
3253
  });
@@ -3268,12 +3270,47 @@ class ApiDaemonSession extends EventEmitter {
3268
3270
  });
3269
3271
  this.socket = socket;
3270
3272
  }
3273
+ async registerMachine() {
3274
+ try {
3275
+ const metadata = {
3276
+ host: this.machineIdentity.machineHost,
3277
+ platform: this.machineIdentity.platform,
3278
+ happyCliVersion: this.machineIdentity.happyCliVersion,
3279
+ happyHomeDirectory: this.machineIdentity.happyHomeDirectory
3280
+ };
3281
+ const encrypted = encrypt(JSON.stringify(metadata), this.secret);
3282
+ const encryptedMetadata = encodeBase64(encrypted);
3283
+ const response = await fetch(`${configuration.serverUrl}/v1/machines`, {
3284
+ method: "POST",
3285
+ headers: {
3286
+ "Authorization": `Bearer ${this.token}`,
3287
+ "Content-Type": "application/json"
3288
+ },
3289
+ body: JSON.stringify({
3290
+ id: this.machineIdentity.machineId,
3291
+ metadata: encryptedMetadata
3292
+ })
3293
+ });
3294
+ if (response.ok) {
3295
+ logger.debug("[DAEMON SESSION] Machine registered/updated successfully");
3296
+ this.machineRegistered = true;
3297
+ } else {
3298
+ logger.debug(`[DAEMON SESSION] Failed to register machine: ${response.status}`);
3299
+ }
3300
+ } catch (error) {
3301
+ logger.debug("[DAEMON SESSION] Failed to register machine:", error);
3302
+ }
3303
+ }
3271
3304
  startKeepAlive() {
3272
3305
  this.stopKeepAlive();
3273
3306
  this.keepAliveInterval = setInterval(() => {
3274
- this.socket.volatile.emit("machine-alive", {
3307
+ const payload = {
3308
+ type: "machine-scoped",
3309
+ machineId: this.machineIdentity.machineId,
3275
3310
  time: Date.now()
3276
- });
3311
+ };
3312
+ logger.debugLargeJson(`[DAEMON SESSION] Emitting session-alive`, payload);
3313
+ this.socket.emit("session-alive", payload);
3277
3314
  }, 2e4);
3278
3315
  }
3279
3316
  stopKeepAlive() {
@@ -3298,15 +3335,26 @@ class ApiDaemonSession extends EventEmitter {
3298
3335
  connect() {
3299
3336
  this.socket.connect();
3300
3337
  }
3338
+ updateMetadata(updates) {
3339
+ const metadata = {
3340
+ host: this.machineIdentity.machineHost,
3341
+ platform: this.machineIdentity.platform,
3342
+ happyCliVersion: updates.happyCliVersion || this.machineIdentity.happyCliVersion,
3343
+ happyHomeDirectory: updates.happyHomeDirectory || this.machineIdentity.happyHomeDirectory
3344
+ };
3345
+ const encrypted = encrypt(JSON.stringify(metadata), this.secret);
3346
+ const encryptedMetadata = encodeBase64(encrypted);
3347
+ this.socket.emit("update-machine-metadata", { metadata: encryptedMetadata });
3348
+ }
3301
3349
  shutdown() {
3302
3350
  logger.debug(`[DAEMON SESSION] Shutting down daemon, killing ${this.spawnedProcesses.size} spawned processes`);
3303
- for (const process2 of this.spawnedProcesses) {
3351
+ for (const process of this.spawnedProcesses) {
3304
3352
  try {
3305
- logger.debug(`[DAEMON SESSION] Killing spawned process with PID: ${process2.pid}`);
3306
- process2.kill("SIGTERM");
3353
+ logger.debug(`[DAEMON SESSION] Killing spawned process with PID: ${process.pid}`);
3354
+ process.kill("SIGTERM");
3307
3355
  setTimeout(() => {
3308
3356
  try {
3309
- process2.kill("SIGKILL");
3357
+ process.kill("SIGKILL");
3310
3358
  } catch (e) {
3311
3359
  }
3312
3360
  }, 1e3);
@@ -3382,7 +3430,8 @@ async function startDaemon() {
3382
3430
  machineId: settings.machineId,
3383
3431
  machineHost: settings.machineHost || hostname(),
3384
3432
  platform: process.platform,
3385
- version: packageJson.version
3433
+ happyCliVersion: packageJson.version,
3434
+ happyHomeDirectory: process.cwd()
3386
3435
  };
3387
3436
  let credentials = await readCredentials();
3388
3437
  if (!credentials) {
package/dist/lib.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var types = require('./types-DXK5YldG.cjs');
3
+ var types = require('./types-eN-YHsuj.cjs');
4
4
  require('axios');
5
5
  require('chalk');
6
6
  require('fs');
package/dist/lib.d.cts CHANGED
@@ -383,6 +383,7 @@ type Metadata = {
383
383
  machineId?: string;
384
384
  tools?: string[];
385
385
  slashCommands?: string[];
386
+ homeDir?: string;
386
387
  };
387
388
  type AgentState = {
388
389
  controlledByUser?: boolean | null | undefined;
package/dist/lib.d.mts CHANGED
@@ -383,6 +383,7 @@ type Metadata = {
383
383
  machineId?: string;
384
384
  tools?: string[];
385
385
  slashCommands?: string[];
386
+ homeDir?: string;
386
387
  };
387
388
  type AgentState = {
388
389
  controlledByUser?: boolean | null | undefined;
package/dist/lib.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, i as initLoggerWithGlobalConfiguration, b as initializeConfiguration, l as logger } from './types-BX4xv8Ty.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, i as initLoggerWithGlobalConfiguration, b as initializeConfiguration, l as logger } from './types-VkaGP8up.mjs';
2
2
  import 'axios';
3
3
  import 'chalk';
4
4
  import 'fs';
@@ -879,4 +879,4 @@ const RawJSONLinesSchema = z.discriminatedUnion("type", [
879
879
  }).passthrough()
880
880
  ]);
881
881
 
882
- export { ApiClient as A, RawJSONLinesSchema as R, ApiSessionClient as a, initializeConfiguration as b, configuration as c, backoff as d, delay as e, encodeBase64 as f, encodeBase64Url as g, decodeBase64 as h, initLoggerWithGlobalConfiguration as i, logger as l };
882
+ export { ApiClient as A, RawJSONLinesSchema as R, ApiSessionClient as a, initializeConfiguration as b, configuration as c, backoff as d, delay as e, encodeBase64 as f, encodeBase64Url as g, decodeBase64 as h, initLoggerWithGlobalConfiguration as i, encrypt as j, logger as l };
@@ -889,5 +889,6 @@ exports.decodeBase64 = decodeBase64;
889
889
  exports.delay = delay;
890
890
  exports.encodeBase64 = encodeBase64;
891
891
  exports.encodeBase64Url = encodeBase64Url;
892
+ exports.encrypt = encrypt;
892
893
  exports.initLoggerWithGlobalConfiguration = initLoggerWithGlobalConfiguration;
893
894
  exports.initializeConfiguration = initializeConfiguration;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "happy-coder",
3
- "version": "0.3.1-beta.1",
3
+ "version": "0.4.0",
4
4
  "description": "Claude Code session sharing CLI",
5
5
  "author": "Kirill Dubovitskiy",
6
6
  "license": "MIT",
@@ -46,15 +46,16 @@
46
46
  "scripts": {
47
47
  "test": "vitest run",
48
48
  "test:watch": "vitest",
49
- "build": "tsc --noEmit && pkgroll",
49
+ "build": "shx rm -rf dist && tsc --noEmit && pkgroll",
50
50
  "prepublishOnly": "yarn build && yarn test",
51
51
  "typecheck": "tsc --noEmit",
52
- "dev": "npx tsx --env-file .env.sample src/index.ts",
53
- "dev:local-server": "HANDY_SERVER_URL=http://localhost:3005 npx tsx --env-file .env.sample src/index.ts",
54
- "prerelease": "npm version prerelease --preid=beta"
52
+ "dev": "yarn build && npx tsx --env-file .env.sample src/index.ts",
53
+ "dev:local-server": "yarn build && cross-env HANDY_SERVER_URL=http://localhost:3005 tsx --env-file .env.sample src/index.ts",
54
+ "version:prerelease": "npm version prerelease --preid=beta",
55
+ "publish:prerelease": "npm publish --tag beta"
55
56
  },
56
57
  "dependencies": {
57
- "@anthropic-ai/claude-code": "^1.0.72",
58
+ "@anthropic-ai/claude-code": "^1.0.73",
58
59
  "@anthropic-ai/sdk": "^0.56.0",
59
60
  "@modelcontextprotocol/sdk": "^1.15.1",
60
61
  "@stablelib/base64": "^2.0.1",
@@ -77,6 +78,7 @@
77
78
  "devDependencies": {
78
79
  "@eslint/compat": "^1",
79
80
  "@types/node": ">=18",
81
+ "cross-env": "^10.0.0",
80
82
  "eslint": "^9",
81
83
  "eslint-config-prettier": "^10",
82
84
  "pkgroll": "^2.14.2",