Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Claude Code UI Environment Configuration
# Only includes variables that are actually used in the code
#
# TIP: Run 'cloudcli status' to see where this file should be located
# and to view your current configuration.
#
# Available CLI commands:
# claude-code-ui - Start the server (default)
# cloudcli start - Start the server
# cloudcli status - Show configuration and data locations
# cloudcli help - Show help information
# cloudcli version - Show version information

# =============================================================================
# SERVER CONFIGURATION
Expand All @@ -19,10 +29,11 @@ VITE_PORT=5173
# =============================================================================

# Path to the authentication database file
# This should be set to a persistent volume path when running in containers
# Default: server/database/auth.db (relative to project root)
# Example for Docker: /data/auth.db
# DATABASE_PATH=/data/auth.db
# This is where user credentials, API keys, and tokens are stored.
#
# To use a custom location:
# DATABASE_PATH=/path/to/your/custom/auth.db
#
# Claude Code context window size (maximum tokens per session)
# Note: VITE_ prefix makes it available to frontend
VITE_CONTEXT_WINDOW=160000
Expand Down
72 changes: 55 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ npx @siteboon/claude-code-ui

The server will start and be accessible at `http://localhost:3001` (or your configured PORT).

**To restart**: Simply run the same `npx` command again after stopping the server (Ctrl+C or Cmd+C).

**To restart**: Simply run the same `npx` command again after stopping the server
### Global Installation (For Regular Use)

For frequent use, install globally once:
Expand All @@ -85,32 +84,71 @@ Then start with a simple command:
claude-code-ui
```

**Benefits**:
- Faster startup (no download/cache check)
- Simple command to remember
- Same experience every time

**To restart**: Stop with Ctrl+C and run `claude-code-ui` again.

### Run as Background Service (Optional)
### CLI Commands

To keep the server running in the background, use PM2:
After global installation, you have access to both `claude-code-ui` and `cloudcli` commands:

```bash
# Start the server (default command)
claude-code-ui
cloudcli start

# Show configuration and data locations
cloudcli status

# Show help information
cloudcli help

# Show version
cloudcli version
```

**The `cloudcli status` command shows you:**
- Installation directory location
- Database location (where credentials are stored)
- Current configuration (PORT, DATABASE_PATH, etc.)
- Claude projects folder location
- Configuration file location

```

### Run as Background Service (Recommended for Production)

For production use, run Claude Code UI as a background service using PM2 (Process Manager 2):

#### Install PM2

```bash
# Install PM2 globally (one-time)
npm install -g pm2
```

#### Start as Background Service

```bash
# Start the server in background
pm2 start claude-code-ui --name "claude-code-ui"

# Or using the shorter alias
pm2 start cloudcli --name "claude-code-ui"
```


#### Auto-Start on System Boot

# Start the server
pm2 start claude-code-ui --name "claude-ui"
To make Claude Code UI start automatically when your system boots:

# Manage the service
pm2 list # View status
pm2 restart claude-ui # Restart
pm2 stop claude-ui # Stop
pm2 logs claude-ui # View logs
pm2 startup # Auto-start on system boot
```bash
# Generate startup script for your platform
pm2 startup

# Save current process list
pm2 save
```


### Local Development Installation

1. **Clone the repository:**
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"type": "module",
"main": "server/index.js",
"bin": {
"claude-code-ui": "server/index.js"
"claude-code-ui": "server/cli.js",
"cloudcli": "server/cli.js"
},
"files": [
"server/",
Expand Down
225 changes: 225 additions & 0 deletions server/cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
#!/usr/bin/env node
/**
* Claude Code UI CLI
*
* Provides command-line utilities for managing Claude Code UI
*
* Commands:
* (no args) - Start the server (default)
* start - Start the server
* status - Show configuration and data locations
* help - Show help information
* version - Show version information
*/

import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// ANSI color codes for terminal output
const colors = {
reset: '\x1b[0m',
bright: '\x1b[1m',
dim: '\x1b[2m',

// Foreground colors
cyan: '\x1b[36m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
magenta: '\x1b[35m',
white: '\x1b[37m',
gray: '\x1b[90m',
};

// Helper to colorize text
const c = {
info: (text) => `${colors.cyan}${text}${colors.reset}`,
ok: (text) => `${colors.green}${text}${colors.reset}`,
warn: (text) => `${colors.yellow}${text}${colors.reset}`,
error: (text) => `${colors.yellow}${text}${colors.reset}`,
tip: (text) => `${colors.blue}${text}${colors.reset}`,
bright: (text) => `${colors.bright}${text}${colors.reset}`,
dim: (text) => `${colors.dim}${text}${colors.reset}`,
};

// Load package.json for version info
const packageJsonPath = path.join(__dirname, '../package.json');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));

// Load environment variables from .env file if it exists
function loadEnvFile() {
try {
const envPath = path.join(__dirname, '../.env');
const envFile = fs.readFileSync(envPath, 'utf8');
envFile.split('\n').forEach(line => {
const trimmedLine = line.trim();
if (trimmedLine && !trimmedLine.startsWith('#')) {
const [key, ...valueParts] = trimmedLine.split('=');
if (key && valueParts.length > 0 && !process.env[key]) {
process.env[key] = valueParts.join('=').trim();
}
}
});
} catch (e) {
// .env file is optional
}
}

