From 81852a3176edf4797a99f0912932a27144c6fc9e Mon Sep 17 00:00:00 2001 From: weishu Date: Sun, 21 Dec 2025 19:16:50 +0800 Subject: [PATCH] refactor: unify runtime directories and environment variables to HAPI_HOME Consolidate CLI and server runtime directories from ~/.config/hapi/ (CLI) and ~/.hapi-server/ (Server) to a single ~/.hapi/ directory. Unify environment variables from HAPI_HOME_DIR (CLI) and HAPI_BOT_DATA_DIR (Server) to a single HAPI_HOME variable across both applications. Update all documentation and configuration references accordingly. Bump bun-types to 1.3.5. --- README.md | 2 +- bun.lock | 5 +++-- cli/CLAUDE.md | 2 +- cli/README.md | 4 ++-- cli/package.json | 1 + cli/src/commands/auth.ts | 4 ++-- cli/src/configuration.ts | 8 ++++---- cli/src/daemon/CLAUDE.md | 4 ++-- cli/src/daemon/daemon.integration.test.ts | 2 +- cli/src/persistence.ts | 2 +- cli/src/ui/doctor.ts | 4 ++-- cli/src/ui/tokenInit.ts | 4 ++-- server/README.md | 2 +- server/package.json | 4 ++-- server/src/configuration.ts | 6 +++--- 15 files changed, 28 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 027c4c96..9e9209af 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ The CLI will prompt for `CLI_API_TOKEN` and save it locally. - In a browser, open `WEBAPP_URL` and log in with `CLI_API_TOKEN`. ## CLI config file -You can store the token in `~/.config/hapi/settings.json` instead of an env var. +You can store the token in `~/.hapi/settings.json` instead of an env var. Environment variables take priority over the file. Example: diff --git a/bun.lock b/bun.lock index db7cfbf1..d894f324 100644 --- a/bun.lock +++ b/bun.lock @@ -39,6 +39,7 @@ "devDependencies": { "@eslint/compat": "^1", "@types/node": ">=20", + "bun-types": "^1.3.5", "cross-env": "^10.1.0", "dotenv": "^16.6.1", "eslint": "^9", @@ -65,7 +66,7 @@ }, "devDependencies": { "@types/node": ">=20", - "bun-types": "^1.2.21", + "bun-types": "^1.3.5", "typescript": "^5", }, }, @@ -828,7 +829,7 @@ "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], - "bun-types": ["bun-types@1.3.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-5ua817+BZPZOlNaRgGBpZJOSAQ9RQ17pkwPD0yR7CfJg+r8DgIILByFifDTa+IPDDxzf5VNhtNlcKqFzDgJvlQ=="], + "bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="], "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], diff --git a/cli/CLAUDE.md b/cli/CLAUDE.md index 211aec37..bba4bc0b 100644 --- a/cli/CLAUDE.md +++ b/cli/CLAUDE.md @@ -149,7 +149,7 @@ hapi daemon status ``` ## Daemon Logs -- Daemon logs are stored in `~/.hapi-dev/logs/` (or `$HAPI_HOME_DIR/logs/`) +- Daemon logs are stored in `~/.hapi/logs/` (or `$HAPI_HOME/logs/`) - Named with format: `YYYY-MM-DD-HH-MM-SS-daemon.log` # Session Forking `claude` and sdk behavior diff --git a/cli/README.md b/cli/README.md index dd6d446a..40b71f6d 100644 --- a/cli/README.md +++ b/cli/README.md @@ -37,10 +37,10 @@ Required: - `CLI_API_TOKEN` - shared secret; must match the server - `HAPI_BOT_URL` - server base URL (default: http://localhost:3006) -`CLI_API_TOKEN` can be set via env or stored in `~/.config/hapi/settings.json` (env wins). +`CLI_API_TOKEN` can be set via env or stored in `~/.hapi/settings.json` (env wins). Optional: -- `HAPI_HOME_DIR` - config/data directory (default: ~/.config/hapi) +- `HAPI_HOME` - config/data directory (default: ~/.hapi) - `HAPI_EXPERIMENTAL` - enable experimental features (true/1/yes) - `HAPI_HTTP_MCP_URL` - default MCP target for `hapi mcp` - `HAPI_CLAUDE_PATH` - path to a specific `claude` executable diff --git a/cli/package.json b/cli/package.json index 72aa4c22..0feaddb2 100644 --- a/cli/package.json +++ b/cli/package.json @@ -105,6 +105,7 @@ "devDependencies": { "@eslint/compat": "^1", "@types/node": ">=20", + "bun-types": "^1.3.5", "cross-env": "^10.1.0", "dotenv": "^16.6.1", "eslint": "^9", diff --git a/cli/src/commands/auth.ts b/cli/src/commands/auth.ts index 4c0f7bb3..3ab531d1 100644 --- a/cli/src/commands/auth.ts +++ b/cli/src/commands/auth.ts @@ -50,7 +50,7 @@ export async function handleAuthCommand(args: string[]): Promise { cliApiToken: token.trim() })) configuration._setCliApiToken(token.trim()) - console.log(chalk.green('\nToken saved to ~/.config/hapi/settings.json')) + console.log(chalk.green(`\nToken saved to ${configuration.settingsFile}`)) } finally { rl.close() } @@ -84,7 +84,7 @@ ${chalk.bold('Usage:')} ${chalk.bold('Token priority (highest to lowest):')} 1. CLI_API_TOKEN environment variable - 2. ~/.config/hapi/settings.json + 2. ~/.hapi/settings.json 3. Interactive prompt (on first run) `) } diff --git a/cli/src/configuration.ts b/cli/src/configuration.ts index 0588e872..3d835639 100644 --- a/cli/src/configuration.ts +++ b/cli/src/configuration.ts @@ -35,13 +35,13 @@ class Configuration { const args = process.argv.slice(2) this.isDaemonProcess = args.length >= 2 && args[0] === 'daemon' && (args[1] === 'start-sync') - // Directory configuration - Priority: HAPI_HOME_DIR env > default home dir - if (process.env.HAPI_HOME_DIR) { + // Directory configuration - Priority: HAPI_HOME env > default home dir + if (process.env.HAPI_HOME) { // Expand ~ to home directory if present - const expandedPath = process.env.HAPI_HOME_DIR.replace(/^~/, homedir()) + const expandedPath = process.env.HAPI_HOME.replace(/^~/, homedir()) this.happyHomeDir = expandedPath } else { - this.happyHomeDir = join(homedir(), '.config', 'hapi') + this.happyHomeDir = join(homedir(), '.hapi') } this.logsDir = join(this.happyHomeDir, 'logs') diff --git a/cli/src/daemon/CLAUDE.md b/cli/src/daemon/CLAUDE.md index c2564e40..c28e7f9d 100644 --- a/cli/src/daemon/CLAUDE.md +++ b/cli/src/daemon/CLAUDE.md @@ -222,7 +222,7 @@ Checks if machine ID exists in settings: "platform": "darwin", "happyCliVersion": "1.0.0", "homeDir": "/Users/john", - "happyHomeDir": "/Users/john/.config/hapi" + "happyHomeDir": "/Users/john/.hapi" }, "daemonState": { "status": "running", @@ -318,7 +318,7 @@ socket.emit('machine-update-metadata', { "platform": "darwin", "happyCliVersion": "1.0.1", "homeDir": "/Users/john", - "happyHomeDir": "/Users/john/.config/hapi" + "happyHomeDir": "/Users/john/.hapi" }, "expectedVersion": 1 }, callback) diff --git a/cli/src/daemon/daemon.integration.test.ts b/cli/src/daemon/daemon.integration.test.ts index c26c3cf2..d7b4d515 100644 --- a/cli/src/daemon/daemon.integration.test.ts +++ b/cli/src/daemon/daemon.integration.test.ts @@ -10,7 +10,7 @@ * and the daemon will not work properly! * * The integration test environment uses .env.integration-test which sets: - * - HAPI_HOME_DIR=~/.hapi-dev-test (DIFFERENT from dev's ~/.hapi-dev!) + * - HAPI_HOME=~/.hapi-dev-test (DIFFERENT from dev's ~/.hapi-dev!) * - HAPI_BOT_URL=http://localhost:3006 (local hapi-server) * - CLI_API_TOKEN=... (must match the server) */ diff --git a/cli/src/persistence.ts b/cli/src/persistence.ts index 2af38a77..20961a88 100644 --- a/cli/src/persistence.ts +++ b/cli/src/persistence.ts @@ -1,7 +1,7 @@ /** * Minimal persistence functions for HAPI CLI * - * Handles settings and private key storage in ~/.config/hapi/ (or HAPI_HOME_DIR override) + * Handles settings and private key storage in ~/.hapi/ (or HAPI_HOME override) */ import { FileHandle } from 'node:fs/promises' diff --git a/cli/src/ui/doctor.ts b/cli/src/ui/doctor.ts index 0cb520f0..89fc698c 100644 --- a/cli/src/ui/doctor.ts +++ b/cli/src/ui/doctor.ts @@ -23,7 +23,7 @@ import packageJson from '../../package.json' export function getEnvironmentInfo(): Record { return { PWD: process.env.PWD, - HAPI_HOME_DIR: process.env.HAPI_HOME_DIR, + HAPI_HOME: process.env.HAPI_HOME, HAPI_BOT_URL: process.env.HAPI_BOT_URL, HAPI_PROJECT_ROOT: process.env.HAPI_PROJECT_ROOT, CLI_API_TOKEN_SET: Boolean(process.env.CLI_API_TOKEN), @@ -116,7 +116,7 @@ export async function runDoctorCommand(filter?: 'all' | 'daemon'): Promise // Environment console.log(chalk.bold('\nšŸŒ Environment Variables')); const env = getEnvironmentInfo(); - console.log(`HAPI_HOME_DIR: ${env.HAPI_HOME_DIR ? chalk.green(env.HAPI_HOME_DIR) : chalk.gray('not set')}`); + console.log(`HAPI_HOME: ${env.HAPI_HOME ? chalk.green(env.HAPI_HOME) : chalk.gray('not set')}`); console.log(`HAPI_BOT_URL: ${env.HAPI_BOT_URL ? chalk.green(env.HAPI_BOT_URL) : chalk.gray('not set')}`); console.log(`CLI_API_TOKEN: ${env.CLI_API_TOKEN_SET ? chalk.green('set') : chalk.gray('not set')}`); console.log(`DANGEROUSLY_LOG_TO_SERVER: ${env.DANGEROUSLY_LOG_TO_SERVER_FOR_AI_AUTO_DEBUGGING ? chalk.yellow('ENABLED') : chalk.gray('not set')}`); diff --git a/cli/src/ui/tokenInit.ts b/cli/src/ui/tokenInit.ts index 2ce65456..0a7d6aa8 100644 --- a/cli/src/ui/tokenInit.ts +++ b/cli/src/ui/tokenInit.ts @@ -3,7 +3,7 @@ * * Handles CLI_API_TOKEN initialization with priority: * 1. Environment variable (highest - allows temporary override) - * 2. Settings file (~/.config/hapi/settings.json) + * 2. Settings file (~/.hapi/settings.json) * 3. Interactive prompt (only when both above are missing) */ @@ -57,7 +57,7 @@ async function promptForToken(): Promise { if (!token.trim()) { throw new Error('Token cannot be empty') } - console.log(chalk.green('\nToken saved to ~/.config/hapi/settings.json')) + console.log(chalk.green(`\nToken saved to ${configuration.settingsFile}`)) return token.trim() } finally { rl.close() diff --git a/server/README.md b/server/README.md index 8770f469..1cb15b9b 100644 --- a/server/README.md +++ b/server/README.md @@ -26,7 +26,7 @@ Optional: - `WEBAPP_PORT` - HTTP port (default: 3006). - `WEBAPP_URL` - public URL for Telegram Mini App button. - `CORS_ORIGINS` - comma-separated origins, or `*`. -- `HAPI_BOT_DATA_DIR` - data directory (default: ~/.hapi-server). +- `HAPI_HOME` - data directory (default: ~/.hapi). - `DB_PATH` - SQLite database path. ## Running diff --git a/server/package.json b/server/package.json index afd64eca..24950b30 100644 --- a/server/package.json +++ b/server/package.json @@ -2,7 +2,7 @@ "name": "hapi-server", "private": true, "version": "0.1.0", - "description": "Telegram Bot client for HAPI - control Claude Code sessions", + "description": "Telegram Bot client for HAPI - control Claude Code sessions", "author": "Kirill Dubovitskiy", "license": "MIT", "type": "module", @@ -23,7 +23,7 @@ }, "devDependencies": { "@types/node": ">=20", - "bun-types": "^1.2.21", + "bun-types": "^1.3.5", "typescript": "^5" } } diff --git a/server/src/configuration.ts b/server/src/configuration.ts index c52f835e..cad700e2 100644 --- a/server/src/configuration.ts +++ b/server/src/configuration.ts @@ -110,11 +110,11 @@ class Configuration { } // Data directory - if (process.env.HAPI_BOT_DATA_DIR) { - const expandedPath = process.env.HAPI_BOT_DATA_DIR.replace(/^~/, homedir()) + if (process.env.HAPI_HOME) { + const expandedPath = process.env.HAPI_HOME.replace(/^~/, homedir()) this.dataDir = expandedPath } else { - this.dataDir = join(homedir(), '.hapi-server') + this.dataDir = join(homedir(), '.hapi') } // DB path (defaults inside dataDir)