zco-claude 0.0.8__py3-none-any.whl

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.
Files changed (34) hide show
  1. ClaudeSettings/DOT.claudeignore +7 -0
  2. ClaudeSettings/README.md +100 -0
  3. ClaudeSettings/commands/generate_changelog.sh +49 -0
  4. ClaudeSettings/commands/show_env +92 -0
  5. ClaudeSettings/commands/zco-clean +164 -0
  6. ClaudeSettings/commands/zco-git-summary +15 -0
  7. ClaudeSettings/commands/zco-git-tag +42 -0
  8. ClaudeSettings/hooks/CHANGELOG.md +157 -0
  9. ClaudeSettings/hooks/README.md +254 -0
  10. ClaudeSettings/hooks/save_chat_plain.py +148 -0
  11. ClaudeSettings/hooks/save_chat_spec.py +398 -0
  12. ClaudeSettings/rules/README.md +270 -0
  13. ClaudeSettings/rules/go/.golangci.yml.template +170 -0
  14. ClaudeSettings/rules/go/GoBuildAutoVersion.v250425.md +95 -0
  15. ClaudeSettings/rules/go/check-standards.sh +128 -0
  16. ClaudeSettings/rules/go/coding-standards.md +973 -0
  17. ClaudeSettings/rules/go/example.go +207 -0
  18. ClaudeSettings/rules/go/go-testing.md +691 -0
  19. ClaudeSettings/rules/go/list-comments.sh +85 -0
  20. ClaudeSettings/settings.sample.json +71 -0
  21. ClaudeSettings/skills/README.md +225 -0
  22. ClaudeSettings/skills/zco-docs-update/SKILL.md +381 -0
  23. ClaudeSettings/skills/zco-help/SKILL.md +601 -0
  24. ClaudeSettings/skills/zco-plan/SKILL.md +661 -0
  25. ClaudeSettings/skills/zco-plan-new/SKILL.md +585 -0
  26. ClaudeSettings/zco-scripts/co-docs-update.sh +150 -0
  27. ClaudeSettings/zco-scripts/test_update_plan_metadata.py +328 -0
  28. ClaudeSettings/zco-scripts/update-plan-metadata.py +324 -0
  29. zco_claude-0.0.8.dist-info/METADATA +190 -0
  30. zco_claude-0.0.8.dist-info/RECORD +34 -0
  31. zco_claude-0.0.8.dist-info/WHEEL +5 -0
  32. zco_claude-0.0.8.dist-info/entry_points.txt +3 -0
  33. zco_claude-0.0.8.dist-info/top_level.txt +1 -0
  34. zco_claude_init.py +1732 -0
