happy-coder 0.10.0-3 → 0.10.0-4

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
@@ -21,6 +21,15 @@ This will:
21
21
  2. Display a QR code to connect from your mobile device
22
22
  3. Allow real-time session sharing between Claude Code and your mobile app
23
23
 
24
+ ## Commands
25
+
26
+ - `happy auth` – Manage authentication
27
+ - `happy codex` – Start Codex mode
28
+ - `happy connect` – Store AI vendor API keys in Happy cloud
29
+ - `happy notify` – Send a push notification to your devices
30
+ - `happy daemon` – Manage background service
31
+ - `happy doctor` – System diagnostics & troubleshooting
32
+
24
33
  ## Options
25
34
 
26
35
  - `-h, --help` - Show help
@@ -40,4 +49,4 @@ This will:
40
49
 
41
50
  ## License
42
51
 
43
- MIT
52
+ MIT
@@ -3,7 +3,7 @@
3
3
  var chalk = require('chalk');
4
4
  var os = require('node:os');
5
5
  var node_crypto = require('node:crypto');
6
- var types = require('./types-CsJGQvQ3.cjs');
6
+ var types = require('./types-BcDnTXMg.cjs');
7
7
  var node_child_process = require('node:child_process');
8
8
  var node_path = require('node:path');
9
9
  var node_readline = require('node:readline');
@@ -923,7 +923,7 @@ class AbortError extends Error {
923
923
  }
924
924
  }
925
925
 
926
- const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-tqOLc1Il.cjs', document.baseURI).href)));
926
+ const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-67rskwL7.cjs', document.baseURI).href)));
927
927
  const __dirname$1 = node_path.join(__filename$1, "..");
