The project tool auto-detects your toolchain from config files and runs the correct commands — no setup, no guessing.
Actions
| Action | Description | Example |
|---|
lint | Run project linter | project(action: "lint") |
typecheck | Run type checker | project(action: "typecheck") |
test | Run test suite | project(action: "test", file: "src/foo.test.ts") |
build | Build project | project(action: "build") |
run | Run dev server or script | project(action: "run", script: "dev") |
list | Discover monorepo packages | project(action: "list") |
Parameters
| Param | Type | Description |
|---|
action | required | lint, typecheck, test, build, run, list |
file | optional | Target specific file (test, lint) |
fix | optional | Auto-fix lint issues (biome —write, eslint —fix, ruff —fix) |
flags | optional | Extra CLI flags |
env | optional | Environment variables |
cwd | optional | Working directory (for monorepos) |
timeout | optional | Timeout in ms (default 120000) |
detectProfile(cwd) scans for config files and lockfiles:
bun.lock -> bun test, bun run lint, bunx tsc --noEmit
Cargo.toml -> cargo test, cargo clippy, cargo check
go.mod -> go test, golangci-lint run, go build
pyproject.toml -> pytest, ruff check, mypy/pyright
composer.json -> phpunit, phpstan/psalm
Gemfile -> rspec, rubocop
build.gradle -> gradle test, gradle check
JS/TS linter detection
Priority order:
biome.json / biome.jsonc -> biome check .
oxlintrc.json / .oxlintrc.json -> oxlint .
eslint.config.js / .eslintrc* -> eslint .
Python type checker detection
pyrightconfig.json exists -> pyright
- Otherwise ->
mypy .
Full ecosystem support
| Ecosystem | Lint | Typecheck | Test | Build |
|---|
| JS/TS (Bun) | biome / oxlint / eslint | tsc | bun test | bun run build |
| JS/TS (Node) | biome / oxlint / eslint | tsc | npm test | npm run build |
| Deno | deno lint | deno check | deno test | — |
| Rust | cargo clippy | cargo check | cargo test | cargo build |
| Go | golangci-lint / go vet | go build | go test | go build |
| Python | ruff / flake8 | pyright / mypy | pytest | — |
| PHP | phpstan / psalm | phpstan / psalm | phpunit | — |
| Ruby | rubocop | — | rspec / rails test | — |
| Swift | swiftlint | swift build | swift test | swift build |
| Elixir | credo | dialyzer | mix test | mix compile |
| Java/Kotlin | gradle check | javac / kotlinc | gradle test | gradle build |
| C/C++ | clang-tidy | cmake build | ctest | cmake build |
| Dart/Flutter | dart analyze | dart analyze | flutter test | flutter build |
| Zig | — | zig build | zig build test | zig build |
| Haskell | hlint | stack build | stack test | stack build |
| Scala | — | sbt compile | sbt test | sbt compile |
| .NET/C# | dotnet format | dotnet build | dotnet test | dotnet build |
| iOS/Xcode | swiftlint | xcodebuild build | xcodebuild test | xcodebuild build |
| Java (Maven) | checkstyle | mvn compile | mvn test | mvn package |
| C/C++ (Make) | — | — | make test | make |
| Clojure | clj-kondo | — | lein test / clj -M:test | lein uberjar |
Pre-commit checks
When the agent runs git commit via the shell tool, SoulForge auto-runs detectNativeChecks(cwd) before allowing the commit:
- JS/TS:
biome check . && tsc --noEmit
- Rust:
cargo clippy && cargo check
- Go:
golangci-lint run && go build ./...
- Python:
ruff check && pyright
If checks fail, the commit is blocked and errors are returned to the agent. This is code-enforced — no prompt instruction needed.
To skip pre-commit checks, commit directly via shell outside SoulForge.
The pre-commit check uses detectNativeChecks() which identifies tools from config files directly, never from package.json scripts. This ensures only known, safe tools are run.
Monorepo discovery
project(action: "list") discovers workspace packages:
- pnpm:
pnpm-workspace.yaml
- npm/yarn:
workspaces field in package.json
- Cargo:
[workspace] members in Cargo.toml
- Go:
use directives in go.work
Example output
5 packages:
@myapp/web -- packages/web (biome) [lint, typecheck, test]
@myapp/api -- packages/api (biome) [lint, typecheck, test]
@myapp/shared -- packages/shared (biome) [lint, typecheck]
@myapp/cli -- packages/cli (biome) [lint]
@myapp/docs -- packages/docs [test]
Use project(action: "lint", cwd: "<path>") to target a specific package.
Each package gets its own detectProfile() call, so capabilities are accurate per-package.
System prompt integration
The detected toolchain is injected into the system prompt:
Toolchain: bun
Project commands: lint: `bun run lint` . typecheck: `bun run typecheck` . test: `bun test` . build: `bun run build`
The agent sees available actions without guessing.
Shell redirect hints
When the agent runs bun run lint, cargo clippy, etc. via shell instead of the project tool, the result includes a hint:
Command succeeded. Next time use project(action: "lint") -- it auto-detects
the toolchain, results are structured, and output is visible in the UI.
This educates the agent to prefer the project tool without blocking the command.