@@ -0,0 +1,254 @@
1
+ # Claude Code 对话自动保存 Hooks
2
+
3
+ 自动保存 Claude Code 对话记录到 Markdown 文件。
4
+
5
+ ## 📦 可用脚本
6
+
7
+ ### 1. `save-conversation-simple.py` - 简洁版 ⭐推荐
8
+
9
+ **特点**:
10
+ - 只保存核心对话内容(用户提问 + Claude 回答)
11
+ - 格式简洁,接近终端输出体验
12
+ - 适合日常快速回顾
13
+
14
+ **文件名**: `claude_log_YYMMDD_HHMMSS_simple.md`
15
+
16
+ ### 2. `save-conversation-enhanced.py` - 增强版
17
+
18
+ **特点**:
19
+ - 包含工具使用统计(如 Bash 14次、Edit 7次)
20
+ - 提取参考资源列表(读取的文件、访问的 URL)
21
+ - 附带详细的工具调用参数
22
+ - 适合深度分析和复盘
23
+
24
+ **文件名**: `YYMMDDHH_{关键词}.md` + `YYMMDDHH_{关键词}_resources.txt`
25
+
26
+ ### 3. `install-to-project.sh` - 一键安装脚本
27
+
28
+ 快速将 hooks 部署到其他项目。
29
+
30
+ ## 🚀 快速安装到其他项目
31
+
32
+ ```bash
33
+ # 方法 1: 使用安装脚本(推荐)
34
+ ./.claude/hooks/install-to-project.sh /path/to/your-project
35
+
36
+ # 方法 2: 手动复制
37
+ mkdir -p /path/to/project/.claude/hooks
38
+ cp .claude/hooks/save-conversation-*.py /path/to/project/.claude/hooks/
39
+ ```
40
+
41
+ 然后在目标项目创建 `.claude/settings.local.json`:
42
+ ```json
43
+ {
44
+ "hooks": {
45
+ "Stop": [{
46
+ "hooks": [{
47
+ "type": "command",
48
+ "command": "python3 \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/save-conversation-simple.py"
49
+ }]
50
+ }]
51
+ }
52
+ }
53
+ ```
54
+
55
+ ## 🔧 跨项目使用说明
56
+
57
+ ### ✅ 关键点
58
+
59
+ **不需要配置的内容**:
60
+ - ✅ `python3` 路径:已在系统 PATH 中,不需要绝对路径
61
+ - ✅ 项目路径:脚本自动从 hook 输入数据中获取 `cwd`
62
+ - ✅ transcript 路径:由 Claude Code 自动传递
63
+
64
+ **环境变量**:
65
+ - `$CLAUDE_PROJECT_DIR`:Claude Code 自动设置,指向当前项目根目录
66
+ - 可以在 `command` 中使用这个变量引用脚本
67
+
68
+ ### 三种部署方案
69
+
70
+ #### 方案 1:每个项目独立(推荐)
71
+
72
+ ```bash
73
+ # 安装
74
+ ./install-to-project.sh /path/to/project-A
75
+ ./install-to-project.sh /path/to/project-B
76
+
77
+ # 每个项目都有自己的配置和脚本副本
78
+ project-A/.claude/hooks/save-conversation-*.py
79
+ project-B/.claude/hooks/save-conversation-*.py
80
+ ```
81
+
82
+ **优点**:每个项目可以独立定制脚本
83
+
84
+ #### 方案 2:全局共享
85
+
86
+ ```bash
87
+ # 1. 创建全局 hooks 目录
88
+ mkdir -p ~/.claude/shared-hooks
89
+ cp .claude/hooks/save-conversation-*.py ~/.claude/shared-hooks/
90
+
91
+ # 2. 在各项目的 .claude/settings.local.json 中引用
92
+ {
93
+ "hooks": {
94
+ "Stop": [{
95
+ "hooks": [{
96
+ "type": "command",
97
+ "command": "python3 ~/.claude/shared-hooks/save-conversation-simple.py"
98
+ }]
99
+ }]
100
+ }
101
+ }
102
+ ```
103
+
104
+ **优点**:所有项目共享一份脚本,便于统一维护
105
+
106
+ #### 方案 3:符号链接
107
+
108
+ ```bash
109
+ # 创建中央仓库
110
+ mkdir -p ~/code/claude-hooks
111
+ cp .claude/hooks/save-conversation-*.py ~/code/claude-hooks/
112
+
113
+ # 在各项目中创建符号链接
114
+ mkdir -p /path/to/project/.claude/hooks
115
+ ln -s ~/code/claude-hooks/save-conversation-simple.py \
116
+ /path/to/project/.claude/hooks/
117
+ ```
118
+
119
+ **优点**:便于版本控制和同步更新
120
+
121
+ ## 工作原理
122
+
123
+ 1. **用户提问** → Claude 回答 → 对话进行中...
124
+ 2. **对话结束** → 触发 `Stop` Hook
125
+ 3. **脚本执行**:
126
+ - 读取会话文件(`transcript_path`)
127
+ - 解析 JSONL 格式的对话记录
128
+ - 提取用户提问和 Claude 回答
129
+ - 生成 Markdown 格式
130
+ - 保存到 `_.claude_hist/`
131
+
132
+ ## 查看保存的对话
133
+
134
+ ```bash
135
+ # 查看最近的对话记录
136
+ ls -lt _.claude_hist/ | head -10
137
+
138
+ # 查看今天的对话
139
+ ls _.claude_hist/$(date +%y%m%d)*.md
140
+
141
+ # 搜索包含特定关键词的对话
142
+ grep -l "API" _.claude_hist/*.md
143
+ ```
144
+
145
+ ## 手动保存对话
146
+
147
+ 如果自动保存未触发,可以手动运行脚本:
148
+
149
+ ```bash
150
+ # 需要知道会话文件路径
151
+ python3 .claude/hooks/save-conversation.py << EOF
152
+ {
153
+ "hook_event_name": "Stop",
154
+ "transcript_path": "~/.claude/projects/项目路径/sessions/会话ID.jsonl",
155
+ "cwd": "$(pwd)"
156
+ }
157
+ EOF
158
+ ```
159
+
160
+ ## 禁用自动保存
161
+
162
+ 如果需要临时禁用自动保存,编辑 `.claude/settings.json`,注释掉 `hooks.Stop` 部分:
163
+
164
+ ```json
165
+ {
166
+ "hooks": {
167
+ // "Stop": [...] // 注释掉这行即可禁用
168
+ }
169
+ }
170
+ ```
171
+
172
+ ## 自定义配置
173
+
174
+ ### 修改关键词提取数量
175
+
176
+ 编辑 `save-conversation.py`,找到 `extract_keywords` 函数:
177
+
178
+ ```python
179
+ def extract_keywords(text: str, max_keywords: int = 3): # 改为你想要的数量
180
+ ```
181
+
182
+ ### 修改文件名格式
183
+
184
+ 编辑 `save-conversation.py`,找到文件名生成部分:
185
+
186
+ ```python
187
+ timestamp = datetime.now().strftime('%y%m%d%H') # 自定义时间格式
188
+ filename = f"{timestamp}_{keywords}.md" # 自定义文件名格式
189
+ ```
190
+
191
+ ### 添加更多元数据
192
+
193
+ 在 Markdown 头部添加更多信息:
194
+
195
+ ```python
196
+ lines.append(f"**时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
197
+ lines.append(f"**项目**: {project_dir}\n") # 添加项目路径
198
+ lines.append(f"**会话ID**: {session_id}\n") # 添加会话ID
199
+ ```
200
+
201
+ ## 故障排查
202
+
203
+ ### 对话没有自动保存
204
+
205
+ 1. 检查脚本是否可执行:
206
+ ```bash
207
+ ls -la .claude/hooks/save-conversation.py
208
+ # 应该有 x 权限
209
+ ```
210
+
211
+ 2. 检查 hooks 配置:
212
+ ```bash
213
+ cat .claude/settings.json | grep -A 10 "hooks"
214
+ ```
215
+
216
+ 3. 查看错误日志(如果有):
217
+ ```bash
218
+ # Claude Code 的日志通常在控制台输出
219
+ ```
220
+
221
+ ### 文件名中的关键词不准确
222
+
223
+ 这是正常的,关键词提取是基于简单的算法。你可以:
224
+ 1. 手动重命名文件
225
+ 2. 修改 `extract_keywords` 函数的逻辑
226
+ 3. 添加更多停用词
227
+
228
+ ### Python 3 未安装
229
+
230
+ 确保系统安装了 Python 3:
231
+
232
+ ```bash
233
+ python3 --version
234
+ # 应该显示 Python 3.x.x
235
+ ```
236
+
237
+ 如果未安装:
238
+ ```bash
239
+ # Ubuntu/Debian
240
+ sudo apt install python3
241
+
242
+ # macOS
243
+ brew install python3
244
+ ```
245
+
246
+ ## 维护
247
+
248
+ - **定期清理**: `_.claude_hist/` 目录可能会积累大量文件,建议定期归档
249
+ - **备份**: 重要对话建议备份到其他位置
250
+ - **版本控制**: 可以选择将对话记录提交到 Git(但建议使用 `.gitignore` 排除)
251
+
252
+ ## 更新日志
253
+
254
+ - 2026-01-06: 初始版本,支持自动保存对话为 Markdown 格式
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Claude Code 对话保存脚本(简单版)
4
+ 直接从 transcript 提取纯文本,保留 Claude 的原始输出格式
5
+
6
+ Environment Variables:
7
+ - YJ_CLAUDE_CHAT_SAVE_PLAIN: Must be "1" to enable this hook
8
+ - YJ_CLAUDE_CHAT_SAVE_DIR: Output directory (default: _.claude_hist)
9
+ """
10
+ import json
11
+ import os
12
+ import sys
13
+ import subprocess
14
+ from datetime import datetime
15
+ from pathlib import Path
16
+
17
+ def get_git_root(project_dir: Path=None) -> Path:
18
+ """获取当前 Git 仓库根目录"""
19
+ try:
20
+ # 执行 git rev-parse --show-toplevel 命令
21
+ if project_dir:
22
+ result = subprocess.run(
23
+ ['git', '-C', str(project_dir), 'rev-parse', '--show-toplevel'],
24
+ capture_output=True, text=True, check=True
25
+ )
26
+ else:
27
+ result = subprocess.run(
28
+ ['git', 'rev-parse', '--show-toplevel'],
29
+ capture_output=True, text=True, check=True
30
+ )
31
+ return Path(result.stdout.strip())
32
+ except (subprocess.CalledProcessError, FileNotFoundError):
33
+ return Path.cwd()
34
+
35
+ def get_hist_dir(project_dir: Path=None) -> Path:
36
+ """获取历史记录目录"""
37
+ hist_dir_name = os.environ.get('YJ_CLAUDE_CHAT_SAVE_DIR', None)
38
+ git_root = get_git_root(project_dir)
39
+ if not hist_dir_name:
40
+ hist_dir = git_root / '_.claude_hist'
41
+ else:
42
+ hist_dir = os.path.abspath(os.path.join(str(git_root), hist_dir_name))
43
+ hist_dir.mkdir(exist_ok=True)
44
+ return hist_dir
45
+
46
+
47
+ def extract_text_from_message(msg: dict) -> str:
48
+ """从消息中提取纯文本"""
49
+ msg_type = msg.get('type', '')
50
+ if msg_type not in ['user', 'assistant']:
51
+ return ''
52
+
53
+ inner_msg = msg.get('message', {})
54
+ content = inner_msg.get('content', '')
55
+
56
+ # 用户消息通常是字符串
57
+ if isinstance(content, str):
58
+ return content
59
+
60
+ # Assistant 消息是列表
61
+ if isinstance(content, list):
62
+ text_parts = []
63
+ for item in content:
64
+ if isinstance(item, dict):
65
+ if item.get('type') == 'text':
66
+ text_parts.append(item.get('text', ''))
67
+ return '\n'.join(text_parts)
68
+
69
+ return ''
70
+
71
+
72
+ def save_simple_conversation(transcript_path: str, project_dir: str):
73
+ """保存对话为简单的纯文本格式"""
74
+ try:
75
+ # 解析 transcript
76
+ messages = []
77
+ with open(transcript_path, 'r', encoding='utf-8') as f:
78
+ for line in f:
79
+ try:
80
+ msg = json.loads(line.strip())
81
+ if msg.get('type') in ['user', 'assistant']:
82
+ messages.append(msg)
83
+ except:
84
+ continue
85
+
86
+ if not messages:
87
+ print("No messages to save", file=sys.stderr)
88
+ return
89
+
90
+ # 生成文件名
91
+ timestamp = datetime.now().strftime('%y%m%d_%H%M%S')
92
+ filename = f"claude_log_{timestamp}_simple.md"
93
+ hist_dir = get_hist_dir(project_dir)
94
+ output_file = hist_dir / filename
95
+
96
+ # 生成简单的 Markdown
97
+ with open(output_file, 'w', encoding='utf-8') as f:
98
+ f.write(f"# Claude Code Conversation\n\n")
99
+ f.write(f"**Time**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
100
+ f.write("---\n\n")
101
+
102
+ for msg in messages:
103
+ msg_type = msg.get('type', '')
104
+ text = extract_text_from_message(msg)
105
+
106
+ if not text.strip():
107
+ continue
108
+
109
+ if msg_type == 'user':
110
+ f.write(f"**User**:\n{text}\n\n")
111
+ elif msg_type == 'assistant':
112
+ f.write(f"**Claude**:\n{text}\n\n")
113
+
114
+ f.write(f"\n---\n*Generated at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*\n")
115
+
116
+ print(f"Simple conversation saved to: {output_file}", file=sys.stderr)
117
+
118
+ except Exception as e:
119
+ print(f"Error: {e}", file=sys.stderr)
120
+ import traceback
121
+ traceback.print_exc(file=sys.stderr)
122
+
123
+
124
+ def main():
125
+ try:
126
+ # Check if this hook is enabled via environment variable
127
+ if os.environ.get('YJ_CLAUDE_CHAT_SAVE_PLAIN') != '1':
128
+ # Silently exit if not enabled
129
+ sys.exit(0)
130
+
131
+ input_data = json.load(sys.stdin)
132
+ hook_event = input_data.get('hook_event_name', '')
133
+
134
+ if hook_event == 'Stop':
135
+ transcript_path = input_data.get('transcript_path', '')
136
+ cwd = input_data.get('cwd', '')
137
+
138
+ if transcript_path and cwd:
139
+ save_simple_conversation(transcript_path, cwd)
140
+
141
+ sys.exit(0)
142
+ except Exception as e:
143
+ print(f"Hook error: {e}", file=sys.stderr)
144
+ sys.exit(1)
145
+
146
+
147
+ if __name__ == '__main__':
148
+ main()