// Get the database path (same logic as db.js)
function getDatabasePath() {
loadEnvFile();
return process.env.DATABASE_PATH || path.join(__dirname, 'database', 'auth.db');
}

// Get the installation directory
function getInstallDir() {
return path.join(__dirname, '..');
}

// Show status command
function showStatus() {
console.log(`\n${c.bright('Claude Code UI - Status')}\n`);
console.log(c.dim('═'.repeat(60)));

// Version info
console.log(`\n${c.info('[INFO]')} Version: ${c.bright(packageJson.version)}`);

// Installation location
const installDir = getInstallDir();
console.log(`\n${c.info('[INFO]')} Installation Directory:`);
console.log(` ${c.dim(installDir)}`);

// Database location
const dbPath = getDatabasePath();
const dbExists = fs.existsSync(dbPath);
console.log(`\n${c.info('[INFO]')} Database Location:`);
console.log(` ${c.dim(dbPath)}`);
console.log(` Status: ${dbExists ? c.ok('[OK] Exists') : c.warn('[WARN] Not created yet (will be created on first run)')}`);

if (dbExists) {
const stats = fs.statSync(dbPath);
console.log(` Size: ${c.dim((stats.size / 1024).toFixed(2) + ' KB')}`);
console.log(` Modified: ${c.dim(stats.mtime.toLocaleString())}`);
}

// Environment variables
console.log(`\n${c.info('[INFO]')} Configuration:`);
console.log(` PORT: ${c.bright(process.env.PORT || '3001')} ${c.dim(process.env.PORT ? '' : '(default)')}`);
console.log(` DATABASE_PATH: ${c.dim(process.env.DATABASE_PATH || '(using default location)')}`);
console.log(` CLAUDE_CLI_PATH: ${c.dim(process.env.CLAUDE_CLI_PATH || 'claude (default)')}`);
console.log(` CONTEXT_WINDOW: ${c.dim(process.env.CONTEXT_WINDOW || '160000 (default)')}`);

// Claude projects folder
const claudeProjectsPath = path.join(process.env.HOME, '.claude', 'projects');
const projectsExists = fs.existsSync(claudeProjectsPath);
console.log(`\n${c.info('[INFO]')} Claude Projects Folder:`);
console.log(` ${c.dim(claudeProjectsPath)}`);
console.log(` Status: ${projectsExists ? c.ok('[OK] Exists') : c.warn('[WARN] Not found')}`);

// Config file location
const envFilePath = path.join(__dirname, '../.env');
const envExists = fs.existsSync(envFilePath);
console.log(`\n${c.info('[INFO]')} Configuration File:`);
console.log(` ${c.dim(envFilePath)}`);
console.log(` Status: ${envExists ? c.ok('[OK] Exists') : c.warn('[WARN] Not found (using defaults)')}`);

console.log('\n' + c.dim('═'.repeat(60)));
console.log(`\n${c.tip('[TIP]')} Hints:`);
console.log(` ${c.dim('>')} Set DATABASE_PATH env variable to use a custom database location`);
console.log(` ${c.dim('>')} Create .env file in installation directory for persistent config`);
console.log(` ${c.dim('>')} Run "claude-code-ui" or "cloudcli start" to start the server`);
console.log(` ${c.dim('>')} Access the UI at http://localhost:3001 (or custom PORT)\n`);
}

// Show help
function showHelp() {
console.log(`
╔═══════════════════════════════════════════════════════════════╗
║ Claude Code UI - Command Line Tool ║
╚═══════════════════════════════════════════════════════════════╝

Usage:
claude-code-ui [command]
cloudcli [command]

Commands:
start Start the Claude Code UI server (default)
status Show configuration and data locations
help Show this help information
version Show version information

Examples:
$ claude-code-ui # Start the server
$ cloudcli status # Show configuration
$ cloudcli help # Show help

Environment Variables:
PORT Set server port (default: 3001)
DATABASE_PATH Set custom database location
CLAUDE_CLI_PATH Set custom Claude CLI path
CONTEXT_WINDOW Set context window size (default: 160000)

Configuration:
Create a .env file in the installation directory to set
persistent environment variables. Use 'cloudcli status' to
see the installation directory path.

Documentation:
${packageJson.homepage || 'https://github.com/siteboon/claudecodeui'}

Report Issues:
${packageJson.bugs?.url || 'https://github.com/siteboon/claudecodeui/issues'}
`);
}

// Show version
function showVersion() {
console.log(`${packageJson.version}`);
}

// Start the server
async function startServer() {
// Import and run the server
await import('./index.js');
}

// Main CLI handler
async function main() {
const args = process.argv.slice(2);
const command = args[0] || 'start';

switch (command) {
case 'start':
await startServer();
break;
case 'status':
case 'info':
showStatus();
break;
case 'help':
case '-h':
case '--help':
showHelp();
break;
case 'version':
case '-v':
case '--version':
showVersion();
break;
default:
console.error(`\n❌ Unknown command: ${command}`);
console.log(' Run "cloudcli help" for usage information.\n');
process.exit(1);
}
}

// Run the CLI
main().catch(error => {
console.error('\n❌ Error:', error.message);
process.exit(1);
});
Loading