@claudetools/tools 0.4.0 → 0.5.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.
@@ -0,0 +1,256 @@
1
+ // =============================================================================
2
+ // CodeDNA Usage Analytics
3
+ // =============================================================================
4
+ //
5
+ // Track CodeDNA usage patterns, token savings, and generator popularity
6
+ // for analytics and optimization insights.
7
+ //
8
+ import { storeFact, searchMemory } from './api-client.js';
9
+ import { DEFAULT_USER_ID, resolveProjectId } from './config.js';
10
+ export class UsageAnalytics {
11
+ static instance;
12
+ constructor() { }
13
+ static getInstance() {
14
+ if (!UsageAnalytics.instance) {
15
+ UsageAnalytics.instance = new UsageAnalytics();
16
+ }
17
+ return UsageAnalytics.instance;
18
+ }
19
+ /**
20
+ * Track a successful generation
21
+ */
22
+ async trackGeneration(event) {
23
+ try {
24
+ const usageEvent = {
25
+ ...event,
26
+ timestamp: new Date().toISOString(),
27
+ success: true,
28
+ };
29
+ const userId = DEFAULT_USER_ID;
30
+ const projectId = event.projectId || resolveProjectId();
31
+ // Store as fact in memory system
32
+ await storeFact(projectId, 'CodeDNA', 'GENERATION_COMPLETED', event.generator || event.operation, JSON.stringify(usageEvent), userId);
33
+ console.log('[CodeDNA Analytics]', {
34
+ operation: event.operation,
35
+ generator: event.generator,
36
+ tokensSaved: event.tokensSaved,
37
+ });
38
+ }
39
+ catch (error) {
40
+ // Don't fail the operation if analytics fails
41
+ console.error('[CodeDNA Analytics Failed]', error);
42
+ }
43
+ }
44
+ /**
45
+ * Track a validation
46
+ */
47
+ async trackValidation(spec, valid, entityName, fieldCount, projectId) {
48
+ await this.trackGeneration({
49
+ operation: 'validate_spec',
50
+ entityName,
51
+ fieldCount,
52
+ specLength: spec.length,
53
+ success: valid,
54
+ projectId,
55
+ });
56
+ }
57
+ }
58
+ // Export singleton instance
59
+ export const analytics = UsageAnalytics.getInstance();
60
+ /**
61
+ * Query usage analytics
62
+ */
63
+ export async function getUsageAnalytics(query) {
64
+ const userId = DEFAULT_USER_ID;
65
+ const projectId = resolveProjectId();
66
+ // Search for usage facts
67
+ const searchQuery = `CodeDNA GENERATION_COMPLETED ${query.operation || ''}`;
68
+ const result = await searchMemory(projectId, searchQuery, 500, userId);
69
+ // Parse usage events from facts
70
+ const events = result.relevant_facts
71
+ .map((fact) => {
72
+ try {
73
+ return JSON.parse(fact.fact);
74
+ }
75
+ catch {
76
+ return null;
77
+ }
78
+ })
79
+ .filter((e) => e !== null)
80
+ .filter((e) => {
81
+ const eventTime = new Date(e.timestamp).getTime();
82
+ const start = new Date(query.startTime).getTime();
83
+ const end = new Date(query.endTime).getTime();
84
+ return eventTime >= start && eventTime <= end;
85
+ })
86
+ .filter((e) => !query.operation || e.operation === query.operation)
87
+ .filter((e) => !query.generator || e.generator === query.generator)
88
+ .filter((e) => !query.framework || e.framework === query.framework);
89
+ // Calculate statistics
90
+ const totalTokensSaved = events.reduce((sum, e) => sum + (e.tokensSaved || 0), 0);
91
+ const totalLinesOfCode = events.reduce((sum, e) => sum + (e.linesOfCode || 0), 0);
92
+ const totalFiles = events.reduce((sum, e) => sum + (e.filesGenerated || 0), 0);
93
+ // Generator statistics
94
+ const generatorStats = {};
95
+ events.forEach(event => {
96
+ const gen = event.generator || 'unknown';
97
+ if (!generatorStats[gen]) {
98
+ generatorStats[gen] = { count: 0, tokensSaved: 0, linesOfCode: 0, filesGenerated: 0 };
99
+ }
100
+ generatorStats[gen].count++;
101
+ generatorStats[gen].tokensSaved += event.tokensSaved || 0;
102
+ generatorStats[gen].linesOfCode += event.linesOfCode || 0;
103
+ generatorStats[gen].filesGenerated += event.filesGenerated || 0;
104
+ });
105
+ // Framework statistics
106
+ const frameworkStats = {};
107
+ events.forEach(event => {
108
+ if (event.framework) {
109
+ frameworkStats[event.framework] = (frameworkStats[event.framework] || 0) + 1;
110
+ }
111
+ });
112
+ // Options usage
113
+ let authCount = 0;
114
+ let validationCount = 0;
115
+ let testsCount = 0;
116
+ events.forEach(event => {
117
+ if (event.options?.auth)
118
+ authCount++;
119
+ if (event.options?.validation)
120
+ validationCount++;
121
+ if (event.options?.tests)
122
+ testsCount++;
123
+ });
124
+ // Entity patterns
125
+ const entityPatterns = {};
126
+ events.forEach(event => {
127
+ if (event.entityName) {
128
+ entityPatterns[event.entityName] = (entityPatterns[event.entityName] || 0) + 1;
129
+ }
130
+ });
131
+ // Average execution time
132
+ const executionTimes = events.filter(e => e.executionTimeMs).map(e => e.executionTimeMs);
133
+ const avgExecutionTime = executionTimes.length > 0
134
+ ? executionTimes.reduce((sum, t) => sum + t, 0) / executionTimes.length
135
+ : undefined;
136
+ return {
137
+ totalGenerations: events.length,
138
+ totalTokensSaved,
139
+ avgTokensSavedPerGeneration: events.length > 0 ? totalTokensSaved / events.length : 0,
140
+ totalLinesOfCode,
141
+ totalFiles,
142
+ generatorStats,
143
+ frameworkStats,
144
+ optionsUsage: {
145
+ auth: authCount,
146
+ validation: validationCount,
147
+ tests: testsCount,
148
+ },
149
+ entityPatterns,
150
+ avgExecutionTime,
151
+ recentGenerations: events.slice(0, 10).reverse(),
152
+ };
153
+ }
154
+ /**
155
+ * Get analytics for last 24 hours
156
+ */
157
+ export async function getLast24HoursAnalytics() {
158
+ const endTime = new Date().toISOString();
159
+ const startTime = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
160
+ return getUsageAnalytics({ startTime, endTime });
161
+ }
162
+ /**
163
+ * Get analytics for last 7 days
164
+ */
165
+ export async function getLast7DaysAnalytics() {
166
+ const endTime = new Date().toISOString();
167
+ const startTime = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
168
+ return getUsageAnalytics({ startTime, endTime });
169
+ }
170
+ /**
171
+ * Get analytics for last 30 days
172
+ */
173
+ export async function getLast30DaysAnalytics() {
174
+ const endTime = new Date().toISOString();
175
+ const startTime = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();
176
+ return getUsageAnalytics({ startTime, endTime });
177
+ }
178
+ /**
179
+ * Print analytics report
180
+ */
181
+ export function printAnalytics(result, title = 'CodeDNA Usage Analytics') {
182
+ console.log('\n=================================================');
183
+ console.log(title);
184
+ console.log('=================================================\n');
185
+ console.log('Overview:');
186
+ console.log(` Total Generations: ${result.totalGenerations}`);
187
+ console.log(` Total Tokens Saved: ${result.totalTokensSaved.toLocaleString()}`);
188
+ console.log(` Avg Tokens/Generation: ${Math.round(result.avgTokensSavedPerGeneration).toLocaleString()}`);
189
+ console.log(` Total Lines of Code: ${result.totalLinesOfCode.toLocaleString()}`);
190
+ console.log(` Total Files Generated: ${result.totalFiles}`);
191
+ if (result.avgExecutionTime) {
192
+ console.log(` Avg Execution Time: ${Math.round(result.avgExecutionTime)}ms`);
193
+ }
194
+ console.log();
195
+ if (Object.keys(result.generatorStats).length > 0) {
196
+ console.log('Generator Usage:');
197
+ Object.entries(result.generatorStats)
198
+ .sort((a, b) => b[1].count - a[1].count)
199
+ .forEach(([gen, stats]) => {
200
+ console.log(` ${gen}:`);
201
+ console.log(` Count: ${stats.count}`);
202
+ console.log(` Tokens Saved: ${stats.tokensSaved.toLocaleString()}`);
203
+ console.log(` Lines of Code: ${stats.linesOfCode.toLocaleString()}`);
204
+ console.log(` Files Generated: ${stats.filesGenerated}`);
205
+ });
206
+ console.log();
207
+ }
208
+ if (Object.keys(result.frameworkStats).length > 0) {
209
+ console.log('Framework Popularity:');
210
+ Object.entries(result.frameworkStats)
211
+ .sort((a, b) => b[1] - a[1])
212
+ .forEach(([framework, count]) => {
213
+ console.log(` ${framework}: ${count} generations`);
214
+ });
215
+ console.log();
216
+ }
217
+ console.log('Options Usage:');
218
+ console.log(` Auth: ${result.optionsUsage.auth} generations`);
219
+ console.log(` Validation: ${result.optionsUsage.validation} generations`);
220
+ console.log(` Tests: ${result.optionsUsage.tests} generations`);
221
+ console.log();
222
+ if (Object.keys(result.entityPatterns).length > 0) {
223
+ console.log('Popular Entities:');
224
+ Object.entries(result.entityPatterns)
225
+ .sort((a, b) => b[1] - a[1])
226
+ .slice(0, 10)
227
+ .forEach(([entity, count]) => {
228
+ console.log(` ${entity}: ${count} times`);
229
+ });
230
+ console.log();
231
+ }
232
+ if (result.recentGenerations.length > 0) {
233
+ console.log('Recent Generations:');
234
+ result.recentGenerations.forEach((gen, i) => {
235
+ console.log(` ${i + 1}. [${gen.timestamp}] ${gen.operation}`);
236
+ console.log(` Generator: ${gen.generator || 'N/A'}`);
237
+ console.log(` Entity: ${gen.entityName || 'N/A'}`);
238
+ console.log(` Tokens Saved: ${(gen.tokensSaved || 0).toLocaleString()}`);
239
+ });
240
+ }
241
+ console.log('\n=================================================\n');
242
+ }
243
+ /**
244
+ * Weekly analytics summary
245
+ */
246
+ export async function weeklyAnalyticsSummary() {
247
+ console.log('Generating weekly CodeDNA analytics summary...\n');
248
+ const result = await getLast7DaysAnalytics();
249
+ printAnalytics(result, 'CodeDNA Weekly Analytics Summary');
250
+ // Calculate ROI
251
+ const estimatedCost = result.totalTokensSaved * 0.00001; // ~$0.01 per 1000 tokens
252
+ console.log('💰 Estimated Cost Savings:');
253
+ console.log(` Traditional approach: $${estimatedCost.toFixed(2)}`);
254
+ console.log(` With CodeDNA: $${(estimatedCost * 0.01).toFixed(2)} (99% savings)`);
255
+ console.log(` Total saved: $${(estimatedCost * 0.99).toFixed(2)}\n`);
256
+ }
@@ -5,7 +5,7 @@ export declare const PROJECT_SECTION_END = "<!-- CLAUDETOOLS:PROJECT:END -->";
5
5
  /**
6
6
  * Global CLAUDE.md content - added to ~/.claude/CLAUDE.md
7
7
  */
