Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
DeepLint is an AI-powered linting tool that provides intelligent code analysis by understanding code semantics and context across an entire codebase. Unlike traditional linters that focus on syntax and style, DeepLint analyzes the meaning and relationships in your code to catch issues that would otherwise go undetected.
Traditional linters are excellent at catching syntax errors, enforcing style guides, and identifying simple patterns. However, they have significant limitations:
They analyze files in isolation, missing cross-file dependencies
They can't understand business logic or semantic correctness
They lack awareness of organizational policies and best practices
DeepLint addresses these limitations by:
Analyzing Code in Context: Understanding relationships between files and components
Semantic Understanding: Comprehending what your code does, not just how it's written
Policy Enforcement: Applying organizational best practices and custom rules
Actionable Feedback: Providing clear explanations and suggested fixes
DeepLint integrates directly into your Git workflow, analyzing code changes before they're committed. This catches issues early in the development process, before they make it into your codebase.
Learn more:
DeepLint builds a comprehensive context of your codebase, including:
Changed files and their content
Related files affected by the changes
Dependencies and relationships between components
Code structure and organization
Learn more:
Define custom rules in plain English, allowing you to codify organizational best practices and project-specific requirements without complex rule configurations.
When issues are detected, DeepLint provides:
Clear explanations of the problem
Context showing why it's an issue
Suggested fixes that can be applied automatically
To start using DeepLint, follow these steps:
- Set up DeepLint in your environment
- Customize settings for your project
- Learn how to analyze your code
- Integrate with your Git workflow
Scenario: A developer removes a field used by other parts of the application.
Traditional Linter: ✅ No issues detected (syntax is valid)
DeepLint: ⚠️ HIGH RISK: Removing field 'x' from function return value
Field is used in 5 other files
Recommendation: Maintain the field or update dependencies
If you're interested in contributing to DeepLint or understanding its architecture, check out the .
- Understand DeepLint's design
- Learn about the CLI architecture
- Explore the context building system
- Start contributing to DeepLint
Developer Note: DeepLint is built with TypeScript and uses a modular architecture that separates context building, analysis, and reporting. The core components are designed to be extensible and configurable.
Explore to understand how DeepLint works
Check out the to learn about available commands
Review the to see what's coming next
This guide will help you install DeepLint and set it up in your project.
Before installing DeepLint, ensure you have the following prerequisites:
Node.js: Version 22.0.0 or higher
Package Manager: npm, yarn, or pnpm (pnpm is recommended)
Git: For Git hook integration
Installing DeepLint globally allows you to use it across multiple projects:
After installation, verify that DeepLint is installed correctly:
You can also install DeepLint as a development dependency in your project:
When installed locally, you can run DeepLint using npx:
DeepLint requires an API key for the LLM provider you want to use. Currently, the following providers are supported:
OpenAI (GPT-4)
Anthropic (Claude)
Google (Gemini)
You can set up your API key in several ways:
Add your API key to your environment variables:
For persistent configuration, add this to your shell profile (.bashrc, .zshrc, etc.).
You can also add your API key to the DeepLint configuration file. We'll cover this in the Configuration section.
Never commit your API keys to version control. If you add them to your configuration file, make sure to add the file to your .gitignore.
If you encounter issues during installation, check the following:
Ensure you have the correct Node.js version (22.0.0+)
Check your network connection
Verify you have the necessary permissions to install global packages
If using pnpm, ensure it's properly configured
For more detailed troubleshooting, run the installation with verbose logging:
DeepLint supports both CommonJS (CJS) and ECMAScript Modules (ESM) environments:
The package automatically detects your project's module format
For ESM projects, use import syntax:
For CJS projects, use require syntax:
All dependencies are bundled for maximum compatibility, including ESM-only dependencies like chalk
This dual-format support means you can use DeepLint in any JavaScript or TypeScript project, regardless of the module system it uses.
Now that you have DeepLint installed, you can:
Configure DeepLint - Set up your project configuration
Run your first analysis - Learn how to analyze your code
Set up Git integration - Integrate with your Git workflow
Command Line Interface - Learn about available commands
Configuration Options - Customize DeepLint for your project
Context Building - Understand how DeepLint analyzes your code
Developer Note: If you're developing DeepLint itself, you can clone the repository and use the development scripts. See the Contributing guide for more information.
If you want to contribute to DeepLint or run it from source, follow these steps:
Clone the Repository
Install Dependencies
Set Up Environment Variables
Copy the sample environment file and modify as needed:
Edit the .env file to include your OpenAI API key:
Build the Project
Run the Development Server
For more detailed information about the development workflow, see the Development Workflow guide.
Next: Configuration →
import { defineConfig } from "deeplint-cli";const { defineConfig } = require("deeplint-cli");git clone https://github.com/your-org/deeplint-cli.git
cd deeplint-clipnpm installcp .env.sample .envOPENAI_API_KEY=your_api_key_here# Using npm
npm install -g deeplint-cli
# Using yarn
yarn global add deeplint-cli
# Using pnpm (recommended)
pnpm add -g deeplint-clideeplint --version# Using npm
npm install --save-dev deeplint-cli
# Using yarn
yarn add --dev deeplint-cli
# Using pnpm (recommended)
pnpm add -D deeplint-clinpx deeplint# For OpenAI
export OPENAI_API_KEY=your-api-key
# For Anthropic
export ANTHROPIC_API_KEY=your-api-key
# For Google
export GOOGLE_API_KEY=your-api-keypnpm add -g deeplint-cli --verbose# Build the project with tsup (generates both ESM and CJS outputs)
pnpm buildpnpm devThis guide will walk you through running DeepLint for the first time and understanding its output.
Before running DeepLint, ensure you have:
(optional, default configuration works for most cases)
A Git repository with some changes (either staged or unstaged)
After installing and configuring DeepLint, you can run it with a simple command:
When run without arguments, DeepLint will:
Look for staged changes in your Git repository
Build context for analysis
Display information about the context (number of files, tokens, etc.)
DeepLint can analyze your code using powerful Large Language Models (LLMs) like OpenAI's GPT-4o. This enables advanced linting, code review, and suggestions powered by AI.
OpenAI API Key: You need an OpenAI API key to use LLM-powered analysis.
Get one at
Set it as an environment variable:
Or add it to your config file under llm.apiKey
To run DeepLint with LLM-powered analysis, use the check command:
This will:
Build context from your code changes
Send the context to the LLM for analysis
Display lint results, explanations, and suggestions
You can control the LLM analysis with these options:
--provider (default: openai)
--model (default: gpt-4o)
--api-key (your OpenAI API key)
See the for full details.
DeepLint supports several command line options to customize its behavior:
For a complete list of options, run:
When you run DeepLint, you'll see output similar to this:
Let's break down what this means:
Running DeepLint on staged changes: DeepLint is analyzing the changes you've staged with git add.
Building context for analysis: DeepLint is gathering information about your codebase.
Context built with X changed files and Y related files: DeepLint has identified the files you've changed and other files that are related to those changes.
If you want to see what information DeepLint is gathering for analysis, you can use the --dump option:
This will save the context to a file, which you can examine to understand what information DeepLint is gathering. The context includes:
Repository information (name, root, structure)
Changes (files, diffs, summary)
Related files (dependencies, content, structure)
Metadata (token counts, generation time)
If you run DeepLint without any staged changes, you'll see an error message:
To fix this, either:
Stage some changes with git add, or
Use the --unstaged flag to analyze unstaged changes:
If you run DeepLint outside of a Git repository, you'll see an error message:
To fix this, either:
Navigate to a Git repository, or
Initialize a Git repository in your current directory:
If your codebase is large, you might see a warning about token limits:
This means that DeepLint had to truncate or exclude some files to stay within the token limit. To address this, you can:
Reduce the number of files being analyzed by making smaller, more focused changes.
Adjust the token limits in your configuration file:
If you're having issues with DeepLint, you can run it in debug mode to get more information:
This will show detailed information about the context building process, including:
For more detailed output without the technical details of debug mode, you can use verbose mode:
This will show additional information about what DeepLint is doing, such as:
For more information about verbose mode, see the guide.
When you run DeepLint, it goes through several steps to build context for analysis:
Git Integration: DeepLint checks for staged or unstaged changes in your Git repository
Repository Scanning: DeepLint scans your repository to understand its structure
Dependency Analysis: DeepLint analyzes dependencies between files
Code Structure Analysis: DeepLint extracts information about the structure of your code
For more detailed information about the context building process, see the documentation.
Now that you've run DeepLint for the first time, you can:
Learn more about to automate DeepLint in your workflow
Explore the to customize DeepLint for your project
Learn about the to get the most out of DeepLint
Developer Note: The context building process is highly optimized to provide the most relevant information while staying within token limits. It's designed to work with a wide range of codebases and can be customized to fit your specific needs.
Previous: | Next:
Model: By default, DeepLint uses gpt-4o. You can change this with the --model flag or in your config.
--instructions (extra prompt instructions)--json (output as JSON)
--unstaged (include unstaged changes)
Ready for LLM analysis: The context is ready for analysis by the LLM.
Context Assembly: DeepLint assembles all this information into a structured context
Token Management: DeepLint manages the context size to fit within token limits
deeplintexport OPENAI_API_KEY=sk-...deeplint checkdeeplint check --model=gpt-4deeplint check --instructions="Focus on security issues."deeplint check --jsondeeplint check --unstaged# Run with debug output
deeplint --debug
# Include unstaged changes
deeplint --unstaged
# Save context to a file for inspection
deeplint --dump context.json
# Enable verbose output
deeplint --verbose
# Combine multiple options
deeplint --debug --unstageddeeplint helpINFO: Running DeepLint on staged changes...
INFO: Building context for analysis...
INFO: Context built with 3 changed files and 5 related files
INFO: Context building statistics:
INFO: - Total files: 8
INFO: - Changed files: 3
INFO: - Related files: 5
INFO: - Total tokens: 4567
INFO: - Build time: 234ms
INFO: Context built successfully!
INFO: Ready for LLM analysis.
INFO: DeepLint analysis completed.deeplint --dump context.jsonERROR: No staged changes found. Stage changes with 'git add' or use --unstaged to analyze unstaged changes.deeplint --unstagedERROR: Not a Git repository. Initialize a Git repository with 'git init' or navigate to a Git repository.git initWARN: Token limit exceeded. Some files may be truncated or excluded.contextBuilder: {
maxTokens: 8000, // Increase this value
tokensPerFile: 1000, // Adjust this value
}deeplint --debugINFO: Building context for LLM analysis...
INFO: Found staged changes. Proceeding with context building...
INFO: Analyzing staged changes in 3 files
INFO: Scanning repository...
INFO: Found 127 files (89 source files, 38 test files)
INFO: Building dependency graph...
INFO: Analyzing code structure...
INFO: Assembling context...
INFO: Context built in 1243ms
INFO: Context size: 5678 tokens (2345 for changes, 3333 for related files)deeplint --verbose🔊 Context building configuration:
🔊 - Repository root: /path/to/your/project
🔊 - Include unstaged changes: false
🔊 - Max tokens: 8000
🔊 - Include dependencies: true
🔊 - Include structure: true
🔊 Starting context building process...
🔊 Context building process completed.This document explains the end-to-end flow of LLM-powered analysis in DeepLint, including how context is built, how the LLM is invoked, how results are parsed and displayed, and how errors are handled.
DeepLint's LLM analysis feature leverages Large Language Models (LLMs) to provide advanced linting, code review, and suggestions. The flow is designed to be modular, extensible, and robust.
Command Execution
User runs deeplint check [options] [files...]
CLI parses arguments and resolves LLM configuration (CLI > env > config > defaults)
Context Building
All LLM errors are wrapped in the LLMError class for consistent handling
Common error cases:
Missing API key
API rate limits or quotas
The prompt template is defined in src/llm/prompt-template.ts
Users can add custom instructions via the --instructions CLI flag
The prompt includes:
New providers can be added by implementing the LLMProvider interface
Prompt templates and schemas can be updated as requirements evolve
The analysis flow is designed to support additional features (e.g., custom rules, multiple providers)
Always validate and sanitize context before sending to the LLM
Use try/catch blocks around all LLM API calls
Log errors with enough context for troubleshooting
Keep prompt templates and schemas up to date
Context building is a core concept in DeepLint that enables intelligent code analysis by providing the LLM with a comprehensive understanding of your codebase.
Context building is the process of gathering relevant information about your codebase to provide the LLM with the context it needs to perform semantic analysis. This includes:
Changed files and their content
Related files affected by the changes
Dependencies and relationships between components
Code structure and organization
Repository information
Traditional linters analyze files in isolation, which limits their ability to detect issues that span multiple files or depend on the relationships between components. DeepLint's context building approach addresses this limitation by:
Understanding Cross-File Dependencies: Identifying how changes in one file affect other parts of the codebase
Capturing Semantic Relationships: Recognizing the meaning and purpose of code beyond its syntax
Providing Holistic View: Giving the LLM a comprehensive view of the codebase structure
The context building process involves several steps:
DeepLint integrates with Git to identify changes in your codebase. It can analyze both staged and unstaged changes, depending on your configuration.
DeepLint scans your repository to understand its structure, collecting information about:
Directory hierarchy
File types and locations
Project organization
File metadata (size, last modified date, etc.)
DeepLint analyzes dependencies between files to identify relationships, such as:
Import/export relationships
Function calls between files
Type references
Component usage
DeepLint extracts information about the structure of your code, including:
Functions and their signatures
Classes and their methods
Interfaces and types
Exports and imports
DeepLint assembles all this information into a structured context that includes:
Repository information (name, root, structure)
Changes (files, diffs, summary)
Related files (dependencies, content, structure)
Metadata (token counts, generation time, context type)
LLMs have token limits, so DeepLint manages the context size by:
Counting tokens using the tiktoken library
Tracking used and available tokens
Truncating file content when necessary
Prioritizing important parts of files (imports, exports, function signatures)
The context built by DeepLint includes:
Changed files with their content
Dependencies of changed files (when includeDependencies is true, which is the default)
Code structure information (when includeStructure is true)
For JavaScript and TypeScript projects, DeepLint automatically analyzes dependencies between files. For other project types, dependency analysis is skipped, but the context still includes changed files and repository structure.
You can customize the context building process through configuration:
You can debug the context building process using the --debug flag:
This will show detailed information about the context building process, including:
Files being scanned
Dependencies being analyzed
Token usage
Context assembly
You can also save the context to a file for inspection using the --dump option:
This is useful for understanding what information is being sent to the LLM and for troubleshooting issues.
This document provides an overview of the LLM (Large Language Model) integration in DeepLint, including architecture, file structure, extension points, and best practices for extending or maintaining the LLM module.
The LLM module powers DeepLint's advanced code analysis using AI models such as OpenAI's GPT-4o. It is designed to be modular, extensible, and provider-agnostic, allowing for future support of additional LLM providers.
types.ts)Defines all shared types for LLM integration:
LintSeverity, LintIssue, LintResult
LLMAnalysisOptions
llm-provider.ts)Defines the LLMProvider interface:
All providers must implement this interface.
openai-provider.ts)Implements the LLMProvider interface for OpenAI:
Handles API key, model selection, and prompt formatting
Sends requests to OpenAI and parses responses
Adds metadata and summary to results
Handles errors with the LLMError class
prompt-template.ts)Defines the main prompt template for linting
Exports the JSON schema for LLM results
index.ts)Exports all LLM components for easy import
To add a new provider (e.g., Anthropic, Gemini):
Create a new provider file (e.g., anthropic-provider.ts)
Implement the LLMProvider interface
Add provider-specific configuration and error handling
Register the provider in the CLI/config system (future)
Context Building: The context builder assembles code, diffs, and metadata.
Prompt Preparation: The provider formats the prompt using the template and context.
API Call: The provider sends the prompt to the LLM API.
Response Parsing: The provider parses the LLM response into a LintResult
All LLM errors are wrapped in the LLMError class for consistent handling.
Common errors: missing API key, rate limits, invalid responses, network issues.
Errors are logged and surfaced to the user with actionable messages.
Use the provider interface for all LLM interactions.
Validate and sanitize all user input before sending to the LLM.
Handle all error cases gracefully and provide clear feedback.
Keep prompt templates and schemas up to date with the latest requirements.
This guide will help you understand how DeepLint works with Git and how to integrate it into your Git workflow.
The ContextBuilder scans the repository, collects changed files, related files, and metadata
Context is assembled with code, diffs, structure, and statistics
Prompt Preparation
The LLM provider (e.g., OpenAIProvider) formats the prompt using the template and context
Custom instructions (if any) are appended
LLM API Call
The provider sends the prompt to the LLM API (e.g., OpenAI)
Model, API key, and other options are resolved from config/env/CLI
Response Parsing
The provider parses the LLM response into a LintResult object
Adds metadata (timestamp, provider, model, context size)
Calculates summary statistics if not provided
Result Display
The CLI displays results using UI components (tables, banners, JSON)
Issues are grouped by file, with severity coloring and explanations
Context too large for model
Network errors
Invalid or empty responses
Timeouts
Errors are logged and surfaced to the user with actionable messages
Fallbacks are provided (e.g., simple text output if table rendering fails)
Output format/schema
Full code context
Result Display: The CLI displays results using UI components (tables, banners, JSON).
Get detailed information about specific commands
See examples of how to use each command
Understand command options and their default values
To display general help information, use the help command:
This will display:
A list of all available commands with descriptions
Default command options
Global options that apply to all commands
Examples of common usage patterns
To get detailed help for a specific command, use:
For example, to get help for the init command:
This will display:
Command description
Usage information
Available options with descriptions and default values
Command aliases
Examples of how to use the command
You can also get help for a command by using the --help flag with the command:
DeepLint's default command runs when you don't specify a command (just deeplint). To get help for the default command:
This will show you all the options available for the default command, such as:
The help command has the following aliases:
h
?
You can use these aliases instead of help:
Here are some examples of using the help command:
Displays a list of all available commands and general usage information.
Displays detailed help for the init command, including options, aliases, and examples.
Displays help for the default command that runs when no command is specified.
Displays help for the init command.
The help output is organized into sections:
Shows the command syntax:
Lists all available options for the command:
Each option includes:
The option name and any aliases
A description of what the option does
The default value (if applicable)
Lists alternative names for the command:
Provides practical examples of using the command:
Now that you understand how to use the help system, you can:
Explore the available commands using deeplint help
Learn about specific commands using deeplint help <command>
Understand the options for the default command using deeplint help default
For more information about DeepLint's configuration, see the Configuration guide.
Git Integration (current page)
DeepLint is designed to work with Git repositories, analyzing changes in your codebase. By default, DeepLint analyzes staged changes, but you can also configure it to include unstaged changes.
The Git integration allows DeepLint to:
Detect staged and unstaged changes in your repository
Parse Git diffs to understand what has changed
Build context for analysis based on these changes
Focus analysis on the parts of your codebase that have changed
To run DeepLint on your Git changes:
You can configure Git integration through your DeepLint configuration file:
Setting includeUnstaged to true will make DeepLint include unstaged changes in the analysis by default, without needing to specify the --unstaged flag.
DeepLint is designed to be integrated into your Git workflow. Here are some common ways to use DeepLint with Git:
Run DeepLint before committing changes to catch issues early:
You can stage specific files and then run DeepLint to analyze only those files:
If you want to analyze changes before staging them:
If you run DeepLint without any staged changes, you'll see an error message:
To fix this, either:
Stage some changes with git add, or
Use the --unstaged flag to analyze unstaged changes:
If you run DeepLint outside of a Git repository, you'll see an error message:
To fix this, either:
Navigate to a Git repository, or
Initialize a Git repository in your current directory:
If Git is not installed or not in your PATH, you'll see an error message:
To fix this, install Git from git-scm.com and ensure it's in your PATH.
If DeepLint doesn't have permission to access the Git repository, you'll see an error message:
To fix this, ensure you have the necessary permissions to access the Git repository.
DeepLint's Git integration consists of two main components:
Git Operations: Interacts with Git repositories to retrieve information about changes
Diff Parser: Parses Git diffs into a structured format for analysis
The Git Operations component provides a clean interface for interacting with Git repositories. It uses the simple-git library to execute Git commands and parse their results. Key operations include:
Checking if there are staged or unstaged changes
Getting the list of staged or unstaged files
Getting the diff for staged or unstaged changes
Getting the diff between two commits
The Diff Parser component parses Git diff output into a structured format that can be easily processed by the Context Builder. It extracts information about:
Changed files and their paths
Additions, deletions, and modifications
Line numbers and content
Context around changes
This structured information is then used by the Context Builder to build context for analysis.
Note: For planned Git features such as pre-commit hooks, CI/CD integration, and pull request analysis, see the Roadmap.
Now that you understand how DeepLint works with Git, you can:
Configure DeepLint to customize the analysis
Learn about the command line options to get the most out of DeepLint
Explore the context building process to understand how DeepLint analyzes your code
For more detailed information about the Git integration implementation, see the Git Operations and Diff Parsing documentation.
Previous: First Run
Short aliases: Single-character shortcuts for frequently used commands
Aliases make it easier to use DeepLint by providing multiple ways to invoke the same command.
Full-word aliases are alternative names for commands that you can use interchangeably with the primary command name. For example, the init command has the following aliases:
initialize
create-config
You can use any of these aliases instead of the primary command name:
All of these commands do exactly the same thing.
Short aliases are single-character shortcuts for commands. For example, the init command has the short alias i. You can use short aliases in two ways:
This is the recommended way to use short aliases, following the pattern used by tools like npm (npm i for install).
Both forms are equivalent to:
Short aliases are particularly useful for frequently used commands, as they require less typing.
Short aliases in DeepLint work by converting the short alias to the corresponding command name before processing the command-line arguments. This means that:
The short alias must be a separate argument (e.g., i or -i, not -i=value or -ivalue)
The short alias must be the first argument after the command name
You can combine short aliases with options (e.g., i --force or -i --force)
For example, these are all valid ways to use short aliases:
With dash prefix (backward compatibility):
But these are not valid:
Here's a list of available commands and their aliases:
The default command runs when you don't specify a command (just deeplint).
Short Aliases:
r: Run DeepLint on staged changes
run: Run DeepLint on staged changes
You can also use the dash prefix for backward compatibility:
The init command initializes DeepLint in your project.
Full-Word Aliases:
initialize: Initialize DeepLint in the current project
create-config: Create a DeepLint configuration file
Short Aliases:
i: Initialize DeepLint in the current project
You can also use the dash prefix for backward compatibility:
The help command displays help information for DeepLint commands.
Full-Word Aliases:
?: Display help information
Short Aliases:
h: Display help information
You can also use the dash prefix for backward compatibility:
You can combine aliases with command options:
Or with the dash prefix for backward compatibility:
Both are equivalent to:
To see the aliases for a specific command, use the help command:
For example:
This will display information about the command, including its aliases.
Use short aliases for frequent operations: Short aliases are designed for commands you use often
Use full-word aliases for clarity in scripts: When writing scripts or documentation, consider using full-word aliases for better readability
Learn the aliases for your most-used commands: Memorizing a few key aliases can significantly speed up your workflow
Now that you understand how to use command aliases, you can:
Try using aliases for your most common DeepLint operations
Learn more about DeepLint's help system
Explore verbose mode for more detailed output
For more information about DeepLint's commands, see the help command:
contextBuilder: {
// Maximum number of tokens to use for the context
maxTokens: 8000,
// Maximum number of tokens to use per file
tokensPerFile: 1000,
// Maximum file size in KB to include in the context
maxFileSize: 500,
// Whether to include dependencies in the context (default: true)
includeDependencies: true,
// Whether to include code structure in the context
includeStructure: true,
}deeplint --debugdeeplint --dump context.jsonsrc/llm/
├── index.ts # Exports all LLM components
├── types.ts # Shared types for LLM integration
├── llm-provider.ts # Provider interface
├── openai-provider.ts # OpenAI provider implementation
├── prompt-template.ts # Prompt templates and schemas
├── parsers/ # (Future) Response parsers for different providersexport interface LLMProvider {
analyze(context: LLMContext, options?: LLMAnalysisOptions): Promise<LintResult>;
}deeplint --helpdeeplint helpdeeplint help initdeeplint help defaultdeeplint init --helpdeeplint helpdeeplint help <command>deeplint help initdeeplint init --helpdeeplint help defaultOPTIONS
--context=<type> Context depth (light, deep) [default: light]
--debug Enable debug output [default: false]
--dump=<file> Dump context to a file
--unstaged Include unstaged changes [default: false]
--help, -h Display help for this commanddeeplint h init
deeplint ? initUSAGE
$ deeplint init [options]OPTIONS
--force, -f Overwrite existing config [default: false]
--help, -h Display help for this commandALIASES
$ deeplint initialize
$ deeplint create-configEXAMPLES
$ deeplint init Create a new configuration
$ deeplint init --force Overwrite existing configuration# Run on staged changes only (default)
deeplint
# Run on both staged and unstaged changes
deeplint --unstagedgit: {
// Whether to include unstaged changes in the analysis
includeUnstaged: false,
}# Stage your changes
git add .
# Run DeepLint on staged changes
deeplint
# If no issues are found, commit your changes
git commit -m "Your commit message"# Stage specific files
git add file1.js file2.js
# Run DeepLint on staged changes
deeplint# Run DeepLint on unstaged changes
deeplint --unstagedERROR: No staged changes found. Stage changes with 'git add' or use --unstaged to analyze unstaged changes.deeplint --unstagedERROR: Not a Git repository. Initialize a Git repository with 'git init' or navigate to a Git repository.git initERROR: Git not found. Please install Git and ensure it's in your PATH.ERROR: Permission denied: Could not access Git repository.deeplint init
deeplint initialize
deeplint create-configdeeplint ideeplint -ideeplint initdeeplint i
deeplint i --force
deeplint h initdeeplint -i
deeplint -i --force
deeplint -h initdeeplint i=value # Not valid, use i --option=value instead
deeplint iforce # Not valid, use i --force instead
deeplint -i=value # Not valid, use -i --option=value instead
deeplint -iforce # Not valid, use -i --force insteaddeeplint r
deeplint rundeeplint -r
deeplint -rundeeplint init
deeplint initialize
deeplint create-config
deeplint ideeplint -ideeplint help
deeplint ?
deeplint hdeeplint -hdeeplint i --forcedeeplint -i --forcedeeplint init --forcedeeplint help <command>deeplint help initdeeplint helpThis guide explains how to use DeepLint's verbose mode to get more detailed information about command execution.
DeepLint provides a verbose mode that outputs additional information during command execution. This can be helpful for:
Debugging issues with DeepLint
Understanding what DeepLint is doing behind the scenes
Getting more context about the analysis process
Troubleshooting configuration problems
To enable verbose mode, use the --verbose flag or its shorthand -v:
This will run the default command with verbose output enabled.
You can also use verbose mode with specific commands:
When verbose mode is enabled, DeepLint will output additional information about:
Configuration loading and validation
Command execution steps
Context building process
File scanning and analysis
For example, when running the default command with verbose mode:
You'll see additional output like:
Verbose mode can be combined with other flags:
This will run the default command with verbose output and include unstaged changes in the analysis.
Here are some examples of using verbose mode with different commands:
Runs the default command with verbose output, showing detailed information about the context building process.
Initializes DeepLint with verbose output, showing detailed information about the configuration file creation process.
Displays help information with verbose output, showing detailed information about the help command execution.
Verbose mode is particularly useful in the following scenarios:
Troubleshooting: When DeepLint isn't behaving as expected, verbose mode can help identify where the issue is occurring.
Learning: If you're new to DeepLint, verbose mode can help you understand what's happening behind the scenes.
Complex Projects: In large projects with many files, verbose mode can provide insights into how DeepLint is analyzing your code.
Custom Configurations: If you've customized your DeepLint configuration, verbose mode can help verify that your settings are being applied correctly.
Now that you understand how to use verbose mode, you can:
Try running DeepLint with verbose mode to see the additional information it provides
Use verbose mode to troubleshoot any issues you encounter
Learn more about
For more information about DeepLint's commands, see the guide.
Command-specific operations
deeplint --verbosedeeplint init --verbose
deeplint help --verbosedeeplint --verbose🔊 Context building configuration:
🔊 - Repository root: /path/to/your/project
🔊 - Context type: light
🔊 - Include unstaged changes: false
🔊 - Max tokens: 8000
🔊 - Include dependencies: false
🔊 - Include structure: true
🔊 Starting context building process...
🔊 Context building process completed.
🔊 Context building statistics:
🔊 - Total files: 42
🔊 - Changed files: 3
🔊 - Related files: 5
🔊 - Total tokens: 2500
🔊 - Build time: 120msdeeplint --verbose --unstageddeeplint --verbosedeeplint init --verbosedeeplint help --verboseNote: The
checkcommand has been merged with the default command. Bothdeeplintanddeeplint checknow provide the same functionality. This documentation is kept for reference, but we recommend using the default command (deeplint) directly.
The check command runs DeepLint's LLM-powered analysis on your codebase, providing advanced linting, code review, and suggestions using AI.
or (for backward compatibility):
DeepLint analyzes staged changes by default.
By default, DeepLint displays results in a formatted table, grouped by file, with severity coloring and detailed explanations.
Example output:
If you use --json, the output will be a machine-readable JSON object matching the LLM result schema.
LLM options can be set via CLI flags, environment variables, or config file. Precedence is:
CLI arguments
Environment variables
Config file (llm section)
Built-in defaults
See the for details.
Missing API Key: Set OPENAI_API_KEY or use --api-key.
Model Not Supported: Check your OpenAI account/model access.
Rate Limits/Quotas: See your OpenAI dashboard for usage.
This document describes how data flows through the DeepLint system, focusing on the current implementation.
DeepLint's data flow is centered around the context building process and LLM-powered analysis, which gathers information from the Git repository and codebase, sends it to an LLM, and displays results.
The data flow begins with the user running the DeepLint CLI:
The CLI parses the command-line arguments using yargs and identifies the appropriate command to execute.
Data: Command name, options, and arguments
The command registry identifies the command class and creates an instance. The command's execute() method is called with the parsed arguments.
Data: Parsed command-line arguments
The command loads configuration from:
Default values
Configuration file (deeplint.config.js or .deeplintrc.yml)
Environment variables
Command-line options
Data: Configuration object with typed properties
The context builder uses Git operations to:
Check if there are staged changes
Get the diff for staged changes
Parse the diff into a structured format
Data:
Staged files list
Diff information (file paths, additions, deletions, changes)
The repository indexing process involves several steps:
The file system scanner traverses the repository to:
Build a directory structure
Collect file metadata
Categorize files by type
Data:
Repository structure (directories, files)
File metadata (path, size, type, last modified)
The dependency analyzer examines files to:
Parse import/export statements
Build a dependency graph
Identify direct dependencies of changed files
Data:
Dependency graph
Direct dependencies of changed files
The code structure analyzer extracts:
Functions and their signatures
Classes and their methods
Interfaces and types
Export information
Data:
Code structure information (functions, classes, interfaces, types)
Export information
The context builder assembles all the gathered information into a structured context:
Data: Assembled context object
The token counter ensures the context fits within LLM token limits:
Count tokens for each part of the context
Truncate file content if necessary
Track total token usage
Data:
Token counts
Truncated file content
The context builder returns the assembled context and statistics:
Data: Context build result
The command formats the results for display:
Summary of context building
Statistics about the context
Debug information if requested
Data: Formatted output
The default command follows the full data flow described above:
Check for staged changes
Build context
Display results or dump context to a file
The init command has a simpler data flow:
Check if configuration file exists
Create configuration file with default values
Display success message
When errors occur, the data flow includes error handling:
Each component includes error handling that:
Catches exceptions
Creates typed errors with context
Logs errors with appropriate level
Returns error information in the result
Data:
Error type
Error message
Error context
Stack trace (in debug mode)
- High-level architecture and design principles
- Detailed component descriptions and relationships
- Detailed documentation of the Context Builder component
This document provides guidelines for creating and maintaining code examples in the DeepLint documentation. Following these guidelines ensures that code examples are consistent, clean, and helpful for users.
Code examples should follow the and be self-explanatory whenever possible. This means:
Use descriptive variable and function names
Keep functions small and focused
Follow consistent formatting
Avoid unnecessary complexity
Examples should be minimal and focused on illustrating a specific concept or feature. Remove any code that isn't directly relevant to what you're demonstrating.
While examples should be minimal, they should also be realistic and demonstrate practical use cases that users might encounter.
Comments in code examples should be used sparingly and only when they add value:
Use comments to explain "why", not "what" or "how"
Use comments to highlight important concepts that might not be immediately obvious
Use comments to indicate where code has been omitted for brevity
Avoid comments that:
Simply restate what the code is doing
Could be made unnecessary by using better variable or function names
Explain basic programming concepts that the target audience should already understand
Are outdated or incorrect
When comments are necessary:
Keep them brief and to the point
Use consistent style (e.g., // Comment for single-line comments)
For multi-line comments, use // Comment line 1 and // Comment line 2 rather than /* ... */
For command line examples:
Use comments to explain the purpose of commands
Include expected output when relevant
Use # for comments in bash code blocks
For configuration examples:
Use comments to explain non-obvious options
Include only relevant configuration sections
Show both JavaScript and YAML examples when applicable
For API usage examples:
Focus on the specific API being documented
Include error handling when relevant
Show complete, working examples
When implementing these guidelines:
Review existing documentation for unnecessary comments in code examples
Prioritize user-facing documentation (Getting Started guides, README, etc.)
Be consistent across all documentation
Test code examples to ensure they work as expected
Use this checklist when creating or reviewing code examples:
By following these guidelines, we can ensure that code examples in the DeepLint documentation are clean, consistent, and helpful for users. Remember that the goal of code examples is to illustrate concepts and features in a way that is easy to understand and apply.
This guide explains how to use the DeepLint init command to set up DeepLint in your project.
The init command initializes DeepLint in your project by creating a configuration file. This is typically the first command you'll run when setting up DeepLint for a new project.
The init command:
Creates a configuration file in your project root
Sets up default configuration options
Prompts you for any required information
To initialize DeepLint in your project, run:
This will create a configuration file with default settings in your project root.
The init command supports the following options:
The --force option allows you to overwrite an existing configuration file:
This is useful when you want to reset your configuration to the default values.
The --js option explicitly specifies that you want to create a JavaScript configuration file:
This is the default behavior, so you don't need to specify this option unless you want to be explicit.
The --yaml option specifies that you want to create a YAML configuration file:
This will create a .deeplintrc.yml file instead of a JavaScript configuration file.
The init command has the following aliases:
Full-Word Aliases:
initialize: Initialize DeepLint in the current project
create-config: Create a DeepLint configuration file
You can use any of these aliases instead of init:
Here are some examples of using the init command:
Creates a JavaScript configuration file (deeplint.config.js) with default settings.
Overwrites an existing configuration file with default settings.
Creates a YAML configuration file (.deeplintrc.yml) with default settings.
All of these commands do the same thing as deeplint init.
The init command creates a configuration file with default settings. Here's an example of the default configuration:
If a configuration file already exists, the init command will fail with an error:
To overwrite the existing configuration file, use the --force option:
If you don't have permission to write to the project directory, the init command will fail with an error:
Make sure you have write permission for the project directory.
After initializing DeepLint, you can:
for your project
For more information about DeepLint's configuration options, see the guide.
This document outlines the comprehensive plan for DeepLint's documentation, including completed tasks, current status, and future improvements.
Getting Started
The DeepLint documentation is organized into the following sections:
Getting Started: Quick start guides for new users
Core Concepts: Explanations of key concepts and features
User Guides: Detailed guides for specific tasks and features
Developer Documentation: Information for contributors and developers
The following documentation will be created as the corresponding features are implemented:
The implementation of these documentation improvements should follow these principles:
Documentation-as-Code: Treat documentation as a first-class citizen in the codebase
Incremental Improvement: Focus on making the documentation better, not redoing it completely
Prioritize Implemented Features: Ensure documentation for implemented features is complete and accurate
Consistency: Maintain consistent style, terminology, and structure
For detailed guidelines on writing and maintaining documentation, see:
Document the remaining context builder components ✅ Completed
Create reference documentation for CLI commands ✅ Completed
Establish documentation maintenance process
Set up documentation testing and versioning
This document provides a high-level overview of DeepLint's architecture, focusing on the current implementation and design principles.
Reference: Detailed reference documentation for APIs, commands, etc.
Documentation Guidelines: Guidelines for writing and maintaining documentation
developer/components/context-builder/dependency-analyzer.mdUser-Centric: Prioritize improvements that enhance the user experience
Create documentation for planned features as they are implemented
✅ Complete
Installation, configuration, first run, Git integration
Core Concepts
🟡 Partial
Context building complete, semantic analysis and auto-fixes planned
User Guides
🟡 Partial
Commands documented, configuration and rules guides planned
Developer Documentation
🟡 Partial
Architecture, code organization, and contributing guides complete
Reference
🟡 Partial
CLI and configuration references complete, API docs planned
Documentation Guidelines
✅ Complete
Style guide, code examples, readability guidelines
--instructions
string
Additional instructions for the LLM
none
--json
boolean
Output results in JSON format
false
--context
string
Context depth for analysis (light or deep)
"light"
--unstaged
boolean
Include unstaged changes in the analysis
false
--debug
boolean
Enable debug output
false
--verbose
boolean
Enable verbose output
false
--temperature
number
Temperature for the LLM (0-1)
0
--max-tokens
number
Maximum tokens for the LLM response
16384
--dump
string
Dump context to a file (specify filename)
none
--provider
string
LLM provider to use
"openai"
--model
string
LLM model to use
process.env.OPENAI_MODEL or "gpt-4o"
--api-key
string
API key for the LLM provider
process.env.OPENAI_API_KEY
Place comments on their own line before the code they describe, not at the end of lines
Update examples when the API or behavior changes
i: Initialize DeepLint in the current project
deeplint [options]deeplint check [options]deeplintdeeplint --model=gpt-4deeplint --instructions="Focus on security issues."deeplint --jsondeeplint --unstageddeeplint --temperature 0.7deeplint --dump context.jsonFile: src/commands/default-command.ts
┌──────────┬──────┬──────────────────────────────────────────────┐
│ Severity │ Line │ Message │
├──────────┼──────┼──────────────────────────────────────────────┤
│ warning │ 1 │ Unused import statement │
│ info │ 60 │ Hardcoded default values │
└──────────┴──────┴──────────────────────────────────────────────┘
Line 1: Unused import statement
Explanation: The import statement for 'Argv' from 'yargs' is not used anywhere in the file.
Suggestion: Remove the unused import statement to clean up the code.deeplint [command] [options]interface LLMContext {
repository: {
name: string;
root: string;
structure: ContextRepositoryStructure;
};
changes: {
files: ContextChange[];
summary: string;
};
relatedFiles: ContextFile[];
metadata: {
contextSize: {
totalTokens: number;
changesTokens: number;
relatedFilesTokens: number;
structureTokens: number;
};
generatedAt: string;
contextType: "light" | "deep";
error?: {
message: string;
timestamp: string;
phase?: string;
};
};
}interface ContextBuildResult {
context: LLMContext;
stats: {
totalFiles: number;
changedFiles: number;
relatedFiles: number;
totalTokens: number;
buildTime: number;
error?: string;
};
}// ❌ Bad: Unnecessary comments
// Create a new context builder
const contextBuilder = new ContextBuilder();
// Build the context
const result = await contextBuilder.buildContext();
// Log the result
console.log(`Built context with ${result.stats.totalTokens} tokens`);// ✅ Good: Self-explanatory code without unnecessary comments
const contextBuilder = new ContextBuilder();
const result = await contextBuilder.buildContext();
console.log(`Built context with ${result.stats.totalTokens} tokens`);// ✅ Good: Comments that add value
// Configure the context builder with custom options
const contextBuilder = new ContextBuilder({
contextType: "deep",
maxTokens: 16000, // Increased token limit for larger codebases
includeDependencies: true,
});
// Process only specific files instead of all staged changes
const result = await contextBuilder.buildContextForFiles(["src/main.ts", "src/utils.ts"]);
// ... rest of implementation omitted for brevity/**
* Builds context for LLM analysis based on staged changes
*
* @param options - Options for the context builder
* @returns Promise resolving to the context build result
* @throws {GitError} If Git operations fail
*/
async function buildContext(
options?: Partial<ContextBuilderOptions>,
): Promise<ContextBuildResult> {
const contextBuilder = new ContextBuilder(options);
return contextBuilder.buildContext();
}# Initialize DeepLint with YAML configuration
$ deeplint init --yaml
# Output:
# DeepLint initialized successfully!
# Configuration file created at: .deeplintrc.yml// JavaScript configuration example
export default defineConfig({
contextBuilder: {
contextType: "light",
maxTokens: 8000, // Adjust based on your codebase size
includeDependencies: false, // Set to true for deeper analysis
},
// Other configuration sections omitted for brevity
});// Example of using the ContextBuilder API
import { ContextBuilder } from "deeplint";
async function analyzeCode() {
try {
const contextBuilder = new ContextBuilder();
const result = await contextBuilder.buildContext();
console.log(`Analysis complete: ${result.stats.changedFiles} files analyzed`);
console.log(`Total tokens: ${result.stats.totalTokens}`);
return result;
} catch (error) {
console.error(`Analysis failed: ${error.message}`);
throw error;
}
}deeplint initOPTIONS
--force, -f Overwrite existing config [default: false]
--js Create JavaScript config [default: true]
--yaml Create YAML config [default: false]
--help, -h Display help for this commanddeeplint init --forcedeeplint init --jsdeeplint init --yamldeeplint initialize
deeplint create-config
deeplint ideeplint initdeeplint init --forcedeeplint init --yamldeeplint i
deeplint initialize
deeplint create-configimport { defineConfig } from "deeplint";
export default defineConfig({
contextBuilder: {
contextType: "light",
maxTokens: 8000,
tokensPerFile: 1000,
maxFileSize: 500,
includeDependencies: false,
maxDependencyDepth: 1,
includeStructure: true,
},
files: {
include: ["**/*.js", "**/*.ts", "**/*.jsx", "**/*.tsx"],
exclude: ["node_modules/**", "dist/**", "build/**"],
useGitignore: true,
},
git: {
includeUnstaged: false,
},
logging: {
level: "info",
},
});contextBuilder:
contextType: light
maxTokens: 8000
tokensPerFile: 1000
maxFileSize: 500
includeDependencies: false
maxDependencyDepth: 1
includeStructure: true
files:
include:
- "**/*.js"
- "**/*.ts"
- "**/*.jsx"
- "**/*.tsx"
exclude:
- "node_modules/**"
- "dist/**"
- "build/**"
useGitignore: true
git:
includeUnstaged: false
logging:
level: infoERROR: Configuration file already exists at /path/to/your/project/deeplint.config.jsdeeplint init --forceERROR: Permission denied: Could not write to /path/to/your/project/deeplint.config.jsAnalyzing the context for issues using LLM
Displaying the results with detailed feedback
This is the command you'll use most frequently when working with DeepLint.
To run the default command, simply use the deeplint command without specifying a command name:
This will analyze the staged changes in your Git repository and display the results.
The default command supports the following options:
The --unstaged option includes unstaged changes in the analysis:
By default, DeepLint only analyzes staged changes. This option allows you to analyze unstaged changes as well.
The --provider option allows you to specify the LLM provider to use:
Currently, only openai is supported.
The --model option allows you to specify the LLM model to use:
Default is gpt-4o or the value of the OPENAI_MODEL environment variable.
The --api-key option allows you to specify the API key for the LLM provider:
If not provided, DeepLint will use the OPENAI_API_KEY environment variable.
The --temperature option allows you to specify the temperature for the LLM (0-1):
Higher values make the output more random, lower values make it more deterministic.
The --max-tokens option allows you to specify the maximum number of tokens for the LLM response:
The --instructions option allows you to provide additional instructions for the LLM:
The --debug option enables debug output:
This displays detailed technical information about the command execution, including:
Configuration values
Context building details
Token usage
Error details
The --dump option allows you to dump the context to a file:
This is useful for debugging and for understanding what information DeepLint is using for analysis.
The --verbose option enables verbose output:
This displays additional information about what DeepLint is doing, such as:
Configuration loading and validation
Context building steps
Analysis progress
The --json option outputs the results in JSON format:
This is useful for integrating DeepLint with other tools or for parsing the results programmatically.
The default command has the following aliases:
Full-Word Aliases:
run: Run DeepLint on staged changes
check: Analyze code for issues (for backward compatibility)
lint: Analyze code for issues (for backward compatibility)
analyze: Analyze code for issues (for backward compatibility)
Short Aliases:
r: Run DeepLint on staged changes
c: Analyze code for issues (for backward compatibility)
You can use any of these aliases instead of the default command:
Here are some examples of using the default command:
Analyzes staged changes with default options.
Analyzes unstaged changes instead of staged changes.
Analyzes staged changes using the GPT-4 model.
Analyzes staged changes with a higher temperature for more creative suggestions.
Analyzes staged changes with custom instructions for the LLM.
Analyzes staged changes and outputs the results in JSON format.
Analyzes staged changes with debug output enabled.
Analyzes staged changes and dumps the context to a file.
Analyzes staged changes with verbose output enabled.
Analyzes unstaged changes with verbose output, GPT-4 model, and higher temperature.
The default command output includes:
A summary of the analysis results, including:
Number of files analyzed
Number of issues found by severity (error, warning, info, hint)
Number of affected files
Example:
Details about each issue found, including:
Issue severity (error, warning, info, hint)
Issue location (file, line, column)
Issue message
Code snippet (if available)
Explanation
Suggestion (if available)
Example:
If there are no staged changes, the default command will display a warning:
To analyze unstaged changes, use the --unstaged option:
If the OpenAI API key is missing, the command will display an error:
Make sure to set the OPENAI_API_KEY environment variable or use the --api-key option.
If the context is too large for the token limit, the command will display a warning:
To reduce the token usage, you can:
Reduce the number of files being analyzed
Increase the token limit in the configuration
Reduce the token limit per file in the configuration
Now that you understand how to use the default command, you can:
Configure DeepLint to customize the analysis
Set up Git integration to run DeepLint automatically
Learn about verbose mode for more detailed output
For more information about DeepLint's commands, use the help command:
Data Flow - How data flows through the system
DeepLint follows a modular architecture with clear separation of concerns. The system is designed to be extensible and maintainable, with well-defined interfaces between components.
The following table shows the implementation status of major components:
CLI
✅ Implemented
Command-line interface and argument parsing
Command System
✅ Implemented
Command registration, discovery, and execution
Context Builder
✅ Implemented
Context building orchestration
Git Integration
✅ Implemented
Git operations, diff parsing
For detailed descriptions of each component, see the Components documentation.
DeepLint's architecture is guided by the following design principles:
Each component has a single responsibility and well-defined interfaces:
CLI: Handles command-line argument parsing and execution
Command System: Manages command registration, discovery, and execution
Context Builder: Orchestrates the context building process
Git Integration: Handles Git repository operations
Repository Indexing: Analyzes repository structure and dependencies
Context Assembly: Assembles context and manages token limits
Configuration: Manages user configuration
The architecture is designed to be extensible:
New commands can be added without modifying existing code
Additional analyzers can be integrated into the context builder
Multiple LLM providers can be supported through a common interface (planned)
DeepLint makes extensive use of TypeScript for type safety:
Interfaces define component contracts
Configuration is strongly typed
Error handling is type-aware
A consistent error handling strategy is implemented:
Custom error types for different categories of errors
Contextual error information
Graceful degradation when errors occur
The command system is responsible for registering, discovering, and executing CLI commands:
BaseCommand: Abstract base class for all commands
CommandRegistry: Registry for command registration and discovery
Command Discovery: Automatic discovery of commands in the commands directory
The context builder is responsible for gathering code context for analysis:
Git Integration: Extracts changes from Git
Repository Indexing: Scans the repository structure and analyzes dependencies
Context Assembly: Assembles the context and manages token limits
The configuration system manages user configuration:
Configuration Store: Persistent storage for configuration
Configuration Schema: Type definitions for configuration
Configuration Validation: Validation of user configuration
Cosmiconfig Integration: Flexible configuration file discovery and loading
The configuration system uses cosmiconfig to find and load configuration from various sources:
package.json with a "deeplint" property
.deeplintrc files in various formats (JSON, YAML, JS)
deeplint.config.js/cjs/mjs/ts files
Configuration in a .config subdirectory
DeepLint uses tsup for building:
Dual Format Output: Generates both ESM and CJS outputs for maximum compatibility
Bundling: Bundles ESM-only dependencies like chalk for CJS compatibility
TypeScript Compilation: Compiles TypeScript to JavaScript
Declaration Files: Generates TypeScript declaration files
Source Maps: Generates source maps for debugging
DeepLint uses the Command pattern for CLI commands:
Each command is a separate class
Commands are registered with a central registry
Commands are discovered automatically
This approach allows for:
Separation of concerns
Easy addition of new commands
Consistent command interface
DeepLint uses a simple form of dependency injection:
Components accept dependencies in their constructors
Default implementations are provided when dependencies are not specified
This facilitates testing and component replacement
DeepLint uses cosmiconfig for flexible configuration management:
Configuration can be defined in multiple file formats (JS, JSON, YAML)
Configuration can be placed in various locations (package.json, .deeplintrc, etc.)
Configuration is defined with TypeScript interfaces for type safety
Default values are provided for all required options
Configuration is validated against a schema
The planned architecture will extend the current design:
LLM Integration: Abstract interface to multiple LLM providers
Analysis Engine: Processes context to identify issues
Auto-fix Generator: Generates fixes for detected issues
Policy Engine: Manages custom rules and policies
For more details on how data flows through the system, see the Data Flow documentation.
DeepLint operates within the following technical constraints:
Node.js Environment: Runs in Node.js v22+
Module Compatibility: Supports both ESM and CJS environments
Git Dependency: Requires Git to be installed
Token Limits: LLMs have token limits that constrain context size
API Key Management: Requires secure management of API keys
Developer Note: The architecture is designed to allow incremental implementation of features. The context building functionality is complete and can be used independently of the analysis capabilities.
deeplintdeeplint --unstageddeeplint --model=gpt-4deeplint --temperature=0.7deeplint --instructions="Focus on security issues."deeplint --jsondeeplintOPTIONS
--debug Enable debug output [default: false]
--dump=<file> Dump context to a file
--unstaged Include unstaged changes [default: false]
--verbose, -v Enable verbose output [default: false]
--json Output results in JSON format [default: false]
--provider=<provider> LLM provider to use [default: openai]
--model=<model> LLM model to use [default: gpt-4o]
--api-key=<key> API key for the LLM provider
--temperature=<temp> Temperature for the LLM (0-1)
--max-tokens=<num> Maximum tokens for LLM response
--instructions=<text> Additional instructions for LLM
--help, -h Display help for this commanddeeplint --unstageddeeplint --provider=openaideeplint --model=gpt-4deeplint --api-key=sk-...deeplint --temperature=0.7deeplint --max-tokens=8192deeplint --instructions="Focus on security issues and performance optimizations."deeplint --debugdeeplint --dump=context.jsondeeplint --verbosedeeplint --jsondeeplint run
deeplint check
deeplint r
deeplint c✅ Analysis complete: found 5 issues in 2 files
Errors: 1 | Warnings: 2 | Info: 1 | Hints: 1File: src/utils.ts
✖ error | Line 42 | Potential null reference
Code snippet: const result = user.profile.name;
Explanation: The 'profile' property might be null or undefined, which would cause a runtime error.
Suggestion: Add a null check before accessing the property: const result = user.profile?.name;⚠️ No changes detected. Nothing to analyze.deeplint --unstaged❌ OpenAI API key is required. Set it in .env file or pass it in the config.⚠️ Token limit exceeded. Some files may be truncated or excluded.deeplint helpRepository Indexing
✅ Implemented
File system scanning, dependency analysis, code structure
Context Assembly
✅ Implemented
Context assembly and token management
Configuration
✅ Implemented
Flexible configuration with cosmiconfig, validation
LLM Integration
✅ Implemented
LLM-powered analysis, OpenAI provider, prompt templates
Analysis Engine
🚧 Planned
Not yet implemented (see Roadmap)
Auto-fix Generator
🚧 Planned
Not yet implemented (see Roadmap)
deeplint --debugdeeplint --dump=context.jsondeeplint --verbosedeeplint --unstaged --verbose --model=gpt-4 --temperature=0.7This document provides guidelines for improving the readability of DeepLint documentation. Following these guidelines ensures that documentation is accessible, engaging, and easy to understand for all users.
Focus on the user's needs and goals
Organize content based on user tasks rather than system architecture
Consider different user personas (beginners, experienced developers, etc.)
Anticipate common questions and provide answers
Use clear, concise language
Avoid unnecessary technical jargon
Define technical terms when they must be used
Use active voice and present tense
Use headings and subheadings to create a clear structure
Use lists and tables to organize information
Use whitespace effectively
Highlight important information
Technical jargon includes:
Acronyms and abbreviations
Domain-specific terminology
Internal project terminology
Complex technical concepts
Use technical terms when:
The term is widely understood by the target audience
The term is necessary for precision
The term is defined when first introduced
There is no simpler alternative
Avoid technical terms when:
A simpler alternative exists
The term is not essential for understanding
The term is internal jargon not familiar to users
The documentation is aimed at beginners
Include different types of examples:
Basic examples: Simple, focused examples for beginners
Common use cases: Examples that solve real-world problems
Advanced examples: More complex examples for experienced users
Troubleshooting examples: Examples that show how to fix common issues
Structure examples consistently:
Context: Explain when and why to use this approach
Code: Show the example code
Explanation: Explain what the code does
Result: Show the expected output or result
This command will analyze the files you've staged with git add and show any issues found.
Output:
This is useful when you want to check files before staging them or when working on specific parts of your codebase.
Output:
Use tables to present:
Comparison of options or features
Configuration settings
Command line arguments
Structured data
Use clear column headers
Align content for readability
Keep tables simple (avoid nested tables)
Use consistent formatting
Use screenshots and images to show:
UI elements and interactions
Expected output
Visual concepts
Step-by-step processes
Use clear, high-quality images
Crop images to focus on relevant content
Add annotations or highlights when necessary
Include alt text for accessibility
When implementing these readability improvements:
Start with user-facing documentation (Getting Started guides, README, etc.)
Focus on one section at a time to maintain consistency
Test with different audiences to ensure clarity
Update examples when the API or behavior changes
Use this checklist when reviewing documentation for readability:
By following these guidelines, we can create documentation that is more readable, accessible, and helpful for all users. Remember that the goal of documentation is to help users understand and use DeepLint effectively, regardless of their technical background or experience level.
Variations: Show alternative approaches (optional)
Use the style guide to maintain consistent formatting
"Utilize"
"Use"
"Implement"
"Create" or "Build"
"Instantiate"
"Create"
"Terminate"
"End" or "Stop"
"Functionality"
"Feature"
"LLM Context"
"Code Analysis Context"
Title: A clear, descriptive title using a single H1 (#) heading
Introduction: A brief overview of what the document covers
Main Content: The primary content of the document, organized into logical sections
Related Resources: Links to related documentation
Next Steps (optional): Suggestions for what to read or do next
Example:
Use a consistent heading hierarchy:
# (H1): Document title (only one per document)
## (H2): Major sections
### (H3): Subsections
#### (H4): Sub-subsections (use sparingly)
Do not skip heading levels (e.g., don't go from H2 to H4 without an H3 in between).
For documents that are part of a series, include navigation hints at the top and bottom:
At the bottom of the document, include navigation links:
Use bold (**bold**) for emphasis and UI elements
Use italic (*italic*) for introducing new terms
Use code (`code`) for code snippets, file names, and commands
Use > blockquotes for important notes or quotes
Use unordered lists (-) for items without a specific order
Use ordered lists (1., 2., etc.) for sequential steps or prioritized items
Maintain consistent indentation for nested lists (2 spaces)
Use triple backticks (```) for code blocks
Specify the language for syntax highlighting (e.g., ```typescript)
For terminal commands, use ```bash and include the command prompt ($) for clarity
Example:
Use tables for structured data:
Use GitBook hint blocks for important information:
Use GitBook tabs for alternative approaches or examples:
Keep diagrams simple and focused on the key concepts. Include a text explanation of the diagram for accessibility.
When including images:
Use descriptive file names
Include alt text for accessibility
Keep images in an assets directory
Optimize images for web viewing
Use a clear, direct, and professional tone
Write in the present tense
Use active voice instead of passive voice
Address the reader directly using "you"
Use consistent terminology throughout the documentation
Define technical terms when they are first introduced
Follow the project's glossary for specific terms
Include practical, real-world examples
Ensure examples are accurate and tested
Provide context for examples
Use consistent formatting for examples
When documenting command line usage:
Include the command and its output
Use $ to indicate the command prompt
Use # for comments within command blocks
Show example output when relevant
For external links, include the full URL and a descriptive link text:
Indicate when features are version-specific:
Clearly mark the status of features:
✅ Implemented: Feature is fully implemented and available
⚠️ Partial: Feature is partially implemented
🚧 Planned: Feature is planned but not yet implemented (see Roadmap)
Example:
Use descriptive link text (not "click here" or "read more")
Include alt text for images
Ensure color is not the only way to convey information
Use proper heading hierarchy for screen readers
Use lowercase for file names
Use hyphens (-) instead of spaces or underscores
Use descriptive, concise names
Group related files in directories
Examples:
getting-started.md
command-system.md
context-building.md
When implementing this style guide:
Start with high-visibility documents (README, Getting Started guides)
Update one section of documentation at a time
Use search and replace for consistent terminology
Verify links after making changes
Test code examples to ensure they work
When applying this style guide to existing documentation:
Structure: Ensure each document follows the recommended structure
Headings: Verify heading hierarchy is consistent
Formatting: Apply consistent formatting for code, lists, tables, etc.
Examples: Update examples to follow the guidelines
Cross-References: Check and update all internal and external links
Status Indicators: Add status indicators for features
Navigation: Add navigation hints for document series
Following this style guide ensures a consistent, high-quality documentation experience for DeepLint users. If you have questions or suggestions for improving this guide, please open an issue or pull request.
To utilize the context builder, instantiate a ContextBuilder object and invoke the buildContext method. The method returns a Promise that resolves to a ContextBuildResult object containing the LLM context and associated metadata.To use the context builder, create a ContextBuilder object and call the buildContext method. This method returns a Promise with the analysis results and related information.### Basic Usage
To analyze staged changes in your Git repository:
```bash
deeplint
```INFO: Running DeepLint on staged changes...
INFO: Context built with 3 changed files
INFO: Analysis complete: No issues found
#### Common Use Case Example
```markdown
### Analyzing Specific Files
If you want to analyze specific files instead of staged changes:
```bash
deeplint --unstaged src/main.ts src/utils.tsINFO: Running DeepLint on specified files...
INFO: Context built with 2 files
INFO: Analysis complete: 1 issue found
WARN: Potential issue in src/utils.ts:42 - Unused variable 'config'
## Improving Visual Elements
### Diagrams
Use diagrams to explain:
- Workflows and processes
- System architecture
- Relationships between components
- Concepts that are difficult to explain in text
#### Diagram Best Practices
- Keep diagrams simple and focused
- Use consistent colors and shapes
- Include a legend if necessary
- Provide a text explanation alongside the diagram
- Use Mermaid for diagrams that can be maintained in Markdown
#### Example: Workflow Diagram
```markdown
<div data-gb-custom-block data-tag="mermaid">
graph TD
A[Stage Changes] -->|git add| B[Run DeepLint]
B --> C{Issues Found?}
C -->|Yes| D[Review Issues]
D --> E[Fix Issues]
E --> A
C -->|No| F[Commit Changes]
</div>
This diagram shows the typical workflow when using DeepLint with Git:
1. Stage your changes using `git add`
2. Run DeepLint to analyze the staged changes
3. If issues are found, review and fix them, then stage the fixes
4. If no issues are found, commit your changes| Option | Description | Default | Example |
| ------------ | ----------------------------- | ------- | --------------------- |
| `--context` | Context depth (light or deep) | `light` | `--context=deep` |
| `--unstaged` | Include unstaged changes | `false` | `--unstaged` |
| `--debug` | Enable debug output | `false` | `--debug` |
| `--dump` | Dump context to a file | - | `--dump=context.json` |
_Figure 1: DeepLint output highlighting an unused variable in src/utils.ts_# Feature Name
Brief introduction to the feature and what it does.
## Overview
More detailed explanation of the feature.
## Usage
How to use the feature.
## Configuration
How to configure the feature.
## Related Resources
- [Related Document 1](path/to/document1.md)
- [Related Document 2](path/to/document2.md)
## Next Steps
- [Next Step 1](path/to/next-step1.md)
- [Next Step 2](path/to/next-step2.md)
<div data-gb-custom-block data-tag="hint" data-style='info'>
This is part of the Getting Started series:
1. [Installation](installation.md)
2. **Configuration** (current page)
3. [First Run](first-run.md)
4. [Git Integration](git-integration.md)
</div>
---
**Previous**: [Installation](installation.md) | **Next**: [First Run →](first-run.md)```typescript
function example(): void {
console.log("Hello, world!");
}
```
```bash
$ deeplint init
```| Column 1 | Column 2 | Column 3 |
| -------- | -------- | -------- |
| Value 1 | Value 2 | Value 3 |
| Value 4 | Value 5 | Value 6 |
<div data-gb-custom-block data-tag="hint" data-style='info'>
This is an informational note.
</div>
<div data-gb-custom-block data-tag="hint" data-style='warning'>
This is a warning.
</div>
<div data-gb-custom-block data-tag="hint" data-style='success'>
This is a success message or tip.
</div>
<div data-gb-custom-block data-tag="hint" data-style='danger'>
This is a danger or error message.
</div>
<div data-gb-custom-block data-tag="tabs">
<div data-gb-custom-block data-tag="tab" data-title='JavaScript'>
```javascript
const example = () => {
console.log("Hello, world!");
};
```const example = (): void => {
console.log("Hello, world!");
};
## Diagrams and Visual Elements
### Mermaid Diagrams
Use Mermaid diagrams for flowcharts, sequence diagrams, and other visual representations:
```markdown
<div data-gb-custom-block data-tag="mermaid">
graph TD
A[Start] --> B[Process]
B --> C[End]
</div>
```bash
# Initialize DeepLint
$ deeplint init
# Output:
# DeepLint initialized successfully!
# Configuration file created at: /path/to/deeplint.config.js
```
### Configuration Examples
When documenting configuration options:
- Show both JavaScript and YAML examples when applicable
- Include comments explaining each option
- Show default values
- Provide complete, working examples
## Cross-References
### Internal Links
Use relative links for internal documentation:
```markdown
See the [Configuration](../getting-started/configuration.md) guide for more information.For more information, see the [TypeScript Documentation](https://www.typescriptlang.org/docs/).
<div data-gb-custom-block data-tag="hint" data-style='info'>
This feature is available in DeepLint v1.2.0 and later.
</div>| Feature | Status | Description |
| --------------- | -------------- | -------------------------------------------------------------------------- |
| Context Builder | ✅ Implemented | Builds context for analysis |
| LLM Integration | 🚧 Planned | Integrates with LLM providers (see [Roadmap](developer/roadmap/mvp-v1.md)) |This document outlines the development workflow for the DeepLint project, including the process for planning, implementing, testing, and releasing changes.
The DeepLint development lifecycle follows these stages:
Before writing any code, we plan the changes to ensure they align with the project's goals and architecture:
Feature Planning: Define the scope, requirements, and acceptance criteria
Architecture Design: Design the high-level architecture and component interactions
Task Breakdown: Break down the work into manageable tasks
Issue Creation: Create GitHub issues for each task
During implementation, we follow these practices:
Branch Creation: Create a feature branch from the main branch
Test-Driven Development: Write tests before implementing features
Incremental Development: Make small, focused commits
Documentation: Update documentation alongside code changes
Testing is an integral part of the development process:
Unit Testing: Test individual components in isolation
Integration Testing: Test interactions between components
End-to-End Testing: Test the entire application flow
Manual Testing: Perform manual testing for user experience
All changes undergo code review before integration:
Pull Request Creation: Create a pull request with a clear description
Code Review: At least one team member reviews the changes
Addressing Feedback: Address all feedback from reviewers
Approval: Obtain approval from reviewers
Once approved, changes are integrated into the main branch:
Merge: Merge the feature branch into the main branch
CI/CD: Continuous integration runs tests and builds
Deployment: Deploy to staging environment for further testing
Releases follow a structured process:
Version Bump: Update version numbers according to semantic versioning
Changelog: Update the changelog with new features and fixes
Release Notes: Create detailed release notes
Tag: Create a Git tag for the release
DeepLint follows a GitHub Flow-based workflow:
main: The primary branch containing the latest stable code
feature/*: Feature branches for new features
fix/*: Fix branches for bug fixes
docs/*: Documentation branches for documentation changes
Creation: Create a branch from the main branch
Development: Make changes and commit them
Push: Push the branch to the remote repository
Pull Request: Create a pull request for review
DeepLint follows semantic versioning (MAJOR.MINOR.PATCH):
MAJOR: Incompatible API changes
MINOR: Backward-compatible new features
PATCH: Backward-compatible bug fixes
Version Bump:
Update Changelog:
Update CHANGELOG.md with the changes in the new version.
Create Release Commit:
Create Tag:
Issues are tracked in GitHub and follow these guidelines:
Bug: Something isn't working as expected
Feature: A new feature request
Enhancement: Improvement to existing functionality
Documentation: Documentation improvements
priority/high: High-priority issues
priority/medium: Medium-priority issues
priority/low: Low-priority issues
status/in-progress: Issues being worked on
Pull requests follow these guidelines:
status/ready-for-review: Ready for review
status/needs-changes: Needs changes based on review
status/approved: Approved and ready to merge
type/bug-fix: Bug fix
DeepLint uses GitHub Actions for continuous integration:
Checkout: Check out the code
Setup: Set up Node.js and pnpm
Install: Install dependencies
Lint: Run linting checks
The CI configuration is defined in .github/workflows/ci.yml:
DeepLint provides a VS Code configuration for consistent development:
Extensions: Recommended extensions are defined in .vscode/extensions.json
Settings: Project-specific settings are defined in .vscode/settings.json
Launch: Debug configurations are defined in .vscode/launch.json
ESLint: For linting
Prettier: For code formatting
TypeScript: For TypeScript support
Jest: For test running and debugging
DeepLint provides several development scripts in package.json:
dev: Run the CLI directly with tsx
dev:direct: Run with proper argument handling
dev:watch: Watch for changes and rerun
Documentation is an integral part of the development process:
API Documentation: JSDoc comments in code
User Documentation: Guides and tutorials in the docs/ directory
Developer Documentation: Development guides in the docs/developer/ directory
Plan: Plan the documentation changes
Write: Write the documentation
Review: Review the documentation for accuracy and clarity
Publish: Merge the documentation changes
Effective communication is essential for successful development:
GitHub Issues: For bug reports, feature requests, and discussions
Pull Requests: For code contributions and reviews
Discussions: For general questions and community discussions
Slack: For real-time communication (internal team)
Sprint Planning: Every two weeks
Daily Standup: Every weekday
Sprint Review: Every two weeks
Retrospective: Every two weeks
Merge Conflicts: Resolve conflicts by merging the main branch into your feature branch
Commit Errors: Ensure you've configured Git with your name and email
Dependency Errors: Run pnpm install to update dependencies
TypeScript Errors: Fix type errors before committing
Failed Tests: Run tests locally before pushing
Flaky Tests: Mark flaky tests and fix them
If you encounter issues, you can:
Check the documentation
Search GitHub issues
Ask in GitHub discussions
Reach out to the team on Slack
Following this development workflow ensures consistent, high-quality contributions to the DeepLint project. If you have any questions or suggestions for improving the workflow, please open an issue or discussion.
This roadmap outlines the features required for the MVP, compares them against the current implementation state as of May 2025, and details the remaining work with priorities and timelines.
✅ Implemented
Feature is fully implemented and functional
High Priority (Required for core functionality)
LLM Integration
Analysis Orchestration
Output Formatting
MVP Requirements:
Basic CLI structure (deeplint, init, check, config, help, version).
MVP Requirements:
Detect staged changes.
Install as a Git pre-commit hook.
Parse Git diffs.
MVP Requirements:
Scan repository structure (files, types).
Basic dependency analysis (imports/exports).
Build "Light" context (diffs, immediate dependencies, repo map).
MVP Requirements:
Abstraction layer for multiple LLM providers (OpenAI, Anthropic, Gemini).
Send constructed context to the selected LLM.
Prompt engineering for analysis and issue detection.
MVP Requirements:
Core built-in rules (cross-file dependencies, security, error handling - interpreted by LLM via prompt).
Natural Language policy definition in config.
Integrate policies into the LLM prompt.
MVP Requirements:
Formatted terminal output (color-coded severity, file/line refs, messages, recommendations).
Structured JSON output (--json flag).
Clear indication of issues found.
MVP Requirements:
LLM generates git-compatible patches for detected issues.
Interactive wizard (--wizard) to review and selectively apply patches.
Safety classification for fixes (though implementation details are vague - likely LLM-driven).
For the initial MVP release, the following components must be completed:
Core CLI & Setup
✅ CLI framework
✅ Command system
✅ Configuration system
The following components are considered stretch goals for the MVP and may be deferred to a post-MVP release:
Auto-Fix & Wizard
Deep Context Analysis
Rule Engine & Policy Definition
LLM Service Core: The central component for interacting with LLMs, including provider abstraction, prompt engineering, and response parsing. (High Priority - Q2 2025)
Analysis Orchestration: Implementing the main analysis logic within the default command to tie together context building, LLM calls, and output. (High Priority - Q2 2025)
Output Formatting: Creating the user-facing terminal and JSON output for analysis results. (High Priority - Q2 2025)
The immediate focus should be on the high-priority items:
Implement the LLM service core
Implement the analysis orchestration
Implement the output formatting for analysis results
These components form the critical path for the MVP and should be completed before moving on to the medium and lower priority items.
This guide will help you configure DeepLint for your project.
Medium Priority (Important for user experience)
Check Command
Config Command
Git Hook Installation
Lower Priority (Nice to have for MVP)
Auto-Fix/Wizard
Deep Analysis Mode
Rule/Policy Integration
Configuration file handling (.deeplint.yml or deeplint.config.js).
Argument parsing (global options like --provider, --api-key, --config, --json, --wizard, --instructions).
Environment variable support for config.
Basic logging.
Current State:
✅ CLI framework (yargs) setup (src/index.ts).
✅ Command registry and discovery (src/commands/registry.ts, src/commands/discovery.ts).
✅ Base command structure (src/commands/base-command.ts).
✅ DefaultCommand implementation with enhanced UI (src/commands/default-command.ts).
✅ InitCommand implementation with enhanced UI (src/commands/init-command.ts).
✅ HelpCommand implementation with formatted help output (src/commands/help-command.ts).
✅ Configuration loading, validation, defaults (src/config/manager.ts, src/config/validator.ts).
✅ Enhanced logging provider (src/providers/logger.ts and src/ui/logger.ts).
✅ Config persistence helpers (src/providers/typed-config-store.ts, src/providers/config.ts).
Remaining Work:
❌ Implement check <files> command logic. (Medium Priority - Q2 2025)
❌ Implement config command logic (view/edit). (Medium Priority - Q2 2025)
❌ Implement handling for specific global options (--json, --wizard, --instructions, etc.) within commands. (Medium Priority - Q2 2025)
❌ Fully implement the main analysis logic within DefaultCommand (or a dedicated analysis command). (High Priority - Q2 2025)
Filter changed files based on config (include/exclude, size).
Current State:
✅ Git operations wrapper (src/context-builder/git/git-operations.ts) to check staged status, get diffs.
✅ Diff parser (src/context-builder/git/diff-parser.ts).
✅ File system scanner (src/context-builder/indexer/file-system-scanner.ts) with include/exclude logic.
🟡 Configuration options exist for hooks (git.hooks.pre_commit) in configuration_examples.md.
Remaining Work:
❌ Implement the actual Git pre-commit hook installation mechanism (e.g., using a tool like husky). (Medium Priority - Q2 2025)
❌ Integrate file filtering logic (from config) into the change detection process. (Medium Priority - Q2 2025)
❌ Ensure GitOperations correctly identifies the project root and functions within the hook context. (Medium Priority - Q2 2025)
Build "Deep" context (diffs, full repo map with exports, agentic file selection).
Handle token limits.
Current State:
✅ FileSystemScanner for repo structure (src/context-builder/indexer/file-system-scanner.ts).
✅ CodeStructureAnalyzer for file structure/exports (src/context-builder/indexer/code-structure-analyzer.ts).
✅ DependencyAnalyzer for building dependency graph (src/context-builder/indexer/dependency-analyzer.ts).
✅ ContextBuilder class (src/context-builder/context/context-builder.ts) with methods for assembling context components.
✅ TokenCounter for managing token limits (src/context-builder/context/token-counter.ts).
Remaining Work:
❌ Implement the specific logic within ContextBuilder to assemble the "Light" context as defined. (High Priority - Q2 2025)
❌ Implement the "Deep" context building logic, including the agentic step where the LLM selects relevant files. (Lower Priority - Q3 2025)
❌ Integrate configuration (analysis.mode, analysis.depth) into ContextBuilder. (Medium Priority - Q2 2025)
❌ Integrate user instructions (--instructions) into the context. (Medium Priority - Q2 2025)
Handle API keys securely (env vars).
Current State:
🟡 Basic config helpers for API keys/models (src/providers/config.ts).
Remaining Work:
❌ Implement the core LLM service/provider abstraction layer. (High Priority - Q2 2025)
❌ Integrate specific LLM SDKs (OpenAI). (High Priority - Q2 2025)
❌ Develop and implement prompt templates for analysis and patch generation. (High Priority - Q2 2025)
❌ Implement logic to call the LLM API with the constructed context and prompt. (High Priority - Q2 2025)
❌ Implement secure API key handling (reading from env vars). (High Priority - Q2 2025)
Current State:
🟡 Configuration structure exists for rules/policies (configuration_examples.md).
Remaining Work:
❌ Implement logic to read custom NL policies from the config. (Lower Priority - Q3 2025)
❌ Integrate built-in rule concepts and custom policies into the LLM prompt construction. (Lower Priority - Q3 2025)
Current State:
✅ Basic logging (src/providers/logger.ts).
✅ Enhanced UI components (src/ui/ directory):
✅ Themed color system for consistent styling (src/ui/theme.ts)
✅ Enhanced logger with structured output (src/ui/logger.ts)
✅ Spinners for long-running operations (src/ui/spinner.ts)
✅ Progress bars for tracking progress (src/ui/progress.ts)
✅ Banners and tables for structured information display (src/ui/banner.ts, src/ui/table.ts)
✅ Interactive prompts for user input (src/ui/prompt.ts)
✅ Command-specific UI enhancements for InitCommand and DefaultCommand
Remaining Work:
❌ Implement the specific terminal output formatting for analysis results as shown in cli_design.md. (High Priority - Q2 2025)
❌ Implement JSON output generation based on the analysis results. (Medium Priority - Q2 2025)
❌ Integrate analysis results into the output manager. (High Priority - Q2 2025)
Apply patches using Git commands.
Override mechanism (implicit via wizard 'n' option).
Note: --fix flag is marked as discontinued in cli_design.md, focus is on --wizard.
Current State:
🟡 UI foundation for wizard implementation:
✅ Interactive prompts system (src/ui/prompt.ts) with confirmation dialogs
✅ Spinner component for tracking patch application progress
✅ Styled output for displaying patch information
❌ Core patch generation and application logic not implemented
Remaining Work:
❌ Enhance LLM prompting to explicitly request git-compatible patches in the structured output. (Lower Priority - Q3 2025)
❌ Implement the interactive terminal UI for the --wizard mode using the existing prompt components. (Lower Priority - Q3 2025)
❌ Implement logic to parse the patch from the LLM response. (Lower Priority - Q3 2025)
❌ Implement logic to apply the patch to the staged files (potentially using git apply). (Lower Priority - Q3 2025)
❌ Implement safety classification (likely based on LLM confidence or specific heuristics). (Lower Priority - Q3 2025)
❌ Integrate the wizard flow into the main command execution. (Lower Priority - Q3 2025)
❌ Check command
❌ Analysis logic
Git Integration
✅ Git operations
✅ Diff parsing
❌ Hook installation
Context Building
✅ File system scanner
✅ Dependency analyzer
✅ Context assembly
❌ Light context implementation
LLM Integration
❌ Provider abstraction
❌ Prompt engineering
❌ Response parsing
Output & UI
✅ UI components
❌ Analysis output
Auto-Fix/Wizard Implementation: The entire workflow for generating, reviewing, and applying patches. (Lower Priority - Q3 2025)
Rule/Policy Integration: Feeding the configured rules and NL policies into the LLM prompt. (Lower Priority - Q3 2025)
Deep Analysis Mode: Implementing the agentic file selection for deeper context. (Lower Priority - Q3 2025)
🟡 Partial
Foundational elements exist, but significant implementation is missing
❌ Planned
Feature is required for MVP but not yet implemented
Code Quality: Follow the coding standards
Publish: Publish the package to npm
refactor/*: Refactoring branches for code improvements
Review: Address feedback from reviewers
Merge: Merge the branch into the main branch
Cleanup: Delete the branch after merging
Push Changes:
Create GitHub Release: Create a new release on GitHub with the release notes.
Publish to npm:
Question: Questions about the project
status/blocked: Issues blocked by other issues
status/needs-review: Issues that need review
type/bug: Bug issues
type/feature: Feature issues
type/enhancement: Enhancement issues
type/documentation: Documentation issues
type/feature: New feature
type/enhancement: Enhancement
type/documentation: Documentation changes
type/refactoring: Code refactoring
Test: Run tests
Build: Build the project
Publish: Publish to npm (for releases)
dev:debug: Run with Node.js inspector
build: Build the project
clean: Clean build artifacts
lint: Run ESLint
format: Run Prettier
test: Run tests
test:watch: Run tests in watch mode
test:coverage: Run tests with coverage
git push origin main --tagspnpm publishpnpm version [major|minor|patch]git add CHANGELOG.md
git commit -m "Release vX.Y.Z"git tag vX.Y.Z## Description
[Description of the issue]
## Steps to Reproduce
1. [Step 1]
2. [Step 2]
3. [Step 3]
## Expected Behavior
[What you expected to happen]
## Actual Behavior
[What actually happened]
## Environment
- DeepLint Version: [version]
- Node.js Version: [version]
- Operating System: [OS]## Description
[Description of the changes]
## Related Issues
[Links to related issues]
## Checklist
- [ ] Tests added/updated
- [ ] Documentation updated
- [ ] Code follows coding standards
- [ ] All tests pass
- [ ] No linting errorsname: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "22.x"
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 10.x
- name: Install dependencies
run: pnpm install
- name: Lint
run: pnpm lint
- name: Test
run: pnpm test
- name: Build
run: pnpm buildThe easiest way to configure DeepLint is to use the initialization command:
This command will:
Create a configuration file in your project root
Set up default configuration options
Detect whether your project is using ESM or CJS and create the appropriate file format
By default, the init command will detect your project's module format and create the appropriate configuration file:
For ESM projects (with "type": "module" in package.json): deeplint.config.js with ESM syntax
For CJS projects: deeplint.config.js or deeplint.config.cjs with CJS syntax
You can also specify the format you want to use:
This will create a deeplint.config.js or deeplint.config.cjs file with CommonJS syntax.
This will create a deeplint.config.js or deeplint.config.mjs file with ECMAScript Modules syntax.
This will create a .deeplintrc.yml file.
This will create a .deeplintrc.json file.
DeepLint uses cosmiconfig to find your configuration file. It will look for configuration in the following places (in order of precedence):
package.json with a "deeplint" property
.deeplintrc file (no extension) in JSON or YAML format
.deeplintrc.json, .deeplintrc.yaml, .deeplintrc.yml, .deeplintrc.js, .deeplintrc.cjs, or .deeplintrc.mjs file
deeplint.config.js, deeplint.config.cjs, deeplint.config.mjs, or deeplint.config.ts file
Any of the above in a .config subdirectory
This flexible configuration system allows you to use the format and location that best fits your project structure.
The configuration file contains settings for DeepLint's behavior. Here are examples for both ESM and CJS:
The following table shows all available configuration options and their implementation status:
contextBuilder
✅ Implemented
Controls how DeepLint builds context for analysis
files
✅ Implemented
Controls which files are included in the analysis
git.includeUnstaged
✅ Implemented
Controls whether to include unstaged changes
logging
✅ Implemented
Controls logging behavior
Note: For planned features such as custom rules, auto-fixes, and advanced hooks, see the Roadmap.
Configure how DeepLint builds context for analysis:
For more details on context building, see Context Building.
Control which files are included in the analysis:
Configure Git integration:
For more details on Git integration, see Git Integration.
Configure logging behavior:
Configure LLM-powered analysis (AI linting):
LLM options can also be set via CLI flags or environment variables:
CLI: --provider, --model, --api-key, --instructions, --unstaged, --json
Env: OPENAI_API_KEY, OPENAI_MODEL
Precedence: CLI > Env > Config file > Defaults
For a full list of options and details, see the LLM Configuration Guide.
DeepLint uses a cascading configuration system powered by cosmiconfig, where values are resolved in the following order (highest precedence first):
Command-line options (e.g., --model, --unstaged)
Environment variables (e.g., OPENAI_API_KEY, OPENAI_MODEL)
Configuration file (searched in the order listed in Configuration File Locations)
Default values
This means that:
Command-line options override everything else
Environment variables override configuration file settings and defaults
Configuration file settings override defaults
Defaults are used when no other value is provided
To verify the configuration values being used by DeepLint, you can use the --debug flag:
This will print the current configuration values to the console, along with other debug information:
This is particularly useful during development to ensure your configuration is being correctly loaded and applied.
To analyze only specific files or directories:
To include unstaged changes in your analysis:
For more comprehensive analysis (at the cost of performance):
DeepLint validates your configuration when it loads it. If there are any issues with your configuration, DeepLint will:
Log warnings about invalid configuration options
Apply default values to fix invalid values
Continue with the corrected configuration
For example, if you specify an invalid value for contextBuilder.maxTokens:
DeepLint will log a warning and use the default value:
Here are some key validation rules:
contextBuilder.maxTokens: Must be a number between 1,000 and 100,000
contextBuilder.tokensPerFile: Must be a number between 100 and 10,000
contextBuilder.maxFileSize: Must be a number between 1 and 10,000
contextBuilder.includeDependencies: Must be a boolean
contextBuilder.includeStructure: Must be a boolean
files.include and files.exclude: Must be arrays of strings
git.includeUnstaged: Must be a boolean
For a complete list of validation rules, see the Configuration System documentation.
Context Building - Learn how context building works
Configuration System - Technical details of the configuration system
Command Line Options - Command line options that override configuration
Developer Note: The configuration system uses a schema-based validation approach with automatic defaults. If a configuration option is invalid, DeepLint will apply a sensible default value and continue running.
Now that you've configured DeepLint, you can:
Run your first analysis - Learn how to analyze your code
Set up Git integration - Integrate with your Git workflow
Previous: Installation | Next: First Run →
This document provides a comprehensive reference for configuring DeepLint, including all available configuration options, their default values, and usage examples.
DeepLint can be configured using a configuration file. By default, DeepLint looks for the following files in the current directory:
deeplint.config.js (JavaScript)
.deeplintrc.js (JavaScript)
.deeplintrc.json (JSON)
.deeplintrc.yml (YAML)
.deeplintrc.yaml (YAML)
You can also specify a custom configuration file using the --config option:
The contextBuilder section configures how DeepLint builds context for analysis.
The git section configures how DeepLint interacts with Git.
The llm section configures how DeepLint performs LLM-powered analysis.
See the for full details, including LLM options, precedence, and environment variables.
The rules section configures how DeepLint applies rules and policies.
The output section configures how DeepLint formats and displays output.
DeepLint also supports configuration through environment variables. Environment variables take precedence over configuration file values.
DeepLint uses a cascading configuration system, where values are resolved in the following order (highest precedence first):
Command-line options
Environment variables
Configuration file
Default values
LLM options follow this same precedence. See the for more.
If you're using TypeScript, you can use the defineConfig helper to get type checking for your configuration:
You can extend existing configurations using the extends property:
DeepLint validates your configuration when it starts. If there are any errors, DeepLint will display an error message and exit.
Common validation errors include:
Invalid option values
Unknown options
Type mismatches
Missing required options
This document provides a detailed overview of the Context Builder component in DeepLint, which is responsible for gathering and assembling the context used for LLM analysis.
The Context Builder is implemented as a set of cooperating classes, each responsible for a specific aspect of context building:
The ContextBuilder class is the main entry point for context building. It orchestrates the process of gathering information from various sources and assembling it into a structured context for LLM analysis.
buildContext(): The main method for building context. It orchestrates the entire process, from getting Git changes to assembling the final context.
assembleContext(): Assembles the context from the parsed diff, repository structure, dependency graph, and code structure.
buildRepositoryStructure(): Builds the repository structure for the context.
buildChangesContext()
The GitOperations class provides methods for interacting with Git to get information about changes in the repository.
The DiffParser class parses Git diffs into a structured format that can be used for context building.
The FileSystemScanner class scans the repository to understand its structure, including directories, files, and their metadata.
The DependencyAnalyzer class analyzes dependencies between files to identify relationships.
The CodeStructureAnalyzer class extracts information about the structure of code files, such as functions, classes, and interfaces.
The TokenCounter class manages token usage and truncation to ensure the context fits within the LLM's token limits.
The context built by the Context Builder has the following structure:
The repository information includes:
name: The name of the repository
root: The root directory of the repository
structure: The structure of the repository, including directories, files, and their metadata
The changes information includes:
files: An array of changed files, each with its content, diff, and type (addition, modification, or deletion)
summary: A summary of the changes
The related files are files that are related to the changed files, such as dependencies or dependents. Each related file includes:
path: The path to the file
relativePath: The path relative to the repository root
content: The content of the file
type: The type of the file (source, test, etc.)
The metadata includes:
contextSize: Information about the token usage
generatedAt: The date and time when the context was generated
error: Error information if context building failed
The Context Builder can be configured through the ContextBuilderOptions interface:
The Context Builder includes robust error handling to ensure that context building doesn't fail catastrophically. If an error occurs during context building, the Context Builder will:
Log the error with detailed information
Create an empty context with error information
Return the empty context with error information
This allows the rest of the application to continue functioning even if context building fails.
The Context Builder uses dependency injection to make testing easier. Each dependency can be injected through the constructor:
This allows for easy mocking of dependencies during testing.
Token management is a critical aspect of context building, as LLMs have token limits. The Context Builder uses the TokenCounter class to manage token usage and truncation.
The token counter:
Counts tokens using the tiktoken library
Tracks used and available tokens
Truncates file content when necessary
Prioritizes important parts of files (imports, exports, function signatures)
The Context Builder includes project type detection to determine if a project is JavaScript/TypeScript or another type. This is used to decide whether to run dependency analysis, as dependency analysis is only useful for JavaScript/TypeScript projects.
The project type detection is implemented in the detectProjectType utility function:
The buildContext method in the ContextBuilder class uses this function to determine whether to run dependency analysis:
Context building can be resource-intensive, especially for large repositories. The Context Builder includes several optimizations to improve performance:
File Filtering: Only relevant files are included in the context
Token Management: File content is truncated to fit within token limits
Smart Prioritization: Files are prioritized based on their importance when token limits are reached
Project Type Detection: Dependency analysis is only run for JavaScript/TypeScript projects
deeplint init --cjsdeeplint init --esmdeeplint init --yamldeeplint init --json// For CJS projects
const { defineConfig } = require("deeplint-cli");
module.exports = defineConfig({
// Context builder configuration
contextBuilder: {
// Maximum number of tokens to use for the context
maxTokens: 8000,
// Maximum number of tokens to use per file
tokensPerFile: 1000,
// Maximum file size in KB to include in the context
maxFileSize: 500,
// Whether to include dependencies in the context
includeDependencies: true,
// Whether to include code structure in the context
includeStructure: true,
},
// File filtering configuration
files: {
// Patterns to include in the analysis
include: ["**/*.js", "**/*.ts", "**/*.jsx", "**/*.tsx"],
// Patterns to exclude from the analysis
exclude: ["node_modules/**", "dist/**", "build/**"],
// Whether to use .gitignore for file filtering
useGitignore: true,
},
// Git integration configuration
git: {
// Whether to include unstaged changes in the analysis
includeUnstaged: false,
},
// Logging configuration
logging: {
// Log level: "debug", "info", "success", "warn", "error", "none"
level: "info",
},
// LLM configuration
llm: {
// LLM provider to use (currently only "openai" is supported)
provider: "openai",
// API key for the provider (optional, can use OPENAI_API_KEY env var)
apiKey: "sk-...",
// Model to use (optional, can use OPENAI_MODEL env var, default: "gpt-4o")
model: "gpt-4o",
// Maximum number of tokens to use for the analysis
maxTokens: 16384,
},
// Additional files to ignore (deprecated, use files.exclude instead)
ignore: ["node_modules", "dist", "build"],
});// For ESM projects (with "type": "module" in package.json)
import { defineConfig } from "deeplint-cli";
export default defineConfig({
// Context builder configuration
contextBuilder: {
// Maximum number of tokens to use for the context
maxTokens: 8000,
// Maximum number of tokens to use per file
tokensPerFile: 1000,
// Maximum file size in KB to include in the context
maxFileSize: 500,
// Whether to include dependencies in the context
includeDependencies: true,
// Whether to include code structure in the context
includeStructure: true,
},
// File filtering configuration
files: {
// Patterns to include in the analysis
include: ["**/*.js", "**/*.ts", "**/*.jsx", "**/*.tsx"],
// Patterns to exclude from the analysis
exclude: ["node_modules/**", "dist/**", "build/**"],
// Whether to use .gitignore for file filtering
useGitignore: true,
},
// Git integration configuration
git: {
// Whether to include unstaged changes in the analysis
includeUnstaged: false,
},
// Logging configuration
logging: {
// Log level: "debug", "info", "success", "warn", "error", "none"
level: "info",
},
// LLM configuration
llm: {
// LLM provider to use (currently only "openai" is supported)
provider: "openai",
// API key for the provider (optional, can use OPENAI_API_KEY env var)
apiKey: "sk-...",
// Model to use (optional, can use OPENAI_MODEL env var, default: "gpt-4o")
model: "gpt-4o",
// Maximum number of tokens to use for the analysis
maxTokens: 16384,
},
// Additional files to ignore (deprecated, use files.exclude instead)
ignore: ["node_modules", "dist", "build"],
});{
"name": "your-project",
"version": "1.0.0",
"type": "module",
"dependencies": {
// ...
},
"devDependencies": {
"deeplint-cli": "^1.0.0"
// ...
},
"deeplint": {
"contextBuilder": {
"maxTokens": 8000,
"tokensPerFile": 1000,
"maxFileSize": 500,
"includeDependencies": true,
"includeStructure": true
},
"files": {
"include": ["**/*.js", "**/*.ts", "**/*.jsx", "**/*.tsx"],
"exclude": ["node_modules/**", "dist/**", "build/**"],
"useGitignore": true
},
"git": {
"includeUnstaged": false
},
"logging": {
"level": "info"
},
"llm": {
"provider": "openai",
"model": "gpt-4o",
"maxTokens": 16384
}
}
}# Context builder configuration
contextBuilder:
# Maximum number of tokens to use for the context
maxTokens: 8000
# Maximum number of tokens to use per file
tokensPerFile: 1000
# Maximum file size in KB to include in the context
maxFileSize: 500
# Whether to include dependencies in the context
includeDependencies: true
# Whether to include code structure in the context
includeStructure: true
# File filtering configuration
files:
# Patterns to include in the analysis
include:
- "**/*.js"
- "**/*.ts"
- "**/*.jsx"
- "**/*.tsx"
# Patterns to exclude from the analysis
exclude:
- "node_modules/**"
- "dist/**"
- "build/**"
# Whether to use .gitignore for file filtering
useGitignore: true
# Git integration configuration
git:
# Whether to include unstaged changes in the analysis
includeUnstaged: false
# Logging configuration
logging:
# Log level: debug, info, success, warn, error, none
level: info
# LLM configuration
llm:
# LLM provider to use (currently only "openai" is supported)
provider: openai
# API key for the provider (optional, can use OPENAI_API_KEY env var)
apiKey: sk-...
# Model to use (optional, can use OPENAI_MODEL env var, default: "gpt-4o")
model: gpt-4o
# Maximum number of tokens to use for the analysis
maxTokens: 16384
# Additional files to ignore (deprecated, use files.exclude instead)
ignore:
- node_modules
- dist
- builddeeplint initcontextBuilder: {
// Maximum number of tokens to use for the context
maxTokens: 8000,
// Maximum number of tokens to use per file
tokensPerFile: 1000,
// Maximum file size in KB to include in the context
maxFileSize: 500,
// Whether to include dependencies in the context
includeDependencies: true,
// Whether to include code structure in the context
includeStructure: true,
},files: {
// Patterns to include in the analysis
include: ["**/*.js", "**/*.ts", "**/*.jsx", "**/*.tsx"],
// Patterns to exclude from the analysis
exclude: ["node_modules/**", "dist/**", "build/**"],
// Whether to use .gitignore for file filtering
useGitignore: true,
},git: {
// Whether to include unstaged changes in the analysis
includeUnstaged: false,
},logging: {
// Log level: "debug", "info", "success", "warn", "error", "none"
level: "info",
},llm: {
// LLM provider (currently only "openai" is supported)
provider: "openai",
// API key for the provider (optional, can use OPENAI_API_KEY env var)
apiKey: "sk-...",
// Model to use (optional, can use OPENAI_MODEL env var, default: "gpt-4o")
model: "gpt-4o",
// Maximum number of tokens to use for the analysis
maxTokens: 16384,
},// Additional files to ignore (deprecated, use files.exclude instead)
ignore: ["node_modules", "dist", "build"],deeplint --debugℹ Current configuration:
ℹ Context Builder Configuration:
ℹ maxTokens: 8000
ℹ tokensPerFile: 1000
ℹ maxFileSize: 500
ℹ includeDependencies: true
ℹ includeStructure: true
ℹ Files Configuration:
ℹ include: ["**/*.js","**/*.ts","**/*.jsx","**/*.tsx"]
ℹ exclude: ["node_modules/**","dist/**","build/**"]
ℹ useGitignore: true
ℹ Git Configuration:
ℹ includeUnstaged: false
ℹ Logging Configuration:
ℹ level: "info"
ℹ LLM Configuration:
ℹ provider: "openai"
ℹ model: "gpt-4o"
ℹ maxTokens: 16384
ℹ Ignore Patterns (deprecated):
ℹ - node_modules
ℹ - dist
ℹ - buildfiles: {
include: ["src/**/*.ts", "lib/**/*.js"],
exclude: ["**/*.test.ts", "**/*.spec.js"],
}git: {
includeUnstaged: true,
}contextBuilder: {
maxTokens: 16000,
includeDependencies: true,
tokensPerFile: 2000,
}contextBuilder: {
maxTokens: "not a number", // Invalid: should be a number
}WARN: Configuration validation failed with 1 errors:
- contextBuilder.maxTokens: Value must be a number.
INFO: Applying defaults to fix invalid values...llm
✅ Implemented
Controls LLM-powered analysis
ignore
⚠️ Deprecated
Use files.exclude instead
maxFileSize
number
500
Maximum file size in KB
includeDependencies
boolean
false
Whether to include dependencies in the context
includeStructure
boolean
true
Whether to include code structure in the context
includeComments
boolean
true
Whether to include comments in the context
maxTokens
number
16384
Maximum tokens for analysis
temperature
number
0
Temperature for the LLM (0-1), controls randomness
instructions
string
(none)
Additional instructions for the LLM
contextType
string
"light"
Context depth ("light" or "deep")
maxTokens
number
8000
Maximum tokens for the entire context
tokensPerFile
number
1000
includeUnstaged
boolean
false
Whether to include unstaged changes
hooks.preCommit
boolean
false
Whether to enable the pre-commit hook
provider
string
"openai"
LLM provider (currently only "openai")
apiKey
string
(none)
API key for the provider
model
string
"gpt-4o"
severity
string
"warning"
Default severity level ("error", "warning", "info")
policies
string[]
[]
Natural language policies to enforce
format
string
"text"
Output format ("text", "json")
colorize
boolean
true
Whether to colorize the output
verbose
boolean
false
OPENAI_API_KEY
OpenAI API key
OPENAI_API_KEY=sk-...
OPENAI_MODEL
Default model for OpenAI
OPENAI_MODEL=gpt-4o
LOG_LEVEL
Set the logging level
LOG_LEVEL=debug
DEBUG
Enable debug mode
DEBUG=true
Maximum tokens per file
LLM model to use
Whether to enable verbose output
buildRelatedFilesContext(): Builds the related files context from the parsed diff and dependency graph.
size: The size of the file in bytes
lastModified: The last modified date of the file
dependencies: An array of file paths that this file depends on
dependents: An array of file paths that depend on this file
structure: The structure of the file, including functions, classes, interfaces, and types
Parallel Processing: Some operations are performed in parallel to improve performance
deeplint --config=custom.config.js// deeplint.config.js
module.exports = {
contextBuilder: {
contextType: "light",
maxTokens: 8000,
tokensPerFile: 1000,
maxFileSize: 500,
includeDependencies: false,
includeStructure: true,
},
files: {
include: ["**/*.js", "**/*.ts", "**/*.jsx", "**/*.tsx"],
exclude: ["node_modules/**", "dist/**", "build/**"],
useGitignore: true,
},
git: {
includeUnstaged: false,
},
logging: {
level: "info",
},
llm: {
provider: "openai",
apiKey: "sk-...", // Optional, can use OPENAI_API_KEY env var
model: "gpt-4o", // Optional, can use OPENAI_MODEL env var
maxTokens: 16384,
temperature: 0, // Optional, controls randomness (0-1)
instructions: "Focus on security issues and performance optimizations", // Optional
},
};# .deeplintrc.yml
contextBuilder:
contextType: light
maxTokens: 8000
tokensPerFile: 1000
maxFileSize: 500
includeDependencies: false
includeStructure: true
files:
include:
- "**/*.js"
- "**/*.ts"
- "**/*.jsx"
- "**/*.tsx"
exclude:
- "node_modules/**"
- "dist/**"
- "build/**"
useGitignore: true
git:
includeUnstaged: false
logging:
level: info
llm:
provider: openai
apiKey: sk-... # Optional, can use OPENAI_API_KEY env var
model: gpt-4o # Optional, can use OPENAI_MODEL env var
maxTokens: 16384
temperature: 0 # Optional, controls randomness (0-1)
instructions: Focus on security issues and performance optimizations # OptionalcontextBuilder: {
contextType: "deep",
maxTokens: 16000,
tokensPerFile: 2000,
maxFileSize: 1000,
includeDependencies: true,
includeStructure: true,
includeComments: true,
}git: {
includeUnstaged: true,
hooks: {
preCommit: true,
},
}llm: {
provider: "openai",
apiKey: "sk-...",
model: "gpt-4o",
maxTokens: 16384,
temperature: 0.7,
instructions: "Focus on security issues and performance optimizations",
}rules: {
severity: "error",
policies: [
"Ensure all functions have proper error handling",
"Follow the repository's naming conventions",
"Avoid using any type in TypeScript",
"Ensure all API endpoints have proper validation",
],
}output: {
format: "json",
colorize: false,
verbose: true,
}// deeplint.config.ts
import { defineConfig } from "deeplint";
export default defineConfig({
contextBuilder: {
contextType: "light",
maxTokens: 8000,
},
// Other options...
});// deeplint.config.js
module.exports = {
// Use all defaults
};// deeplint.config.js
module.exports = {
contextBuilder: {
contextType: "light",
maxTokens: 8000,
},
git: {
includeUnstaged: true,
},
output: {
verbose: true,
},
};// deeplint.config.js
module.exports = {
contextBuilder: {
contextType: "deep",
maxTokens: 16000,
includeDependencies: true,
},
git: {
hooks: {
preCommit: true,
},
},
rules: {
severity: "error",
policies: [
"Ensure all functions have proper error handling",
"Follow the repository's naming conventions",
],
},
};// deeplint.config.js
module.exports = {
rules: {
severity: "warning",
policies: [
"Ensure all functions have proper error handling",
"Follow the repository's naming conventions",
"Avoid using any type in TypeScript",
"Ensure all API endpoints have proper validation",
"Use async/await instead of raw promises",
"Avoid deeply nested conditionals",
"Keep functions small and focused",
"Use descriptive variable names",
],
},
};// deeplint.config.js
module.exports = {
extends: "./base.config.js",
contextBuilder: {
maxTokens: 16000, // Override the base configuration
},
};export class ContextBuilder {
private options: ContextBuilderOptions;
private gitOperations: GitOperations;
private diffParser: DiffParser;
private fileSystemScanner: FileSystemScanner;
private dependencyAnalyzer: DependencyAnalyzer;
private codeStructureAnalyzer: CodeStructureAnalyzer;
private tokenCounter: TokenCounter;
private configOptions: ContextBuilderConfig;
constructor(
options: Partial<ContextBuilderOptions>,
dependencies?: {
gitOperations?: GitOperations;
diffParser?: DiffParser;
fileSystemScanner?: FileSystemScanner;
dependencyAnalyzer?: DependencyAnalyzer;
codeStructureAnalyzer?: CodeStructureAnalyzer;
tokenCounter?: TokenCounter;
},
) {
// Initialize options and dependencies
}
async buildContext(): Promise<ContextBuildResult> {
// Build context for LLM analysis
}
private async assembleContext(
parsedDiff: ParsedDiff,
repoStructure: RepositoryStructure,
dependencyGraph: DependencyGraph,
codeStructure: CodeStructure,
): Promise<LLMContext> {
// Assemble context from various sources
}
// Other helper methods
}export class GitOperations {
private repositoryRoot: string;
constructor(repositoryRoot: string) {
this.repositoryRoot = repositoryRoot;
}
async hasStagedChanges(): Promise<boolean> {
// Check if there are staged changes
}
async hasUnstagedChanges(): Promise<boolean> {
// Check if there are unstaged changes
}
async getStagedDiff(): Promise<string> {
// Get the diff for staged changes
}
async getUnstagedDiff(): Promise<string> {
// Get the diff for unstaged changes
}
}export class DiffParser {
parse(diffText: string): ParsedDiff {
// Parse the diff text into a structured format
}
generateSummary(parsedDiff: ParsedDiff): string {
// Generate a summary of the changes
}
}export class FileSystemScanner {
private repositoryRoot: string;
constructor(repositoryRoot: string) {
this.repositoryRoot = repositoryRoot;
}
async scanRepository(options: ScanOptions): Promise<RepositoryStructure> {
// Scan the repository and return its structure
}
}export class DependencyAnalyzer {
private repositoryRoot: string;
constructor(repositoryRoot: string) {
this.repositoryRoot = repositoryRoot;
}
async buildDependencyGraph(files: FileInfo[]): Promise<DependencyGraph> {
// Build a dependency graph for the files
}
}export class CodeStructureAnalyzer {
private repositoryRoot: string;
constructor(repositoryRoot: string) {
this.repositoryRoot = repositoryRoot;
}
async analyzeCodeStructure(files: FileInfo[]): Promise<CodeStructure> {
// Analyze the structure of code files
}
}export class TokenCounter {
private model: TiktokenModel;
private maxTokens: number;
private usedTokens: number = 0;
private reservedTokens: number = 0;
constructor(
model: string = "gpt-4",
maxTokens: number = 8192,
reservedTokens: number = 1000,
) {
// Initialize token counter
}
countTokens(text: string): number {
// Count the number of tokens in a text
}
addTokens(count: number): void {
// Add tokens to the used tokens count
}
getUsedTokens(): number {
// Get the number of tokens used
}
getAvailableTokens(): number {
// Get the number of tokens available
}
hasEnoughTokens(count: number): boolean {
// Check if there are enough tokens available
}
reset(): void {
// Reset the token counter
}
truncateToFit(text: string, maxTokens: number): string {
// Truncate text to fit within a token limit
}
truncateFileContent(content: string, maxTokens: number): string {
// Truncate a file content to fit within a token limit
}
}export interface LLMContext {
// Repository information
repository: {
name: string;
root: string;
structure: ContextRepositoryStructure;
};
// Changes information
changes: {
files: ContextChange[];
summary: string;
};
// Related files
relatedFiles: ContextFile[];
// Metadata
metadata: {
contextSize: {
totalTokens: number;
changesTokens: number;
relatedFilesTokens: number;
structureTokens: number;
};
generatedAt: string;
error?: {
message: string;
timestamp: string;
phase?: string;
};
};
}export interface ContextBuilderOptions {
// Repository options
repositoryRoot: string;
// File options
maxFileSize?: number; // in KB
includePatterns?: string[];
excludePatterns?: string[];
// Token management
maxTokens?: number;
tokensPerFile?: number;
// Git options
useUnstagedChanges?: boolean;
// Dependency options
includeDependencies?: boolean;
// Structure options
includeStructure?: boolean;
// File filtering options
useGitignore?: boolean;
}constructor(
options: Partial<ContextBuilderOptions>,
dependencies?: {
gitOperations?: GitOperations;
diffParser?: DiffParser;
fileSystemScanner?: FileSystemScanner;
dependencyAnalyzer?: DependencyAnalyzer;
codeStructureAnalyzer?: CodeStructureAnalyzer;
tokenCounter?: TokenCounter;
},
) {
// Initialize options and dependencies
}export enum ProjectType {
JAVASCRIPT = "javascript",
TYPESCRIPT = "typescript",
OTHER = "other",
}
export function detectProjectType(rootDir: string): ProjectType {
// Check for TypeScript configuration
const hasTsConfig = existsSync(join(rootDir, "tsconfig.json"));
if (hasTsConfig) {
return ProjectType.TYPESCRIPT;
}
// Check for JavaScript project indicators
const hasPackageJson = existsSync(join(rootDir, "package.json"));
const hasJsFiles =
existsSync(join(rootDir, "index.js")) ||
existsSync(join(rootDir, "src/index.js")) ||
existsSync(join(rootDir, "lib/index.js"));
const hasNodeModules = existsSync(join(rootDir, "node_modules"));
if (hasPackageJson || hasJsFiles || hasNodeModules) {
return ProjectType.JAVASCRIPT;
}
// Default to other
return ProjectType.OTHER;
}// Check if this is a JavaScript/TypeScript project
const isJsProject = isJavaScriptOrTypeScriptProject(this.options.repositoryRoot);
// Build dependency graph only for JavaScript/TypeScript projects
let dependencyGraph: DependencyGraph;
if (isJsProject && this.options.includeDependencies) {
logger.info("JavaScript/TypeScript project detected. Building dependency graph...");
dependencyGraph = await this.dependencyAnalyzer.buildDependencyGraph(
repoStructure.allFiles,
);
} else {
if (!isJsProject) {
logger.info(
"Non-JavaScript/TypeScript project detected. Skipping dependency analysis.",
);
} else if (!this.options.includeDependencies) {
logger.info("Dependency analysis disabled in configuration. Skipping.");
}
// Create empty dependency graph
dependencyGraph = {
files: new Map(),
getDirectDependencies: () => [],
getDirectDependents: () => [],
getImmediateDependenciesOfChangedFiles: () => [],
};
}This document provides guidelines and instructions for contributing to the DeepLint project.
Thank you for your interest in contributing to DeepLint! This guide will help you get started with the development process.
Before you begin, ensure you have the following installed:
Node.js: Version 22.0.0 or higher
pnpm: Version 10.x or higher
Git: For version control
Fork the Repository
Start by forking the DeepLint repository to your GitHub account.
Clone Your Fork
Install Dependencies
Set Up Environment Variables
Use the following naming convention for branches:
feature/short-description: For new features
fix/short-description: For bug fixes
docs/short-description: For documentation changes
Examples:
Follow these guidelines for commit messages:
Use the present tense ("Add feature" not "Added feature")
Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
Limit the first line to 72 characters or less
Reference issues and pull requests liberally after the first line
Example:
Create a Branch
Make Your Changes
Implement your changes, following the .
Run Tests
Ensure your changes pass all tests:
Fill in the Pull Request Template
Provide a clear description of the changes and reference any related issues.
Update Documentation
Ensure that any new features or changes are documented.
Pass CI Checks
Make sure your pull request passes all CI checks.
Be responsive to feedback
Explain your design decisions
Break large changes into smaller, more manageable pull requests
Test your changes thoroughly
Be respectful and constructive
Focus on the code, not the person
Provide specific, actionable feedback
Consider the context and constraints
Use JSDoc comments for public APIs
Document parameters, return values, and exceptions
Include examples for complex functions
Example:
Update README.md with any new features or changes
Update the documentation in the docs/ directory
Create new documentation files as needed
Write tests for all new features
Ensure tests are deterministic and isolated
Use mocks for external dependencies
Aim for high test coverage
Example:
Run the development server with debugging enabled:
This will start the server with the Node.js inspector enabled. You can then attach a debugger to it.
A .vscode/launch.json file is provided for VS Code users. You can use the "Debug DeepLint" configuration to debug the application.
To debug a specific command:
Open the file you want to debug
Set breakpoints by clicking in the gutter
Press F5 to start debugging
Select the "Debug DeepLint" configuration
Example launch configuration:
Create a new file in src/commands/ with the naming convention command-name-command.ts
Extend the BaseCommand class
Implement the required methods
Example:
Update the configuration types in src/config/types.ts
Update the default configuration in src/config/templates.ts
Update the configuration validation in src/config/validator.ts
Example:
Update the context builder implementation in src/context-builder/context/context-builder.ts
Update the context types in src/context-builder/context/context-types.ts
Update the tests in tests/context-builder/
Example:
Identify the component that needs to be modified
Make the necessary changes
Add tests for the new feature
Update documentation
Example: Adding a --format option to the default command
We expect all contributors to follow our Code of Conduct (Coming Soon). Please be respectful and constructive in all interactions.
GitHub Issues: For bug reports, feature requests, and discussions
Pull Requests: For code contributions
Discussions: For general questions and community discussions
All contributors will be recognized in the CONTRIBUTORS.md file (Coming Soon).
Thank you for contributing to DeepLint! Your efforts help make this project better for everyone.
Edit the .env file to include your OpenAI API key:
Build the Project
Run the Development Server
This will start the development server, allowing you to run DeepLint with changes you make to the codebase.
Verify Your Setup
Run a simple command to verify that your development environment is set up correctly:
You should see the help output for DeepLint.
refactor/short-description: For code refactoringEnsure your code follows the linting rules:
Format Your Code
Ensure your code is properly formatted:
Commit Your Changes
Push to Your Fork
Create a Pull Request
Go to the DeepLint repository and create a pull request from your fork.
Code Review
Address any feedback from code reviewers.
Merge
Once approved, your pull request will be merged.
docs/getting-started/configuration.mddocs/concepts/context-building.mdpnpm buildpnpm devpnpm dev -- --helppnpm formatgit add .
git commit -m "Your descriptive commit message"git push origin feature/your-feature-namegit clone https://github.com/YOUR_USERNAME/deeplint-cli.git
cd deeplint-clipnpm installgit checkout -b feature/add-rule-engine
git checkout -b fix/context-builder-token-limit
git checkout -b docs/improve-getting-started
git checkout -b refactor/command-systemAdd context building functionality
- Implement file system scanner
- Add dependency analyzer
- Create token counter
- Fixes #123git checkout -b feature/your-feature-namepnpm test/**
* Builds context for LLM analysis based on staged changes
*
* @param options - Options for the context builder
* @returns Promise resolving to the context build result
* @throws {GitError} If Git operations fail
* @throws {ContextBuildingError} If context building fails
*
* @example
* ```typescript
* const contextBuilder = new ContextBuilder();
* const result = await contextBuilder.buildContext();
* console.log(`Built context with ${result.stats.totalTokens} tokens`);
* ```
*/
async function buildContext(
options?: Partial<ContextBuilderOptions>,
): Promise<ContextBuildResult> {
// Implementation
}describe("ContextBuilder", () => {
let contextBuilder: ContextBuilder;
let mockGitOperations: MockGitOperations;
beforeEach(() => {
mockGitOperations = new MockGitOperations();
contextBuilder = new ContextBuilder({
gitOperations: mockGitOperations,
});
});
describe("buildContext", () => {
it("should return empty context when no changes are staged", async () => {
mockGitOperations.hasStagedChanges.mockResolvedValue(false);
const result = await contextBuilder.buildContext();
expect(result.context.changes.files).toHaveLength(0);
expect(result.stats.changedFiles).toBe(0);
});
it("should process staged changes", async () => {
mockGitOperations.hasStagedChanges.mockResolvedValue(true);
mockGitOperations.getStagedFiles.mockResolvedValue(["file1.ts", "file2.ts"]);
mockGitOperations.getStagedDiff.mockResolvedValue("diff content");
const result = await contextBuilder.buildContext();
expect(result.context.changes.files).toHaveLength(2);
expect(result.stats.changedFiles).toBe(2);
});
});
});# Run all tests
pnpm test
# Run specific tests
pnpm test -- --testPathPattern=context-builder
# Run tests in watch mode
pnpm test:watch
# Run tests with coverage
pnpm test:coveragepnpm dev:debug{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug DeepLint",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/src/index.ts",
"args": ["--debug"],
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"sourceMaps": true,
"console": "integratedTerminal"
}
]
}// src/commands/analyze-command.ts
import { Argv } from "yargs";
import { BaseCommand } from "./base-command";
import { logger } from "../providers/logger";
import { ContextBuilder } from "../context-builder/context/context-builder";
export class AnalyzeCommand extends BaseCommand {
get name(): string {
return "analyze";
}
get description(): string {
return "Analyze specific files";
}
get aliases(): string[] {
return ["a", "check"];
}
configure(yargs: Argv): Argv {
return yargs.command({
command: "analyze [files..]",
describe: this.description,
builder: (y) => {
return y
.positional("files", {
describe: "Files to analyze",
type: "string",
array: true,
})
.option("context", {
describe: "Context depth (light, deep)",
type: "string",
choices: ["light", "deep"],
default: "light",
});
},
handler: (argv) => this.run(argv),
});
}
async execute(args: any): Promise<void> {
const { files, context } = args;
logger.info(`Analyzing ${files.length} files with ${context} context...`);
const contextBuilder = new ContextBuilder({
contextType: context,
});
// Implementation details
logger.success("Analysis complete!");
}
}// Step 1: Update types in src/config/types.ts
export interface ContextBuilderConfig {
// Existing options
contextType: "light" | "deep";
maxTokens: number;
tokensPerFile: number;
maxFileSize: number;
includeDependencies: boolean;
maxDependencyDepth: number;
includeStructure: boolean;
// New option
includeComments: boolean;
}
// Step 2: Update default configuration in src/config/templates.ts
export const getDefaultConfig = (): Config => ({
contextBuilder: {
contextType: "light",
maxTokens: 8000,
tokensPerFile: 1000,
maxFileSize: 500,
includeDependencies: false,
maxDependencyDepth: 1,
includeStructure: true,
includeComments: true, // New option with default value
},
// Other configuration sections
});
// Step 3: Update validation in src/config/validator.ts
private validateContextBuilderConfig(config: ContextBuilderConfig): ValidationResult {
const errors: ValidationError[] = [];
// Existing validation
// New validation
if (typeof config.includeComments !== "boolean") {
errors.push({
path: "contextBuilder.includeComments",
message: "Value must be a boolean.",
value: config.includeComments,
});
}
return { isValid: errors.length === 0, errors };
}// src/context-builder/context/context-builder.ts
export class ContextBuilder {
private readonly options: ContextBuilderOptions;
private readonly gitOperations: GitOperations;
private readonly fileSystemScanner: FileSystemScanner;
private readonly tokenCounter: TokenCounter;
constructor(options: Partial<ContextBuilderOptions> = {}) {
this.options = { ...getDefaultOptions(), ...options };
this.gitOperations = options.gitOperations || new GitOperations();
this.fileSystemScanner = options.fileSystemScanner || new FileSystemScanner();
this.tokenCounter = options.tokenCounter || new TokenCounter();
}
async buildContext(): Promise<ContextBuildResult> {
const startTime = Date.now();
try {
// Check if there are staged changes
const hasStagedChanges = await this.gitOperations.hasStagedChanges();
if (!hasStagedChanges && !this.options.includeUnstaged) {
logger.warn("No staged changes found.");
return this.createEmptyContext(startTime);
}
// Get staged or unstaged files
const files = this.options.includeUnstaged
? await this.gitOperations.getUnstagedFiles()
: await this.gitOperations.getStagedFiles();
// Scan repository
const repoStructure = await this.fileSystemScanner.scan({
include: this.options.include,
exclude: this.options.exclude,
useGitignore: this.options.useGitignore,
});
// Build context
const context = {
repository: {
name: path.basename(process.cwd()),
root: process.cwd(),
structure: repoStructure,
},
changes: {
files: this.processFiles(files),
summary: this.generateSummary(files),
},
relatedFiles: [],
metadata: {
contextSize: {
totalTokens: 0,
changesTokens: 0,
relatedFilesTokens: 0,
structureTokens: 0,
},
generatedAt: new Date().toISOString(),
contextType: this.options.contextType,
},
};
// Count tokens
const tokenCounts = this.tokenCounter.countTokens(context);
context.metadata.contextSize = tokenCounts;
return {
context,
stats: {
totalFiles: files.length,
changedFiles: files.length,
relatedFiles: 0,
totalTokens: tokenCounts.totalTokens,
buildTime: Date.now() - startTime,
},
};
} catch (error) {
logger.error(`Error building context: ${error.message}`);
throw new ContextBuildingError(`Failed to build context: ${error.message}`, {
cause: error,
});
}
}
// Helper methods
private processFiles(files: string[]): ContextChange[] {
// Implementation
}
private generateSummary(files: string[]): string {
// Implementation
}
private createEmptyContext(startTime: number): ContextBuildResult {
// Implementation
}
}// src/commands/default-command.ts
configure(yargs: Argv): Argv {
return yargs
.usage("Usage: $0 [options]")
.option("context", {
describe: "Context depth (light, deep)",
type: "string",
choices: ["light", "deep"],
default: "light",
})
.option("debug", {
describe: "Enable debug output",
type: "boolean",
default: false,
})
.option("dump", {
describe: "Dump context to a file",
type: "string",
})
.option("unstaged", {
describe: "Include unstaged changes",
type: "boolean",
default: false,
})
// New option
.option("format", {
describe: "Output format (text, json)",
type: "string",
choices: ["text", "json"],
default: "text",
});
}
async execute(args: any): Promise<void> {
// Existing implementation
// Handle the new format option
const { format } = args;
if (format === "json") {
console.log(JSON.stringify(result, null, 2));
} else {
// Default text output
logger.info(`Context built with ${result.stats.changedFiles} changed files and ${result.stats.relatedFiles} related files`);
logger.info(`Context building statistics:`);
logger.info(`- Total files: ${result.stats.totalFiles}`);
logger.info(`- Changed files: ${result.stats.changedFiles}`);
logger.info(`- Related files: ${result.stats.relatedFiles}`);
logger.info(`- Total tokens: ${result.stats.totalTokens}`);
logger.info(`- Build time: ${result.stats.buildTime}ms`);
}
}cp .env.sample .envOPENAI_API_KEY=your_api_key_herepnpm lintThis document provides a comprehensive reference for the DeepLint command-line interface (CLI), including all available commands, options, and usage examples.
DeepLint commands follow this general structure:
If no command is specified, DeepLint runs the default command, which analyzes staged changes in the current Git repository.
These options can be used with any command:
The default command runs when no command is specified. It analyzes staged changes in the current Git repository.
The init command initializes DeepLint in a repository, creating a configuration file.
The help command displays help information for DeepLint or a specific command.
The check command analyzes your codebase using LLM-powered analysis, providing advanced linting, code review, and suggestions using AI.
If no files are specified, DeepLint analyzes staged changes by default.
You can specify files or directories to analyze specific targets.
The following commands are planned for future releases:
The config command will allow viewing and modifying configuration values.
get: Get a configuration value
set: Set a configuration value
list: List all configuration values
DeepLint supports the following environment variables:
DeepLint uses the following exit codes:
DeepLint can be configured using a configuration file. By default, DeepLint looks for the following files in the current directory:
deeplint.config.js
.deeplintrc.js
.deeplintrc.json
You can also specify a custom configuration file using the --config option.
LLM options can be set via CLI flags, environment variables, or config file. Precedence is:
CLI arguments
Environment variables
Config file (llm section)
Built-in defaults
For more information about LLM configuration, see the . For general configuration, see the .
If you run DeepLint without any staged changes, you'll see an error message:
To fix this, either:
Stage some changes with git add, or
Use the --unstaged flag to analyze unstaged changes:
If you run DeepLint outside of a Git repository, you'll see an error message:
To fix this, either:
Navigate to a Git repository, or
Initialize a Git repository in your current directory:
If DeepLint can't find a configuration file, it will use default values. To create a configuration file:
deeplint [command] [options]--verbose
Enable verbose output
false
deeplint --verbose
--config
Specify a custom config file
-
deeplint --config=custom.config.js
--json
Output results in JSON format
false
deeplint --json
--instructions
Custom instructions for analysis
-
deeplint --instructions="Focus on security issues"
--json
Output results in JSON format
false
--context
Context depth for analysis (light or deep)
"light"
--unstaged
Include unstaged changes in the analysis
false
--debug
Enable debug output
false
--verbose
Enable verbose output
false
OPENAI_MODEL
Default model for OpenAI
OPENAI_MODEL=gpt-4o
.deeplintrc.yml.deeplintrc.yaml
--help, -h
Show help information
-
deeplint --help
--version, -v
Show version information
-
deeplint --version
--debug
Enable debug output
false
--context
Context depth (light or deep)
light
deeplint --context=deep
--unstaged
Include unstaged changes
false
deeplint --unstaged
--dump
Dump context to a file
-
--force, -f
Overwrite existing configuration
false
deeplint init --force
--yaml
Use YAML format for configuration
false
deeplint init --yaml
--js
Use JavaScript format for configuration
true
--provider
LLM provider to use
"openai"
--model
LLM model to use
process.env.OPENAI_MODEL or "gpt-4o"
--api-key
API key for the LLM provider
process.env.OPENAI_API_KEY
--instructions
Additional instructions for the LLM
DEEPLINT_CONFIG_PATH
Path to the configuration file
DEEPLINT_CONFIG_PATH=/path/to/config.js
DEEPLINT_DEBUG
Enable debug output
DEEPLINT_DEBUG=true
DEEPLINT_VERBOSE
Enable verbose output
DEEPLINT_VERBOSE=true
OPENAI_API_KEY
OpenAI API key for LLM integration
OPENAI_API_KEY=sk-...
0
Success - No issues found
1
Error - Command failed to execute
2
Issues - Issues were found during analysis
deeplint --debug
deeplint --dump=context.json
deeplint init --js
none
deeplint [options]# Analyze staged changes with default options
deeplint
# Analyze unstaged changes with deep context
deeplint --unstaged --context=deep
# Analyze staged changes and dump context to a file
deeplint --dump=context.json
# Analyze staged changes with custom instructions
deeplint --instructions="Check for memory leaks"deeplint init [options]# Initialize DeepLint with JavaScript configuration
deeplint init
# Initialize DeepLint with YAML configuration
deeplint init --yaml
# Force overwrite of existing configuration
deeplint init --forcedeeplint help [command]# Show general help
deeplint help
# Show help for the init command
deeplint help initdeeplint check [options] [files...]# Analyze staged changes with LLM-powered analysis
deeplint check
# Analyze with a custom model
deeplint check --model=gpt-4
# Add custom instructions
deeplint check --instructions="Focus on security issues."
# Output as JSON
deeplint check --json
# Analyze unstaged changes
deeplint check --unstaged
# Analyze specific files
deeplint check src/llm/ src/commands/check-command.tsdeeplint config [action] [key] [value] [options]# Get a configuration value
deeplint config get contextBuilder.maxTokens
# Set a configuration value
deeplint config set contextBuilder.maxTokens 16000
# List all configuration values
deeplint config list# Initialize DeepLint in a repository
deeplint init
# Analyze staged changes
git add .
deeplint
# Analyze unstaged changes
deeplint --unstaged# Analyze staged changes with deep context and custom instructions
deeplint --context=deep --instructions="Focus on performance issues"
# Analyze staged changes and output results in JSON format
deeplint --json > results.json
# Initialize DeepLint with YAML configuration and force overwrite
deeplint init --yaml --forceERROR: No staged changes found. Stage changes with 'git add' or use --unstaged to analyze unstaged changes.deeplint --unstagedERROR: Not a Git repository. Initialize a Git repository with 'git init' or navigate to a Git repository.git initdeeplint initThe UI module provides a set of components and utilities for creating a consistent and user-friendly command-line interface. This document provides an overview of the UI module and how to use it.
The UI module is designed to provide a consistent visual language across the CLI, making it easier to create a polished and professional user experience. It includes:
Theme System: A centralized theme system that defines colors, typography, symbols, and spacing.
Enhanced Logger: An enhanced logger that uses the theme system to create visually appealing log messages.
Interactive Elements: Spinners, progress bars, and interactive prompts for better user interaction.
Command Output Enhancements: Banners, tables, and JSON output for better command output.
To use the UI module, import it in your code:
The theme system provides a consistent visual language across the CLI. It includes:
The theme system defines a set of colors for different purposes:
The theme system defines a set of symbols for different message types:
The theme system defines a set of typography styles for consistent text formatting:
The theme system defines a set of spacing constants for consistent layout:
The theme system provides utility functions for common tasks:
The enhanced logger provides a more visually appealing and structured logging experience. It includes:
Always use the theme system to ensure a consistent visual language across the CLI. This makes it easier to maintain and update the UI in the future.
Use the enhanced logger for all logging to ensure a consistent logging experience. The enhanced logger provides better formatting, support for structured output, and log levels.
Use log groups to organize related logs. This makes it easier to understand the structure of the output.
Use the appropriate log level for each message. This allows users to control the verbosity of the output.
The spinner component provides a loading indicator for long-running operations. It uses the library for the actual spinner implementation.
The progress bar component provides a visual indicator for tracking progress in long-running operations. It uses the library for the actual progress bar implementation.
The interactive prompts component provides a set of utilities for creating interactive prompts in the CLI. It uses the library for the actual prompt implementation.
The interactive prompts component provides several helper functions for common prompt types:
The banner component provides a way to display headers and messages in the CLI. It uses the library for creating boxes around text.
The table component provides a way to display structured data in the CLI. It uses a custom implementation that's designed to be robust and handle edge cases gracefully.
The table component is designed to handle edge cases gracefully:
Empty or null data
Missing or malformed headers
ANSI color codes in cell content
Varying row lengths
Always provide explicit headers when possible to ensure consistent table structure:
Handle potential null/undefined values in your data before passing to the table:
Use try/catch blocks when displaying tables with potentially problematic data:
The UI module will be enhanced with additional components in the future:
JSON Output: For programmatic consumption
import * as ui from "../ui";// Primary colors
ui.colors.primary; // Blue - Primary brand color
ui.colors.secondary; // Purple - Secondary brand color
// Status colors
ui.colors.success; // Green - Success messages
ui.colors.warning; // Yellow - Warning messages
ui.colors.error; // Red - Error messages
ui.colors.info; // Blue - Info messages
// Neutral colors
ui.colors.muted; // Gray - Muted text
ui.colors.subtle; // Light gray - Subtle text
// Text colors
ui.colors.heading; // White bold - Headings
ui.colors.text; // White - Normal text
// Special colors
ui.colors.highlight; // Yellow - Highlighted text
ui.colors.link; // Blue underlined - Linksui.symbols.info; // ℹ - Info messages
ui.symbols.success; // ✓ - Success messages
ui.symbols.warning; // ⚠ - Warning messages
ui.symbols.error; // ✖ - Error messages
ui.symbols.debug; // 🔍 - Debug messages
ui.symbols.verbose; // 🔎 - Verbose messages
ui.symbols.bullet; // • - Bullet points
ui.symbols.arrow; // → - Arrows
ui.symbols.pointer; // ❯ - Pointersui.typography.heading1("Heading 1"); // Bold white text
ui.typography.heading2("Heading 2"); // Bold white text
ui.typography.heading3("Heading 3"); // Bold white text
ui.typography.text("Normal text"); // White text
ui.typography.muted("Muted text"); // Gray text
ui.typography.code("Code"); // Code with backgroundui.spacing.xs; // 2 spaces - Extra small spacing
ui.spacing.sm; // 4 spaces - Small spacing
ui.spacing.md; // 8 spaces - Medium spacing
ui.spacing.lg; // 12 spaces - Large spacing
ui.spacing.xl; // 16 spaces - Extra large spacing// Create indentation
ui.indent(2); // 8 spaces (2 * spacing.sm)
// Create a horizontal line
ui.line(); // 80 characters of "─"
ui.line(40); // 40 characters of "─"
ui.line(40, "="); // 40 characters of "="
// Apply theme to a message
ui.applyTheme("info", "Hello, world!"); // Blue "ℹ Hello, world!"ui.logger.debug("Debug message"); // Gray "🔍 Debug message"
ui.logger.verbose("Verbose message"); // Gray "🔎 Verbose message"
ui.logger.info("Info message"); // Blue "ℹ Info message"
ui.logger.success("Success message"); // Green "✓ Success message"
ui.logger.warn("Warning message"); // Yellow "⚠ Warning message"
ui.logger.error("Error message"); // Red "✖ Error message"try {
// Some code that might throw an error
} catch (error) {
ui.logger.errorWithContext("Failed to process file", error, {
file: "example.txt",
line: 42,
});
// Red "✖ Failed to process file (file: example.txt, line: 42) Error: Something went wrong"
}ui.logger.group("Configuration", () => {
ui.logger.info("Loading configuration...");
ui.logger.info("Configuration loaded successfully.");
});
// ▼ Configuration
// ℹ Loading configuration...
// ℹ Configuration loaded successfully.ui.logger.group(
"Details",
() => {
ui.logger.info("Some details...");
},
{ collapsed: true },
);
// ▶ Detailsui.logger.group("Parent", () => {
ui.logger.info("Parent info");
ui.logger.group(
"Child",
() => {
ui.logger.info("Child info");
},
{ indentLevel: 1 },
);
});
// ▼ Parent
// ℹ Parent info
// ▼ Child
// ℹ Child info// Set output format to JSON
ui.logger.setOutputFormat("json");
// Log messages
ui.logger.info("Info message");
// {"level":"info","message":"Info message","timestamp":"2025-04-30T10:00:00.000Z"}
// Reset output format to text
ui.logger.setOutputFormat("text");// Set log level
ui.logger.setLogLevel(ui.logger.LogLevel.DEBUG); // Show all logs
ui.logger.setLogLevel(ui.logger.LogLevel.INFO); // Show info and above
ui.logger.setLogLevel(ui.logger.LogLevel.ERROR); // Show only errors
ui.logger.setLogLevel("debug"); // String version
// Get current log level
const level = ui.logger.getLogLevel(); // Returns LogLevel enum value
const levelName = ui.logger.getLogLevelName(); // Returns string (e.g., "INFO")// Good
console.log(ui.colors.primary("Primary text"));
// Bad
console.log("\x1b[34mPrimary text\x1b[0m");// Good
ui.logger.info("Info message");
// Bad
console.log("Info message");// Good
ui.logger.group("Configuration", () => {
ui.logger.info("Loading configuration...");
ui.logger.info("Configuration loaded successfully.");
});
// Bad
ui.logger.info("Configuration:");
ui.logger.info("Loading configuration...");
ui.logger.info("Configuration loaded successfully.");// Debug information (only shown with --debug)
ui.logger.debug("Detailed debug information");
// Verbose information (only shown with --verbose)
ui.logger.verbose("More details than normal");
// Normal information
ui.logger.info("Normal information");
// Success messages
ui.logger.success("Operation completed successfully");
// Warning messages
ui.logger.warn("Something might be wrong");
// Error messages
ui.logger.error("Something went wrong");import * as ui from "../ui";
// Create and start a spinner
const spinner = new ui.Spinner({ text: "Loading..." }).start();
// Do some work
// ...
// Update the spinner text
spinner.text("Still loading...");
// Mark the spinner as succeeded
spinner.succeed("Loaded successfully!");const spinner = new ui.Spinner({
text: "Loading...", // Text to display next to the spinner
type: "dots", // Spinner type (default, dots, line, star, arrow, bouncingBar, bouncingBall)
color: "primary", // Color of the spinner (primary, secondary, success, warning, error, info, muted)
enabled: true, // Whether to show the spinner
});// Start the spinner
spinner.start();
// Stop the spinner
spinner.stop();
// Update the spinner text
spinner.text("New text");
// Mark the spinner as succeeded
spinner.succeed("Success message");
// Mark the spinner as failed
spinner.fail("Error message");
// Mark the spinner as warned
spinner.warn("Warning message");
// Mark the spinner as information
spinner.info("Info message");
// Clear the spinner
spinner.clear();
// Reset the spinner
spinner.reset();// Create and start a spinner
const spinner = ui.Spinner.start({ text: "Loading..." });
// Create a spinner for a promise
const result = await ui.Spinner.promise(
{ text: "Loading data..." },
fetchData(),
"Data loaded successfully!",
"Failed to load data",
);// Create and start a spinner
const spinner = ui.spinner({ text: "Loading..." });
// Create a spinner for a promise
const result = await ui.spinnerPromise(
{ text: "Loading data..." },
fetchData(),
"Data loaded successfully!",
"Failed to load data",
);import * as ui from "../ui";
// Create and start a progress bar
const progressBar = new ui.ProgressBar({ total: 100 }).start();
// Update the progress bar
progressBar.update(25, { status: "Processing..." });
// Increment the progress bar
progressBar.increment(5, { status: "Still processing..." });
// Stop the progress bar
progressBar.stop();const progressBar = new ui.ProgressBar({
total: 100, // Total number of steps
start: 0, // Initial value
format: "{bar} {percentage}%", // Format string
barWidth: 40, // Width of the progress bar
barCompleteChar: "█", // Character for completed part
barIncompleteChar: "░", // Character for incomplete part
clearOnComplete: true, // Clear on completion
stopOnComplete: true, // Stop on completion
hideCursor: true, // Hide cursor
enabled: true, // Whether to show the progress bar
color: "primary", // Color of the progress bar
});// Start the progress bar
progressBar.start(0, { status: "Starting..." });
// Update the progress bar
progressBar.update(50, { status: "Halfway done..." });
// Increment the progress bar
progressBar.increment(10, { status: "Making progress..." });
// Stop the progress bar
progressBar.stop();
// Update the total value
progressBar.setTotal(200);// Process an array of items with a progress bar
const items = ["item1", "item2", "item3", "item4", "item5"];
const results = await ui.ProgressBar.forEachAsync(
{ total: items.length, color: "primary" },
items,
async (item, index) => {
// Process the item
await processItem(item);
return `Processed ${item}`;
},
(item, index) => `Processing ${item}...`,
);
// Or use the helper function
const results = await ui.progressForEach(
{ total: items.length, color: "primary" },
items,
async (item, index) => {
// Process the item
await processItem(item);
return `Processed ${item}`;
},
(item, index) => `Processing ${item}...`,
);// Create a multi-bar container
const multiBar = ui.ProgressBar.createMultiBar();
// Create progress bars in the container
const bar1 = multiBar.create("bar1", { total: 100, color: "primary" });
const bar2 = multiBar.create("bar2", { total: 200, color: "secondary" });
const bar3 = multiBar.create("bar3", { total: 300, color: "success" });
// Update the progress bars
bar1.update(25, { status: "Processing bar 1..." });
bar2.update(50, { status: "Processing bar 2..." });
bar3.update(75, { status: "Processing bar 3..." });
// Stop all progress bars
multiBar.stop();import * as ui from "../ui";
// Initialize the prompt system
ui.init("DeepLint CLI");
// Show a text input prompt
const name = await ui.text({
message: "What is your name?",
placeholder: "Enter your name",
validate: (value) => {
if (!value) return "Name is required";
},
});
// Check if the user cancelled the prompt
if (ui.isCancel(name)) {
ui.cancel("Operation cancelled");
process.exit(1);
}
// Show a confirmation prompt
const confirm = await ui.confirm({
message: "Are you sure?",
initialValue: true,
});
// Show a select prompt
const option = await ui.select({
message: "Select an option",
options: [
{ value: "option1", label: "Option 1" },
{ value: "option2", label: "Option 2" },
{ value: "option3", label: "Option 3" },
],
});
// Show a multi-select prompt
const options = await ui.multiselect({
message: "Select options",
options: [
{ value: "option1", label: "Option 1" },
{ value: "option2", label: "Option 2" },
{ value: "option3", label: "Option 3" },
],
required: true,
});
// Show a note
ui.note("This is a note", "Note Title");
// Show a themed note
ui.info("This is an info note");
ui.success("This is a success note");
ui.warning("This is a warning note");
ui.error("This is an error note");
// Run a task with a spinner
const result = await ui.task(
"Running task...",
async () => {
// Do some work
return "Task result";
},
"Task completed successfully!",
"Task failed",
);
// End the prompt session
ui.done("All done!");const name = await ui.text({
message: "What is your name?",
placeholder: "Enter your name",
initialValue: "John Doe",
validate: (value) => {
if (!value) return "Name is required";
},
});const password = await ui.password({
message: "Enter your password",
validate: (value) => {
if (!value) return "Password is required";
if (value.length < 8) return "Password must be at least 8 characters";
},
});const confirm = await ui.confirm({
message: "Are you sure?",
initialValue: true,
active: "Yes",
inactive: "No",
});const option = await ui.select({
message: "Select an option",
options: [
{ value: "option1", label: "Option 1", hint: "This is option 1" },
{ value: "option2", label: "Option 2", hint: "This is option 2" },
{ value: "option3", label: "Option 3", hint: "This is option 3" },
],
initialValue: "option1",
});const options = await ui.multiselect({
message: "Select options",
options: [
{ value: "option1", label: "Option 1", hint: "This is option 1" },
{ value: "option2", label: "Option 2", hint: "This is option 2" },
{ value: "option3", label: "Option 3", hint: "This is option 3" },
],
required: true,
max: 2,
});// Regular note
ui.note("This is a note", "Note Title");
// Themed notes
ui.info("This is an info note");
ui.success("This is a success note");
ui.warning("This is a warning note");
ui.error("This is an error note");const result = await ui.task(
"Running task...",
async () => {
// Do some work
return "Task result";
},
"Task completed successfully!",
"Task failed",
);// Check if the user cancelled the prompt
if (ui.isCancel(result)) {
ui.cancel("Operation cancelled");
process.exit(1);
}// Initialize the prompt session
ui.init("DeepLint CLI");
// End the prompt session
ui.done("All done!");import * as ui from "../ui";
// Create a simple banner
const simpleBanner = ui.banner("Hello, world!", {
title: "Welcome",
borderColor: "primary",
});
console.log(simpleBanner);const banner = ui.banner("Hello, world!", {
title: "Welcome", // Title of the banner
subtitle: "This is a subtitle", // Subtitle of the banner
borderStyle: "round", // Border style (single, double, round, bold, classic)
borderColor: "primary", // Border color (primary, secondary, success, warning, error, info, muted)
align: "center", // Text alignment (left, center, right)
padding: 1, // Padding (number or object)
margin: 1, // Margin (number or object)
width: 60, // Width of the banner
dimBorder: false, // Whether to dim the border
});// Create an app banner
const appBanner = ui.appBanner({
name: "DeepLint",
version: "1.0.0",
description: "A CLI tool for linting code with AI",
borderColor: "primary",
borderStyle: "bold",
});
console.log(appBanner);// Create a command banner
const commandBanner = ui.commandBanner({
command: "init",
description: "Initialize DeepLint in the current project",
usage: "deeplint init [options]",
examples: ["deeplint init", "deeplint init --force"],
borderColor: "primary",
borderStyle: "round",
});
console.log(commandBanner);// Create a success banner
const successBanner = ui.successBanner("Operation completed successfully!", "Success");
// Create a warning banner
const warningBanner = ui.warningBanner("This operation might take a while.", "Warning");
// Create an error banner
const errorBanner = ui.errorBanner(
"An error occurred while processing your request.",
"Error",
);
// Create an info banner
const infoBanner = ui.infoBanner("This is an informational message.", "Info");// Create a banner with custom padding and margin
const customBanner = ui.banner("Hello, world!", {
padding: {
top: 1,
right: 2,
bottom: 1,
left: 2,
},
margin: {
top: 1,
right: 0,
bottom: 1,
left: 0,
},
});import * as ui from "../ui";
// Create a simple table
const table = ui.createTable({
headers: ["Name", "Age", "Location"],
});
// Add rows to the table
table.push(["John", "25", "New York"]);
table.push(["Jane", "30", "San Francisco"]);
table.push(["Bob", "35", "Chicago"]);
// Display the table
console.log(table.toString());const table = ui.createTable({
headers: ["Name", "Age", "Location"], // Table headers
style: "default", // Table style (default, compact, markdown, borderless)
colors: {
header: "primary", // Header color (primary, secondary, success, warning, error, info, muted)
border: "muted", // Border color (primary, secondary, success, warning, error, info, muted)
},
});// Default style
const defaultTable = ui.createTable({
style: "default",
headers: ["Name", "Age", "Location"],
});
// Compact style
const compactTable = ui.createTable({
style: "compact",
headers: ["Name", "Age", "Location"],
});
// Markdown style
const markdownTable = ui.createTable({
style: "markdown",
headers: ["Name", "Age", "Location"],
});
// Borderless style
const borderlessTable = ui.createTable({
style: "borderless",
headers: ["Name", "Age", "Location"],
});// Create a table from an array of objects
const users = [
{ name: "John", age: 25, location: "New York" },
{ name: "Jane", age: 30, location: "San Francisco" },
{ name: "Bob", age: 35, location: "Chicago" },
];
const objectTable = ui.createTableFromObjects(users, {
style: "compact",
colors: { header: "primary" },
});
console.log(objectTable.toString());
// Create a table from an array of arrays
const data = [
["Name", "Age", "Location"],
["John", "25", "New York"],
["Jane", "30", "San Francisco"],
["Bob", "35", "Chicago"],
];
const arrayTable = ui.createTableFromArrays(data, {
style: "compact",
colors: { header: "primary" },
});
console.log(arrayTable.toString());
// Create a key-value table
const config = {
apiKey: "abc123",
endpoint: "https://api.example.com",
timeout: 5000,
retries: 3,
};
const keyValueTable = ui.createKeyValueTable(config, {
style: "compact",
colors: { header: "primary" },
});
console.log(keyValueTable.toString());// Format a table as a string
const table = ui.createTable({
headers: ["Name", "Age", "Location"],
});
table.push(["John", "25", "New York"]);
table.push(["Jane", "30", "San Francisco"]);
table.push(["Bob", "35", "Chicago"]);
const tableString = ui.formatTable(table);
console.log(tableString);
// Format an array of objects as a table string
const users = [
{ name: "John", age: 25, location: "New York" },
{ name: "Jane", age: 30, location: "San Francisco" },
{ name: "Bob", age: 35, location: "Chicago" },
];
const objectTableString = ui.formatObjectsAsTable(users, {
style: "compact",
colors: { header: "primary" },
});
console.log(objectTableString);
// Format an array of arrays as a table string
const data = [
["Name", "Age", "Location"],
["John", "25", "New York"],
["Jane", "30", "San Francisco"],
["Bob", "35", "Chicago"],
];
const arrayTableString = ui.formatArraysAsTable(data, {
style: "compact",
colors: { header: "primary" },
});
console.log(arrayTableString);
// Format a key-value object as a table string
const config = {
apiKey: "abc123",
endpoint: "https://api.example.com",
timeout: 5000,
retries: 3,
};
const keyValueTableString = ui.formatKeyValueAsTable(config, {
style: "compact",
colors: { header: "primary" },
});
console.log(keyValueTableString);// The table will handle these edge cases gracefully
const robustTable = ui.createTableFromObjects(
[
{ name: "John", age: 25 },
{ name: "Jane", age: null },
null,
{ name: undefined, age: 35 },
],
{
headers: ["Name", "Age"], // Explicit headers are recommended
},
);
console.log(robustTable.toString());const table = ui.createTableFromObjects(data, {
headers: ["Name", "Age", "Location"],
});const safeData = data.filter((item) => item != null);
const table = ui.createTableFromObjects(safeData);try {
const table = ui.createTableFromObjects(data);
console.log(table.toString());
} catch (error) {
logger.error("Error displaying table:", error);
// Fallback to simple display
for (const item of data) {
if (item) console.log(`${item.name}: ${item.value}`);
}
}