u
This commit is contained in:
232
claude-config.js
Normal file
232
claude-config.js
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const fs = require('fs')
|
||||||
|
const os = require('os')
|
||||||
|
const path = require('path')
|
||||||
|
const readline = require('readline')
|
||||||
|
|
||||||
|
async function askQuestion (rl, prompt, defaultValue = '') {
|
||||||
|
const suffix = defaultValue ? ` [${defaultValue}]` : ''
|
||||||
|
const answer = await new Promise(resolve => {
|
||||||
|
rl.question(`${prompt}${suffix}>> `, value => resolve(value))
|
||||||
|
})
|
||||||
|
|
||||||
|
const trimmed = answer.trim()
|
||||||
|
return trimmed || defaultValue || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function readJsonIfExists (filePath) {
|
||||||
|
if (!fs.existsSync(filePath)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const content = fs.readFileSync(filePath, 'utf8')
|
||||||
|
return JSON.parse(content)
|
||||||
|
} catch (error) {
|
||||||
|
// fall through to JS parsing below
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const content = fs.readFileSync(filePath, 'utf8')
|
||||||
|
const normalized = content
|
||||||
|
.replace(/module\.exports\s*=\s*/, 'return ')
|
||||||
|
.replace(/export\s+default\s*/, 'return ')
|
||||||
|
.replace(/export\s+const\s+(\w+)\s*=\s*/, 'const $1 = ')
|
||||||
|
.replace(/export\s+let\s+(\w+)\s*=\s*/, 'let $1 = ')
|
||||||
|
.replace(/export\s+function\s+(\w+)\s*\(/, 'function $1(')
|
||||||
|
|
||||||
|
const wrapper = new Function(`return (function(){${normalized}})()`)
|
||||||
|
return wrapper()
|
||||||
|
} catch (error) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeJson (filePath, value) {
|
||||||
|
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
||||||
|
fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8')
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveValue (source, fallbackPaths) {
|
||||||
|
for (const candidate of fallbackPaths) {
|
||||||
|
if (!candidate) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const parts = candidate.split('.')
|
||||||
|
let current = source
|
||||||
|
let found = true
|
||||||
|
|
||||||
|
for (const part of parts) {
|
||||||
|
if (
|
||||||
|
current === null ||
|
||||||
|
current === undefined ||
|
||||||
|
typeof current !== 'object' ||
|
||||||
|
!(part in current)
|
||||||
|
) {
|
||||||
|
found = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
current = current[part]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found && current !== undefined && current !== null && current !== '') {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
const settingsFile = path.join(os.homedir(), '.claude', 'settings.json')
|
||||||
|
const claudeFile = path.join(os.homedir(), '.claude.json')
|
||||||
|
|
||||||
|
const existingSettings = readJsonIfExists(settingsFile) || {}
|
||||||
|
const existingEnv = existingSettings.env || {}
|
||||||
|
|
||||||
|
const existingAuthToken = existingEnv.ANTHROPIC_AUTH_TOKEN || ''
|
||||||
|
const existingBaseUrl = existingEnv.ANTHROPIC_BASE_URL || ''
|
||||||
|
const existingModel = existingEnv.ANTHROPIC_MODEL || 'glm-5.2'
|
||||||
|
|
||||||
|
const rl = readline.createInterface({
|
||||||
|
input: process.stdin,
|
||||||
|
output: process.stdout
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
'Please \n - enter a [file path] to load secret values from a file, \n - or [leave blank] to enter values directly.'
|
||||||
|
)
|
||||||
|
|
||||||
|
const filePath = (await askQuestion(rl, '', '')).trim()
|
||||||
|
|
||||||
|
let authToken = existingAuthToken
|
||||||
|
let baseUrl = existingBaseUrl
|
||||||
|
let model = existingModel
|
||||||
|
|
||||||
|
if (filePath) {
|
||||||
|
const secret = readJsonIfExists(filePath)
|
||||||
|
if (!secret || typeof secret !== 'object' || Array.isArray(secret)) {
|
||||||
|
rl.close()
|
||||||
|
console.error(
|
||||||
|
'The selected file did not contain a JSON or JavaScript object.'
|
||||||
|
)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const keys = Object.keys(secret)
|
||||||
|
let selectedSecret = secret
|
||||||
|
|
||||||
|
if (keys.length > 0) {
|
||||||
|
console.log('Available keys:')
|
||||||
|
keys.forEach((key, index) => console.log(`${index + 1}. ${key}`))
|
||||||
|
const chosenKey = (
|
||||||
|
await askQuestion(rl, 'Choose a configuration from the file', '')
|
||||||
|
).trim()
|
||||||
|
|
||||||
|
if (chosenKey) {
|
||||||
|
const numericChoice = Number(chosenKey)
|
||||||
|
if (
|
||||||
|
!Number.isNaN(numericChoice) &&
|
||||||
|
numericChoice >= 1 &&
|
||||||
|
numericChoice <= keys.length
|
||||||
|
) {
|
||||||
|
selectedSecret = secret[keys[numericChoice - 1]]
|
||||||
|
} else {
|
||||||
|
selectedSecret = secret[chosenKey]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!selectedSecret ||
|
||||||
|
typeof selectedSecret !== 'object' ||
|
||||||
|
Array.isArray(selectedSecret)
|
||||||
|
) {
|
||||||
|
rl.close()
|
||||||
|
console.error('The selected key did not contain an object.')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
authToken =
|
||||||
|
resolveValue(selectedSecret, [
|
||||||
|
'apikey',
|
||||||
|
'apiKey',
|
||||||
|
'authToken',
|
||||||
|
'token'
|
||||||
|
]) || existingAuthToken
|
||||||
|
baseUrl =
|
||||||
|
resolveValue(selectedSecret, [
|
||||||
|
'url.anthropic',
|
||||||
|
'url.anthropic.baseUrl',
|
||||||
|
'baseUrl',
|
||||||
|
'url'
|
||||||
|
]) || existingBaseUrl
|
||||||
|
model = resolveValue(selectedSecret, ['model']) || existingModel
|
||||||
|
|
||||||
|
if (!authToken) {
|
||||||
|
console.log('Auth token was not found in the selected file.')
|
||||||
|
authToken = await askQuestion(
|
||||||
|
rl,
|
||||||
|
'ANTHROPIC_AUTH_TOKEN',
|
||||||
|
existingAuthToken
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!baseUrl) {
|
||||||
|
console.log('Base URL was not found in the selected file.')
|
||||||
|
baseUrl = await askQuestion(rl, 'ANTHROPIC_BASE_URL', existingBaseUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!model) {
|
||||||
|
console.log('Model was not found in the selected file.')
|
||||||
|
model = await askQuestion(rl, 'ANTHROPIC_MODEL', existingModel)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Loaded values from the selected file or original:')
|
||||||
|
console.log(` Auth Token: ${authToken}`)
|
||||||
|
console.log(` Base URL: ${baseUrl}`)
|
||||||
|
console.log(` Model: ${model}`)
|
||||||
|
} else {
|
||||||
|
console.log('\nPlease provide your Anthropic configuration.')
|
||||||
|
authToken = await askQuestion(rl, 'ANTHROPIC_AUTH_TOKEN', existingAuthToken)
|
||||||
|
baseUrl = await askQuestion(rl, 'ANTHROPIC_BASE_URL', existingBaseUrl)
|
||||||
|
model = await askQuestion(rl, 'ANTHROPIC_MODEL', existingModel)
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.close()
|
||||||
|
|
||||||
|
if (!authToken || !baseUrl || !model) {
|
||||||
|
console.error(
|
||||||
|
'Missing required values. Please re-run the script and provide all fields.'
|
||||||
|
)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextSettings = {
|
||||||
|
...existingSettings,
|
||||||
|
env: {
|
||||||
|
...existingSettings.env,
|
||||||
|
ANTHROPIC_AUTH_TOKEN: authToken,
|
||||||
|
ANTHROPIC_BASE_URL: baseUrl,
|
||||||
|
ANTHROPIC_MODEL: model
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeJson(settingsFile, nextSettings)
|
||||||
|
|
||||||
|
const nextClaudeConfig = {
|
||||||
|
hasCompletedOnboarding: true
|
||||||
|
}
|
||||||
|
|
||||||
|
writeJson(claudeFile, nextClaudeConfig)
|
||||||
|
|
||||||
|
console.log(`\nUpdated ${settingsFile}`)
|
||||||
|
console.log(`Updated ${claudeFile}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(error => {
|
||||||
|
console.error(error.message)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
62
claude-config.sh
Normal file
62
claude-config.sh
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Update ~/.claude/settings.json with Claude environment settings
|
||||||
|
settings_file="$HOME/.claude/settings.json"
|
||||||
|
mkdir -p "$(dirname "$settings_file")"
|
||||||
|
|
||||||
|
existing_auth_token=""
|
||||||
|
existing_base_url=""
|
||||||
|
existing_model="glm-5.2"
|
||||||
|
|
||||||
|
if [ -f "$settings_file" ]; then
|
||||||
|
existing_auth_token="$(jq -r '.env.ANTHROPIC_AUTH_TOKEN // empty' "$settings_file" 2>/dev/null)"
|
||||||
|
existing_base_url="$(jq -r '.env.ANTHROPIC_BASE_URL // empty' "$settings_file" 2>/dev/null)"
|
||||||
|
existing_model="$(jq -r '.env.ANTHROPIC_MODEL // "glm-5.2"' "$settings_file" 2>/dev/null)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Please provide your Anthropic configuration."
|
||||||
|
read -s -r -p "Anthropic auth token${existing_auth_token:+ [current value hidden]}: " auth_token
|
||||||
|
echo
|
||||||
|
read -r -p "Anthropic base URL${existing_base_url:+ [current: $existing_base_url]}: " base_url
|
||||||
|
read -r -p "Anthropic model${existing_model:+ [current: $existing_model]}: " model
|
||||||
|
|
||||||
|
if [ -z "$auth_token" ]; then
|
||||||
|
auth_token="$existing_auth_token"
|
||||||
|
fi
|
||||||
|
if [ -z "$base_url" ]; then
|
||||||
|
base_url="$existing_base_url"
|
||||||
|
fi
|
||||||
|
if [ -z "$model" ]; then
|
||||||
|
model="$existing_model"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$auth_token" ] || [ -z "$base_url" ] || [ -z "$model" ]; then
|
||||||
|
echo "Missing required values. Please re-run the script and provide all fields." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$settings_file" ]; then
|
||||||
|
jq --arg auth_token "$auth_token" \
|
||||||
|
--arg base_url "$base_url" \
|
||||||
|
--arg model "$model" \
|
||||||
|
'.env.ANTHROPIC_AUTH_TOKEN = $auth_token |
|
||||||
|
.env.ANTHROPIC_BASE_URL = $base_url |
|
||||||
|
.env.ANTHROPIC_MODEL = $model' "$settings_file" > "$settings_file.tmp" && mv "$settings_file.tmp" "$settings_file"
|
||||||
|
else
|
||||||
|
cat > "$settings_file" <<EOF
|
||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"ANTHROPIC_AUTH_TOKEN": "$auth_token",
|
||||||
|
"ANTHROPIC_BASE_URL": "$base_url",
|
||||||
|
"ANTHROPIC_MODEL": "$model"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Update ~/.claude.json with the new settings: "hasCompletedOnbording:true"
|
||||||
|
if [ -f "$HOME/.claude.json" ]; then
|
||||||
|
jq '.hasCompletedOnboarding = true' "$HOME/.claude.json" > "$HOME/.claude.json.tmp" && mv "$HOME/.claude.json.tmp" "$HOME/.claude.json"
|
||||||
|
else
|
||||||
|
echo '{"hasCompletedOnboarding": true}' > "$HOME/.claude.json"
|
||||||
|
fi
|
||||||
4
claude-install.sh
Normal file
4
claude-install.sh
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Install Claude CLI
|
||||||
|
curl -fsSL https://claude.ai/install.sh | bash
|
||||||
12
md5.js
Normal file
12
md5.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// convert plain text password to 32bit MD5 encrypted hexadecimal to be used in FutuOpenD.xml
|
||||||
|
// usage: node md5.js "your_password_here"
|
||||||
|
|
||||||
|
const crypto = require('crypto')
|
||||||
|
|
||||||
|
function md5Hex32 (str) {
|
||||||
|
return crypto.createHash('md5').update(String(str), 'utf8').digest('hex') // 32 hex chars
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example:
|
||||||
|
const password = process.argv[2] || 'your_password_here'
|
||||||
|
console.log(md5Hex32(password))
|
||||||
@@ -144,9 +144,9 @@ elif [ -f /etc/ubuntu_version ]; then
|
|||||||
MYOSVERSION=Ubt`cat /etc/ubuntu_version 2>/dev/null`
|
MYOSVERSION=Ubt`cat /etc/ubuntu_version 2>/dev/null`
|
||||||
fi
|
fi
|
||||||
if [ "$color_prompt" = yes ]; then
|
if [ "$color_prompt" = yes ]; then
|
||||||
PS1='<\[\033[$PSTYLE;${PTYPE}2m\]\t\[\033[00m\] \[\033[$PSTYLE;${PTYPE}5m\]\u\[\033[00m\] @\[\033[$PSTYLE;${PTYPE}1m\]\h\[\033[00m\] =\[\033[$PSTYLE;${PTYPE}6m\]$MYIPPUB\[\033[00m\] #\[\033[$PSTYLE;${PTYPE}5m\]$(uname -m),$(uname),$MYOSVERSION\[\033[00m\] \[\033[$PSTYLE;${PTYPE}2m\]\w/\[\033[00m\]>\n[\[\033[05;34m\]\W/\[\033[00m\]] '
|
PS1='<\[\033[$PSTYLE;${PTYPE}2m\]\t\[\033[00m\] \[\033[$PSTYLE;${PTYPE}5m\]\u\[\033[00m\] @\[\033[$PSTYLE;${PTYPE}1m\]\h\[\033[00m\] =\[\033[$PSTYLE;${PTYPE}6m\]$MYIPPUB\[\033[00m\] #\[\033[$PSTYLE;${PTYPE}5m\]$(uname -m),$(uname),$MYOSVERSION\[\033[00m\] \[\033[$PSTYLE;${PTYPE}2m\]\w/\[\033[00m\]>\n\[\033[05;44m\]\W/\[\033[00m\] '
|
||||||
else
|
else
|
||||||
PS1='<\t \u @\h =$MYIPPUB #$(uname -m),$(uname),$MYOSVERSION \w/>\n[\W/] ' # \w shows absolute path, \W shows current folder.
|
PS1='<\t \u @\h =$MYIPPUB #$(uname -m),$(uname),$MYOSVERSION \w/>\n\W/ ' # \w shows absolute path, \W shows current folder.
|
||||||
fi
|
fi
|
||||||
unset color_prompt force_color_prompt
|
unset color_prompt force_color_prompt
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user