declare-cc 0.3.1 → 0.3.4
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/bin/install.js +83 -60
- package/package.json +1 -1
package/bin/install.js
CHANGED
|
@@ -475,7 +475,7 @@ function convertClaudeToOpencodeFrontmatter(content) {
|
|
|
475
475
|
convertedContent = convertedContent.replace(/\bSlashCommand\b/g, 'skill');
|
|
476
476
|
convertedContent = convertedContent.replace(/\bTodoWrite\b/g, 'todowrite');
|
|
477
477
|
// Replace /gsd:command with /gsd-command for opencode (flat command structure)
|
|
478
|
-
convertedContent = convertedContent.replace(/\/
|
|
478
|
+
convertedContent = convertedContent.replace(/\/declare:/g, '/declare-');
|
|
479
479
|
// Replace ~/.claude with ~/.config/opencode (OpenCode's correct config location)
|
|
480
480
|
convertedContent = convertedContent.replace(/~\/\.claude\b/g, '~/.config/opencode');
|
|
481
481
|
// Replace general-purpose subagent type with OpenCode's equivalent "general"
|
|
@@ -661,9 +661,11 @@ function copyFlattenedCommands(srcDir, destDir, prefix, pathPrefix, runtime) {
|
|
|
661
661
|
const globalClaudeRegex = /~\/\.claude\//g;
|
|
662
662
|
const localClaudeRegex = /\.\/\.claude\//g;
|
|
663
663
|
const opencodeDirRegex = /~\/\.opencode\//g;
|
|
664
|
+
const distToolsRegex = /dist\/declare-tools\.cjs/g;
|
|
664
665
|
content = content.replace(globalClaudeRegex, pathPrefix);
|
|
665
666
|
content = content.replace(localClaudeRegex, `./${getDirName(runtime)}/`);
|
|
666
667
|
content = content.replace(opencodeDirRegex, pathPrefix);
|
|
668
|
+
content = content.replace(distToolsRegex, `${pathPrefix}declare-tools.cjs`);
|
|
667
669
|
content = processAttribution(content, getCommitAttribution(runtime));
|
|
668
670
|
content = convertClaudeToOpencodeFrontmatter(content);
|
|
669
671
|
|
|
@@ -699,12 +701,14 @@ function copyWithPathReplacement(srcDir, destDir, pathPrefix, runtime) {
|
|
|
699
701
|
if (entry.isDirectory()) {
|
|
700
702
|
copyWithPathReplacement(srcPath, destPath, pathPrefix, runtime);
|
|
701
703
|
} else if (entry.name.endsWith('.md')) {
|
|
702
|
-
// Replace ~/.claude
|
|
704
|
+
// Replace ~/.claude/, ./.claude/, and dist/declare-tools.cjs with runtime-appropriate paths
|
|
703
705
|
let content = fs.readFileSync(srcPath, 'utf8');
|
|
704
706
|
const globalClaudeRegex = /~\/\.claude\//g;
|
|
705
707
|
const localClaudeRegex = /\.\/\.claude\//g;
|
|
708
|
+
const distToolsRegex = /dist\/declare-tools\.cjs/g;
|
|
706
709
|
content = content.replace(globalClaudeRegex, pathPrefix);
|
|
707
710
|
content = content.replace(localClaudeRegex, `./${dirName}/`);
|
|
711
|
+
content = content.replace(distToolsRegex, `${pathPrefix}declare-tools.cjs`);
|
|
708
712
|
content = processAttribution(content, getCommitAttribution(runtime));
|
|
709
713
|
|
|
710
714
|
// Convert frontmatter for opencode compatibility
|
|
@@ -733,7 +737,7 @@ function copyWithPathReplacement(srcDir, destDir, pathPrefix, runtime) {
|
|
|
733
737
|
function cleanupOrphanedFiles(configDir) {
|
|
734
738
|
const orphanedFiles = [
|
|
735
739
|
'hooks/gsd-notify.sh', // Removed in v1.6.x
|
|
736
|
-
'hooks/statusline.js', // Renamed to
|
|
740
|
+
'hooks/statusline.js', // Renamed to declare-statusline.js in v1.9.0
|
|
737
741
|
];
|
|
738
742
|
|
|
739
743
|
for (const relPath of orphanedFiles) {
|
|
@@ -751,7 +755,7 @@ function cleanupOrphanedFiles(configDir) {
|
|
|
751
755
|
function cleanupOrphanedHooks(settings) {
|
|
752
756
|
const orphanedHookPatterns = [
|
|
753
757
|
'gsd-notify.sh', // Removed in v1.6.x
|
|
754
|
-
'hooks/statusline.js', // Renamed to
|
|
758
|
+
'hooks/statusline.js', // Renamed to declare-statusline.js in v1.9.0
|
|
755
759
|
'gsd-intel-index.js', // Removed in v1.9.2
|
|
756
760
|
'gsd-intel-session.js', // Removed in v1.9.2
|
|
757
761
|
'gsd-intel-prune.js', // Removed in v1.9.2
|
|
@@ -790,13 +794,13 @@ function cleanupOrphanedHooks(settings) {
|
|
|
790
794
|
// Fix #330: Update statusLine if it points to old statusline.js path
|
|
791
795
|
if (settings.statusLine && settings.statusLine.command &&
|
|
792
796
|
settings.statusLine.command.includes('statusline.js') &&
|
|
793
|
-
!settings.statusLine.command.includes('
|
|
797
|
+
!settings.statusLine.command.includes('declare-statusline.js')) {
|
|
794
798
|
// Replace old path with new path
|
|
795
799
|
settings.statusLine.command = settings.statusLine.command.replace(
|
|
796
800
|
/statusline\.js/,
|
|
797
|
-
'
|
|
801
|
+
'declare-statusline.js'
|
|
798
802
|
);
|
|
799
|
-
console.log(` ${green}✓${reset} Updated statusline path (statusline.js →
|
|
803
|
+
console.log(` ${green}✓${reset} Updated statusline path (statusline.js → declare-statusline.js)`);
|
|
800
804
|
}
|
|
801
805
|
|
|
802
806
|
return settings;
|
|
@@ -825,7 +829,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
825
829
|
if (runtime === 'opencode') runtimeLabel = 'OpenCode';
|
|
826
830
|
if (runtime === 'gemini') runtimeLabel = 'Gemini';
|
|
827
831
|
|
|
828
|
-
console.log(` Uninstalling
|
|
832
|
+
console.log(` Uninstalling Declare from ${cyan}${runtimeLabel}${reset} at ${cyan}${locationLabel}${reset}\n`);
|
|
829
833
|
|
|
830
834
|
// Check if target directory exists
|
|
831
835
|
if (!fs.existsSync(targetDir)) {
|
|
@@ -836,59 +840,63 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
836
840
|
|
|
837
841
|
let removedCount = 0;
|
|
838
842
|
|
|
839
|
-
// 1. Remove
|
|
843
|
+
// 1. Remove Declare commands directory
|
|
840
844
|
if (isOpencode) {
|
|
841
|
-
// OpenCode: remove command/
|
|
845
|
+
// OpenCode: remove command/declare-*.md files (and old gsd-*.md)
|
|
842
846
|
const commandDir = path.join(targetDir, 'command');
|
|
843
847
|
if (fs.existsSync(commandDir)) {
|
|
844
848
|
const files = fs.readdirSync(commandDir);
|
|
845
849
|
for (const file of files) {
|
|
846
|
-
if (file.startsWith('gsd-') && file.endsWith('.md')) {
|
|
850
|
+
if ((file.startsWith('declare-') || file.startsWith('gsd-')) && file.endsWith('.md')) {
|
|
847
851
|
fs.unlinkSync(path.join(commandDir, file));
|
|
848
852
|
removedCount++;
|
|
849
853
|
}
|
|
850
854
|
}
|
|
851
|
-
console.log(` ${green}✓${reset} Removed
|
|
855
|
+
console.log(` ${green}✓${reset} Removed Declare commands from command/`);
|
|
852
856
|
}
|
|
853
857
|
} else {
|
|
854
|
-
// Claude Code & Gemini: remove commands/gsd/
|
|
855
|
-
const
|
|
856
|
-
|
|
857
|
-
fs.
|
|
858
|
-
|
|
859
|
-
|
|
858
|
+
// Claude Code & Gemini: remove commands/declare/ (and legacy commands/gsd/)
|
|
859
|
+
for (const dir of ['declare', 'gsd']) {
|
|
860
|
+
const cmdDir = path.join(targetDir, 'commands', dir);
|
|
861
|
+
if (fs.existsSync(cmdDir)) {
|
|
862
|
+
fs.rmSync(cmdDir, { recursive: true });
|
|
863
|
+
removedCount++;
|
|
864
|
+
console.log(` ${green}✓${reset} Removed commands/${dir}/`);
|
|
865
|
+
}
|
|
860
866
|
}
|
|
861
867
|
}
|
|
862
868
|
|
|
863
|
-
// 2. Remove get-shit-done
|
|
864
|
-
const
|
|
865
|
-
|
|
866
|
-
fs.
|
|
867
|
-
|
|
868
|
-
|
|
869
|
+
// 2. Remove declare/ metadata directory (and legacy get-shit-done/)
|
|
870
|
+
for (const dir of ['declare', 'get-shit-done']) {
|
|
871
|
+
const metaDir = path.join(targetDir, dir);
|
|
872
|
+
if (fs.existsSync(metaDir)) {
|
|
873
|
+
fs.rmSync(metaDir, { recursive: true });
|
|
874
|
+
removedCount++;
|
|
875
|
+
console.log(` ${green}✓${reset} Removed ${dir}/`);
|
|
876
|
+
}
|
|
869
877
|
}
|
|
870
878
|
|
|
871
|
-
// 3. Remove
|
|
879
|
+
// 3. Remove Declare agents (declare-*.md and legacy gsd-*.md files)
|
|
872
880
|
const agentsDir = path.join(targetDir, 'agents');
|
|
873
881
|
if (fs.existsSync(agentsDir)) {
|
|
874
882
|
const files = fs.readdirSync(agentsDir);
|
|
875
883
|
let agentCount = 0;
|
|
876
884
|
for (const file of files) {
|
|
877
|
-
if (file.startsWith('gsd-') && file.endsWith('.md')) {
|
|
885
|
+
if ((file.startsWith('declare-') || file.startsWith('gsd-')) && file.endsWith('.md')) {
|
|
878
886
|
fs.unlinkSync(path.join(agentsDir, file));
|
|
879
887
|
agentCount++;
|
|
880
888
|
}
|
|
881
889
|
}
|
|
882
890
|
if (agentCount > 0) {
|
|
883
891
|
removedCount++;
|
|
884
|
-
console.log(` ${green}✓${reset} Removed ${agentCount}
|
|
892
|
+
console.log(` ${green}✓${reset} Removed ${agentCount} Declare agents`);
|
|
885
893
|
}
|
|
886
894
|
}
|
|
887
895
|
|
|
888
|
-
// 4. Remove
|
|
896
|
+
// 4. Remove Declare hooks
|
|
889
897
|
const hooksDir = path.join(targetDir, 'hooks');
|
|
890
898
|
if (fs.existsSync(hooksDir)) {
|
|
891
|
-
const gsdHooks = ['
|
|
899
|
+
const gsdHooks = ['declare-statusline.js', 'declare-check-update.js', 'gsd-check-update.sh', 'gsd-statusline.js', 'gsd-check-update.js'];
|
|
892
900
|
let hookCount = 0;
|
|
893
901
|
for (const hook of gsdHooks) {
|
|
894
902
|
const hookPath = path.join(hooksDir, hook);
|
|
@@ -925,30 +933,35 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
925
933
|
let settings = readSettings(settingsPath);
|
|
926
934
|
let settingsModified = false;
|
|
927
935
|
|
|
928
|
-
// Remove GSD statusline if it references our
|
|
936
|
+
// Remove Declare/GSD statusline if it references our hooks
|
|
929
937
|
if (settings.statusLine && settings.statusLine.command &&
|
|
930
|
-
settings.statusLine.command.includes('
|
|
938
|
+
(settings.statusLine.command.includes('declare-statusline') ||
|
|
939
|
+
settings.statusLine.command.includes('gsd-statusline'))) {
|
|
931
940
|
delete settings.statusLine;
|
|
932
941
|
settingsModified = true;
|
|
933
|
-
console.log(` ${green}✓${reset} Removed
|
|
942
|
+
console.log(` ${green}✓${reset} Removed Declare statusline from settings`);
|
|
934
943
|
}
|
|
935
944
|
|
|
936
|
-
// Remove GSD hooks from SessionStart
|
|
945
|
+
// Remove Declare/GSD hooks from SessionStart
|
|
937
946
|
if (settings.hooks && settings.hooks.SessionStart) {
|
|
938
947
|
const before = settings.hooks.SessionStart.length;
|
|
939
948
|
settings.hooks.SessionStart = settings.hooks.SessionStart.filter(entry => {
|
|
940
949
|
if (entry.hooks && Array.isArray(entry.hooks)) {
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
950
|
+
const hasDeclareHook = entry.hooks.some(h =>
|
|
951
|
+
h.command && (
|
|
952
|
+
h.command.includes('declare-check-update') ||
|
|
953
|
+
h.command.includes('declare-statusline') ||
|
|
954
|
+
h.command.includes('gsd-check-update') ||
|
|
955
|
+
h.command.includes('gsd-statusline')
|
|
956
|
+
)
|
|
944
957
|
);
|
|
945
|
-
return !
|
|
958
|
+
return !hasDeclareHook;
|
|
946
959
|
}
|
|
947
960
|
return true;
|
|
948
961
|
});
|
|
949
962
|
if (settings.hooks.SessionStart.length < before) {
|
|
950
963
|
settingsModified = true;
|
|
951
|
-
console.log(` ${green}✓${reset} Removed
|
|
964
|
+
console.log(` ${green}✓${reset} Removed Declare hooks from settings`);
|
|
952
965
|
}
|
|
953
966
|
// Clean up empty array
|
|
954
967
|
if (settings.hooks.SessionStart.length === 0) {
|
|
@@ -985,7 +998,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
985
998
|
if (config.permission[permType]) {
|
|
986
999
|
const keys = Object.keys(config.permission[permType]);
|
|
987
1000
|
for (const key of keys) {
|
|
988
|
-
if (key.includes('get-shit-done')) {
|
|
1001
|
+
if (key.includes('get-shit-done') || key.includes('/declare/')) {
|
|
989
1002
|
delete config.permission[permType][key];
|
|
990
1003
|
modified = true;
|
|
991
1004
|
}
|
|
@@ -1013,11 +1026,11 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
1013
1026
|
}
|
|
1014
1027
|
|
|
1015
1028
|
if (removedCount === 0) {
|
|
1016
|
-
console.log(` ${yellow}⚠${reset} No
|
|
1029
|
+
console.log(` ${yellow}⚠${reset} No Declare files found to remove.`);
|
|
1017
1030
|
}
|
|
1018
1031
|
|
|
1019
1032
|
console.log(`
|
|
1020
|
-
${green}Done!${reset}
|
|
1033
|
+
${green}Done!${reset} Declare has been uninstalled from ${runtimeLabel}.
|
|
1021
1034
|
Your other files and settings have been preserved.
|
|
1022
1035
|
`);
|
|
1023
1036
|
}
|
|
@@ -1119,12 +1132,12 @@ function configureOpencodePermissions(isGlobal = true) {
|
|
|
1119
1132
|
config.permission = {};
|
|
1120
1133
|
}
|
|
1121
1134
|
|
|
1122
|
-
// Build the
|
|
1135
|
+
// Build the Declare path using the actual config directory
|
|
1123
1136
|
// Use ~ shorthand if it's in the default location, otherwise use full path
|
|
1124
1137
|
const defaultConfigDir = path.join(os.homedir(), '.config', 'opencode');
|
|
1125
1138
|
const gsdPath = opencodeConfigDir === defaultConfigDir
|
|
1126
|
-
? '~/.config/opencode/
|
|
1127
|
-
: `${opencodeConfigDir.replace(/\\/g, '/')}/
|
|
1139
|
+
? '~/.config/opencode/declare/*'
|
|
1140
|
+
: `${opencodeConfigDir.replace(/\\/g, '/')}/declare/*`;
|
|
1128
1141
|
|
|
1129
1142
|
let modified = false;
|
|
1130
1143
|
|
|
@@ -1152,7 +1165,7 @@ function configureOpencodePermissions(isGlobal = true) {
|
|
|
1152
1165
|
|
|
1153
1166
|
// Write config back
|
|
1154
1167
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
1155
|
-
console.log(` ${green}✓${reset} Configured read permission for
|
|
1168
|
+
console.log(` ${green}✓${reset} Configured read permission for Declare docs`);
|
|
1156
1169
|
}
|
|
1157
1170
|
|
|
1158
1171
|
/**
|
|
@@ -1197,8 +1210,8 @@ function verifyFileInstalled(filePath, description) {
|
|
|
1197
1210
|
// Local Patch Persistence
|
|
1198
1211
|
// ──────────────────────────────────────────────────────
|
|
1199
1212
|
|
|
1200
|
-
const PATCHES_DIR_NAME = '
|
|
1201
|
-
const MANIFEST_NAME = '
|
|
1213
|
+
const PATCHES_DIR_NAME = 'declare-local-patches';
|
|
1214
|
+
const MANIFEST_NAME = 'declare-file-manifest.json';
|
|
1202
1215
|
|
|
1203
1216
|
/**
|
|
1204
1217
|
* Compute SHA256 hash of file contents
|
|
@@ -1232,19 +1245,19 @@ function generateManifest(dir, baseDir) {
|
|
|
1232
1245
|
* Write file manifest after installation for future modification detection
|
|
1233
1246
|
*/
|
|
1234
1247
|
function writeManifest(configDir) {
|
|
1235
|
-
const
|
|
1236
|
-
const commandsDir = path.join(configDir, 'commands', '
|
|
1248
|
+
const declareDir = path.join(configDir, 'declare');
|
|
1249
|
+
const commandsDir = path.join(configDir, 'commands', 'declare');
|
|
1237
1250
|
const agentsDir = path.join(configDir, 'agents');
|
|
1238
1251
|
const manifest = { version: pkg.version, timestamp: new Date().toISOString(), files: {} };
|
|
1239
1252
|
|
|
1240
|
-
const
|
|
1241
|
-
for (const [rel, hash] of Object.entries(
|
|
1242
|
-
manifest.files['
|
|
1253
|
+
const declareHashes = generateManifest(declareDir);
|
|
1254
|
+
for (const [rel, hash] of Object.entries(declareHashes)) {
|
|
1255
|
+
manifest.files['declare/' + rel] = hash;
|
|
1243
1256
|
}
|
|
1244
1257
|
if (fs.existsSync(commandsDir)) {
|
|
1245
1258
|
const cmdHashes = generateManifest(commandsDir);
|
|
1246
1259
|
for (const [rel, hash] of Object.entries(cmdHashes)) {
|
|
1247
|
-
manifest.files['commands/
|
|
1260
|
+
manifest.files['commands/declare/' + rel] = hash;
|
|
1248
1261
|
}
|
|
1249
1262
|
}
|
|
1250
1263
|
if (fs.existsSync(agentsDir)) {
|
|
@@ -1319,7 +1332,7 @@ function reportLocalPatches(configDir) {
|
|
|
1319
1332
|
}
|
|
1320
1333
|
console.log('');
|
|
1321
1334
|
console.log(' Your modifications are saved in ' + cyan + PATCHES_DIR_NAME + '/' + reset);
|
|
1322
|
-
console.log(' Run ' + cyan + '/
|
|
1335
|
+
console.log(' Run ' + cyan + '/declare:reapply-patches' + reset + ' to merge them into the new version.');
|
|
1323
1336
|
console.log(' Or manually compare and merge the files.');
|
|
1324
1337
|
console.log('');
|
|
1325
1338
|
}
|
|
@@ -1435,6 +1448,16 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1435
1448
|
}
|
|
1436
1449
|
}
|
|
1437
1450
|
|
|
1451
|
+
// Copy declare-tools.cjs bundle so commands can run `node {pathPrefix}declare-tools.cjs`
|
|
1452
|
+
const bundleSrc = path.join(src, 'dist', 'declare-tools.cjs');
|
|
1453
|
+
const bundleDest = path.join(targetDir, 'declare-tools.cjs');
|
|
1454
|
+
if (fs.existsSync(bundleSrc)) {
|
|
1455
|
+
fs.copyFileSync(bundleSrc, bundleDest);
|
|
1456
|
+
console.log(` ${green}✓${reset} Installed declare-tools.cjs`);
|
|
1457
|
+
} else {
|
|
1458
|
+
failures.push('declare-tools.cjs');
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1438
1461
|
// Ensure declare/ metadata dir exists for VERSION and CHANGELOG
|
|
1439
1462
|
const declareMetaDir = path.join(targetDir, 'declare');
|
|
1440
1463
|
fs.mkdirSync(declareMetaDir, { recursive: true });
|
|
@@ -1506,11 +1529,11 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1506
1529
|
const settingsPath = path.join(targetDir, 'settings.json');
|
|
1507
1530
|
const settings = cleanupOrphanedHooks(readSettings(settingsPath));
|
|
1508
1531
|
const statuslineCommand = isGlobal
|
|
1509
|
-
? buildHookCommand(targetDir, '
|
|
1510
|
-
: 'node ' + dirName + '/hooks/
|
|
1532
|
+
? buildHookCommand(targetDir, 'declare-statusline.js')
|
|
1533
|
+
: 'node ' + dirName + '/hooks/declare-statusline.js';
|
|
1511
1534
|
const updateCheckCommand = isGlobal
|
|
1512
|
-
? buildHookCommand(targetDir, '
|
|
1513
|
-
: 'node ' + dirName + '/hooks/
|
|
1535
|
+
? buildHookCommand(targetDir, 'declare-check-update.js')
|
|
1536
|
+
: 'node ' + dirName + '/hooks/declare-check-update.js';
|
|
1514
1537
|
|
|
1515
1538
|
// Enable experimental agents for Gemini CLI (required for custom sub-agents)
|
|
1516
1539
|
if (isGemini) {
|
|
@@ -1628,13 +1651,13 @@ function handleStatusline(settings, isInteractive, callback) {
|
|
|
1628
1651
|
Your current statusline:
|
|
1629
1652
|
${dim}command: ${existingCmd}${reset}
|
|
1630
1653
|
|
|
1631
|
-
|
|
1654
|
+
Declare includes a statusline showing:
|
|
1632
1655
|
• Model name
|
|
1633
1656
|
• Current task (from todo list)
|
|
1634
1657
|
• Context window usage (color-coded)
|
|
1635
1658
|
|
|
1636
1659
|
${cyan}1${reset}) Keep existing
|
|
1637
|
-
${cyan}2${reset}) Replace with
|
|
1660
|
+
${cyan}2${reset}) Replace with Declare statusline
|
|
1638
1661
|
`);
|
|
1639
1662
|
|
|
1640
1663
|
rl.question(` Choice ${dim}[1]${reset}: `, (answer) => {
|
package/package.json
CHANGED