project-detect 0.1.1

Zero-config project type detection — identify any project's language, build system, and toolchain from directory contents
Documentation
<div align="center">
  <h1>project-detect</h1>
  <p><strong>Zero-config project type detection for 29 ecosystems.</strong></p>

  <p>
    <a href="https://crates.io/crates/project-detect"><img alt="crates.io" src="https://img.shields.io/crates/v/project-detect?logo=rust&logoColor=white&color=orange"></a>
    <a href="https://docs.rs/project-detect"><img alt="docs.rs" src="https://img.shields.io/docsrs/project-detect"></a>
    <a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue"></a>
  </p>
</div>

---

Point it at a directory and it tells you what kind of project lives there. No config files, no setup — just file detection.

```rust
use project_detect::{detect, ProjectKind};

if let Some(kind) = detect(".") {
    println!("{} project ({})", kind.label(), kind.detected_file());
    // "Rust project (Cargo.toml)"
}
```

## Features

- **29 ecosystems** detected out of the box
- **Priority-ordered** — language-specific files win over generic build systems
- **Ecosystem metadata** — Node.js package manager, Flutter vs Dart, Stack vs Cabal, etc.
- **Directory walking**`detect_walk` searches up the directory tree for monorepo support
- **Artifact directories** — know what to clean for every ecosystem
- **Zero dependencies** beyond `serde_json` (for package.json parsing)

## Supported Ecosystems

| Priority | File | Ecosystem | Label |
|:--------:|------|-----------|-------|
| 1 | `Cargo.toml` | Rust | `"Rust"` |
| 2 | `go.mod` | Go | `"Go"` |
| 3 | `mix.exs` | Elixir | `"Elixir"` |
| 4 | `pyproject.toml` / `setup.py` | Python | `"Python"` |
| 5 | `package.json` | Node.js | `"Node.js"` |
| 6 | `build.gradle` | Gradle (Java/Kotlin) | `"Gradle"` |
| 7 | `pom.xml` | Maven (Java) | `"Maven"` |
| 8 | `build.sbt` | Scala | `"Scala"` |
| 9 | `Gemfile` | Ruby | `"Ruby"` |
| 10 | `Package.swift` | Swift | `"Swift"` |
| 11 | `build.zig` | Zig | `"Zig"` |
| 12 | `*.csproj` / `*.sln` | .NET | `".NET"` |
| 13 | `composer.json` | PHP | `"PHP"` |
| 14 | `pubspec.yaml` | Dart / Flutter | `"Dart"` / `"Flutter"` |
| 15 | `stack.yaml` / `*.cabal` | Haskell | `"Haskell"` |
| 16 | `project.clj` / `deps.edn` | Clojure | `"Clojure"` |
| 17 | `rebar.config` | Erlang | `"Erlang"` |
| 18 | `dune-project` | OCaml | `"OCaml"` |
| 19 | `cpanfile` / `Makefile.PL` | Perl | `"Perl"` |
| 20 | `Project.toml` | Julia | `"Julia"` |
| 21 | `*.nimble` | Nim | `"Nim"` |
| 22 | `shard.yml` | Crystal | `"Crystal"` |
| 23 | `v.mod` | V | `"V"` |
| 24 | `gleam.toml` | Gleam | `"Gleam"` |
| 25 | `*.rockspec` | Lua | `"Lua"` |
| 26 | `MODULE.bazel` / `WORKSPACE` | Bazel | `"Bazel"` |
| 27 | `meson.build` | Meson | `"Meson"` |
| 28 | `CMakeLists.txt` | CMake | `"CMake"` |
| 29 | `Makefile` | Make | `"Make"` |

## Usage

### Basic detection

```rust
use project_detect::{detect, ProjectKind};

let kind = detect("/path/to/project").unwrap();
println!("{}", kind.label());           // "Rust"
println!("{}", kind.detected_file());   // "Cargo.toml"
```

### Walk up the directory tree

```rust
use project_detect::detect_walk;

// Running from src/lib/ inside a Cargo workspace?
// detect_walk finds the Cargo.toml in the parent.
if let Some((kind, project_dir)) = detect_walk(".") {
    println!("Found {} at {}", kind.label(), project_dir.display());
}
```

### Ecosystem metadata

```rust
use project_detect::{detect, ProjectKind, NodePM};

match detect(".") {
    Some(ProjectKind::Node { manager: NodePM::Pnpm }) => println!("pnpm project"),
    Some(ProjectKind::Dart { flutter: true }) => println!("Flutter app"),
    Some(ProjectKind::Haskell { stack: true }) => println!("Stack project"),
    Some(ProjectKind::Haskell { stack: false }) => println!("Cabal project"),
    Some(kind) => println!("{}", kind.label()),
    None => println!("No project detected"),
}
```

### Clean artifacts

```rust
use project_detect::detect;

if let Some(kind) = detect(".") {
    for dir in kind.artifact_dirs() {
        println!("Can remove: {dir}/");
    }
    // Rust: ["target"]
    // Node.js: ["node_modules", ".next", ".nuxt", ".turbo"]
    // Haskell (Stack): [".stack-work"]
}
```

### Node.js helpers

```rust
use project_detect::{node_has_script, node_has_bin, detect_node_workspace};
use std::path::Path;

let dir = Path::new(".");
if node_has_script(dir, "build") { /* has a build script */ }
if node_has_bin(dir) { /* has a bin field */ }
if let Some(packages) = detect_node_workspace(dir) {
    for pkg in packages {
        println!("{}: {}", pkg.name, pkg.dev_script);
    }
}
```

## License

MIT