Skip to main content
Glama

preview_changes_enhanced

Preview code changes in multiple formats like unified, side-by-side, stat, or word-diff. Control context lines, ignore whitespace, filter by file pattern, and set working directory.

Instructions

Enhanced change preview with multiple format options

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
formatNoPreview format
contextLinesNoNumber of context lines
ignoreWhitespaceNoIgnore whitespace changes
filePatternNoFile pattern filter
cwdNoWorking directory

Implementation Reference

  • The main handler function for 'preview_changes_enhanced'. Accepts options: format, contextLines, ignoreWhitespace, filePattern, cwd. Checks git repo, retrieves staged/unstaged diffs (with optional file pattern filtering), builds an enhanced preview output with summary stats.
    async previewChangesEnhanced(options: {
      format?: 'unified' | 'side-by-side' | 'stat' | 'word-diff';
      contextLines?: number;
      ignoreWhitespace?: boolean;
      filePattern?: string;
      cwd?: string;
    } = {}): Promise<ToolResult> {
      try {
        const {
          format = 'unified',
          contextLines = 3,
          ignoreWhitespace = false,
          filePattern,
          cwd
        } = options;
        
        const workingDir = cwd || this.workspaceService.getCurrentWorkspace();
        
        // Check if we're in a git repository first
        const gitCheckResult = await this.gitCommand(['rev-parse', '--git-dir'], workingDir);
        if (gitCheckResult.isError) {
          return {
            isError: true,
            content: [{
              type: 'text',
              text: `Failed to preview changes: ${gitCheckResult.content[0]?.text || 'Not a git repository'}`
            }]
          };
        }
        
        let output = `Change Preview (${format} format):\n\n`;
        
        // Add format-specific headers and options
        if (format === 'side-by-side') {
          output += 'Side-by-side comparison:\n\n';
        } else if (ignoreWhitespace) {
          output += 'Ignoring whitespace changes:\n\n';
        } else if (filePattern) {
          output += `File Pattern: ${filePattern}\n\n`;
        }
        
        output += 'Enhanced Change Preview:\n\n';
        
        // Get unstaged changes
        const unstagedOptions: GitDiffOptions = {
          staged: false,
          format,
          contextLines,
          ignoreWhitespace,
          cwd: workingDir
        };
        
        // Get staged changes
        const stagedOptions: GitDiffOptions = {
          staged: true,
          format,
          contextLines,
          ignoreWhitespace,
          cwd: workingDir
        };
        
        // Apply file pattern filtering if specified
        if (filePattern) {
          // Get list of files matching pattern first
          const statusResult = await this.gitStatus({ cwd: workingDir });
          if (!statusResult.isError && statusResult.content[0]?.text) {
            const statusLines = statusResult.content[0].text.split('\n').filter(line => line.trim());
            const matchingFiles = statusLines
              .map(line => line.substring(2).trim()) // Remove git status prefix
              .filter(filename => {
                // Simple glob matching for *.ext pattern
                if (filePattern.startsWith('*.')) {
                  const ext = filePattern.substring(2);
                  return filename.endsWith(ext);
                }
                // For other patterns, use simple includes for now
                return filename.includes(filePattern.replace('*', ''));
              });
            
            // If we have matching files, process them individually
            if (matchingFiles.length > 0) {
              let unstagedChanges = '';
              let stagedChanges = '';
              
              for (const file of matchingFiles) {
                const unstagedFileResult = await this.enhancedGitDiff({
                  ...unstagedOptions,
                  file
                });
                
                const stagedFileResult = await this.enhancedGitDiff({
                  ...stagedOptions,
                  file
                });
                
                if (!unstagedFileResult.isError && unstagedFileResult.content[0]?.text?.trim() && 
                    !unstagedFileResult.content[0].text.includes('No changes found')) {
                  unstagedChanges += unstagedFileResult.content[0].text + '\n';
                }
                
                if (!stagedFileResult.isError && stagedFileResult.content[0]?.text?.trim() && 
                    !stagedFileResult.content[0].text.includes('No changes found')) {
                  stagedChanges += stagedFileResult.content[0].text + '\n';
                }
              }
              
              // Display filtered results
              if (stagedChanges) {
                output += 'Staged Changes:\n';
                output += stagedChanges;
                output += '\n';
              }
              
              if (unstagedChanges) {
                output += 'Unstaged Changes:\n';
                output += unstagedChanges;
                output += '\n';
              }
            } else {
              output += `No files matching pattern "${filePattern}" have changes.\n`;
            }
          }
        } else {
          // No file pattern filtering - get all changes
          const unstagedResult = await this.enhancedGitDiff(unstagedOptions);
          const stagedResult = await this.enhancedGitDiff(stagedOptions);
          
          // Display staged changes
          if (!stagedResult.isError && stagedResult.content[0]?.text?.trim() && 
              !stagedResult.content[0].text.includes('Command completed successfully') && 
              !stagedResult.content[0].text.includes('No changes found')) {
            output += 'Staged Changes:\n';
            output += stagedResult.content[0].text;
            output += '\n\n';
          }
          
          // Display unstaged changes  
          if (!unstagedResult.isError && unstagedResult.content[0]?.text?.trim() && 
              !unstagedResult.content[0].text.includes('Command completed successfully') &&
              !unstagedResult.content[0].text.includes('No changes found')) {
            output += 'Unstaged Changes:\n';
            output += unstagedResult.content[0].text;
            output += '\n\n';
          }
        }
        
        // Get stats for both
        const stagedStats = await this.getDiffStats({ staged: true, cwd: workingDir });
        const unstagedStats = await this.getDiffStats({ staged: false, cwd: workingDir });
        
        output += '=== SUMMARY ===\n';
        if (!stagedStats.isError && stagedStats.content[0]?._meta) {
          const meta = stagedStats.content[0]._meta as any;
          if (meta.filesChanged > 0) {
            output += `Staged: ${meta.filesChanged} files, +${meta.insertions}/-${meta.deletions} lines\n`;
          }
        }
        
        if (!unstagedStats.isError && unstagedStats.content[0]?._meta) {
          const meta = unstagedStats.content[0]._meta as any;
          if (meta.filesChanged > 0) {
            output += `Unstaged: ${meta.filesChanged} files, +${meta.insertions}/-${meta.deletions} lines\n`;
          }
        }
        
        if (!output.includes('STAGED CHANGES') && !output.includes('UNSTAGED CHANGES')) {
          output += 'No changes to preview';
        }
        
        return {
          content: [{
            type: 'text',
            text: output,
            _meta: {
              format,
              stagedStats: stagedStats.content[0]?._meta,
              unstagedStats: unstagedStats.content[0]?._meta
            }
          }]
        };
        
      } catch (error) {
        return {
          isError: true,
          content: [{
            type: 'text',
            text: `Enhanced preview failed: ${error instanceof Error ? error.message : String(error)}`
          }]
        };
  • Input schema definition for 'preview_changes_enhanced' tool. Defines properties: format (enum: unified, side-by-side, stat, word-diff), contextLines, ignoreWhitespace, filePattern, cwd.
    {
      name: 'preview_changes_enhanced',
      description: 'Enhanced change preview with multiple format options',
      inputSchema: {
        type: 'object',
        properties: {
          format: { 
            type: 'string', 
            enum: ['unified', 'side-by-side', 'stat', 'word-diff'],
            description: 'Preview format' 
          },
          contextLines: { type: 'number', description: 'Number of context lines' },
          ignoreWhitespace: { type: 'boolean', description: 'Ignore whitespace changes' },
          filePattern: { type: 'string', description: 'File pattern filter' },
          cwd: { type: 'string', description: 'Working directory' }
        }
      }
    },
    
    // Enhanced File Operations & Diff Management
  • src/index.ts:450-451 (registration)
    Registration/case branch in index.ts that routes 'preview_changes_enhanced' to gitService.previewChangesEnhanced(args).
    case 'preview_changes_enhanced':
      return await this.gitService.previewChangesEnhanced(args);
  • Helper calls to getDiffStats and enhancedGitDiff used within the previewChangesEnhanced handler to retrieve and format diff data for both staged and unstaged changes.
    const unstagedOptions: GitDiffOptions = {
      staged: false,
      format,
      contextLines,
      ignoreWhitespace,
      cwd: workingDir
    };
    
    // Get staged changes
    const stagedOptions: GitDiffOptions = {
      staged: true,
      format,
      contextLines,
      ignoreWhitespace,
      cwd: workingDir
    };
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description must disclose behavior. It only mentions format options but does not state that the tool is read-only, what operations are performed, or any side effects (e.g., file system impact). This is insufficient for a tool with 5 parameters.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely short (a phrase), which is concise but lacks substantive content. It is front-loaded but does not provide enough information to justify its brevity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 5 parameters, no output schema, no annotations, and multiple sibling diff/preview tools (e.g., preview_changes, enhanced_git_diff), the description is incomplete. It fails to explain the output format, how it differs from siblings, or when to choose it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema descriptions cover all 5 parameters (100% coverage), so baseline is 3. The description adds 'multiple format options' which hints at the format enum but does not elaborate on parameter meanings beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Enhanced change preview with multiple format options' indicates the tool previews changes and offers format options, but it's vague about what exactly is 'enhanced' compared to sibling tools like preview_changes. It does not specify the resource (e.g., working directory diffs) or clearly distinguish from similar tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool over alternatives like preview_changes or enhanced_git_diff. There are no usage conditions, prerequisites, or cues for selection, leaving the agent to guess.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/agentics-ai/code-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server