Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,3 +288,4 @@ publish actions on shared state. Write the files, hand the user the commands.
- The **current branch's tip** — your own unmerged work obviously can't be what the comment is reacting to.
Always disambiguate "released," "merged-but-unreleased," and "in-progress" before agreeing that a user-reported problem is unfixed (or that a fix is incomplete). A user saying "your fix only covers X" about a recent PR is usually pointing at the *released* shortcomings — your in-flight branch may already address them but they have no way to know that.
- **Version-tag every image referenced in `README.md`.** GitHub caches README images (`raw.githubusercontent.com` with a 5-minute TTL; third-party hosts sit behind the long-lived camo proxy), so updating an asset in place can keep showing the stale version. Give each README image URL a `?v=N` query tag and **bump `N` in the same commit whenever the asset bytes change** — e.g. `assets/waitlist.svg?v=2`. The changed URL sidesteps every cache so the new image shows immediately instead of waiting on a TTL to expire.
- For contributor-facing guidance (PR workflow, commit conventions), see `CONTRIBUTING.md`. To add a new language, use the `/add-lang` skill (`.claude/skills/add-lang/SKILL.md`).
280 changes: 280 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
# Contributing to CodeGraph

Thanks for your interest in contributing! This guide covers everything you need to
get started.

## Table of Contents

