v4.3.20: 미커밋 자산 일괄 정리 + 유저 워크스페이스/세션토큰 gitignore
그동안 쌓여 있던 미커밋 파일들을 정리. 소스·자산만 올리고, 개인 데이터와 런타임 상태는 gitignore로 차단. 추가된 자산: - web-ui/audiomass, web-ui/wavacity — 자체 호스팅 오디오 에디터 - web-ui/drums — 드럼 샘플 - wol-gate — WOL 프록시 컨테이너(Dockerfile + server.js) - glm-1m-fix — GLM 1M 컨텍스트 설치 스크립트(linux/windows) - RENODE_FIXES_SUMMARY*.md, CCTV정보_서울특별시.csv, .claude/plans 수정: - edge_tts_synth.py: rate 인자 추가(말하기 속도 조절) - .smallclaw/config.json: google(gemini) provider 등록 — 키는 vault 참조 - assets/SmallClaw*.png 삭제분 반영 gitignore (중요): - .smallclaw/users/*/workspace/ 전체 차단. 기존 패턴이 memory/uploads와 일부 확장자만 막아서 detective/(고소장·통화녹취·의사소견서·가족관계증명서), generated-media/, music/, pptx/ 등 앱 생성 개인 데이터 403MB가 노출돼 있었음 - .smallclaw/active-sessions.json 차단 — 살아있는 bearer 토큰과 admin 역할이 평문으로 들어있어 커밋 시 게이트웨이 관리자 자격증명이 그대로 공개됨 - google-usage.json, config.json.bak-*, workspace/memory·weather-maps· task_result_*, voice/ 등 런타임 상태도 함께 차단 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
#!/bin/bash
|
||||
# GLM context 보정 패치 v2 (Linux) — 옵션 3: 모델별 런타임 env 주입
|
||||
#
|
||||
# 설치 파일:
|
||||
# ~/.claude/statusline-glm-fix.js stdin 보정 wrapper (표시 fallback)
|
||||
# ~/.claude/launch-claude.sh 모델별 context 를 ollama에서 읽어
|
||||
# CLAUDE_CODE_MAX_CONTEXT_TOKENS 로 주입하고 exec
|
||||
# settings.json:
|
||||
# statusLine -> statusline-glm-fix.js
|
||||
# env.CLAUDE_CODE_MAX_CONTEXT_TOKENS 제거 (launch-claude.sh 가 모델별로 주입)
|
||||
#
|
||||
# 사용: bash install-linux.sh
|
||||
# 이후 claude 실행: bash ~/.claude/launch-claude.sh (ollama launch claude 대신)
|
||||
# 되돌리기: settings.json statusLine.command 를 원래 dist/index.js 경로로.
|
||||
set -euo pipefail
|
||||
|
||||
HC="$HOME/.claude"
|
||||
WRAPPER="$HC/statusline-glm-fix.js"
|
||||
LAUNCH="$HC/launch-claude.sh"
|
||||
SETTINGS="$HC/settings.json"
|
||||
PATCHER="$(mktemp -t glm-patch.XXXXXX.js)"
|
||||
trap 'rm -f "$PATCHER"' EXIT
|
||||
mkdir -p "$HC"
|
||||
|
||||
# --- 1) statusline wrapper ---
|
||||
cat > "$WRAPPER" <<'WRAPPER_EOF'
|
||||
// Thin statusline wrapper: Claude Code reports context_window_size=200000 for
|
||||
// non-Anthropic models like glm-5.2:cloud, but GLM's real context window is 1M.
|
||||
// Patch the stdin before forwarding to the real claude-dashboard, so it shows
|
||||
// e.g. "0/1M" instead of "0/200K". Leaves the plugin cache untouched.
|
||||
// (launch-claude.sh 가 모델별 env를 주입하면 이 wrapper는 대부분 no-op 이지만,
|
||||
// env 없이 그냥 실행한 경우의 표시 fallback 역할.)
|
||||
// To revert: set settings.json statusLine.command back to the dist/index.js path.
|
||||
const { spawn } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
|
||||
function resolveDashboard() {
|
||||
const base = path.join(os.homedir(), '.claude/plugins/cache/claude-dashboard/claude-dashboard');
|
||||
let dirs;
|
||||
try { dirs = fs.readdirSync(base); } catch { dirs = []; }
|
||||
const ver = dirs.filter((d) => /^\d+\.\d+\.\d+$/.test(d)).sort((a, b) => {
|
||||
const pa = a.split('.').map(Number), pb = b.split('.').map(Number);
|
||||
for (let i = 0; i < 3; i++) if (pa[i] !== pb[i]) return pa[i] - pb[i];
|
||||
return 0;
|
||||
}).pop();
|
||||
return ver ? path.join(base, ver, 'dist/index.js') : path.join(base, '1.30.0/dist/index.js');
|
||||
}
|
||||
const DASHBOARD = resolveDashboard();
|
||||
|
||||
let raw = '';
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', (c) => { raw += c; });
|
||||
process.stdin.on('end', () => {
|
||||
let payload = raw;
|
||||
try {
|
||||
const json = JSON.parse(raw);
|
||||
const cw = json?.context_window;
|
||||
const size = cw?.context_window_size;
|
||||
const modelId = String(json?.model?.id || '').toLowerCase();
|
||||
if (modelId.includes('glm') && size === 200000) {
|
||||
cw.context_window_size = 1000000;
|
||||
const usage = cw.current_usage;
|
||||
if (usage) {
|
||||
const input = (usage.input_tokens || 0) + (usage.cache_creation_input_tokens || 0) + (usage.cache_read_input_tokens || 0);
|
||||
cw.used_percentage = Math.round((input / 1000000) * 100);
|
||||
if (typeof cw.remaining_percentage === 'number') cw.remaining_percentage = 100 - cw.used_percentage;
|
||||
}
|
||||
payload = JSON.stringify(json);
|
||||
}
|
||||
} catch { /* pass through */ }
|
||||
const child = spawn('node', [DASHBOARD], { stdio: ['pipe', 'inherit', 'inherit'] });
|
||||
child.stdin.write(payload);
|
||||
child.stdin.end();
|
||||
});
|
||||
WRAPPER_EOF
|
||||
|
||||
# --- 2) launch-claude.sh ---
|
||||
cat > "$LAUNCH" <<'LAUNCH_EOF'
|
||||
#!/bin/bash
|
||||
# claude를 모델별 실제 context window에 맞춰 실행.
|
||||
# config.json 의 claude 모델 -> ollama show 로 context length -> CLAUDE_CODE_MAX_CONTEXT_TOKENS 주입 -> exec.
|
||||
# compact 트리거 = min(AUTO_COMPACT_WINDOW, 모델 context) 이라 MAX_CONTEXT_TOKENS 만 주면 됨.
|
||||
set -euo pipefail
|
||||
CFG="$HOME/.ollama/config.json"
|
||||
[ ! -f "$CFG" ] && { echo "⚠️ $CFG 없음 — env 없이 실행" >&2; exec ollama launch claude; }
|
||||
MODEL=$(node -e 'const fs=require("fs"),os=require("os");const p=os.homedir()+"/.ollama/config.json";const d=JSON.parse(fs.readFileSync(p,"utf8"));const m=(d.integrations&&d.integrations.claude&&d.integrations.claude.models)||[];process.stdout.write(m[0]||"");' 2>/dev/null || true)
|
||||
if [ -z "$MODEL" ]; then echo "⚠️ claude 모델 못 읽음 — env 없이 실행" >&2; exec ollama launch claude; fi
|
||||
CTX=$(ollama show "$MODEL" 2>/dev/null | awk '/context length/{print $3; exit}' || true)
|
||||
if ! [[ "$CTX" =~ ^[0-9]+$ ]] || [ "$CTX" -eq 0 ]; then echo "⚠️ '$MODEL' context length 못 읽음 — env 없이 실행" >&2; exec ollama launch claude; fi
|
||||
echo "▶ model=$MODEL context=$CTX → CLAUDE_CODE_MAX_CONTEXT_TOKENS=$CTX" >&2
|
||||
export CLAUDE_CODE_MAX_CONTEXT_TOKENS="$CTX"
|
||||
exec ollama launch claude
|
||||
LAUNCH_EOF
|
||||
chmod +x "$LAUNCH"
|
||||
|
||||
# --- 3) settings.json 패치: statusLine 교체 + 정적 env 제거 ---
|
||||
cat > "$PATCHER" <<'PATCHER_EOF'
|
||||
const fs = require('fs');
|
||||
const settingsPath = process.argv[2];
|
||||
const wrapperPath = process.argv[3];
|
||||
const s = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
||||
const beforeSL = s.statusLine && s.statusLine.command;
|
||||
const beforeEnv = s.env && s.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS;
|
||||
s.statusLine = { type: 'command', command: 'node ' + wrapperPath };
|
||||
// launch-claude.sh 가 모델별로 env를 주입하므로 정적 env는 제거 (충돌 방지).
|
||||
if (s.env) {
|
||||
delete s.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS;
|
||||
if (Object.keys(s.env).length === 0) delete s.env;
|
||||
}
|
||||
fs.writeFileSync(settingsPath, JSON.stringify(s, null, 2) + '\n');
|
||||
console.log('statusLine before: ' + beforeSL);
|
||||
console.log('statusLine after : ' + s.statusLine.command);
|
||||
console.log('env removed (was): ' + (beforeEnv || '(none)'));
|
||||
console.log('env now : ' + JSON.stringify(s.env || {}));
|
||||
PATCHER_EOF
|
||||
|
||||
node "$PATCHER" "$SETTINGS" "$WRAPPER"
|
||||
|
||||
echo ""
|
||||
echo "✅ 설치 완료."
|
||||
echo " 이후 claude 실행은 ollama launch claude 대신"
|
||||
echo " bash ~/.claude/launch-claude.sh 로 하세요 (모델별 context 자동 주입)."
|
||||
@@ -0,0 +1,114 @@
|
||||
# GLM context 보정 패치 v2 (Windows) — 옵션 3: 모델별 런타임 env 주입
|
||||
#
|
||||
# 설치 파일:
|
||||
# %USERPROFILE%\.claude\statusline-glm-fix.js stdin 보정 wrapper (표시 fallback)
|
||||
# %USERPROFILE%\.claude\launch-claude.ps1 모델별 context 를 ollama에서 읽어
|
||||
# CLAUDE_CODE_MAX_CONTEXT_TOKENS 로 주입하고 exec
|
||||
# settings.json:
|
||||
# statusLine -> statusline-glm-fix.js
|
||||
# env.CLAUDE_CODE_MAX_CONTEXT_TOKENS 제거 (launch-claude.ps1 가 모델별로 주입)
|
||||
#
|
||||
# 사용: powershell -ExecutionPolicy Bypass -File .\install-windows.ps1
|
||||
# 이후 claude 실행: powershell -ExecutionPolicy Bypass -File ~/.claude/launch-claude.ps1
|
||||
# (ollama launch claude 대신. 단 Windows 에서 ollama launch 통합이 있을 때.)
|
||||
# 되돌리기: settings.json statusLine.command 를 원래 dist/index.js 경로로.
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$HC = Join-Path $env:USERPROFILE '.claude'
|
||||
$Wrapper = Join-Path $HC 'statusline-glm-fix.js'
|
||||
$Launch = Join-Path $HC 'launch-claude.ps1'
|
||||
$Settings = Join-Path $HC 'settings.json'
|
||||
$Patcher = Join-Path $env:TEMP "glm-patch-$([System.Guid]::NewGuid()).js"
|
||||
New-Item -ItemType Directory -Force -Path $HC | Out-Null
|
||||
|
||||
# --- 1) statusline wrapper ---
|
||||
$wrapperJs = @'
|
||||
const { spawn } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
|
||||
function resolveDashboard() {
|
||||
const base = path.join(os.homedir(), '.claude/plugins/cache/claude-dashboard/claude-dashboard');
|
||||
let dirs;
|
||||
try { dirs = fs.readdirSync(base); } catch { dirs = []; }
|
||||
const ver = dirs.filter((d) => /^\d+\.\d+\.\d+$/.test(d)).sort((a, b) => {
|
||||
const pa = a.split('.').map(Number), pb = b.split('.').map(Number);
|
||||
for (let i = 0; i < 3; i++) if (pa[i] !== pb[i]) return pa[i] - pb[i];
|
||||
return 0;
|
||||
}).pop();
|
||||
return ver ? path.join(base, ver, 'dist/index.js') : path.join(base, '1.30.0/dist/index.js');
|
||||
}
|
||||
const DASHBOARD = resolveDashboard();
|
||||
|
||||
let raw = '';
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', (c) => { raw += c; });
|
||||
process.stdin.on('end', () => {
|
||||
let payload = raw;
|
||||
try {
|
||||
const json = JSON.parse(raw);
|
||||
const cw = json?.context_window;
|
||||
const size = cw?.context_window_size;
|
||||
const modelId = String(json?.model?.id || '').toLowerCase();
|
||||
if (modelId.includes('glm') && size === 200000) {
|
||||
cw.context_window_size = 1000000;
|
||||
const usage = cw.current_usage;
|
||||
if (usage) {
|
||||
const input = (usage.input_tokens || 0) + (usage.cache_creation_input_tokens || 0) + (usage.cache_read_input_tokens || 0);
|
||||
cw.used_percentage = Math.round((input / 1000000) * 100);
|
||||
if (typeof cw.remaining_percentage === 'number') cw.remaining_percentage = 100 - cw.used_percentage;
|
||||
}
|
||||
payload = JSON.stringify(json);
|
||||
}
|
||||
} catch { /* pass through */ }
|
||||
const child = spawn('node', [DASHBOARD], { stdio: ['pipe', 'inherit', 'inherit'] });
|
||||
child.stdin.write(payload);
|
||||
child.stdin.end();
|
||||
});
|
||||
'@
|
||||
Set-Content -Path $Wrapper -Value $wrapperJs -Encoding UTF8
|
||||
|
||||
# --- 2) launch-claude.ps1 ---
|
||||
$launchPs = @'
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$Cfg = Join-Path $env:USERPROFILE '.ollama\config.json'
|
||||
if (-not (Test-Path $Cfg)) { Write-Host "⚠️ $Cfg 없음 — env 없이 실행" -ForegroundColor Yellow; & ollama launch claude; return }
|
||||
$Model = node -e "const fs=require('fs'),os=require('os');const p=os.homedir()+'/.ollama/config.json';const d=JSON.parse(fs.readFileSync(p,'utf8'));const m=(d.integrations&&d.integrations.claude&&d.integrations.claude.models)||[];process.stdout.write(m[0]||'');"
|
||||
if (-not $Model) { Write-Host "⚠️ claude 모델 못 읽음 — env 없이 실행" -ForegroundColor Yellow; & ollama launch claude; return }
|
||||
$line = ollama show $Model 2>$null | Select-String -Pattern 'context length'
|
||||
$Ctx = ($line -split '\s+')[-1]
|
||||
if (-not ($Ctx -match '^\d+$') -or $Ctx -eq '0') { Write-Host "⚠️ '$Model' context length 못 읽음 — env 없이 실행" -ForegroundColor Yellow; & ollama launch claude; return }
|
||||
Write-Host "▶ model=$Model context=$Ctx → CLAUDE_CODE_MAX_CONTEXT_TOKENS=$Ctx" -ForegroundColor Cyan
|
||||
$env:CLAUDE_CODE_MAX_CONTEXT_TOKENS = $Ctx
|
||||
& ollama launch claude
|
||||
'@
|
||||
Set-Content -Path $Launch -Value $launchPs -Encoding UTF8
|
||||
|
||||
# --- 3) settings.json 패치: statusLine 교체 + 정적 env 제거 ---
|
||||
$patcherJs = @'
|
||||
const fs = require('fs');
|
||||
const settingsPath = process.argv[2];
|
||||
const wrapperPath = process.argv[3];
|
||||
const s = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
||||
const beforeSL = s.statusLine && s.statusLine.command;
|
||||
const beforeEnv = s.env && s.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS;
|
||||
s.statusLine = { type: 'command', command: 'node ' + wrapperPath };
|
||||
if (s.env) {
|
||||
delete s.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS;
|
||||
if (Object.keys(s.env).length === 0) delete s.env;
|
||||
}
|
||||
fs.writeFileSync(settingsPath, JSON.stringify(s, null, 2) + '\n');
|
||||
console.log('statusLine before: ' + beforeSL);
|
||||
console.log('statusLine after : ' + s.statusLine.command);
|
||||
console.log('env removed (was): ' + (beforeEnv || '(none)'));
|
||||
console.log('env now : ' + JSON.stringify(s.env || {}));
|
||||
'@
|
||||
Set-Content -Path $Patcher -Value $patcherJs -Encoding UTF8
|
||||
& node $Patcher $Settings $Wrapper
|
||||
Remove-Item -Path $Patcher -Force -ErrorAction SilentlyContinue
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "✅ 설치 완료."
|
||||
Write-Host " 이후 claude 실행은 ollama launch claude 대신"
|
||||
Write-Host " powershell -ExecutionPolicy Bypass -File ~/.claude/launch-claude.ps1"
|
||||
Reference in New Issue
Block a user