新增基础设施: - TokenTracker: 真实Token使用量追踪和费用估算(按模型定价) - SkillLoader: .claude/skills/ 扫描加载,支持YAML frontmatter元数据 - GitContext: Git分支/状态/最近提交收集,注入系统提示词 新增命令 (4个): - /init: 项目CLAUDE.md初始化向导,自动检测项目类型(Maven/Gradle/Node/Python等) - /status: 会话状态仪表板(模型、Token、内存、运行时间等) - /context: 上下文概览(CLAUDE.md、Skills、Git、系统提示词大小) - /config: 配置查看/设置(支持model快捷切换和API key显示) 增强命令 (3个): - /cost: 从占位→真实Token统计,显示input/output/cache tokens和费用 - /model: 支持快捷名称切换(sonnet/opus/haiku),显示可用模型列表 - /compact: 增强显示压缩前后消息数和Token使用量 系统提示词增强: - 集成Skills摘要和Git上下文到系统提示词 - 新增Shell环境信息和更详细的Guidelines 命令总数: 6 → 10, 工具总数: 11 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
103 lines
3.9 KiB
Java
103 lines
3.9 KiB
Java
package com.claudecode.command.impl;
|
|
|
|
import com.claudecode.command.CommandContext;
|
|
import com.claudecode.command.SlashCommand;
|
|
import com.claudecode.console.AnsiStyle;
|
|
import com.claudecode.context.ClaudeMdLoader;
|
|
import com.claudecode.context.GitContext;
|
|
import com.claudecode.context.SkillLoader;
|
|
|
|
import java.nio.file.Path;
|
|
|
|
/**
|
|
* /context 命令 —— 显示当前上下文信息。
|
|
* <p>
|
|
* 展示已加载的 CLAUDE.md、Skills、Git 上下文和 Token 预算使用情况。
|
|
*/
|
|
public class ContextCommand implements SlashCommand {
|
|
|
|
@Override
|
|
public String name() {
|
|
return "context";
|
|
}
|
|
|
|
@Override
|
|
public String description() {
|
|
return "Show current context (CLAUDE.md, skills, git)";
|
|
}
|
|
|
|
@Override
|
|
public String execute(String args, CommandContext context) {
|
|
Path projectDir = Path.of(System.getProperty("user.dir"));
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.append("\n");
|
|
sb.append(AnsiStyle.bold(" 📋 Context Overview\n"));
|
|
sb.append(" ").append("─".repeat(40)).append("\n\n");
|
|
|
|
// CLAUDE.md 状态
|
|
sb.append(AnsiStyle.bold(" CLAUDE.md:\n"));
|
|
ClaudeMdLoader loader = new ClaudeMdLoader(projectDir);
|
|
String claudeMd = loader.load();
|
|
if (claudeMd.isEmpty()) {
|
|
sb.append(AnsiStyle.dim(" (none loaded) — run /init to create one\n"));
|
|
} else {
|
|
// 显示摘要(前 200 字符)
|
|
int lines = claudeMd.split("\n").length;
|
|
sb.append(" ").append(AnsiStyle.green(lines + " lines loaded")).append("\n");
|
|
String preview = claudeMd.length() > 200
|
|
? claudeMd.substring(0, 200) + "..."
|
|
: claudeMd;
|
|
for (String line : preview.split("\n")) {
|
|
sb.append(AnsiStyle.dim(" │ " + line)).append("\n");
|
|
}
|
|
}
|
|
sb.append("\n");
|
|
|
|
// Skills 状态
|
|
sb.append(AnsiStyle.bold(" Skills:\n"));
|
|
SkillLoader skillLoader = new SkillLoader(projectDir);
|
|
var skills = skillLoader.loadAll();
|
|
if (skills.isEmpty()) {
|
|
sb.append(AnsiStyle.dim(" (none loaded) — add .md files to .claude/skills/\n"));
|
|
} else {
|
|
for (var skill : skills) {
|
|
sb.append(" • ").append(AnsiStyle.cyan(skill.name()));
|
|
if (!skill.description().isEmpty()) {
|
|
sb.append(AnsiStyle.dim(" — " + skill.description()));
|
|
}
|
|
sb.append(AnsiStyle.dim(" [" + skill.source() + "]")).append("\n");
|
|
}
|
|
}
|
|
sb.append("\n");
|
|
|
|
// Git 上下文
|
|
sb.append(AnsiStyle.bold(" Git:\n"));
|
|
GitContext git = new GitContext(projectDir).collect();
|
|
if (!git.isGitRepo()) {
|
|
sb.append(AnsiStyle.dim(" (not a git repository)\n"));
|
|
} else {
|
|
sb.append(" Branch: ").append(AnsiStyle.cyan(git.getBranch() != null ? git.getBranch() : "unknown")).append("\n");
|
|
if (git.getStatus() != null) {
|
|
long modifiedCount = git.getStatus().lines()
|
|
.filter(l -> !l.startsWith("##"))
|
|
.count();
|
|
if (modifiedCount > 0) {
|
|
sb.append(" Modified: ").append(AnsiStyle.yellow(modifiedCount + " file(s)")).append("\n");
|
|
} else {
|
|
sb.append(" Working tree: ").append(AnsiStyle.green("clean")).append("\n");
|
|
}
|
|
}
|
|
}
|
|
sb.append("\n");
|
|
|
|
// Token 预算
|
|
sb.append(AnsiStyle.bold(" System Prompt:\n"));
|
|
String sysPrompt = context.agentLoop().getSystemPrompt();
|
|
int charCount = sysPrompt.length();
|
|
int estimatedTokens = charCount / 4; // 粗略估算
|
|
sb.append(" Size: ").append(charCount).append(" chars (~").append(estimatedTokens).append(" tokens)\n");
|
|
|
|
return sb.toString();
|
|
}
|
|
}
|