vision
This document defines the long-term vision, mission, and guiding principles for the Lintro project. It serves as the north star for all development decisions.
Lintro Vision and Mission
This document defines the long-term vision, mission, and guiding principles for the Lintro project. It serves as the north star for all development decisions.
Mission Statement
Lintro aims to be the universal, all-in-one CLI for code quality - a single tool that provides linting, formatting, and testing capabilities for ANY modern programming language, with the highest standards of code quality, usability, and performance.
Vision
The Problem We Solve
Modern software development requires numerous code quality tools:
- Python developers need Ruff, Black, Mypy, Bandit, pytest
- JavaScript developers need ESLint, Prettier, Oxlint, Oxfmt
- DevOps engineers need Hadolint, Actionlint, Yamllint
- And the list grows with every language and framework
Each tool has its own:
- Installation process
- Configuration format
- Output format
- CLI interface
Lintro unifies this fragmented landscape into a single, consistent experience.
The Future We’re Building
Today (12 tools): Future (50+ tools):
┌─────────────────┐ ┌─────────────────────────────────┐
│ Python │ │ Python, JavaScript, TypeScript, │
│ JavaScript │ │ Go, Rust, Java, C/C++, Ruby, │
│ YAML, Docker │ │ PHP, Swift, Kotlin, Scala, │
│ Markdown │ → │ Elixir, Haskell, YAML, Docker, │
│ GitHub Actions │ │ Terraform, Kubernetes, SQL, │
│ │ │ GraphQL, Protobuf, and more... │
└─────────────────┘ └─────────────────────────────────┘
Success Criteria
Lintro will be successful when:
- Any developer can install a single tool and get code quality checks for their stack
- No Python required - distributed as standalone binaries for all platforms
- Consistent experience - same CLI, same output formats, same configuration approach
- Exemplary quality - Lintro itself is the gold standard for code quality
- Community-driven - easy for contributors to add new tool integrations
Core Principles
These principles are non-negotiable and guide every decision.
1. DRY (Don’t Repeat Yourself)
Every piece of knowledge must have a single, authoritative representation.
Applied to Lintro:
- Tool definitions should be data, not duplicated code
- Parsers should be generic and reusable
- Configuration patterns should be centralized
# BAD: Duplicated logic in every tool
class RuffTool:
def parse_json_output(self, output): ...
class OxlintTool:
def parse_json_output(self, output): ... # Same logic!
# GOOD: Single generic parser
json_parser = create_parser(format="json_lines", field_mapping={...})
2. SOLID Principles
Single Responsibility
Each module, class, and function has one reason to change.
parsers/- only parsing logicformatters/- only output formattingtools/- only tool orchestration
Open/Closed
Open for extension, closed for modification.
- Adding a new tool should NOT require modifying core code
- Plugin architecture enables this
Liskov Substitution
All tools are interchangeable through the BaseToolPlugin interface.
Interface Segregation
Clients depend only on interfaces they use.
ToolResultprovides a minimal, focused interfaceBaseIssuedefines only what formatters need
Dependency Inversion
High-level modules don’t depend on low-level modules.
- Core orchestration depends on abstractions (
ToolDefinition) - Concrete tools implement those abstractions
3. Maintainability Over Cleverness
Code should be readable by developers unfamiliar with the codebase.
Guidelines:
- Prefer explicit over implicit
- Avoid overly clever one-liners
- Use descriptive variable and function names
- Write self-documenting code, add comments for “why” not “what”
# BAD: Clever but unclear
if cmd := self._get_cmd() or self._fallback():
return cmd
# GOOD: Explicit and clear
command = self._get_primary_command()
if command is None:
command = self._get_fallback_command()
return command
4. File Size Discipline
Large files are hard to maintain. Break them into logical units.
Guidelines:
- Target: < 300 lines per file (soft limit)
- Maximum: 500 lines per file (hard limit)
- If a file grows too large, split by responsibility
# BAD: Monolithic file
tool_executor.py (800 lines)
# GOOD: Split by responsibility
tool_executor/
├── __init__.py
├── executor.py (execution logic)
├── discovery.py (file discovery)
├── parallel.py (parallel execution)
└── result_collector.py (result aggregation)
5. No Issue Obfuscation
Lintro must pass its own strict linting rules.
Guidelines:
- Never disable linter rules without documented justification
- Fix issues properly, don’t suppress them
- If a rule seems wrong, discuss removing it project-wide
- The codebase IS the example of good code quality
6. Test Everything
Quality without testing is wishful thinking.
Guidelines:
- Minimum 70% code coverage (target: 90%)
- Every new feature requires tests
- Every bug fix requires a regression test
- Integration tests for tool workflows
Quality Standards
Code Quality Metrics
| Metric | Threshold | Target |
|---|---|---|
| Test Coverage | ≥ 70% | 90% |
| Type Annotation Coverage | ≥ 95% | 100% |
| Docstring Coverage | ≥ 90% | 100% |
| File Length | ≤ 500 | 300 lines |
| Function Length | ≤ 50 | 25 lines |
| Cyclomatic Complexity | ≤ 15 | 10 |
Self-Validation
Lintro runs on itself. The CI pipeline includes:
lintro check . # Must pass with zero issues
lintro format . # Must result in no changes
lintro test . # Must pass with coverage threshold
Error Handling Standards
# REQUIRED: Specific exception handling
try:
result = execute_tool(command)
except subprocess.TimeoutExpired:
logger.warning(f"Tool {name} timed out after {timeout}s")
raise ToolTimeoutError(name, timeout) from None
except FileNotFoundError:
logger.error(f"Tool {name} not found in PATH")
raise ToolNotFoundError(name) from None
# FORBIDDEN: Silent failures
try:
result = parse_output(output)
except Exception:
return None # Never do this!
Success Metrics
Short-term (Current → 6 months)
- Test coverage reaches 70%
- Error handling audit complete (no silent failures)
- All 12 current tools have comprehensive documentation
- Binary distribution via Nuitka or PyOxidizer
Medium-term (6 months → 1 year)
- 25+ tool integrations
- Test coverage reaches 80%
- Performance benchmarks established
- Plugin ecosystem for community tools
Long-term (1+ years)
- 50+ tool integrations covering all major languages
- Optional GUI/TUI interface
- Language server protocol (LSP) integration
- IDE plugins (VS Code, JetBrains)
- Test coverage at 90%
Decision Framework
When making architectural decisions, use this priority order:
- Correctness - Does it work correctly in all cases?
- Maintainability - Can future developers understand and modify it?
- Extensibility - Does it support future growth without major changes?
- Performance - Is it fast enough for the use case?
- Elegance - Is it simple and beautiful?
If two approaches are equal in higher priorities, optimize for lower ones.
Related Documents
- ARCHITECTURE.md - Technical architecture and design decisions
- ROADMAP.md - Prioritized list of improvements and features
- ../style-guide.md - Coding standards and conventions
- ../contributing.md - How to contribute to the project