cc-goto-work 0.8.0
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.
- package/README.md +21 -0
- package/bin/cli.js +483 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# cc-goto-work
|
|
2
|
+
|
|
3
|
+
让 Claude Code 自动继续未完成的工作。
|
|
4
|
+
|
|
5
|
+
## 使用
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx cc-goto-work
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
运行后会显示交互式菜单,可以选择:
|
|
12
|
+
|
|
13
|
+
- **1** - 完整安装 (下载 + 配置 API + 配置 Hook)
|
|
14
|
+
- **2** - 仅下载二进制文件
|
|
15
|
+
- **3** - 仅配置 API 设置
|
|
16
|
+
- **4** - 仅配置 Claude Code Hook
|
|
17
|
+
- **0** - 退出
|
|
18
|
+
|
|
19
|
+
## 许可证
|
|
20
|
+
|
|
21
|
+
MIT License
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const readline = require('readline');
|
|
4
|
+
const https = require('https');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
const { spawn } = require('child_process');
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Constants
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
const REPO = 'pdxxxx/cc-goto-work';
|
|
15
|
+
const INSTALL_DIR = path.join(os.homedir(), '.claude', 'cc-goto-work');
|
|
16
|
+
const CONFIG_FILE = path.join(INSTALL_DIR, 'config.yaml');
|
|
17
|
+
const CLAUDE_SETTINGS_DIR = path.join(os.homedir(), '.claude');
|
|
18
|
+
const CLAUDE_SETTINGS_FILE = path.join(CLAUDE_SETTINGS_DIR, 'settings.json');
|
|
19
|
+
|
|
20
|
+
// Colors (ANSI escape codes)
|
|
21
|
+
const colors = {
|
|
22
|
+
reset: '\x1b[0m',
|
|
23
|
+
red: '\x1b[31m',
|
|
24
|
+
green: '\x1b[32m',
|
|
25
|
+
yellow: '\x1b[33m',
|
|
26
|
+
blue: '\x1b[34m',
|
|
27
|
+
cyan: '\x1b[36m',
|
|
28
|
+
bold: '\x1b[1m',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Utilities
|
|
33
|
+
// ============================================================================
|
|
34
|
+
|
|
35
|
+
function print(msg) {
|
|
36
|
+
console.log(msg);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function printBanner() {
|
|
40
|
+
print(`${colors.cyan}${colors.bold}`);
|
|
41
|
+
print('╔════════════════════════════════════════════════════════════╗');
|
|
42
|
+
print('║ cc-goto-work 安装程序 ║');
|
|
43
|
+
print('║ 让 Claude Code 自动继续未完成的工作 ║');
|
|
44
|
+
print('╚════════════════════════════════════════════════════════════╝');
|
|
45
|
+
print(`${colors.reset}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function printStep(msg) {
|
|
49
|
+
print(`${colors.green}▶${colors.reset} ${msg}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function printSuccess(msg) {
|
|
53
|
+
print(`${colors.green}✔${colors.reset} ${msg}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function printWarning(msg) {
|
|
57
|
+
print(`${colors.yellow}⚠${colors.reset} ${msg}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function printError(msg) {
|
|
61
|
+
print(`${colors.red}✖${colors.reset} ${msg}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function printMenu() {
|
|
65
|
+
print('');
|
|
66
|
+
print(`${colors.bold}请选择操作:${colors.reset}`);
|
|
67
|
+
print('');
|
|
68
|
+
print(` ${colors.cyan}1${colors.reset} - 完整安装 (下载 + 配置 API + 配置 Hook)`);
|
|
69
|
+
print(` ${colors.cyan}2${colors.reset} - 仅下载二进制文件`);
|
|
70
|
+
print(` ${colors.cyan}3${colors.reset} - 仅配置 API 设置`);
|
|
71
|
+
print(` ${colors.cyan}4${colors.reset} - 仅配置 Claude Code Hook`);
|
|
72
|
+
print(` ${colors.cyan}0${colors.reset} - 退出`);
|
|
73
|
+
print('');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ============================================================================
|
|
77
|
+
// Readline Interface
|
|
78
|
+
// ============================================================================
|
|
79
|
+
|
|
80
|
+
function createRL() {
|
|
81
|
+
return readline.createInterface({
|
|
82
|
+
input: process.stdin,
|
|
83
|
+
output: process.stdout,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function question(rl, prompt) {
|
|
88
|
+
return new Promise((resolve) => {
|
|
89
|
+
rl.question(prompt, (answer) => {
|
|
90
|
+
resolve(answer.trim());
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function promptInput(rl, prompt, defaultValue = '') {
|
|
96
|
+
const displayDefault = defaultValue ? ` [${defaultValue}]` : '';
|
|
97
|
+
const answer = await question(rl, `${prompt}${displayDefault}: `);
|
|
98
|
+
return answer || defaultValue;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function promptConfirm(rl, prompt, defaultYes = true) {
|
|
102
|
+
const hint = defaultYes ? '[Y/n]' : '[y/N]';
|
|
103
|
+
const answer = await question(rl, `${prompt} ${hint}: `);
|
|
104
|
+
if (!answer) return defaultYes;
|
|
105
|
+
return answer.toLowerCase().startsWith('y');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ============================================================================
|
|
109
|
+
// Platform Detection
|
|
110
|
+
// ============================================================================
|
|
111
|
+
|
|
112
|
+
function detectPlatform() {
|
|
113
|
+
const platform = os.platform();
|
|
114
|
+
const arch = os.arch();
|
|
115
|
+
|
|
116
|
+
if (platform === 'linux') {
|
|
117
|
+
if (arch === 'x64') return 'linux-amd64';
|
|
118
|
+
if (arch === 'arm64') return 'linux-arm64';
|
|
119
|
+
} else if (platform === 'darwin') {
|
|
120
|
+
if (arch === 'x64') return 'macos-amd64';
|
|
121
|
+
if (arch === 'arm64') return 'macos-arm64';
|
|
122
|
+
} else if (platform === 'win32') {
|
|
123
|
+
if (arch === 'x64') return 'windows-amd64';
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function getBinaryName(platformStr) {
|
|
130
|
+
if (platformStr.startsWith('windows')) {
|
|
131
|
+
return 'cc-goto-work.exe';
|
|
132
|
+
}
|
|
133
|
+
return 'cc-goto-work';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ============================================================================
|
|
137
|
+
// GitHub API
|
|
138
|
+
// ============================================================================
|
|
139
|
+
|
|
140
|
+
function httpsGet(url) {
|
|
141
|
+
return new Promise((resolve, reject) => {
|
|
142
|
+
const options = {
|
|
143
|
+
headers: { 'User-Agent': 'cc-goto-work-installer' },
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
https.get(url, options, (res) => {
|
|
147
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
148
|
+
// Follow redirect
|
|
149
|
+
httpsGet(res.headers.location).then(resolve).catch(reject);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (res.statusCode !== 200) {
|
|
154
|
+
reject(new Error(`HTTP ${res.statusCode}`));
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const chunks = [];
|
|
159
|
+
res.on('data', (chunk) => chunks.push(chunk));
|
|
160
|
+
res.on('end', () => resolve(Buffer.concat(chunks)));
|
|
161
|
+
res.on('error', reject);
|
|
162
|
+
}).on('error', reject);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async function getLatestVersion() {
|
|
167
|
+
const url = `https://api.github.com/repos/${REPO}/releases/latest`;
|
|
168
|
+
const data = await httpsGet(url);
|
|
169
|
+
const json = JSON.parse(data.toString());
|
|
170
|
+
return json.tag_name;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ============================================================================
|
|
174
|
+
// Download Binary
|
|
175
|
+
// ============================================================================
|
|
176
|
+
|
|
177
|
+
async function downloadBinary(version, platformStr) {
|
|
178
|
+
const binaryName = getBinaryName(platformStr);
|
|
179
|
+
const fileName = platformStr.startsWith('windows')
|
|
180
|
+
? `cc-goto-work-${platformStr}.exe`
|
|
181
|
+
: `cc-goto-work-${platformStr}`;
|
|
182
|
+
|
|
183
|
+
const url = `https://github.com/${REPO}/releases/download/${version}/${fileName}`;
|
|
184
|
+
const destPath = path.join(INSTALL_DIR, binaryName);
|
|
185
|
+
|
|
186
|
+
printStep(`正在下载 ${version} (${platformStr})...`);
|
|
187
|
+
|
|
188
|
+
// Ensure directory exists
|
|
189
|
+
fs.mkdirSync(INSTALL_DIR, { recursive: true });
|
|
190
|
+
|
|
191
|
+
const data = await httpsGet(url);
|
|
192
|
+
fs.writeFileSync(destPath, data);
|
|
193
|
+
|
|
194
|
+
// Make executable on Unix
|
|
195
|
+
if (!platformStr.startsWith('windows')) {
|
|
196
|
+
fs.chmodSync(destPath, 0o755);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
printSuccess(`二进制文件已下载到: ${destPath}`);
|
|
200
|
+
return destPath;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ============================================================================
|
|
204
|
+
// Configuration
|
|
205
|
+
// ============================================================================
|
|
206
|
+
|
|
207
|
+
function createConfig(apiBase, apiKey, model) {
|
|
208
|
+
const configContent = `# cc-goto-work configuration
|
|
209
|
+
# https://github.com/${REPO}
|
|
210
|
+
|
|
211
|
+
# OpenAI compatible API base URL
|
|
212
|
+
api_base: ${apiBase}
|
|
213
|
+
|
|
214
|
+
# API key for authentication
|
|
215
|
+
api_key: ${apiKey}
|
|
216
|
+
|
|
217
|
+
# Model name to use
|
|
218
|
+
model: ${model}
|
|
219
|
+
|
|
220
|
+
# Request timeout in seconds (optional)
|
|
221
|
+
timeout: 30
|
|
222
|
+
|
|
223
|
+
# Enable debug logging (optional)
|
|
224
|
+
debug: false
|
|
225
|
+
`;
|
|
226
|
+
|
|
227
|
+
fs.mkdirSync(INSTALL_DIR, { recursive: true });
|
|
228
|
+
fs.writeFileSync(CONFIG_FILE, configContent, { mode: 0o600 });
|
|
229
|
+
printSuccess(`配置文件已创建: ${CONFIG_FILE}`);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async function configureAPI(rl) {
|
|
233
|
+
print('');
|
|
234
|
+
print('此工具使用 AI 模型来检测未完成的会话。');
|
|
235
|
+
print('请提供 OpenAI 兼容的 API 端点信息。');
|
|
236
|
+
print('');
|
|
237
|
+
|
|
238
|
+
const apiBase = await promptInput(rl, 'API 地址', 'https://api.openai.com/v1');
|
|
239
|
+
const apiKey = await promptInput(rl, 'API 密钥', '');
|
|
240
|
+
const model = await promptInput(rl, '模型名称', 'gpt-4o-mini');
|
|
241
|
+
|
|
242
|
+
if (!apiKey) {
|
|
243
|
+
printWarning('未提供 API 密钥,请在使用前编辑配置文件');
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
createConfig(apiBase, apiKey, model);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// ============================================================================
|
|
250
|
+
// Claude Settings
|
|
251
|
+
// ============================================================================
|
|
252
|
+
|
|
253
|
+
function configureClaudeSettings(binaryPath) {
|
|
254
|
+
fs.mkdirSync(CLAUDE_SETTINGS_DIR, { recursive: true });
|
|
255
|
+
|
|
256
|
+
const hookConfig = {
|
|
257
|
+
hooks: {
|
|
258
|
+
Stop: [
|
|
259
|
+
{
|
|
260
|
+
hooks: [
|
|
261
|
+
{
|
|
262
|
+
type: 'command',
|
|
263
|
+
command: binaryPath,
|
|
264
|
+
timeout: 120,
|
|
265
|
+
},
|
|
266
|
+
],
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
let settings = {};
|
|
273
|
+
|
|
274
|
+
if (fs.existsSync(CLAUDE_SETTINGS_FILE)) {
|
|
275
|
+
try {
|
|
276
|
+
const content = fs.readFileSync(CLAUDE_SETTINGS_FILE, 'utf8');
|
|
277
|
+
if (content.trim()) {
|
|
278
|
+
settings = JSON.parse(content);
|
|
279
|
+
|
|
280
|
+
// Backup existing
|
|
281
|
+
fs.writeFileSync(`${CLAUDE_SETTINGS_FILE}.backup`, content);
|
|
282
|
+
printWarning(`已备份现有配置到: ${CLAUDE_SETTINGS_FILE}.backup`);
|
|
283
|
+
|
|
284
|
+
// Check if Stop hook exists
|
|
285
|
+
if (settings.hooks && settings.hooks.Stop) {
|
|
286
|
+
printWarning('Stop hook 已存在,正在更新...');
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
} catch (e) {
|
|
290
|
+
printWarning('无法解析现有配置,将创建新配置');
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Merge hooks
|
|
295
|
+
settings.hooks = settings.hooks || {};
|
|
296
|
+
settings.hooks.Stop = hookConfig.hooks.Stop;
|
|
297
|
+
|
|
298
|
+
fs.writeFileSync(CLAUDE_SETTINGS_FILE, JSON.stringify(settings, null, 2));
|
|
299
|
+
printSuccess(`Claude Code 配置已更新: ${CLAUDE_SETTINGS_FILE}`);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// ============================================================================
|
|
303
|
+
// Installation Actions
|
|
304
|
+
// ============================================================================
|
|
305
|
+
|
|
306
|
+
async function fullInstall(rl) {
|
|
307
|
+
printStep('开始完整安装...');
|
|
308
|
+
print('');
|
|
309
|
+
|
|
310
|
+
// Detect platform
|
|
311
|
+
const platformStr = detectPlatform();
|
|
312
|
+
if (!platformStr) {
|
|
313
|
+
printError(`不支持的平台: ${os.platform()} ${os.arch()}`);
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
print(` 平台: ${platformStr}`);
|
|
317
|
+
|
|
318
|
+
// Get latest version
|
|
319
|
+
printStep('获取最新版本...');
|
|
320
|
+
let version;
|
|
321
|
+
try {
|
|
322
|
+
version = await getLatestVersion();
|
|
323
|
+
print(` 版本: ${version}`);
|
|
324
|
+
} catch (e) {
|
|
325
|
+
printError(`获取版本失败: ${e.message}`);
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
print('');
|
|
330
|
+
if (!(await promptConfirm(rl, `确认安装 cc-goto-work ${version}?`))) {
|
|
331
|
+
print('安装已取消');
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Download binary
|
|
336
|
+
print('');
|
|
337
|
+
let binaryPath;
|
|
338
|
+
try {
|
|
339
|
+
binaryPath = await downloadBinary(version, platformStr);
|
|
340
|
+
} catch (e) {
|
|
341
|
+
printError(`下载失败: ${e.message}`);
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Configure API
|
|
346
|
+
print('');
|
|
347
|
+
await configureAPI(rl);
|
|
348
|
+
|
|
349
|
+
// Configure Claude settings
|
|
350
|
+
print('');
|
|
351
|
+
if (await promptConfirm(rl, '自动配置 Claude Code?')) {
|
|
352
|
+
configureClaudeSettings(binaryPath);
|
|
353
|
+
} else {
|
|
354
|
+
print('');
|
|
355
|
+
print('请手动添加以下配置到 Claude Code:');
|
|
356
|
+
print(` 命令: ${binaryPath}`);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return true;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
async function downloadOnly(rl) {
|
|
363
|
+
printStep('仅下载二进制文件...');
|
|
364
|
+
print('');
|
|
365
|
+
|
|
366
|
+
const platformStr = detectPlatform();
|
|
367
|
+
if (!platformStr) {
|
|
368
|
+
printError(`不支持的平台: ${os.platform()} ${os.arch()}`);
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
print(` 平台: ${platformStr}`);
|
|
372
|
+
|
|
373
|
+
printStep('获取最新版本...');
|
|
374
|
+
let version;
|
|
375
|
+
try {
|
|
376
|
+
version = await getLatestVersion();
|
|
377
|
+
print(` 版本: ${version}`);
|
|
378
|
+
} catch (e) {
|
|
379
|
+
printError(`获取版本失败: ${e.message}`);
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
print('');
|
|
384
|
+
try {
|
|
385
|
+
await downloadBinary(version, platformStr);
|
|
386
|
+
} catch (e) {
|
|
387
|
+
printError(`下载失败: ${e.message}`);
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
async function configureAPIOnly(rl) {
|
|
395
|
+
printStep('配置 API 设置...');
|
|
396
|
+
await configureAPI(rl);
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
async function configureHookOnly(rl) {
|
|
401
|
+
printStep('配置 Claude Code Hook...');
|
|
402
|
+
print('');
|
|
403
|
+
|
|
404
|
+
const platformStr = detectPlatform();
|
|
405
|
+
const binaryName = getBinaryName(platformStr || 'linux-amd64');
|
|
406
|
+
const binaryPath = path.join(INSTALL_DIR, binaryName);
|
|
407
|
+
|
|
408
|
+
if (!fs.existsSync(binaryPath)) {
|
|
409
|
+
printWarning(`二进制文件不存在: ${binaryPath}`);
|
|
410
|
+
if (!(await promptConfirm(rl, '是否继续配置?', false))) {
|
|
411
|
+
return false;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
configureClaudeSettings(binaryPath);
|
|
416
|
+
return true;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// ============================================================================
|
|
420
|
+
// Main
|
|
421
|
+
// ============================================================================
|
|
422
|
+
|
|
423
|
+
async function main() {
|
|
424
|
+
printBanner();
|
|
425
|
+
|
|
426
|
+
const rl = createRL();
|
|
427
|
+
|
|
428
|
+
try {
|
|
429
|
+
while (true) {
|
|
430
|
+
printMenu();
|
|
431
|
+
|
|
432
|
+
const choice = await question(rl, '请输入选项 (0-4): ');
|
|
433
|
+
|
|
434
|
+
let success = false;
|
|
435
|
+
|
|
436
|
+
switch (choice) {
|
|
437
|
+
case '1':
|
|
438
|
+
success = await fullInstall(rl);
|
|
439
|
+
break;
|
|
440
|
+
case '2':
|
|
441
|
+
success = await downloadOnly(rl);
|
|
442
|
+
break;
|
|
443
|
+
case '3':
|
|
444
|
+
success = await configureAPIOnly(rl);
|
|
445
|
+
break;
|
|
446
|
+
case '4':
|
|
447
|
+
success = await configureHookOnly(rl);
|
|
448
|
+
break;
|
|
449
|
+
case '0':
|
|
450
|
+
case 'q':
|
|
451
|
+
case 'exit':
|
|
452
|
+
print('');
|
|
453
|
+
print('再见!');
|
|
454
|
+
rl.close();
|
|
455
|
+
return;
|
|
456
|
+
default:
|
|
457
|
+
printError('无效选项,请输入 0-4');
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (success) {
|
|
462
|
+
print('');
|
|
463
|
+
printSuccess('操作完成!');
|
|
464
|
+
print('');
|
|
465
|
+
print('请重启 Claude Code 以使配置生效。');
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
print('');
|
|
469
|
+
if (!(await promptConfirm(rl, '继续其他操作?', false))) {
|
|
470
|
+
print('');
|
|
471
|
+
print('再见!');
|
|
472
|
+
break;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
} finally {
|
|
476
|
+
rl.close();
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
main().catch((err) => {
|
|
481
|
+
printError(`发生错误: ${err.message}`);
|
|
482
|
+
process.exit(1);
|
|
483
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cc-goto-work",
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"description": "让 Claude Code 自动继续未完成的工作",
|
|
5
|
+
"bin": {
|
|
6
|
+
"cc-goto-work": "./bin/cli.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"test": "node bin/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"claude",
|
|
13
|
+
"claude-code",
|
|
14
|
+
"hook",
|
|
15
|
+
"ai",
|
|
16
|
+
"automation"
|
|
17
|
+
],
|
|
18
|
+
"author": "",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/pdxxxx/cc-goto-work.git"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=14.0.0"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"bin/"
|
|
29
|
+
]
|
|
30
|
+
}
|