- [Code of Conduct](#code-of-conduct)
- [Getting Started](#getting-started)
- [Development Setup](#development-setup)
- [Project Architecture](#project-architecture)
- [Making Changes](#making-changes)
- [Adding a New Language](#adding-a-new-language)
- [Testing](#testing)
- [Commit Messages](#commit-messages)
- [Pull Requests](#pull-requests)
- [Reporting Issues](#reporting-issues)

---

## Code of Conduct

Be respectful and constructive. We're all here to build something useful.

## Getting Started

### Prerequisites

- **Node.js** >= 20.0.0, < 25.0.0 (Node 25.x has a V8 WASM JIT bug — see
[#81](https://github.com/colbymchenry/codegraph/issues/81))
- **npm** (ships with Node)
- **Git**

### Fork and Clone

```bash
# Fork via GitHub UI, then:
git clone https://github.com/<your-username>/codegraph.git
cd codegraph
git remote add upstream https://github.com/colbymchenry/codegraph.git
```

### Install and Verify

```bash
npm install
npm run build
npm test
```

If all tests pass, you're ready to go.

## Development Setup

### Useful Commands

| Command | What it does |
|---|---|
| `npm run build` | Compile TypeScript + copy assets into `dist/` |
| `npm run dev` | Watch mode — rebuilds on file change |
| `npm run clean` | Remove `dist/` |
| `npm test` | Run the full test suite (vitest) |
| `npm run test:watch` | Run tests in watch mode |
| `npm run cli` | Build then run the local CLI binary |

### Running a Single Test

```bash
npx vitest run __tests__/extraction.test.ts -t "Groovy"
```

### Project Structure

```
src/
├── index.ts # Public API (CodeGraph class)
├── types.ts # Core type definitions (NodeKind, EdgeKind, Language)
├── db/ # SQLite database layer (schema, queries)
├── extraction/ # Tree-sitter parsing and per-language extractors
│ ├── index.ts # ExtractionOrchestrator — drives the pipeline
│ ├── tree-sitter.ts # Core tree-sitter extraction engine
│ ├── grammars.ts # Grammar loading + extension-to-language map
│ ├── languages/ # One file per language (python.ts, go.ts, ...)
│ ├── parse-worker.ts # Heavy parsing off the main thread
│ ├── *-extractor.ts # Standalone extractors for non-tree-sitter formats
│ │ # (svelte, vue, astro, liquid, dfm, razor, ...)
│ └── wasm/ # Vendored grammar .wasm files
├── resolution/ # Cross-file reference resolution
│ └── frameworks/ # Framework-specific resolvers (Express, Django, ...)
├── graph/ # Graph traversal (BFS/DFS, impact radius)
├── context/ # Context building for AI consumption
├── mcp/ # MCP server (tools, transport, daemon, session)
├── installer/ # Multi-agent installer (11 targets — see below)
├── search/ # FTS5 query parsing
├── sync/ # File watcher and git hooks
└── bin/ # CLI entry point
__tests__/ # Tests mirror the module they cover
docs/ # Design docs, benchmarks, cookbooks
```

## Making Changes

### Branching

Always branch off `upstream/main`:

```bash
git checkout -b feat/my-feature upstream/main
```

Use descriptive branch names: `feat/`, `fix/`, `docs/`, `refactor/`.

### What to Edit

- **Types** (`src/types.ts`): `NodeKind`, `EdgeKind`, and `Language` are
runtime-iterable `const` arrays. Changing them affects the entire pipeline.
- **Extractors** (`src/extraction/languages/`): Each language has its own file
exporting a `LanguageExtractor` config. See
[Adding a New Language](#adding-a-new-language).
- **MCP tools** (`src/mcp/`): `server-instructions.ts` is the **single source
of truth** for agent-facing tool guidance — edit it and nowhere else. (The
installer used to duplicate this guidance into each agent's instructions file,
but that was removed in issue #529.)
- **Installer** (`src/installer/`): Adding a new agent target is one new file in
`targets/` + one entry in `registry.ts`. All changes need test coverage in
`__tests__/installer-targets.test.ts`.

### Installer Targets

The installer supports 11 agent targets:

| Target | MCP config file |
|---|---|
| Claude Code | `.mcp.json` |
| Cursor | `.cursor/mcp.json` |
| Codex CLI | `~/.codex/config.toml` |
| opencode | `opencode.jsonc` / `opencode.json` |
| Hermes | `~/.hermes/config.yaml` |
| Gemini CLI | `~/.gemini/settings.json` |
| Antigravity | `~/.gemini/config/mcp_config.json` |
| Kiro | `~/.kiro/settings/mcp.json` |
| Copilot (VS Code) | `.vscode/mcp.json` |
| Copilot CLI | `~/.copilot/mcp-config.json` |
| Copilot (JetBrains) | plugin `mcp.json` |

### Build Verification

Before committing, always run:

```bash
npm run build && npm test
```

TypeScript strict mode is fully enabled — the compiler catches a lot. The build
also copies `.wasm` files and `schema.sql` into `dist/`; if you add new assets,
make sure `copy-assets` picks them up.

## Adding a New Language

Use the interactive `/add-lang` skill (`.claude/skills/add-lang/SKILL.md`) — it
walks through the full workflow:

1. Sourcing a tree-sitter `.wasm` grammar
2. Probing the AST before writing code
3. Registering the language (one new file + two registry lines)
4. Writing the extractor (two patterns: `LanguageExtractor` config vs custom class)
5. Testing and PR checklist

## Testing

### Philosophy

Tests use **real files** and **real SQLite** — there is no DB mocking. Each test
creates a temp directory with `fs.mkdtempSync` and cleans up in `afterAll`/`afterEach`.

### Running Tests

```bash
npm test # full suite
npx vitest run __tests__/extraction.test.ts # single file
npx vitest run -t "TypeScript" # filter by test name
```

### Writing Tests

- Place tests in `__tests__/` mirroring the module they cover
- Use `extractFromSource(filename, code)` for extraction unit tests
- Use `it.runIf(process.platform === 'win32')(...)` for platform-gated tests
- Clean up temp dirs in `afterEach`/`afterAll`
- Don't skip or mock the database — integration tests must hit real SQLite

### Evaluation Tests

The `__tests__/evaluation/` directory has retrieval quality benchmarks. Run
with:

```bash
npm run eval # builds first, then runs the evaluation runner
```

These are not part of the standard test suite and are run separately.

## Commit Messages

We follow [Conventional Commits](https://www.conventionalcommits.org/):

```
type(scope): description
```

**Types:** `feat`, `fix`, `docs`, `chore`, `refactor`, `test`, `perf`

**Common scopes:** `extraction`, `resolution`, `mcp`, `cli`, `installer`,
`watcher`, `npm`, `release`

**Examples:**

```
feat(extraction): add Groovy language support
fix(resolution): stream node-kind scans in synthesis to fix OOM
docs(readme): link to the website & docs site
chore: update vitest to v2.1.9
```

- Use the imperative mood ("add" not "added")
- Keep the subject line under 72 characters
- Reference issues with `Closes #123` or `Relates to #123` in the body

## Pull Requests

### Before Opening

1. Rebase on the latest `upstream/main`
2. Run `npm run build && npm test` — everything must pass
3. Run `npx tsc --noEmit` — no type errors
4. Keep changes focused — one concern per PR

### Changelog

If your change is user-facing, add a bullet under `## [Unreleased]` in
`CHANGELOG.md`. Use `### New Features`, `### Fixes`, or `### Security` sections
(not `### Added` / `### Changed` / `### Fixed`). Write one plain-language
sentence per bullet — what changed and why it matters to a user. Strip internal
file paths, symbol names, and benchmark numbers. Reference issues by number,
e.g. `(#123)`.

### PR Description

Include:

- **What** changed and **why**
- Test plan (what you ran, what passed)
- Any known limitations or follow-up work
- For language additions: grammar source, version, license, and sha256 if
vendored

### Review Process

- Maintainers may request changes — please respond to feedback
- Keep PRs up to date with `upstream/main` via rebase (not merge commits)
- Squash commits if the history is messy

## Reporting Issues

When filing a bug report, please include:

- CodeGraph version (`codegraph --version` or `npx @colbymchenry/codegraph --version`)
- Node.js version (`node --version`)
- Operating system and version
- Steps to reproduce
- Expected vs actual behavior
- Relevant log output or error messages

For feature requests, describe the use case and why existing functionality
doesn't cover it.

## License

By contributing, you agree that your contributions will be licensed under the
[MIT License](LICENSE).
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,12 @@ Framework routing is validated the same way, on a canonical app per framework: E

**Very large repositories (hundreds of thousands of files), or a large `.codegraph/codegraph.db-wal` file** — The `-wal` file is SQLite's write-ahead log: writes waiting to be folded into `codegraph.db`. While a big index is being built, CodeGraph lets it grow in proportion to the index (soft threshold = the larger of 256 MB and a quarter of the index size, up to 2 GB) before folding it back, because folding too often is what made large indexes slow on ordinary disks. At rest it is trimmed to 64 MB, and a leftover from a killed session is folded and trimmed the next time the project opens — the index itself has no size limit. Two environment variables tune this: `CODEGRAPH_WAL_VALVE_MB` (the soft threshold during indexing) and `CODEGRAPH_WAL_HEAL_MB` (the resting size and the trim threshold). `CODEGRAPH_WAL_VALVE_DEBUG=1` prints every decision to stderr.

## Contributing

Contributions are welcome! See [`CONTRIBUTING.md`](CONTRIBUTING.md) for development setup, testing conventions, and PR guidelines.

Want to add a new language? Use the `/add-lang` skill (`.claude/skills/add-lang/SKILL.md`) — it walks through sourcing a tree-sitter grammar, probing the AST, choosing an extractor pattern, and the worked examples in the existing extractors.

## License

MIT
Expand Down