taphoaapi 1.0.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.
package/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # prox-claude-installer
2
+
3
+ CLI tool to install and configure Claude Code with custom proxy settings.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g prox-claude-installer
9
+ ```
10
+
11
+ Or run directly with bunx/npx:
12
+
13
+ ```bash
14
+ bunx prox-claude-installer
15
+ # or
16
+ npx prox-claude-installer
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ Simply run:
22
+
23
+ ```bash
24
+ prox-claude-installer
25
+ ```
26
+
27
+ The CLI will guide you through:
28
+ 1. Enter your Anthropic Auth Token
29
+ 2. Enter your proxy Base URL
30
+ 3. Select your operating system
31
+ 4. Choose default Claude model
32
+
33
+ ## Features
34
+
35
+ - Interactive CLI with Vietnamese interface
36
+ - Automatic Claude Code installation
37
+ - Configuration management for Claude Code
38
+ - Permanent environment variable setup
39
+ - Support for Windows, macOS, and Linux
40
+
41
+ ## Requirements
42
+
43
+ - Node.js >= 18.0.0
44
+ - Bun or npm (for running the installer)
45
+
46
+ ## License
47
+
48
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * CLI Entry Point for prox-claude-installer
5
+ * Main interactive CLI for setting up Claude Code with proxy
6
+ */
7
+
8
+ import inquirer from 'inquirer';
9
+ import chalk from 'chalk';
10
+ import { installClaude } from '../src/installer.js';
11
+ import { updateConfig } from '../src/config.js';
12
+ import { setEnvironmentVariable } from '../src/env.js';
13
+
14
+ const QUESTIONS = [
15
+ {
16
+ type: 'input',
17
+ name: 'authToken',
18
+ message: '🔑 Nhập Auth Token của bạn:',
19
+ validate: (input) => {
20
+ if (!input || input.trim() === '') {
21
+ return 'Vui lòng nhập Auth Token!';
22
+ }
23
+ if (!input.startsWith('sk-')) {
24
+ return 'Token phải bắt đầu bằng sk-';
25
+ }
26
+ return true;
27
+ }
28
+ },
29
+ {
30
+ type: 'input',
31
+ name: 'baseUrl',
32
+ message: '🌐 Nhập Base URL (proxy):',
33
+ default: 'https://taphoaapi.info.vn/',
34
+ validate: (input) => {
35
+ if (!input || input.trim() === '') {
36
+ return 'Vui lòng nhập Base URL!';
37
+ }
38
+ try {
39
+ new URL(input);
40
+ return true;
41
+ } catch {
42
+ return 'URL không hợp lệ!';
43
+ }
44
+ }
45
+ },
46
+ {
47
+ type: 'list',
48
+ name: 'os',
49
+ message: '🖥️ Chọn hệ điều hành của bạn:',
50
+ choices: [
51
+ { name: 'Windows (PowerShell)', value: 'windows' },
52
+ { name: 'macOS (Zsh)', value: 'macos' },
53
+ { name: 'Linux (Bash)', value: 'linux' }
54
+ ]
55
+ },
56
+ {
57
+ type: 'list',
58
+ name: 'model',
59
+ message: '🤖 Chọn model Claude mặc định:',
60
+ choices: [
61
+ { name: 'Opus (cao cấp nhất)', value: 'opus' },
62
+ { name: 'Sonnet (cân bằng)', value: 'sonnet' },
63
+ { name: 'Haiku (nhanh nhất)', value: 'haiku' }
64
+ ],
65
+ default: 'sonnet'
66
+ }
67
+ ];
68
+
69
+ async function main() {
70
+ // Banner
71
+ console.log(chalk.cyan(`
72
+ ╔═══════════════════════════════════════════╗
73
+ ║ ║
74
+ ║ 🚀 TaphoaAPI Claude Setup ║
75
+ ║ ║
76
+ ╚═══════════════════════════════════════════╝
77
+ `));
78
+
79
+ console.log(chalk.gray(' Đang khởi động installer...\n'));
80
+
81
+ try {
82
+ // Collect user inputs
83
+ const answers = await inquirer.prompt(QUESTIONS);
84
+
85
+ console.log(chalk.yellow('\n⚙️ Đang xử lý...\n'));
86
+
87
+ // Step 1: Install Claude Code
88
+ console.log(chalk.blue('📦 Đang cài đặt Claude Code...'));
89
+ await installClaude();
90
+ console.log(chalk.green('✅ Claude Code đã cài đặt thành công!'));
91
+
92
+ // Step 2: Update config
93
+ console.log(chalk.blue('\n⚙️ Đang cập nhật cấu hình...'));
94
+ await updateConfig(answers);
95
+ console.log(chalk.green('✅ Cấu hình đã được cập nhật!'));
96
+
97
+ // Step 3: Set environment variables
98
+ console.log(chalk.blue('\n🔧 Đang thiết lập biến môi trường...'));
99
+ await setEnvironmentVariable('ANTHROPIC_AUTH_TOKEN', answers.authToken, answers.os);
100
+ await setEnvironmentVariable('ANTHROPIC_BASE_URL', answers.baseUrl, answers.os);
101
+ console.log(chalk.green('✅ Thiết lập biến môi trường thành công!'));
102
+
103
+ // Success message
104
+ console.log(chalk.green(`
105
+
106
+ ╔═══════════════════════════════════════════╗
107
+ ║ ║
108
+ ║ ✨ Setup complete! ║
109
+ ║ ║
110
+ ║ Gõ "claude" để bắt đầu sử dụng ║
111
+ ║ ║
112
+ ╚═══════════════════════════════════════════╝
113
+ `));
114
+
115
+ } catch (error) {
116
+ console.error(chalk.red('\n❌ Lỗi:'), error.message);
117
+ process.exit(1);
118
+ }
119
+ }
120
+
121
+ main();
package/index.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * prox-claude-installer
3
+ * CLI tool to install and configure Claude Code with custom proxy settings
4
+ *
5
+ * @module prox-claude-installer
6
+ */
7
+
8
+ // Export all modules
9
+ export { installClaude, isClaudeInstalled, getClaudeVersion } from './src/installer.js';
10
+ export { updateConfig, readCurrentConfig, getConfigValue } from './src/config.js';
11
+ export { setEnvironmentVariable, getEnv, hasEnv } from './src/env.js';
12
+
13
+ // Package info
14
+ export const name = 'prox-claude-installer';
15
+ export const version = '1.0.3';
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "taphoaapi",
3
+ "version": "1.0.0",
4
+ "description": "CLI tool to install and configure Claude Code with taphoaapi proxy",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "bin": {
8
+ "taphoaapi": "./bin/cli.js"
9
+ },
10
+ "scripts": {
11
+ "start": "node bin/cli.js",
12
+ "test": "echo \"Error: no test specified\" && exit 1"
13
+ },
14
+ "keywords": [
15
+ "claude",
16
+ "anthropic",
17
+ "ai",
18
+ "cli",
19
+ "installer",
20
+ "taphoaapi"
21
+ ],
22
+ "author": "",
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "chalk": "^5.3.0",
26
+ "inquirer": "^9.2.0"
27
+ },
28
+ "engines": {
29
+ "node": ">=18.0.0"
30
+ },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/yourusername/taphoaapi"
34
+ },
35
+ "bugs": {
36
+ "url": "https://github.com/yourusername/taphoaapi/issues"
37
+ }
38
+ }
package/src/config.js ADDED
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Configuration Manager Module
3
+ * Handles reading and writing Claude Code settings
4
+ */
5
+
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+ import os from 'os';
9
+ import chalk from 'chalk';
10
+
11
+ /**
12
+ * Get the Claude config directory path
13
+ * @returns {string}
14
+ */
15
+ function getConfigDir() {
16
+ const homeDir = os.homedir();
17
+ return path.join(homeDir, '.claude');
18
+ }
19
+
20
+ /**
21
+ * Get the Claude settings.json path
22
+ * @returns {string}
23
+ */
24
+ function getConfigPath() {
25
+ return path.join(getConfigDir(), 'settings.json');
26
+ }
27
+
28
+ /**
29
+ * Read existing config or create default
30
+ * @returns {Object}
31
+ */
32
+ function readConfig() {
33
+ const configPath = getConfigPath();
34
+
35
+ if (fs.existsSync(configPath)) {
36
+ try {
37
+ const content = fs.readFileSync(configPath, 'utf-8');
38
+ return JSON.parse(content);
39
+ } catch (error) {
40
+ console.log(chalk.yellow(' ⚠️ Config file corrupted, creating new...'));
41
+ }
42
+ }
43
+
44
+ return {
45
+ env: {},
46
+ permissions: {
47
+ allow: [],
48
+ deny: []
49
+ }
50
+ };
51
+ }
52
+
53
+ /**
54
+ * Update Claude Code configuration
55
+ * @param {Object} answers - User answers from CLI
56
+ * @returns {Promise<void>}
57
+ */
58
+ export async function updateConfig(answers) {
59
+ const configPath = getConfigPath();
60
+ const configDir = getConfigDir();
61
+
62
+ // Ensure config directory exists
63
+ if (!fs.existsSync(configDir)) {
64
+ fs.mkdirSync(configDir, { recursive: true });
65
+ console.log(chalk.gray(` Created config directory: ${configDir}`));
66
+ }
67
+
68
+ // Read existing config
69
+ const config = readConfig();
70
+
71
+ // Prepare model mapping
72
+ const modelMap = {
73
+ opus: 'claude-opus-4-8',
74
+ sonnet: 'claude-sonnet-4-6',
75
+ haiku: 'claude-haiku-4-5-20251001'
76
+ };
77
+
78
+ // Update env variables
79
+ config.env = {
80
+ ANTHROPIC_AUTH_TOKEN: answers.authToken,
81
+ ANTHROPIC_BASE_URL: answers.baseUrl,
82
+ ANTHROPIC_DEFAULT_OPUS_MODEL: modelMap.opus,
83
+ ANTHROPIC_DEFAULT_SONNET_MODEL: modelMap.sonnet,
84
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: modelMap.haiku,
85
+ CLAUDE_CODE_SUBAGENT_MODEL: modelMap[answers.model] || modelMap.sonnet,
86
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1',
87
+ API_TIMEOUT_MS: '3000000'
88
+ };
89
+
90
+ // Add default permissions if not exists
91
+ if (!config.permissions) {
92
+ config.permissions = {
93
+ allow: [],
94
+ deny: []
95
+ };
96
+ }
97
+
98
+ // Write config
99
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
100
+ console.log(chalk.gray(` Updated: ${configPath}`));
101
+ }
102
+
103
+ /**
104
+ * Read current configuration
105
+ * @returns {Object|null}
106
+ */
107
+ export function readCurrentConfig() {
108
+ const configPath = getConfigPath();
109
+
110
+ if (!fs.existsSync(configPath)) {
111
+ return null;
112
+ }
113
+
114
+ try {
115
+ const content = fs.readFileSync(configPath, 'utf-8');
116
+ return JSON.parse(content);
117
+ } catch {
118
+ return null;
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Get a specific config value
124
+ * @param {string} key - Config key
125
+ * @returns {string|null}
126
+ */
127
+ export function getConfigValue(key) {
128
+ const config = readCurrentConfig();
129
+ if (!config || !config.env) return null;
130
+ return config.env[key] || null;
131
+ }
package/src/env.js ADDED
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Environment Variable Manager Module
3
+ * Handles setting permanent environment variables across OS
4
+ */
5
+
6
+ import { execSync } from 'child_process';
7
+ import fs from 'fs';
8
+ import chalk from 'chalk';
9
+
10
+ /**
11
+ * Set environment variable for Windows (PowerShell)
12
+ * @param {string} key - Environment variable name
13
+ * @param {string} value - Environment variable value
14
+ */
15
+ function setWindows(key, value) {
16
+ const escapedValue = value.replace(/"/g, '\\"');
17
+ const cmd = `[Environment]::SetEnvironmentVariable("${key}", "${escapedValue}", "User")`;
18
+
19
+ execSync(`powershell -Command "${cmd}"`, {
20
+ stdio: 'inherit',
21
+ shell: true
22
+ });
23
+ }
24
+
25
+ /**
26
+ * Set environment variable for macOS/Linux (bash/zsh)
27
+ * @param {string} key - Environment variable name
28
+ * @param {string} value - Environment variable value
29
+ * @param {string} shellType - 'bash' or 'zsh'
30
+ */
31
+ async function setUnix(key, value, shellType) {
32
+ const configFile = shellType === 'zsh' ? '.zshrc' : '.bashrc';
33
+ const exportLine = `\nexport ${key}="${value}"\n`;
34
+
35
+ // Check if export already exists
36
+ const homeDir = process.env.HOME;
37
+ const configPath = `${homeDir}/${configFile}`;
38
+
39
+ let content = '';
40
+ if (fs.existsSync(configPath)) {
41
+ content = fs.readFileSync(configPath, 'utf-8');
42
+
43
+ // Check if key already exists
44
+ const regex = new RegExp(`^export\\s+${key}=`, 'm');
45
+ if (regex.test(content)) {
46
+ // Replace existing export
47
+ content = content.replace(
48
+ new RegExp(`^export\\s+${key}=.*$\\n?`, 'm'),
49
+ `export ${key}="${value}"\n`
50
+ );
51
+ } else {
52
+ // Append new export
53
+ content += exportLine;
54
+ }
55
+ } else {
56
+ content = exportLine;
57
+ }
58
+
59
+ fs.writeFileSync(configPath, content);
60
+ console.log(chalk.gray(` Added to ~/${configFile}`));
61
+ }
62
+
63
+ /**
64
+ * Set environment variable permanently
65
+ * @param {string} key - Environment variable name
66
+ * @param {string} value - Environment variable value
67
+ * @param {string} os - Operating system: 'windows', 'macos', or 'linux'
68
+ * @returns {Promise<void>}
69
+ */
70
+ export async function setEnvironmentVariable(key, value, os) {
71
+ console.log(chalk.gray(` Setting ${key}=${value.substring(0, 10)}...`));
72
+
73
+ try {
74
+ if (os === 'windows') {
75
+ setWindows(key, value);
76
+ } else {
77
+ const shellType = os === 'macos' ? 'zsh' : 'bash';
78
+ await setUnix(key, value, shellType);
79
+ }
80
+ } catch (error) {
81
+ throw new Error(`Failed to set environment variable ${key}: ${error.message}`);
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Get environment variable (current session only)
87
+ * @param {string} key - Environment variable name
88
+ * @returns {string|null}
89
+ */
90
+ export function getEnv(key) {
91
+ return process.env[key] || null;
92
+ }
93
+
94
+ /**
95
+ * Check if environment variable is set
96
+ * @param {string} key - Environment variable name
97
+ * @returns {boolean}
98
+ */
99
+ export function hasEnv(key) {
100
+ return key in process.env;
101
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Claude Code Installer Module
3
+ * Handles installation of Claude Code CLI
4
+ */
5
+
6
+ import { execSync } from 'child_process';
7
+ import chalk from 'chalk';
8
+
9
+ /**
10
+ * Install Claude Code using bunx
11
+ * @returns {Promise<void>}
12
+ */
13
+ export async function installClaude() {
14
+ try {
15
+ console.log(chalk.gray(' Running: bunx @anthropic-ai/claude-code'));
16
+
17
+ execSync('bunx @anthropic-ai/claude-code', {
18
+ stdio: 'inherit',
19
+ env: { ...process.env }
20
+ });
21
+ } catch (error) {
22
+ // If bunx fails, try npm
23
+ console.log(chalk.yellow(' bunx not available, trying npm...'));
24
+
25
+ try {
26
+ execSync('npx @anthropic-ai/claude-code', {
27
+ stdio: 'inherit',
28
+ env: { ...process.env }
29
+ });
30
+ } catch (npmError) {
31
+ throw new Error('Không thể cài đặt Claude Code. Vui lòng kiểm tra kết nối mạng.');
32
+ }
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Check if Claude Code is already installed
38
+ * @returns {boolean}
39
+ */
40
+ export function isClaudeInstalled() {
41
+ try {
42
+ execSync('claude --version', { stdio: 'ignore' });
43
+ return true;
44
+ } catch {
45
+ return false;
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Get Claude Code version
51
+ * @returns {string|null}
52
+ */
53
+ export function getClaudeVersion() {
54
+ try {
55
+ const version = execSync('claude --version', { encoding: 'utf-8' });
56
+ return version.trim();
57
+ } catch {
58
+ return null;
59
+ }
60
+ }