claude-chats-sync 0.0.7 → 0.1.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/LICENSE +21 -21
- package/README.md +337 -307
- package/README.zh-CN.md +335 -305
- package/bin/claude-chats-sync +7 -7
- package/bin/claude-chats-sync.cmd +5 -5
- package/bin/claude-chats-sync.js +125 -1
- package/bin/claude-chats-sync.ps1 +17 -17
- package/package.json +2 -1
package/bin/claude-chats-sync.js
CHANGED
|
@@ -442,6 +442,7 @@ function setupGitFilter(projectPath, folderName = '.claudeCodeSessions', showMes
|
|
|
442
442
|
|
|
443
443
|
const filterScript = `#!/usr/bin/env node
|
|
444
444
|
const fs = require('fs');
|
|
445
|
+
const path = require('path');
|
|
445
446
|
|
|
446
447
|
// Pattern for Anthropic API keys (normal format)
|
|
447
448
|
const apiKeyPattern = /"primaryApiKey"\\\\s*:\\\\s*"sk-ant-[^"]*"/g;
|
|
@@ -467,6 +468,21 @@ process.stdin.on('end', () => {
|
|
|
467
468
|
cleaned = cleaned.replace(apiKeyPatternEscaped, '\\\\\\\\"primaryApiKey\\\\\\\\": \\\\"[REDACTED]\\\\"');
|
|
468
469
|
cleaned = cleaned.replace(authTokenPatternEscaped, '\\\\\\\\"ANTHROPIC_AUTH_TOKEN\\\\\\\\": \\\\"[REDACTED]\\\\"');
|
|
469
470
|
cleaned = cleaned.replace(genericApiKeyPattern, '"$1": "[REDACTED]"');
|
|
471
|
+
|
|
472
|
+
// Replace absolute path in cwd with project name only
|
|
473
|
+
// Extract the last directory name from absolute paths
|
|
474
|
+
cleaned = cleaned.replace(
|
|
475
|
+
/"cwd"\\s*:\\s*"[^"]+?\\\\([^"\\\\]+)"/g,
|
|
476
|
+
(match, projectName) => {
|
|
477
|
+
return '"cwd": "' + projectName + '"';
|
|
478
|
+
}
|
|
479
|
+
);
|
|
480
|
+
// Also handle Unix-style paths
|
|
481
|
+
cleaned = cleaned.replace(
|
|
482
|
+
/"cwd"\\s*:\\s*"\\/[^/]+\\/([^"]+)"/g,
|
|
483
|
+
'"cwd": "$1"'
|
|
484
|
+
);
|
|
485
|
+
|
|
470
486
|
process.stdout.write(cleaned);
|
|
471
487
|
});
|
|
472
488
|
`;
|
|
@@ -483,6 +499,59 @@ process.stdin.on('end', () => {
|
|
|
483
499
|
}
|
|
484
500
|
}
|
|
485
501
|
|
|
502
|
+
// 创建 smudge 过滤器脚本
|
|
503
|
+
// Create smudge filter script
|
|
504
|
+
const smudgeScriptPath = path.join(projectPath, '.gitfilters', 'smudge-sessions.js');
|
|
505
|
+
|
|
506
|
+
const smudgeScript = `#!/usr/bin/env node
|
|
507
|
+
const path = require('path');
|
|
508
|
+
|
|
509
|
+
let data = '';
|
|
510
|
+
process.stdin.setEncoding('utf8');
|
|
511
|
+
|
|
512
|
+
process.stdin.on('data', (chunk) => {
|
|
513
|
+
data += chunk;
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
process.stdin.on('end', () => {
|
|
517
|
+
// Get current working directory (absolute path)
|
|
518
|
+
const currentPath = process.cwd();
|
|
519
|
+
const projectName = path.basename(currentPath);
|
|
520
|
+
|
|
521
|
+
// Replace project name in cwd with full absolute path
|
|
522
|
+
// Pattern matches "cwd":"project-name"
|
|
523
|
+
// Replaces with "cwd":"d:\\Projects\\tubo\\project-name" or "cwd":"/home/user/projects/project-name"
|
|
524
|
+
const smudged = data.replace(
|
|
525
|
+
/"cwd"\\s*:\\s*"([^"\\\/]+)"/g,
|
|
526
|
+
(match, projectNameInFile) => {
|
|
527
|
+
// Only replace if it looks like a project name (no path separators)
|
|
528
|
+
if (!projectNameInFile.includes('\\\\') && !projectNameInFile.includes('/')) {
|
|
529
|
+
// Convert to proper absolute path format for the current OS
|
|
530
|
+
const absolutePath = path.resolve(currentPath);
|
|
531
|
+
// Escape backslashes for JSON
|
|
532
|
+
const escapedPath = absolutePath.replace(/\\\\/g, '\\\\\\\\');
|
|
533
|
+
return '"cwd": "' + escapedPath + '"';
|
|
534
|
+
}
|
|
535
|
+
return match;
|
|
536
|
+
}
|
|
537
|
+
);
|
|
538
|
+
|
|
539
|
+
process.stdout.write(smudged);
|
|
540
|
+
});
|
|
541
|
+
`;
|
|
542
|
+
|
|
543
|
+
fs.writeFileSync(smudgeScriptPath, smudgeScript, 'utf-8');
|
|
544
|
+
|
|
545
|
+
// 在 Unix-like 系统上设置为可执行
|
|
546
|
+
// Make it executable on Unix-like systems
|
|
547
|
+
if (process.platform !== 'win32') {
|
|
548
|
+
try {
|
|
549
|
+
fs.chmodSync(smudgeScriptPath, 0o755);
|
|
550
|
+
} catch (e) {
|
|
551
|
+
// Ignore permission errors
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
486
555
|
// 在 .gitconfig 中配置 Git 过滤器
|
|
487
556
|
// Configure Git filter in .gitconfig
|
|
488
557
|
const gitConfigPath = path.join(projectPath, '.gitconfig');
|
|
@@ -498,6 +567,7 @@ process.stdin.on('end', () => {
|
|
|
498
567
|
}
|
|
499
568
|
gitConfig += `[filter "claude-clean"]
|
|
500
569
|
clean = node .gitfilters/clean-sessions.js
|
|
570
|
+
smudge = node .gitfilters/smudge-sessions.js
|
|
501
571
|
`;
|
|
502
572
|
fs.writeFileSync(gitConfigPath, gitConfig, 'utf-8');
|
|
503
573
|
}
|
|
@@ -509,6 +579,10 @@ process.stdin.on('end', () => {
|
|
|
509
579
|
`git config filter.claude-clean.clean "node .gitfilters/clean-sessions.js"`,
|
|
510
580
|
{ cwd: projectPath, stdio: 'pipe' }
|
|
511
581
|
);
|
|
582
|
+
execSync(
|
|
583
|
+
`git config filter.claude-clean.smudge "node .gitfilters/smudge-sessions.js"`,
|
|
584
|
+
{ cwd: projectPath, stdio: 'pipe' }
|
|
585
|
+
);
|
|
512
586
|
} catch (err) {
|
|
513
587
|
warn(`Failed to configure local Git filter: ${err.message}`);
|
|
514
588
|
}
|
|
@@ -522,7 +596,7 @@ process.stdin.on('end', () => {
|
|
|
522
596
|
gitAttributes = fs.readFileSync(gitAttributesPath, 'utf-8');
|
|
523
597
|
}
|
|
524
598
|
|
|
525
|
-
const filterLine = `${folderName}
|
|
599
|
+
const filterLine = `${folderName}/**/*.jsonl filter=claude-clean`;
|
|
526
600
|
|
|
527
601
|
if (!gitAttributes.includes(filterLine)) {
|
|
528
602
|
if (gitAttributes && !gitAttributes.endsWith('\n')) {
|
|
@@ -618,6 +692,49 @@ function openFolder(projectPath, options = {}) {
|
|
|
618
692
|
}
|
|
619
693
|
}
|
|
620
694
|
|
|
695
|
+
/**
|
|
696
|
+
* 更新 Git 过滤器配置
|
|
697
|
+
* Update Git filter configuration
|
|
698
|
+
*/
|
|
699
|
+
function updateGitFilter(projectPath, options = {}) {
|
|
700
|
+
const { folderName = '.claudeCodeSessions' } = options;
|
|
701
|
+
|
|
702
|
+
try {
|
|
703
|
+
// 检查是否为 Git 仓库
|
|
704
|
+
// Check if we're in a Git repository
|
|
705
|
+
const gitDir = path.join(projectPath, '.git');
|
|
706
|
+
if (!fs.existsSync(gitDir)) {
|
|
707
|
+
error('Not a Git repository');
|
|
708
|
+
return false;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// 检查是否已经初始化
|
|
712
|
+
// Check if already initialized
|
|
713
|
+
const historyFolder = getHistoryFolderPath(projectPath, folderName);
|
|
714
|
+
if (!fs.existsSync(historyFolder)) {
|
|
715
|
+
error('Project not initialized. Please run "init" first.');
|
|
716
|
+
return false;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
info('Updating Git filter configuration...');
|
|
720
|
+
|
|
721
|
+
// 重新设置 Git 过滤器
|
|
722
|
+
// Re-setup Git filter
|
|
723
|
+
setupGitFilter(projectPath, folderName, true);
|
|
724
|
+
|
|
725
|
+
success('Git filter updated successfully!');
|
|
726
|
+
info('New features:');
|
|
727
|
+
info(' - Smudge filter: Restores absolute paths on checkout');
|
|
728
|
+
info(' - Enhanced clean filter: Removes absolute paths from cwd field');
|
|
729
|
+
info(' - Updated pattern: Matches all .jsonl files in subdirectories');
|
|
730
|
+
|
|
731
|
+
return true;
|
|
732
|
+
} catch (err) {
|
|
733
|
+
error(`Failed to update: ${err.message}`);
|
|
734
|
+
return false;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
621
738
|
/**
|
|
622
739
|
* 显示帮助信息
|
|
623
740
|
* Show help message
|
|
@@ -635,6 +752,7 @@ Commands:
|
|
|
635
752
|
open Open history folder in file manager
|
|
636
753
|
clean Clean sensitive data from session files
|
|
637
754
|
setup-git-filter Setup Git filter for automatic cleaning
|
|
755
|
+
update Update Git filter to latest version
|
|
638
756
|
help Show this help message
|
|
639
757
|
|
|
640
758
|
Options:
|
|
@@ -649,6 +767,9 @@ Examples:
|
|
|
649
767
|
node claude-chats-sync.js status
|
|
650
768
|
node claude-chats-sync.js clean
|
|
651
769
|
node claude-chats-sync.js setup-git-filter
|
|
770
|
+
node claude-chats-sync.js update
|
|
771
|
+
|
|
772
|
+
For more information, visit: https://github.com/tubo70/claude-chats-sync-cli
|
|
652
773
|
|
|
653
774
|
Environment Variables:
|
|
654
775
|
ANTHROPIC_AUTH_TOKEN Recommended: Configure API key via env var
|
|
@@ -705,6 +826,9 @@ function main() {
|
|
|
705
826
|
case 'setup-git-filter':
|
|
706
827
|
setupGitFilter(projectPath, options.folderName, true);
|
|
707
828
|
break;
|
|
829
|
+
case 'update':
|
|
830
|
+
updateGitFilter(projectPath, options);
|
|
831
|
+
break;
|
|
708
832
|
default:
|
|
709
833
|
error(`Unknown command: ${command}`);
|
|
710
834
|
info('Run "node claude-sync-cli.js help" for usage information');
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
# Claude Code Sync CLI - PowerShell wrapper
|
|
2
|
-
|
|
3
|
-
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
4
|
-
$CliScript = Join-Path $ScriptDir "claude-sync.js"
|
|
5
|
-
|
|
6
|
-
# Check if Node.js is installed
|
|
7
|
-
try {
|
|
8
|
-
$null = & node --version 2>&1
|
|
9
|
-
} catch {
|
|
10
|
-
Write-Host "❌ Error: Node.js is not installed or not in PATH" -ForegroundColor Red
|
|
11
|
-
Write-Host "Please install Node.js from https://nodejs.org/" -ForegroundColor Yellow
|
|
12
|
-
exit 1
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
# Run the CLI script
|
|
16
|
-
& node $CliScript $args
|
|
17
|
-
exit $LASTEXITCODE
|
|
1
|
+
# Claude Code Sync CLI - PowerShell wrapper
|
|
2
|
+
|
|
3
|
+
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
4
|
+
$CliScript = Join-Path $ScriptDir "claude-sync.js"
|
|
5
|
+
|
|
6
|
+
# Check if Node.js is installed
|
|
7
|
+
try {
|
|
8
|
+
$null = & node --version 2>&1
|
|
9
|
+
} catch {
|
|
10
|
+
Write-Host "❌ Error: Node.js is not installed or not in PATH" -ForegroundColor Red
|
|
11
|
+
Write-Host "Please install Node.js from https://nodejs.org/" -ForegroundColor Yellow
|
|
12
|
+
exit 1
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
# Run the CLI script
|
|
16
|
+
& node $CliScript $args
|
|
17
|
+
exit $LASTEXITCODE
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-chats-sync",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Cross-platform CLI tool to sync Claude Code chat sessions to project directory",
|
|
5
5
|
"main": "bin/claude-chats-sync.js",
|
|
6
6
|
"bin": {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"open": "node bin/claude-chats-sync.js open",
|
|
13
13
|
"clean": "node bin/claude-chats-sync.js clean",
|
|
14
14
|
"setup-git-filter": "node bin/claude-chats-sync.js setup-git-filter",
|
|
15
|
+
"update": "node bin/claude-chats-sync.js update",
|
|
15
16
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
16
17
|
},
|
|
17
18
|
"keywords": [
|