# stubtree

Generate a bird's-eye view of your codebase with all the important symbols (functions, classes, methods) shown inline. Perfect for documentation, code reviews, or understanding new projects.

```bash
$ stubtree --root ./src --lang ts

src/
├── index.ts
│   ├── class FileProcessor
│   │   ├── constructor(options: ProcessorOptions)
│   │   ├── processDirectory(dirPath: string): Promise<TreeNode>
│   │   └── shouldIgnoreFile(filePath: string): boolean
├── parser.ts
│   ├── parseTags(input: string): Promise<Tag[]>
│   └── interface Tag
│       ├── name: string
│       ├── path: string
│       └── kind: string
└── renderer.ts
    ├── renderTree(node: TreeNode, options?: RenderOptions): string
    └── formatSymbol(tag: Tag): string
```

## What is stubtree?

stubtree is a CLI tool that combines the power of ctags with a clean tree visualization to help you quickly understand any codebase. Unlike regular tree commands that only show files and folders, stubtree extracts and displays the actual code structure - classes, methods, functions, and more - giving you instant insight into how a project is organized.

**Perfect for AI coding assistants:** Tools like Claude, GitHub Copilot, and Cursor can better understand your codebase when provided with stubtree's structured output, leading to more accurate suggestions and refactoring.

## Installation

```bash
# Install globally
npm install -g @zapier/stubtree

# Or with yarn
yarn global add @zapier/stubtree

# Or use directly with npx
npx @zapier/stubtree
```

### Prerequisites

stubtree requires `ctags`:

```bash
# macOS
brew install ctags

# Ubuntu/Debian
sudo apt-get install ctags
```

## Getting Started

```bash
# Scan current directory
stubtree

# Scan specific directory with TypeScript files
stubtree --root ./src --lang ts,tsx

# Limit depth for large projects
stubtree --depth 3

# Export as JSON for processing
stubtree --json > structure.json
```

## Options

- `--root <dir>` - Root directory to scan (default: current directory)
- `--lang <globs>` - Comma-separated file extensions to include (e.g., `py,ts,tsx`)
- `--depth <n>` - Maximum directory depth to traverse
- `--json` - Output raw JSON instead of ASCII tree

### Examples

#### TypeScript/JavaScript project

```bash
stubtree --root ./src --lang ts,tsx,js,jsx
```

Output:
```
src/
├── main.ts
│   ├── init_app() -> void
│   └── class Service
│       ├── start() -> Promise<void>
│       └── stop() -> Promise<void>
└── utils/
    └── io.ts
        ├── read(path: string) -> string
        └── write(path: string, data: string) -> void
```

#### Python project with depth limit

```bash
stubtree --root ./myproject --lang py --depth 2
```

#### JSON output

```bash
stubtree --json > project-structure.json
```

## Features

- Fast parsing using ctags JSON output with advanced pattern extraction
- Extracts function signatures, return types, and async modifiers
- Shows class inheritance and property type annotations
- Respects file order as encountered (no sorting)
- Colorized output when outputting to TTY
- Ignores common directories (.git, node_modules, etc.) and test files
- Supports multiple programming languages through ctags
- Smart filtering to show only relevant symbols (classes, functions, methods, not internal variables)

## How it Works

### Behind the Scenes

stubtree combines the power of ctags with Node.js's streaming capabilities to efficiently parse and render your codebase:

1. **Symbol Extraction**: We spawn `ctags` as a child process with specific flags:
   ```bash
   ctags --output-format=json --fields=+neKStr --extras=+q --sort=no -R .
   ```
   - `--output-format=json`: Outputs newline-delimited JSON, one symbol per line
   - `--fields=+neKStr`: Includes line numbers, end lines, kind info, scope, type refs, and roles
   - `--extras=+q`: Includes extra tag information like signatures
   - `--sort=no`: Preserves file discovery order
   - `-R`: Recursively scans directories

2. **Streaming JSON Parser**: Instead of loading all ctags output into memory, we use Node's `readline` interface to process the JSON stream line-by-line. Each line contains a symbol like:
   ```json
   {"name":"readFile","path":"/project/src/io.ts","kind":"function","signature":"(path: string): Promise<string>"}
   ```

3. **Tree Building**: We build the tree structure in two passes:
   - First, we group all tags by their file paths
   - Then, we walk the actual filesystem to build the directory structure, attaching the relevant tags to each file node

4. **Smart Filtering**: 
   - Language filtering happens at the tag parsing stage based on file extensions
   - Directory traversal respects `--depth` limits and ignores common non-source directories
   - Empty directories are automatically pruned from the output

5. **ASCII Rendering**: The tree renderer uses a recursive algorithm with careful prefix tracking:
   - `├──` for non-last items
   - `└──` for last items
   - `│   ` for continuation lines
   - Tags are indented one level deeper than their containing file

6. **Color Support**: We detect TTY output using Node's `isatty()` and apply colors via chalk:
   - Blue for directories
   - Green for files
   - Gray for symbols

### Performance Optimizations

- **Streaming**: We never load the entire ctags output into memory
- **Lazy Directory Walking**: We only traverse directories that contain matching files
- **Early Filtering**: Language filters are applied during tag parsing, not after
- **Minimal Dependencies**: Just `commander` for CLI parsing and `chalk` for colors

## Performance

stubtree is designed to be fast, typically scanning and rendering a project tree in under 1 second on a typical laptop.

## Limitations

- Symbol information is limited to what ctags provides
- No language-specific type inference beyond ctags capabilities
- Requires ctags to be installed separately

## Development

```bash
# Install dependencies
npm install

# Run in development mode
npm run dev

# Run tests
npm test

# Build
npm run build

# Lint
npm run lint

# Type check
npm run typecheck
```

### Known Issues

- The tool gracefully handles broken symlinks and files that can't be accessed by skipping them during directory traversal

## License

MIT