8
- export declare const GLOBAL_TEMPLATE = "\n<!-- CLAUDETOOLS:START -->\n# ClaudeTools Memory System\n\nYou have access to a persistent memory system via the `claudetools_memory` MCP server. Use it to remember context across sessions.\n\n## Memory Tools\n\n### Searching Memory\n```\nmemory_search(query: \"authentication patterns\")\n```\nSearch for relevant facts, entities, and past context. Use this when:\n- Starting work on a feature to recall past decisions\n- Looking for patterns or conventions used before\n- Finding related code or architectural context\n\n### Storing Facts\n```\nmemory_store_fact(\n entity1: \"UserService\",\n relationship: \"USES\",\n entity2: \"bcrypt\",\n context: \"Password hashing uses bcrypt with 12 rounds\"\n)\n```\nStore important facts as relationships between entities. Use for:\n- Architectural decisions\n- Code patterns and conventions\n- Dependencies and relationships\n- User preferences learned during conversation\n\n### Context Injection\nContext is automatically injected at the start of each session based on the current project. Check `~/.claudetools/session-context.md` for project-specific context.\n\n## Task Management\n\n### Creating Work Plans with Auto-Dispatch\n```\ntask_plan(\n goal: \"Add user authentication\",\n epic_title: \"User Auth System\",\n tasks: [...]\n)\n```\nBreak down complex work into tracked tasks. **Tasks are automatically set to `ready` status.**\n\nAfter `task_plan` completes, you will receive Task tool invocations to spawn parallel agents.\n**Execute ALL Task tool calls in a SINGLE message** to enable parallel execution.\n\n### Parallel Agent Workflow\n1. User describes work needed\n2. Call `task_plan_draft` to present the plan\n3. User says \"go\" to approve\n4. Call `task_plan` - tasks created in `ready` status\n5. Execute the provided Task tool calls in ONE message\n6. Agents work in parallel, each calling `task_complete` when done\n\n### Manual Task Start (Sequential)\n```\ntask_start(task_id: \"task_xxx\")\n```\nClaim a task before working on it. Use for sequential execution.\n\n### Completing Tasks\n```\ntask_complete(task_id: \"task_xxx\", summary: \"Implemented JWT auth with refresh tokens\")\n```\nMark tasks done with a summary of work completed. **Always call this when a task is finished.**\n\n## Codebase Intelligence\n\n### Finding Code\n```\ncodebase_map() # Get overview of project structure\ncodebase_find(\"UserService\") # Find symbols/files\ncodebase_context(\"src/auth.ts\") # Get file dependencies\n```\n\n### Impact Analysis\n```\nanalyze_impact(function_name: \"validateToken\")\n```\nSee what would be affected by changing a function.\n\n## Best Practices\n\n1. **Search before implementing** - Check memory for existing patterns\n2. **Store decisions** - Save architectural choices as facts\n3. **Use task tracking** - Break complex work into tasks\n4. **Complete tasks** - Always mark tasks done with summaries\n<!-- CLAUDETOOLS:END -->\n";
8
+ export declare const GLOBAL_TEMPLATE = "\n<!-- CLAUDETOOLS:START -->\n# ClaudeTools Memory System\n\nYou have access to a persistent memory system via the `claudetools_memory` MCP server. Use it to remember context across sessions.\n\n## Memory Tools\n\n### Searching Memory\n```\nmemory_search(query: \"authentication patterns\")\n```\nSearch for relevant facts, entities, and past context. Use this when:\n- Starting work on a feature to recall past decisions\n- Looking for patterns or conventions used before\n- Finding related code or architectural context\n\n### Storing Facts\n```\nmemory_store_fact(\n entity1: \"UserService\",\n relationship: \"USES\",\n entity2: \"bcrypt\",\n context: \"Password hashing uses bcrypt with 12 rounds\"\n)\n```\nStore important facts as relationships between entities. Use for:\n- Architectural decisions\n- Code patterns and conventions\n- Dependencies and relationships\n- User preferences learned during conversation\n\n### Context Injection\nContext is automatically injected at the start of each session based on the current project. Check `~/.claudetools/session-context.md` for project-specific context.\n\n## Task Management\n\n### Creating Work Plans with Auto-Dispatch\n```\ntask_plan(\n goal: \"Add user authentication\",\n epic_title: \"User Auth System\",\n tasks: [...]\n)\n```\nBreak down complex work into tracked tasks. **Tasks are automatically set to `ready` status.**\n\nAfter `task_plan` completes, you will receive Task tool invocations to spawn parallel agents.\n**Execute ALL Task tool calls in a SINGLE message** to enable parallel execution.\n\n### Parallel Agent Workflow\n1. User describes work needed\n2. Call `task_plan_draft` to present the plan\n3. User says \"go\" to approve\n4. Call `task_plan` - tasks created in `ready` status\n5. Execute the provided Task tool calls in ONE message\n6. Agents work in parallel, each calling `task_complete` when done\n\n### Manual Task Start (Sequential)\n```\ntask_start(task_id: \"task_xxx\")\n```\nClaim a task before working on it. Use for sequential execution.\n\n### Completing Tasks\n```\ntask_complete(task_id: \"task_xxx\", summary: \"Implemented JWT auth with refresh tokens\")\n```\nMark tasks done with a summary of work completed. **Always call this when a task is finished.**\n\n## Codebase Intelligence\n\n### Finding Code\n```\ncodebase_map() # Get overview of project structure\ncodebase_find(\"UserService\") # Find symbols/files\ncodebase_context(\"src/auth.ts\") # Get file dependencies\n```\n\n### Impact Analysis\n```\nanalyze_impact(function_name: \"validateToken\")\n```\nSee what would be affected by changing a function.\n\n## CodeDNA: AI Code Generation (95-99% Token Savings)\n\n**CRITICAL: Use CodeDNA for repetitive code generation to save massive tokens.**\n\n### When to Use CodeDNA\n- Creating REST APIs with CRUD operations\n- Generating database models, controllers, routes\n- Building validation middleware\n- Setting up authentication systems\n- Creating test suites\n\n### Available Generators\n```\ncodedna_generate_api(spec, framework, options)\ncodedna_validate_spec(spec)\ncodedna_list_generators()\n```\n\n### Entity DSL Syntax\n```\nEntityName(field:type:constraint, field:type:constraint, ...)\n\nExamples:\nUser(email:string:unique:required, password:string:hashed, age:integer:min(18))\nPost(title:string:required, content:string, author:ref(User))\nProduct(name:string, price:decimal:min(0), stock:integer:default(0))\n```\n\n### Constraints\n- `unique` - Unique constraint\n- `required` - NOT NULL\n- `hashed` - Bcrypt hashing (for passwords)\n- `min(n)` - Minimum value\n- `max(n)` - Maximum value\n- `default(value)` - Default value\n\n### Token Savings Example\n**Traditional approach:**\n- AI writes 1000 lines of code\n- Tokens: ~30,000 (input + output)\n- Cost: ~$0.30\n- Time: 2-3 minutes\n\n**CodeDNA approach:**\n```\ncodedna_generate_api({\n spec: \"User(email:string:unique, password:string:hashed, role:enum(admin,user))\",\n framework: \"express\",\n options: { auth: true, validation: true, tests: true }\n})\n```\n- Tokens: ~200\n- Cost: ~$0.002\n- Time: 5-10 seconds\n- **Savings: 99.3% cost, 90% time**\n\n### Generated Files (Express)\n1. `models/entity.model.ts` - Sequelize ORM model\n2. `controllers/entity.controller.ts` - CRUD controllers\n3. `routes/entity.routes.ts` - Express routes\n4. `validators/entity.validator.ts` - Input validation (optional)\n5. `middleware/auth.middleware.ts` - JWT auth (optional)\n6. `tests/entity.test.ts` - Jest tests (optional)\n\n### Usage Pattern\n1. User asks: \"Create a User API with authentication\"\n2. **YOU MUST** call `codedna_generate_api` instead of writing code\n3. Receive 6 production-ready files\n4. Save 99% tokens and time\n\n**DO NOT write boilerplate code manually when CodeDNA can generate it.**\n\n## Best Practices\n\n1. **Search before implementing** - Check memory for existing patterns\n2. **Store decisions** - Save architectural choices as facts\n3. **Use task tracking** - Break complex work into tasks\n4. **Complete tasks** - Always mark tasks done with summaries\n5. **Use CodeDNA for APIs** - Save 95-99% tokens on boilerplate generation\n<!-- CLAUDETOOLS:END -->\n";
9
9
  /**
10
10
  * Project-level CLAUDE.md content - added to .claude/CLAUDE.md
11
11
  */
