mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-22 00:05:51 +00:00
feat: 添加工具类命令(teleport、recap、break-cache、env、tui 等)
- /teleport: 从 claude.ai 恢复会话 - /recap: 生成会话摘要 - /break-cache: 提示缓存管理(once/always/off/status) - /env: 环境信息展示(含密钥脱敏) - /tui: 无闪烁 TUI 模式管理 - /onboarding: 引导流程 - /perf-issue: 性能问题诊断 - /debug-tool-call: 工具调用调试 - /usage: 用量统计(合并 /cost 和 /stats 别名) Co-Authored-By: glm-5-turbo <zai-org@claude-code-best.win>
This commit is contained in:
102
src/commands/env/index.ts
vendored
Normal file
102
src/commands/env/index.ts
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
import type { Command, LocalCommandResult } from '../../types/command.js'
|
||||
import { getSessionId } from '../../bootstrap/state.js'
|
||||
|
||||
/**
|
||||
* /env — show the user a snapshot of the current environment, claude config,
|
||||
* feature flags, and version info. All secrets are masked.
|
||||
*
|
||||
* Pure-local command: no Anthropic backend dependency. Restored from stub
|
||||
* 2026-04-29 (was Anthropic-internal in upstream; safe to expose to fork
|
||||
* users since output is local-only).
|
||||
*/
|
||||
|
||||
const SECRET_KEY_PATTERNS = [
|
||||
/token/i,
|
||||
/secret/i,
|
||||
/password/i,
|
||||
/api[_-]?key/i,
|
||||
/auth/i,
|
||||
/private/i,
|
||||
/credential/i,
|
||||
/jwt/i,
|
||||
/session[_-]?id$/i,
|
||||
]
|
||||
|
||||
function isSecretKey(key: string): boolean {
|
||||
return SECRET_KEY_PATTERNS.some(rx => rx.test(key))
|
||||
}
|
||||
|
||||
function maskValue(value: string): string {
|
||||
if (value.length <= 8) return '***'
|
||||
return `${value.slice(0, 4)}…${value.slice(-2)} (${value.length} chars)`
|
||||
}
|
||||
|
||||
const ENV_PREFIX_ALLOWLIST = [
|
||||
'CLAUDE_',
|
||||
'FEATURE_',
|
||||
'ANTHROPIC_',
|
||||
'BUN_',
|
||||
'NODE_',
|
||||
'GEMINI_',
|
||||
'OPENAI_',
|
||||
'GROK_',
|
||||
'CCR_',
|
||||
'KAIROS_',
|
||||
'BUGHUNTER_',
|
||||
]
|
||||
|
||||
function shouldShowEnv(key: string): boolean {
|
||||
return ENV_PREFIX_ALLOWLIST.some(prefix => key.startsWith(prefix))
|
||||
}
|
||||
|
||||
function formatEnvVars(): string {
|
||||
const entries = Object.entries(process.env)
|
||||
.filter(([k]) => shouldShowEnv(k))
|
||||
.map(([k, v]): [string, string] => {
|
||||
const display = isSecretKey(k) && v ? maskValue(v) : (v ?? '')
|
||||
return [k, display]
|
||||
})
|
||||
.sort(([a], [b]) => a.localeCompare(b))
|
||||
|
||||
if (entries.length === 0) {
|
||||
return ' (no recognized env vars set)'
|
||||
}
|
||||
return entries.map(([k, v]) => ` ${k}=${v}`).join('\n')
|
||||
}
|
||||
|
||||
function formatRuntime(): string {
|
||||
const lines = [
|
||||
` platform: ${process.platform} ${process.arch}`,
|
||||
` cwd: ${process.cwd()}`,
|
||||
` pid: ${process.pid}`,
|
||||
` bun: ${typeof Bun !== 'undefined' ? Bun.version : 'n/a'}`,
|
||||
` node: ${process.version}`,
|
||||
` session: ${getSessionId()}`,
|
||||
]
|
||||
return lines.join('\n')
|
||||
}
|
||||
|
||||
const env: Command = {
|
||||
type: 'local',
|
||||
name: 'env',
|
||||
description: 'Show current environment, runtime, and feature flags',
|
||||
isHidden: false,
|
||||
isEnabled: () => true,
|
||||
supportsNonInteractive: true,
|
||||
load: async () => ({
|
||||
call: async (): Promise<LocalCommandResult> => {
|
||||
const text = [
|
||||
'## Runtime',
|
||||
formatRuntime(),
|
||||
'',
|
||||
'## Environment Variables (allowlisted prefixes)',
|
||||
formatEnvVars(),
|
||||
'',
|
||||
'_Secrets matching token/password/auth/api_key are masked. Set additional `CLAUDE_*` / `FEATURE_*` env vars to see them here._',
|
||||
].join('\n')
|
||||
return { type: 'text', value: text }
|
||||
},
|
||||
}),
|
||||
}
|
||||
|
||||
export default env
|
||||
Reference in New Issue
Block a user