928
928
  function getDefaultClaudeCodePath() {
929
929
  return node_path.join(__dirname$1, "..", "..", "..", "node_modules", "@anthropic-ai", "claude-code", "cli.js");
@@ -3684,7 +3684,7 @@ function displayQRCode(url) {
3684
3684
 
3685
3685
  function generateWebAuthUrl(publicKey) {
3686
3686
  const publicKeyBase64 = types.encodeBase64(publicKey, "base64url");
3687
- return `https://app.happy.engineering/terminal/connect#key=${publicKeyBase64}`;
3687
+ return `${types.configuration.webappUrl}/terminal/connect#key=${publicKeyBase64}`;
3688
3688
  }
3689
3689
 
3690
3690
  async function openBrowser(url) {
@@ -3751,7 +3751,8 @@ async function doAuth() {
3751
3751
  console.log(`[AUTH DEBUG] Sending auth request to: ${types.configuration.serverUrl}/v1/auth/request`);
3752
3752
  console.log(`[AUTH DEBUG] Public key: ${types.encodeBase64(keypair.publicKey).substring(0, 20)}...`);
3753
3753
  await axios.post(`${types.configuration.serverUrl}/v1/auth/request`, {
3754
- publicKey: types.encodeBase64(keypair.publicKey)
3754
+ publicKey: types.encodeBase64(keypair.publicKey),
3755
+ supportsV2: true
3755
3756
  });
3756
3757
  console.log(`[AUTH DEBUG] Auth request sent successfully`);
3757
3758
  } catch (error) {
@@ -3830,20 +3831,50 @@ async function waitForAuthentication(keypair) {
3830
3831
  while (!cancelled) {
3831
3832
  try {
3832
3833
  const response = await axios.post(`${types.configuration.serverUrl}/v1/auth/request`, {
3833
- publicKey: types.encodeBase64(keypair.publicKey)
3834
+ publicKey: types.encodeBase64(keypair.publicKey),
3835
+ supportsV2: true
3834
3836
  });
3835
3837
  if (response.data.state === "authorized") {
3836
3838
  let token = response.data.token;
3837
3839
  let r = types.decodeBase64(response.data.response);
3838
3840
  let decrypted = decryptWithEphemeralKey(r, keypair.secretKey);
3839
3841
  if (decrypted) {
3840
- const credentials = {
3841
- secret: decrypted,
3842
- token
3843
- };
3844
- await types.writeCredentials(credentials);
3845
- console.log("\n\n\u2713 Authentication successful\n");
3846
- return credentials;
3842
+ if (decrypted.length === 32) {
3843
+ const credentials = {
3844
+ secret: decrypted,
3845
+ token
3846
+ };
3847
+ await types.writeCredentialsLegacy(credentials);
3848
+ console.log("\n\n\u2713 Authentication successful\n");
3849
+ return {
3850
+ encryption: {
3851
+ type: "legacy",
3852
+ secret: decrypted
3853
+ },
3854
+ token
3855
+ };
3856
+ } else {
3857
+ if (decrypted[0] === 0) {
3858
+ const credentials = {
3859
+ publicKey: decrypted.slice(1, 33),
3860
+ machineKey: node_crypto.randomBytes(32),
3861
+ token
3862
+ };
3863
+ await types.writeCredentialsDataKey(credentials);
3864
+ console.log("\n\n\u2713 Authentication successful\n");
3865
+ return {
3866
+ encryption: {
3867
+ type: "dataKey",
3868
+ publicKey: credentials.publicKey,
3869
+ machineKey: credentials.machineKey
3870
+ },
3871
+ token
3872
+ };
3873
+ } else {
3874
+ console.log("\n\nFailed to decrypt response. Please try again.");
3875
+ return null;
3876
+ }
3877
+ }
3847
3878
  } else {
3848
3879
  console.log("\n\nFailed to decrypt response. Please try again.");
3849
3880
  return null;
@@ -3875,6 +3906,7 @@ function decryptWithEphemeralKey(encryptedBundle, recipientSecretKey) {
3875
3906
  async function authAndSetupMachineIfNeeded() {
3876
3907
  types.logger.debug("[AUTH] Starting auth and machine setup...");
3877
3908
  let credentials = await types.readCredentials();
3909
+ let newAuth = false;
3878
3910
  if (!credentials) {
3879
3911
  types.logger.debug("[AUTH] No credentials found, starting authentication flow...");
3880
3912
  const authResult = await doAuth();
@@ -3882,13 +3914,12 @@ async function authAndSetupMachineIfNeeded() {
3882
3914
  throw new Error("Authentication failed or was cancelled");
3883
3915
  }
3884
3916
  credentials = authResult;
3917
+ newAuth = true;
3885
3918
  } else {
3886
3919
  types.logger.debug("[AUTH] Using existing credentials");
3887
3920
  }
3888
3921
  const settings = await types.updateSettings(async (s) => {
3889
- if (!s.machineId) {
3890
- const newMachineId = node_crypto.randomUUID();
3891
- types.logger.debug(`[AUTH] No machine ID found, generating new one: ${newMachineId}; We will not create machine on startup since we don't have api client intialized`);
3922
+ if (newAuth || !s.machineId) {
3892
3923
  return {
3893
3924
  ...s,
3894
3925
  machineId: node_crypto.randomUUID()
@@ -4368,7 +4399,7 @@ async function startDaemon() {
4368
4399
  httpPort: controlPort,
4369
4400
  startedAt: Date.now()
4370
4401
  };
4371
- const api = new types.ApiClient(credentials.token, credentials.secret);
4402
+ const api = await types.ApiClient.create(credentials);
4372
4403
  const machine = await api.getOrCreateMachine({
4373
4404
  machineId,
4374
4405
  metadata: initialMachineMetadata,
@@ -4572,7 +4603,7 @@ async function runClaude(credentials, options = {}) {
4572
4603
  types.logger.debug("Daemon spawn requested with local mode - forcing remote mode");
4573
4604
  options.startingMode = "remote";
4574
4605
  }
4575
- const api = new types.ApiClient(credentials.token, credentials.secret);
4606
+ const api = await types.ApiClient.create(credentials);
4576
4607
  let state = {};
4577
4608
  const settings = await types.readSettings();
4578
4609
  let machineId = settings?.machineId;
@@ -4942,33 +4973,6 @@ async function uninstall() {
4942
4973
  await uninstall$1();
4943
4974
  }
4944
4975
 
4945
- const BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
4946
- function bytesToBase32(bytes) {
4947
- let result = "";
4948
- let buffer = 0;
4949
- let bufferLength = 0;
4950
- for (const byte of bytes) {
4951
- buffer = buffer << 8 | byte;
4952
- bufferLength += 8;
4953
- while (bufferLength >= 5) {
4954
- bufferLength -= 5;
4955
- result += BASE32_ALPHABET[buffer >> bufferLength & 31];
4956
- }
4957
- }
4958
- if (bufferLength > 0) {
4959
- result += BASE32_ALPHABET[buffer << 5 - bufferLength & 31];
4960
- }
4961
- return result;
4962
- }
4963
- function formatSecretKeyForBackup(secretBytes) {
4964
- const base32 = bytesToBase32(secretBytes);
4965
- const groups = [];
4966
- for (let i = 0; i < base32.length; i += 5) {
4967
- groups.push(base32.slice(i, i + 5));
4968
- }
4969
- return groups.join("-");
4970
- }
4971
-
4972
4976
  async function handleAuthCommand(args) {
4973
4977
  const subcommand = args[0];
4974
4978
  if (!subcommand || subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
@@ -4982,9 +4986,9 @@ async function handleAuthCommand(args) {
4982
4986
  case "logout":
4983
4987
  await handleAuthLogout();
4984
4988
  break;
4985
- case "show-backup":
4986
- await handleAuthShowBackup();
4987
- break;
4989
+ // case 'backup':
4990
+ // await handleAuthShowBackup();
4991
+ // break;
4988
4992
  case "status":
4989
4993
  await handleAuthStatus();
4990
4994
  break;
@@ -5007,11 +5011,6 @@ ${chalk.bold("Usage:")}
5007
5011
 
5008
5012
  ${chalk.bold("Options:")}
5009
5013
  --force Clear credentials, machine ID, and stop daemon before re-auth
5010
-
5011
- ${chalk.bold("Notes:")}
5012
- \u2022 Use 'auth login --force' when you need to re-register your machine
5013
- \u2022 'auth show-backup' displays the key format expected by mobile/web clients
5014
- \u2022 The backup key allows linking multiple devices to the same account
5015
5014
  `);
5016
5015
  }
5017
5016
  async function handleAuthLogin(args) {
@@ -5096,31 +5095,6 @@ async function handleAuthLogout() {
5096
5095
  console.log(chalk.blue("Logout cancelled"));
5097
5096
  }
5098
5097
  }
5099
- async function handleAuthShowBackup() {
5100
- const credentials = await types.readCredentials();
5101
- const settings = await types.readSettings();
5102
- if (!credentials) {
5103
- console.log(chalk.yellow("Not authenticated"));
5104
- console.log(chalk.gray('Run "happy auth login" to authenticate first'));
5105
- return;
5106
- }
5107
- const formattedBackupKey = formatSecretKeyForBackup(credentials.secret);
5108
- console.log(chalk.bold("\n\u{1F4F1} Backup Key\n"));
5109
- console.log(chalk.cyan("Your backup key:"));
5110
- console.log(chalk.bold(formattedBackupKey));
5111
- console.log("");
5112
- console.log(chalk.cyan("Machine Information:"));
5113
- console.log(` Machine ID: ${settings?.machineId || "not set"}`);
5114
- console.log(` Host: ${os.hostname()}`);
5115
- console.log("");
5116
- console.log(chalk.bold("How to use this backup key:"));
5117
- console.log(chalk.gray("\u2022 In Happy mobile app: Go to restore/link device and enter this key"));
5118
- console.log(chalk.gray("\u2022 This key format matches what the mobile app expects"));
5119
- console.log(chalk.gray("\u2022 You can type it with or without dashes - the app will normalize it"));
5120
- console.log(chalk.gray("\u2022 Common typos (0\u2192O, 1\u2192I) are automatically corrected"));
5121
- console.log("");
5122
- console.log(chalk.yellow("\u26A0\uFE0F Keep this key secure - it provides full access to your account"));
5123
- }
5124
5098
  async function handleAuthStatus() {
5125
5099
  const credentials = await types.readCredentials();
5126
5100
  const settings = await types.readSettings();
@@ -5657,7 +5631,7 @@ ${chalk.bold("happy connect")} - Connect AI vendor API keys to Happy cloud
5657
5631
 
5658
5632
  ${chalk.bold("Usage:")}
5659
5633
  happy connect codex Store your Codex API key in Happy cloud
5660
- happy connect anthropic Store your Anthropic API key in Happy cloud
5634
+ happy connect claude Store your Anthropic API key in Happy cloud
5661
5635
  happy connect gemini Store your Gemini API key in Happy cloud
5662
5636
  happy connect help Show this help message
5663
5637
 
@@ -5668,7 +5642,7 @@ ${chalk.bold("Description:")}
5668
5642
 
5669
5643
  ${chalk.bold("Examples:")}
5670
5644
  happy connect codex
5671
- happy connect anthropic
5645
+ happy connect claude
5672
5646
  happy connect gemini
5673
5647
 
5674
5648
  ${chalk.bold("Notes:")}
@@ -5687,7 +5661,7 @@ async function handleConnectVendor(vendor, displayName) {
5687
5661
  console.log(chalk.gray(' Please run "happy auth login" first'));
5688
5662
  process.exit(1);
5689
5663
  }
5690
- const api = new types.ApiClient(credentials.token, credentials.secret);
5664
+ const api = await types.ApiClient.create(credentials);
5691
5665
  if (vendor === "codex") {
5692
5666
  console.log("\u{1F680} Registering Codex token with server");
5693
5667
  const codexAuthTokens = await authenticateCodex();
@@ -5752,11 +5726,11 @@ async function handleConnectVendor(vendor, displayName) {
5752
5726
  return;
5753
5727
  } else if (subcommand === "codex") {
5754
5728
  try {
5755
- const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-BxLD6H6G.cjs'); });
5729
+ const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-BLNf5zb1.cjs'); });
5756
5730
  const {
5757
5731
  credentials
5758
5732
  } = await authAndSetupMachineIfNeeded();
5759
- await runCodex(credentials);
5733
+ await runCodex({ credentials });
5760
5734
  } catch (error) {
5761
5735
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
5762
5736
  if (process.env.DEBUG) {
@@ -5924,6 +5898,9 @@ ${chalk.bold("happy")} - Claude Code On the Go
5924
5898
  ${chalk.bold("Usage:")}
5925
5899
  happy [options] Start Claude with mobile control
5926
5900
  happy auth Manage authentication
5901
+ happy codex Start Codex mode
5902
+ happy connect Connect AI vendor API keys
5903
+ happy notify Send push notification
5927
5904
  happy daemon Manage background service that allows
5928
5905
  to spawn new sessions away from your computer
5929
5906
  happy doctor System diagnostics & troubleshooting
@@ -6022,12 +5999,12 @@ ${chalk.bold("Examples:")}
6022
5999
  }
6023
6000
  let credentials = await types.readCredentials();
6024
6001
  if (!credentials) {
6025
- console.error(chalk.red('Error: Not authenticated. Please run "happy --auth" first.'));
6002
+ console.error(chalk.red('Error: Not authenticated. Please run "happy auth login" first.'));
6026
6003
  process.exit(1);
6027
6004
  }
6028
6005
  console.log(chalk.blue("\u{1F4F1} Sending push notification..."));
6029
6006
  try {
6030
- const api = new types.ApiClient(credentials.token, credentials.secret);
6007
+ const api = await types.ApiClient.create(credentials);
6031
6008
  const notificationTitle = title || "Happy";
6032
6009
  api.push().sendToAllDevices(
6033
6010
  notificationTitle,
@@ -1,7 +1,7 @@
1
1
  import chalk from 'chalk';
2
2
  import os$1, { homedir } from 'node:os';
3
3
  import { randomUUID, randomBytes } from 'node:crypto';
4
- import { l as logger, p as projectPath, d as backoff, e as delay, R as RawJSONLinesSchema, f as AsyncLock, g as readDaemonState, h as clearDaemonState, b as packageJson, c as configuration, r as readSettings, i as readCredentials, j as encodeBase64, u as updateSettings, k as encodeBase64Url, m as decodeBase64, w as writeCredentials, n as acquireDaemonLock, o as writeDaemonState, A as ApiClient, q as releaseDaemonLock, s as clearCredentials, t as clearMachineId, v as getLatestDaemonLog } from './types-xds_c-JJ.mjs';
4
+ import { l as logger, p as projectPath, d as backoff, e as delay, R as RawJSONLinesSchema, f as AsyncLock, g as readDaemonState, h as clearDaemonState, b as packageJson, c as configuration, r as readSettings, i as readCredentials, j as encodeBase64, u as updateSettings, k as encodeBase64Url, m as decodeBase64, w as writeCredentialsLegacy, n as writeCredentialsDataKey, o as acquireDaemonLock, q as writeDaemonState, A as ApiClient, s as releaseDaemonLock, t as clearCredentials, v as clearMachineId, x as getLatestDaemonLog } from './types-2wHnX7UW.mjs';
5
5
  import { spawn, execSync, execFileSync } from 'node:child_process';
6
6
  import { resolve, join } from 'node:path';
7
7
  import { createInterface } from 'node:readline';
@@ -3681,7 +3681,7 @@ function displayQRCode(url) {
3681
3681
 
3682
3682
  function generateWebAuthUrl(publicKey) {
3683
3683
  const publicKeyBase64 = encodeBase64(publicKey, "base64url");
3684
- return `https://app.happy.engineering/terminal/connect#key=${publicKeyBase64}`;
3684
+ return `${configuration.webappUrl}/terminal/connect#key=${publicKeyBase64}`;
3685
3685
  }
3686
3686
 
3687
3687
  async function openBrowser(url) {
@@ -3748,7 +3748,8 @@ async function doAuth() {
3748
3748
  console.log(`[AUTH DEBUG] Sending auth request to: ${configuration.serverUrl}/v1/auth/request`);
3749
3749
  console.log(`[AUTH DEBUG] Public key: ${encodeBase64(keypair.publicKey).substring(0, 20)}...`);
3750
3750
  await axios.post(`${configuration.serverUrl}/v1/auth/request`, {
3751
- publicKey: encodeBase64(keypair.publicKey)
3751
+ publicKey: encodeBase64(keypair.publicKey),
3752
+ supportsV2: true
3752
3753
  });
3753
3754
  console.log(`[AUTH DEBUG] Auth request sent successfully`);
3754
3755
  } catch (error) {
@@ -3827,20 +3828,50 @@ async function waitForAuthentication(keypair) {
3827
3828
  while (!cancelled) {
3828
3829
  try {
3829
3830
  const response = await axios.post(`${configuration.serverUrl}/v1/auth/request`, {
3830
- publicKey: encodeBase64(keypair.publicKey)
3831
+ publicKey: encodeBase64(keypair.publicKey),
3832
+ supportsV2: true
3831
3833
  });
3832
3834
  if (response.data.state === "authorized") {
3833
3835
  let token = response.data.token;
3834
3836
  let r = decodeBase64(response.data.response);
3835
3837
  let decrypted = decryptWithEphemeralKey(r, keypair.secretKey);
3836
3838
  if (decrypted) {
3837
- const credentials = {
3838
- secret: decrypted,
3839
- token
3840
- };
3841
- await writeCredentials(credentials);
3842
- console.log("\n\n\u2713 Authentication successful\n");
3843
- return credentials;
3839
+ if (decrypted.length === 32) {
3840
+ const credentials = {
3841
+ secret: decrypted,
3842
+ token
3843
+ };
3844
+ await writeCredentialsLegacy(credentials);
3845
+ console.log("\n\n\u2713 Authentication successful\n");
3846
+ return {
3847
+ encryption: {
3848
+ type: "legacy",
3849
+ secret: decrypted
3850
+ },
3851
+ token
3852
+ };
3853
+ } else {
3854
+ if (decrypted[0] === 0) {
3855
+ const credentials = {
3856
+ publicKey: decrypted.slice(1, 33),
3857
+ machineKey: randomBytes(32),
3858
+ token
3859
+ };
3860
+ await writeCredentialsDataKey(credentials);
3861
+ console.log("\n\n\u2713 Authentication successful\n");
3862
+ return {
3863
+ encryption: {
3864
+ type: "dataKey",
3865
+ publicKey: credentials.publicKey,
3866
+ machineKey: credentials.machineKey
3867
+ },
3868
+ token
3869
+ };
3870
+ } else {
3871
+ console.log("\n\nFailed to decrypt response. Please try again.");
3872
+ return null;
3873
+ }
3874
+ }
3844
3875
  } else {
3845
3876
  console.log("\n\nFailed to decrypt response. Please try again.");
3846
3877
  return null;
@@ -3872,6 +3903,7 @@ function decryptWithEphemeralKey(encryptedBundle, recipientSecretKey) {
3872
3903
  async function authAndSetupMachineIfNeeded() {
3873
3904
  logger.debug("[AUTH] Starting auth and machine setup...");
3874
3905
  let credentials = await readCredentials();
3906
+ let newAuth = false;
3875
3907
  if (!credentials) {
3876
3908
  logger.debug("[AUTH] No credentials found, starting authentication flow...");
3877
3909
  const authResult = await doAuth();
@@ -3879,13 +3911,12 @@ async function authAndSetupMachineIfNeeded() {
3879
3911
  throw new Error("Authentication failed or was cancelled");
3880
3912
  }
3881
3913
  credentials = authResult;
3914
+ newAuth = true;
3882
3915
  } else {
3883
3916
  logger.debug("[AUTH] Using existing credentials");
3884
3917
  }
3885
3918
  const settings = await updateSettings(async (s) => {
3886
- if (!s.machineId) {
3887
- const newMachineId = randomUUID();
3888
- logger.debug(`[AUTH] No machine ID found, generating new one: ${newMachineId}; We will not create machine on startup since we don't have api client intialized`);
3919
+ if (newAuth || !s.machineId) {
3889
3920
  return {
3890
3921
  ...s,
3891
3922
  machineId: randomUUID()
@@ -4365,7 +4396,7 @@ async function startDaemon() {
4365
4396
  httpPort: controlPort,
4366
4397
  startedAt: Date.now()
4367
4398
  };
4368
- const api = new ApiClient(credentials.token, credentials.secret);
4399
+ const api = await ApiClient.create(credentials);
4369
4400
  const machine = await api.getOrCreateMachine({
4370
4401
  machineId,
4371
4402
  metadata: initialMachineMetadata,
@@ -4569,7 +4600,7 @@ async function runClaude(credentials, options = {}) {
4569
4600
  logger.debug("Daemon spawn requested with local mode - forcing remote mode");
4570
4601
  options.startingMode = "remote";
4571
4602
  }
4572
- const api = new ApiClient(credentials.token, credentials.secret);
4603
+ const api = await ApiClient.create(credentials);
4573
4604
  let state = {};
4574
4605
  const settings = await readSettings();
4575
4606
  let machineId = settings?.machineId;
@@ -4939,33 +4970,6 @@ async function uninstall() {
4939
4970
  await uninstall$1();
4940
4971
  }
4941
4972
 
4942
- const BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
4943
- function bytesToBase32(bytes) {
4944
- let result = "";
4945
- let buffer = 0;
4946
- let bufferLength = 0;
4947
- for (const byte of bytes) {
4948
- buffer = buffer << 8 | byte;
4949
- bufferLength += 8;
4950
- while (bufferLength >= 5) {
4951
- bufferLength -= 5;
4952
- result += BASE32_ALPHABET[buffer >> bufferLength & 31];
4953
- }
4954
- }
4955
- if (bufferLength > 0) {
4956
- result += BASE32_ALPHABET[buffer << 5 - bufferLength & 31];
4957
- }
4958
- return result;
4959
- }
4960
- function formatSecretKeyForBackup(secretBytes) {
4961
- const base32 = bytesToBase32(secretBytes);
4962
- const groups = [];
4963
- for (let i = 0; i < base32.length; i += 5) {
4964
- groups.push(base32.slice(i, i + 5));
4965
- }
4966
- return groups.join("-");
4967
- }
4968
-
4969
4973
  async function handleAuthCommand(args) {
4970
4974
  const subcommand = args[0];
4971
4975
  if (!subcommand || subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
@@ -4979,9 +4983,9 @@ async function handleAuthCommand(args) {
4979
4983
  case "logout":
4980
4984
  await handleAuthLogout();
4981
4985
  break;
4982
- case "show-backup":
4983
- await handleAuthShowBackup();
4984
- break;
4986
+ // case 'backup':
4987
+ // await handleAuthShowBackup();
4988
+ // break;
4985
4989
  case "status":
4986
4990
  await handleAuthStatus();
4987
4991
  break;
@@ -5004,11 +5008,6 @@ ${chalk.bold("Usage:")}
5004
5008
 
5005
5009
  ${chalk.bold("Options:")}
5006
5010
  --force Clear credentials, machine ID, and stop daemon before re-auth
5007
-
5008
- ${chalk.bold("Notes:")}
5009
- \u2022 Use 'auth login --force' when you need to re-register your machine
5010
- \u2022 'auth show-backup' displays the key format expected by mobile/web clients
5011
- \u2022 The backup key allows linking multiple devices to the same account
5012
5011
  `);
5013
5012
  }
5014
5013
  async function handleAuthLogin(args) {
@@ -5093,31 +5092,6 @@ async function handleAuthLogout() {
5093
5092
  console.log(chalk.blue("Logout cancelled"));
5094
5093
  }
5095
5094
  }
5096
- async function handleAuthShowBackup() {
5097
- const credentials = await readCredentials();
5098
- const settings = await readSettings();
5099
- if (!credentials) {
5100
- console.log(chalk.yellow("Not authenticated"));
5101
- console.log(chalk.gray('Run "happy auth login" to authenticate first'));
5102
- return;
5103
- }
5104
- const formattedBackupKey = formatSecretKeyForBackup(credentials.secret);
5105
- console.log(chalk.bold("\n\u{1F4F1} Backup Key\n"));
5106
- console.log(chalk.cyan("Your backup key:"));
5107
- console.log(chalk.bold(formattedBackupKey));
5108
- console.log("");
5109
- console.log(chalk.cyan("Machine Information:"));
5110
- console.log(` Machine ID: ${settings?.machineId || "not set"}`);
5111
- console.log(` Host: ${os$1.hostname()}`);
5112
- console.log("");
5113
- console.log(chalk.bold("How to use this backup key:"));
5114
- console.log(chalk.gray("\u2022 In Happy mobile app: Go to restore/link device and enter this key"));
5115
- console.log(chalk.gray("\u2022 This key format matches what the mobile app expects"));
5116
- console.log(chalk.gray("\u2022 You can type it with or without dashes - the app will normalize it"));
5117
- console.log(chalk.gray("\u2022 Common typos (0\u2192O, 1\u2192I) are automatically corrected"));
5118
- console.log("");
5119
- console.log(chalk.yellow("\u26A0\uFE0F Keep this key secure - it provides full access to your account"));
5120
- }
5121
5095
  async function handleAuthStatus() {
5122
5096
  const credentials = await readCredentials();
5123
5097
  const settings = await readSettings();
@@ -5654,7 +5628,7 @@ ${chalk.bold("happy connect")} - Connect AI vendor API keys to Happy cloud
5654
5628
 
5655
5629
  ${chalk.bold("Usage:")}
5656
5630
  happy connect codex Store your Codex API key in Happy cloud
5657
- happy connect anthropic Store your Anthropic API key in Happy cloud
5631
+ happy connect claude Store your Anthropic API key in Happy cloud
5658
5632
  happy connect gemini Store your Gemini API key in Happy cloud
5659
5633
  happy connect help Show this help message
5660
5634
 
@@ -5665,7 +5639,7 @@ ${chalk.bold("Description:")}
5665
5639
 
5666
5640
  ${chalk.bold("Examples:")}
5667
5641
  happy connect codex
5668
- happy connect anthropic
5642
+ happy connect claude
5669
5643
  happy connect gemini
5670
5644
 
5671
5645
  ${chalk.bold("Notes:")}
@@ -5684,7 +5658,7 @@ async function handleConnectVendor(vendor, displayName) {
5684
5658
  console.log(chalk.gray(' Please run "happy auth login" first'));
5685
5659
  process.exit(1);
5686
5660
  }
5687
- const api = new ApiClient(credentials.token, credentials.secret);
5661
+ const api = await ApiClient.create(credentials);
5688
5662
  if (vendor === "codex") {
5689
5663
  console.log("\u{1F680} Registering Codex token with server");
5690
5664
  const codexAuthTokens = await authenticateCodex();
@@ -5749,11 +5723,11 @@ async function handleConnectVendor(vendor, displayName) {
5749
5723
  return;
5750
5724
  } else if (subcommand === "codex") {
5751
5725
  try {
5752
- const { runCodex } = await import('./runCodex-C07HQlsW.mjs');
5726
+ const { runCodex } = await import('./runCodex-BNH8w4O9.mjs');
5753
5727
  const {
5754
5728
  credentials
5755
5729
  } = await authAndSetupMachineIfNeeded();
5756
- await runCodex(credentials);
5730
+ await runCodex({ credentials });
5757
5731
  } catch (error) {
5758
5732
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
5759
5733
  if (process.env.DEBUG) {
@@ -5921,6 +5895,9 @@ ${chalk.bold("happy")} - Claude Code On the Go
5921
5895
  ${chalk.bold("Usage:")}
5922
5896
  happy [options] Start Claude with mobile control
5923
5897
  happy auth Manage authentication
5898
+ happy codex Start Codex mode
5899
+ happy connect Connect AI vendor API keys
5900
+ happy notify Send push notification
5924
5901
  happy daemon Manage background service that allows
5925
5902
  to spawn new sessions away from your computer
5926
5903
  happy doctor System diagnostics & troubleshooting
@@ -6019,12 +5996,12 @@ ${chalk.bold("Examples:")}
6019
5996
  }
6020
5997
  let credentials = await readCredentials();
6021
5998
  if (!credentials) {
6022
- console.error(chalk.red('Error: Not authenticated. Please run "happy --auth" first.'));
5999
+ console.error(chalk.red('Error: Not authenticated. Please run "happy auth login" first.'));
6023
6000
  process.exit(1);
6024
6001
  }
6025
6002
  console.log(chalk.blue("\u{1F4F1} Sending push notification..."));
6026
6003
  try {
6027
- const api = new ApiClient(credentials.token, credentials.secret);
6004
+ const api = await ApiClient.create(credentials);
6028
6005
  const notificationTitle = title || "Happy";
6029
6006
  api.push().sendToAllDevices(
6030
6007
  notificationTitle,
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  require('chalk');
4
- require('./index-tqOLc1Il.cjs');
5
- require('./types-CsJGQvQ3.cjs');
4
+ require('./index-67rskwL7.cjs');
5
+ require('./types-BcDnTXMg.cjs');
6
6
  require('zod');
7
7
  require('node:child_process');
8
8
  require('node:os');
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import 'chalk';
2
- import './index-DPVbp4Yx.mjs';
3
- import './types-xds_c-JJ.mjs';
2
+ import './index-Dw96QD4T.mjs';
3
+ import './types-2wHnX7UW.mjs';
4
4
  import 'zod';
5
5
  import 'node:child_process';
6
6
  import 'node:os';
package/dist/lib.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var types = require('./types-CsJGQvQ3.cjs');
3
+ var types = require('./types-BcDnTXMg.cjs');
4
4
  require('axios');
5
5
  require('chalk');
6
6
  require('fs');