@@ -95,12 +95,85 @@ analyze_impact(function_name: "validateToken")
95
95
  \`\`\`
96
96
  See what would be affected by changing a function.
97
97
 
98
+ ## CodeDNA: AI Code Generation (95-99% Token Savings)
99
+
100
+ **CRITICAL: Use CodeDNA for repetitive code generation to save massive tokens.**
101
+
102
+ ### When to Use CodeDNA
103
+ - Creating REST APIs with CRUD operations
104
+ - Generating database models, controllers, routes
105
+ - Building validation middleware
106
+ - Setting up authentication systems
107
+ - Creating test suites
108
+
109
+ ### Available Generators
110
+ \`\`\`
111
+ codedna_generate_api(spec, framework, options)
112
+ codedna_validate_spec(spec)
113
+ codedna_list_generators()
114
+ \`\`\`
115
+
116
+ ### Entity DSL Syntax
117
+ \`\`\`
118
+ EntityName(field:type:constraint, field:type:constraint, ...)
119
+
120
+ Examples:
121
+ User(email:string:unique:required, password:string:hashed, age:integer:min(18))
122
+ Post(title:string:required, content:string, author:ref(User))
123
+ Product(name:string, price:decimal:min(0), stock:integer:default(0))
124
+ \`\`\`
125
+
126
+ ### Constraints
127
+ - \`unique\` - Unique constraint
128
+ - \`required\` - NOT NULL
129
+ - \`hashed\` - Bcrypt hashing (for passwords)
130
+ - \`min(n)\` - Minimum value
131
+ - \`max(n)\` - Maximum value
132
+ - \`default(value)\` - Default value
133
+
134
+ ### Token Savings Example
135
+ **Traditional approach:**
136
+ - AI writes 1000 lines of code
137
+ - Tokens: ~30,000 (input + output)
138
+ - Cost: ~$0.30
139
+ - Time: 2-3 minutes
140
+
141
+ **CodeDNA approach:**
142
+ \`\`\`
143
+ codedna_generate_api({
144
+ spec: "User(email:string:unique, password:string:hashed, role:enum(admin,user))",
145
+ framework: "express",
146
+ options: { auth: true, validation: true, tests: true }
147
+ })
148
+ \`\`\`
149
+ - Tokens: ~200
150
+ - Cost: ~$0.002
151
+ - Time: 5-10 seconds
152
+ - **Savings: 99.3% cost, 90% time**
153
+
154
+ ### Generated Files (Express)
155
+ 1. \`models/entity.model.ts\` - Sequelize ORM model
156
+ 2. \`controllers/entity.controller.ts\` - CRUD controllers
157
+ 3. \`routes/entity.routes.ts\` - Express routes
158
+ 4. \`validators/entity.validator.ts\` - Input validation (optional)
159
+ 5. \`middleware/auth.middleware.ts\` - JWT auth (optional)
160
+ 6. \`tests/entity.test.ts\` - Jest tests (optional)
161
+
162
+ ### Usage Pattern
163
+ 1. User asks: "Create a User API with authentication"
164
+ 2. **YOU MUST** call \`codedna_generate_api\` instead of writing code
165
+ 3. Receive 6 production-ready files
166
+ 4. Save 99% tokens and time
167
+
168
+ **DO NOT write boilerplate code manually when CodeDNA can generate it.**
169
+
98
170
  ## Best Practices
99
171
 
100
172
  1. **Search before implementing** - Check memory for existing patterns
101
173
  2. **Store decisions** - Save architectural choices as facts
102
174
  3. **Use task tracking** - Break complex work into tasks
103
175
  4. **Complete tasks** - Always mark tasks done with summaries
176
+ 5. **Use CodeDNA for APIs** - Save 95-99% tokens on boilerplate generation
104
177
  ${SECTION_END}
105
178
  `;
106
179
  /**