Skip to content
Development
Command

/estimate-assistant

Generate accurate project time estimates

From plugin
claude-command-suite
1.4k199 skills89 agents199 commands
$ npx -y skills add qdhenry/Claude-Command-Suite --agent claude-code

Command definition

estimate-assistant.md

estimate-assistant

Generate accurate project time estimates

Purpose

This command analyzes past commits, PR completion times, code complexity metrics, and team performance to provide accurate task estimates. It helps teams move beyond gut-feel estimates to data-backed predictions.

Usage

# Estimate a specific task based on description
claude "Estimate task: Implement OAuth2 login flow with Google"

# Analyze historical accuracy of estimates
claude "Show estimation accuracy for the last 10 sprints"

# Estimate based on code changes
claude "Estimate effort for refactoring src/api/users module"

# Get team member specific estimates
claude "How long would it take Alice to implement the payment webhook handler?"

Instructions

1. Gather Historical Data

Collect data from git history and Linear:

# Get commit history with timestamps and authors
git log --pretty=format:"%h|%an|%ad|%s" --date=iso --since="6 months ago" > commit_history.txt

# Analyze PR completion times
gh pr list --state closed --limit 100 --json number,title,createdAt,closedAt,additions,deletions,files

# Get file change frequency
git log --pretty=format: --name-only --since="6 months ago" | sort | uniq -c | sort -rn

# Analyze commit patterns by author
git shortlog -sn --since="6 months ago"

2. Calculate Code Complexity Metrics

Analyze code characteristics:

function analyzeComplexity(filePath) {
  const metrics = {
    lines: 0,
    cyclomaticComplexity: 0,
    dependencies: 0,
    testCoverage: 0,
    similarFiles: []
  };
  
  // Count lines of code
  const content = readFile(filePath);
  metrics.lines = content.split('\n').length;
  
  // Cyclomatic complexity (simplified)
  const conditions = content.match(/if\s*\(|while\s*\(|for\s*\(|case\s+|\?\s*:/g);
  metrics.cyclomaticComplexity = (conditions?.length || 0) + 1;
  
  // Count imports/dependencies
  const imports = content.match(/import.*from|require\(/g);
  metrics.dependencies = imports?.length || 0;
  
  // Find similar files by structure
  metrics.similarFiles = findSimilarFiles(filePath);
  
  return metrics;
}

3. Build Estimation Models

Time-Based Estimation

class HistoricalEstimator {
  constructor(gitData, linearData) {
    this.gitData = gitData;
    this.linearData = linearData;
    this.authorVelocity = new Map();
    this.fileTypeMultipliers = new Map();
  }
  
  calculateAuthorVelocity(author) {
    const authorCommits = this.gitData.filter(c => c.author === author);
    const taskCompletions = this.linearData.filter(t => 
      t.assignee === author && t.completedAt
    );
    
    // Lines of code per day
    const totalLines = authorCommits.reduce((sum, c) => 
      sum + c.additions + c.deletions, 0
    );
    const totalDays = this.calculateWorkDays(authorCommits);
    const linesPerDay = totalLines / totalDays;
    
    // Story points per sprint
    const pointsCompleted = taskCompletions.reduce((sum, t) => 
      sum + (t.estimate || 0), 0
    );
    const sprintCount = this.countSprints(taskCompletions);
    const pointsPerSprint = pointsCompleted / sprintCount;
    
    return {
      linesPerDay,
      pointsPerSprint,
      averageTaskDuration: this.calculateAverageTaskDuration(taskCompletions),
      accuracy: this.calculateEstimateAccuracy(taskCompletions)
    };
  }
  
  estimateTask(description, assignee = null) {
    // Extract key features from description
    const features = this.extractFeatures(description);
    
    // Find similar completed tasks
    const similarTasks = this.findSimilarTasks(features);
    
    // Base estimate from similar tasks
    let baseEstimate = this.calculateMedianEstimate(similarTasks);
    
    // Adjust for complexity indicators
    const complexityMultiplier = this.calculateComplexityMultiplier(features);
    baseEstimate *= complexityMultiplier;
    
    // Adjust for assignee if specified
    if (assignee) {
      const velocity = this.calculateAuthorVelocity(assignee);
      const teamAvgVelocity = this.calculateTeamAverageVelocity();
      const velocityRatio = velocity.pointsPerSprint / teamAvgVelocity;
      baseEstimate *= (2 - velocityRatio); // Faster devs get lower estimates
    }
    
    // Add confidence interval
    const confidence = this.calculateConfidence(similarTasks.length, features);
    
    return {
      estimate: Math.round(baseEstimate),
      confidence,
      range: {
        min: Math.round(baseEstimate * 0.7),
        max: Math.round(baseEstimate * 1.5)
      },
      basedOn: similarTasks.slice(0, 3),
      factors: this.explainFactors(features, complexityMultiplier)
    };
  }
}

Pattern Recognition

function extractFeatures(taskDescription) {
  const features = {
    keywords: [],
    fileTypes: [],
    modules: [],
    complexity: 'medium',
    type: 'feature', // feature, bug, refactor, etc.
    hasTests: false,
    hasUI: false,
    hasAPI: false,
    hasDatabase: false
  };
  
  // Keywords that indicate complexity
  const complexityKeywords = {
    high: ['refactor', 'migrate', 'redesign', 'optimize', 'architecture'],
    medium: ['implement', 'add', 'create', 'update', 'integrate'],
    low: ['fix', 'adjust', 'tweak', 'change', 'modify']
  };
  
  // Detect task type
  if (taskDescription.match(/bug|fix|repair|broken/i)) {
    features.type = 'bug';
  } else if (taskDescription.match(/refactor|cleanup|optimize/i)) {
    features.type = 'refactor';
  } else if (taskDescription.match(/test|spec|coverage/i)) {
    features.type = 'test';
  }
  
  // Detect components
  features.hasUI = /UI|frontend|component|view|page/i.test(taskDescription);
  features.hasAPI = /API|endpoint|route|REST|GraphQL/i.test(taskDescription);
  features.hasDatabase = /database|DB|migration|schema|query/i.test(taskDescription);
  features.hasTests = /test|spec|TDD|coverage/i.test(taskDescription);
  
  // Extract file types mentioned
  const fileTypeMatches = taskDescription.match(/\.(
Read more
@qdhenry
Ships withclaude-command-suite

A comprehensive development toolkit designed following Anthropic's Claude Code Best Practices for AI-assisted software development.

1.4k12 skills89 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
1.4k
Star history of qdhenry/Claude-Command-Suite on GitHub, a chart by star-history.com

Other commands on claude-command-suite.

More commands from other plugins.

build
Auto-invoked

build

Command

Implement tasks incrementally — build, test, verify, commit. Add "auto" to run the whole plan in one approved pass.

@addyosmani@addyosmaniInstall Command