claude-autopm 2.8.9 → 2.11.1
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/autopm/.claude/agents-compressed-example.md +218 -0
- package/autopm/.claude/quick-ref/agent-quick-ref.md +153 -0
- package/autopm/.claude/quick-ref/common-patterns.md +215 -0
- package/autopm/.claude/quick-ref/context7-queries.md +122 -0
- package/autopm/.claude/quick-ref/tdd-cycle.md +49 -0
- package/autopm/.claude/quick-ref/workflow-steps.md +103 -0
- package/autopm/.claude/rules/agent-mandatory-optimized.md +91 -0
- package/autopm/.claude/rules/context7-enforcement-optimized.md +221 -0
- package/autopm/.claude/templates/claude-templates/addons/task-workflow.md +612 -0
- package/autopm/.claude/templates/claude-templates/base-optimized.md +245 -0
- package/autopm/.claude/templates/claude-templates/base.md +66 -14
- package/autopm/.claude/templates/plugin-manifest-template.xml +36 -0
- package/bin/commands/plugin.js +126 -1
- package/install/install.js +4 -0
- package/install/plugin-manifest-generator.js +182 -0
- package/lib/plugins/PluginManager.js +131 -0
- package/package.json +1 -1
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Plugin Manifest Generator
|
|
5
|
+
*
|
|
6
|
+
* Generates compressed plugin manifests for token-optimized CLAUDE.md
|
|
7
|
+
* Reduces plugin metadata from thousands of tokens to ~50 tokens per plugin
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
|
|
13
|
+
const CHARS_PER_TOKEN = 4;
|
|
14
|
+
|
|
15
|
+
function estimateTokens(text) {
|
|
16
|
+
const normalized = text.replace(/\s+/g, ' ').trim();
|
|
17
|
+
return Math.ceil(normalized.length / CHARS_PER_TOKEN);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Generate compressed manifest for a single plugin
|
|
22
|
+
*/
|
|
23
|
+
function generatePluginManifest(pluginData, pluginId) {
|
|
24
|
+
const agentNames = (pluginData.agents || []).map(a => a.name).join('|');
|
|
25
|
+
const commandNames = (pluginData.commands || []).map(c => c.name).join('|');
|
|
26
|
+
const ruleCount = (pluginData.rules || []).length;
|
|
27
|
+
|
|
28
|
+
const manifest = `<plugin id="${pluginId}">
|
|
29
|
+
agents: ${agentNames || 'None'}
|
|
30
|
+
commands: ${commandNames || 'None'}
|
|
31
|
+
rules: ${ruleCount} files (on-demand)
|
|
32
|
+
📖 .claude/plugins/${pluginId}/
|
|
33
|
+
</plugin>`;
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
manifest,
|
|
37
|
+
tokens: estimateTokens(manifest),
|
|
38
|
+
stats: {
|
|
39
|
+
agents: pluginData.agents?.length || 0,
|
|
40
|
+
commands: pluginData.commands?.length || 0,
|
|
41
|
+
rules: ruleCount
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Generate complete plugins section for CLAUDE.md
|
|
48
|
+
*/
|
|
49
|
+
function generatePluginsSection(installedPlugins, packagesDir) {
|
|
50
|
+
const manifests = [];
|
|
51
|
+
const pluginList = [];
|
|
52
|
+
let totalTokens = 0;
|
|
53
|
+
let totalFiles = 0;
|
|
54
|
+
|
|
55
|
+
installedPlugins.forEach(pluginId => {
|
|
56
|
+
const pluginPath = path.join(packagesDir, `plugin-${pluginId}`, 'plugin.json');
|
|
57
|
+
|
|
58
|
+
if (!fs.existsSync(pluginPath)) {
|
|
59
|
+
console.warn(`⚠️ Plugin ${pluginId} not found at ${pluginPath}`);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
const pluginData = JSON.parse(fs.readFileSync(pluginPath, 'utf-8'));
|
|
65
|
+
const result = generatePluginManifest(pluginData, pluginId);
|
|
66
|
+
|
|
67
|
+
manifests.push(result.manifest);
|
|
68
|
+
pluginList.push(pluginId);
|
|
69
|
+
totalTokens += result.tokens;
|
|
70
|
+
totalFiles += result.stats.agents + result.stats.commands + result.stats.rules;
|
|
71
|
+
|
|
72
|
+
console.log(`✅ ${pluginId}: ${result.tokens} tokens (${result.stats.agents} agents, ${result.stats.commands} commands, ${result.stats.rules} rules)`);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error(`❌ Error processing ${pluginId}:`, error.message);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const pluginsSection = `<plugins>
|
|
79
|
+
<installed>${pluginList.join('|')}</installed>
|
|
80
|
+
|
|
81
|
+
<manifest>
|
|
82
|
+
${manifests.join('\n\n')}
|
|
83
|
+
</manifest>
|
|
84
|
+
|
|
85
|
+
<lazy_loading>
|
|
86
|
+
<enabled>true</enabled>
|
|
87
|
+
<triggers>
|
|
88
|
+
commands: "/[plugin-id]:[command-name]"
|
|
89
|
+
agents: "@[agent-name]" (from plugin)
|
|
90
|
+
rules: on-violation or explicit reference
|
|
91
|
+
</triggers>
|
|
92
|
+
</lazy_loading>
|
|
93
|
+
|
|
94
|
+
<usage>
|
|
95
|
+
Commands: Type /[plugin-id]:[command] to invoke
|
|
96
|
+
Agents: Type @[agent-name] to invoke
|
|
97
|
+
Rules: Automatically loaded when needed
|
|
98
|
+
Files: All available in .claude/plugins/[plugin-id]/
|
|
99
|
+
</usage>
|
|
100
|
+
</plugins>`;
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
section: pluginsSection,
|
|
104
|
+
tokens: estimateTokens(pluginsSection),
|
|
105
|
+
totalFiles,
|
|
106
|
+
pluginCount: pluginList.length
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Calculate token savings
|
|
112
|
+
*/
|
|
113
|
+
function calculateSavings(optimizedTokens, totalFiles) {
|
|
114
|
+
// Estimate: average 600 tokens per agent, 300 per command, 1500 per rule
|
|
115
|
+
const estimatedOldTokens = totalFiles * 800; // Conservative average
|
|
116
|
+
const savings = estimatedOldTokens - optimizedTokens;
|
|
117
|
+
const percent = ((savings / estimatedOldTokens) * 100).toFixed(1);
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
old: estimatedOldTokens,
|
|
121
|
+
new: optimizedTokens,
|
|
122
|
+
saved: savings,
|
|
123
|
+
percent
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Main function
|
|
129
|
+
*/
|
|
130
|
+
function main() {
|
|
131
|
+
const args = process.argv.slice(2);
|
|
132
|
+
|
|
133
|
+
if (args.length < 2) {
|
|
134
|
+
console.log('Usage: node plugin-manifest-generator.js <packages-dir> <plugin1,plugin2,...>');
|
|
135
|
+
console.log('Example: node plugin-manifest-generator.js ./packages core,pm,cloud');
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const packagesDir = path.resolve(args[0]);
|
|
140
|
+
const pluginIds = args[1].split(',').map(p => p.trim());
|
|
141
|
+
|
|
142
|
+
console.log('\n🔧 Plugin Manifest Generator');
|
|
143
|
+
console.log('='.repeat(70));
|
|
144
|
+
console.log(`Packages directory: ${packagesDir}`);
|
|
145
|
+
console.log(`Plugins to process: ${pluginIds.join(', ')}`);
|
|
146
|
+
console.log('');
|
|
147
|
+
|
|
148
|
+
const result = generatePluginsSection(pluginIds, packagesDir);
|
|
149
|
+
|
|
150
|
+
console.log('\n' + '='.repeat(70));
|
|
151
|
+
console.log('📊 Generation Complete');
|
|
152
|
+
console.log('='.repeat(70));
|
|
153
|
+
console.log(`Plugins processed: ${result.pluginCount}`);
|
|
154
|
+
console.log(`Total files: ${result.totalFiles}`);
|
|
155
|
+
console.log(`Manifest tokens: ${result.tokens}`);
|
|
156
|
+
|
|
157
|
+
const savings = calculateSavings(result.tokens, result.totalFiles);
|
|
158
|
+
console.log(`\n💰 Token Savings:`);
|
|
159
|
+
console.log(` Old system (est): ${savings.old.toLocaleString()} tokens`);
|
|
160
|
+
console.log(` New manifest: ${savings.new.toLocaleString()} tokens`);
|
|
161
|
+
console.log(` Savings: ${savings.saved.toLocaleString()} tokens (${savings.percent}%)`);
|
|
162
|
+
|
|
163
|
+
console.log('\n📄 Generated Manifest:');
|
|
164
|
+
console.log('='.repeat(70));
|
|
165
|
+
console.log(result.section);
|
|
166
|
+
console.log('='.repeat(70));
|
|
167
|
+
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Export for use in other scripts
|
|
172
|
+
module.exports = {
|
|
173
|
+
generatePluginManifest,
|
|
174
|
+
generatePluginsSection,
|
|
175
|
+
calculateSavings,
|
|
176
|
+
estimateTokens
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// Run if called directly
|
|
180
|
+
if (require.main === module) {
|
|
181
|
+
main();
|
|
182
|
+
}
|
|
@@ -908,6 +908,137 @@ class PluginManager extends EventEmitter {
|
|
|
908
908
|
}
|
|
909
909
|
}
|
|
910
910
|
|
|
911
|
+
/**
|
|
912
|
+
* Update an installed plugin to the latest version
|
|
913
|
+
* @param {string} pluginName - Plugin name (with or without scope)
|
|
914
|
+
* @param {Object} options - Update options
|
|
915
|
+
* @param {boolean} options.verbose - Show detailed output
|
|
916
|
+
* @param {boolean} options.force - Force update even if versions match
|
|
917
|
+
* @returns {Promise<Object>} Update result
|
|
918
|
+
*/
|
|
919
|
+
async updatePlugin(pluginName, options = {}) {
|
|
920
|
+
const { verbose = false, force = false } = options;
|
|
921
|
+
const { execSync } = require('child_process');
|
|
922
|
+
|
|
923
|
+
const fullName = pluginName.includes('/') ? pluginName : `${this.options.scopePrefix}/${pluginName}`;
|
|
924
|
+
const shortName = pluginName.replace(`${this.options.scopePrefix}/`, '');
|
|
925
|
+
|
|
926
|
+
this.emit('update:start', { name: fullName });
|
|
927
|
+
|
|
928
|
+
try {
|
|
929
|
+
// Check if plugin is installed
|
|
930
|
+
if (!this.isInstalled(shortName)) {
|
|
931
|
+
throw new Error(`Plugin ${shortName} is not installed. Use 'autopm plugin install ${shortName}' to install it.`);
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// Get current installed version from plugin.json
|
|
935
|
+
const plugin = this.plugins.get(fullName);
|
|
936
|
+
if (!plugin || !plugin.loaded) {
|
|
937
|
+
await this.loadPlugin(fullName);
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
const currentMetadata = this.plugins.get(fullName)?.metadata;
|
|
941
|
+
const currentVersion = currentMetadata?.version || 'unknown';
|
|
942
|
+
|
|
943
|
+
// Check npm for available version
|
|
944
|
+
let availableVersion;
|
|
945
|
+
try {
|
|
946
|
+
const npmInfo = execSync(`npm view ${fullName} version`, { encoding: 'utf-8' }).trim();
|
|
947
|
+
availableVersion = npmInfo;
|
|
948
|
+
} catch (error) {
|
|
949
|
+
throw new Error(`Failed to check npm for ${fullName}: ${error.message}`);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
// Compare versions
|
|
953
|
+
if (currentVersion === availableVersion && !force) {
|
|
954
|
+
this.emit('update:skipped', {
|
|
955
|
+
name: fullName,
|
|
956
|
+
reason: 'Already up to date',
|
|
957
|
+
version: currentVersion
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
return {
|
|
961
|
+
upToDate: true,
|
|
962
|
+
currentVersion,
|
|
963
|
+
updated: false
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
if (verbose) {
|
|
968
|
+
console.log(` Current version: ${currentVersion}`);
|
|
969
|
+
console.log(` Available version: ${availableVersion}`);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
// Uninstall old version
|
|
973
|
+
if (verbose) {
|
|
974
|
+
console.log(` Removing old version...`);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
const wasEnabled = this.isEnabled(shortName);
|
|
978
|
+
await this.uninstallPlugin(fullName);
|
|
979
|
+
|
|
980
|
+
// Update npm package globally
|
|
981
|
+
if (verbose) {
|
|
982
|
+
console.log(` Updating npm package...`);
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
try {
|
|
986
|
+
execSync(`npm update -g ${fullName}`, {
|
|
987
|
+
stdio: verbose ? 'inherit' : 'ignore'
|
|
988
|
+
});
|
|
989
|
+
} catch (error) {
|
|
990
|
+
throw new Error(`Failed to update npm package: ${error.message}`);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
// Reload plugin metadata from updated package
|
|
994
|
+
await this.discoverPlugins();
|
|
995
|
+
|
|
996
|
+
// Reinstall with new version
|
|
997
|
+
if (verbose) {
|
|
998
|
+
console.log(` Installing new version...`);
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
const installResult = await this.installPlugin(fullName);
|
|
1002
|
+
|
|
1003
|
+
// Restore enabled state
|
|
1004
|
+
if (wasEnabled) {
|
|
1005
|
+
this.enablePlugin(shortName);
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
this.emit('update:complete', {
|
|
1009
|
+
name: fullName,
|
|
1010
|
+
oldVersion: currentVersion,
|
|
1011
|
+
newVersion: availableVersion,
|
|
1012
|
+
stats: {
|
|
1013
|
+
agents: installResult.agentsInstalled,
|
|
1014
|
+
commands: installResult.commandsInstalled,
|
|
1015
|
+
rules: installResult.rulesInstalled,
|
|
1016
|
+
hooks: installResult.hooksInstalled,
|
|
1017
|
+
scripts: installResult.scriptsInstalled
|
|
1018
|
+
}
|
|
1019
|
+
});
|
|
1020
|
+
|
|
1021
|
+
return {
|
|
1022
|
+
updated: true,
|
|
1023
|
+
oldVersion: currentVersion,
|
|
1024
|
+
newVersion: availableVersion,
|
|
1025
|
+
stats: {
|
|
1026
|
+
agents: installResult.agentsInstalled,
|
|
1027
|
+
commands: installResult.commandsInstalled,
|
|
1028
|
+
rules: installResult.rulesInstalled,
|
|
1029
|
+
hooks: installResult.hooksInstalled,
|
|
1030
|
+
scripts: installResult.scriptsInstalled
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1033
|
+
} catch (error) {
|
|
1034
|
+
this.emit('update:error', {
|
|
1035
|
+
name: fullName,
|
|
1036
|
+
error: error.message
|
|
1037
|
+
});
|
|
1038
|
+
throw error;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
|
|
911
1042
|
/**
|
|
912
1043
|
* Get list of installed plugins (from registry)
|
|
913
1044
|
*/
|
package/package.json
CHANGED