npm package: @noderith/cli
Description: Noderith CLI — codebase analysis, architecture enforcement, and zero-code-upload push to Noderith
Author: Noderith
Latest version: 0.1.1

# @noderith/cli

Analyze your codebase locally, enforce architecture rules in CI, and push results to [Noderith](https://noderith.com) — your source code never leaves your machine.

## Install

```bash
npm install -g @noderith/cli
```

Requires Node.js 18+.

## Quick Start

```bash
# Analyze a repo and see the health report
noderith analyze .

# JSON output for scripting
noderith analyze . --json

# Push results to Noderith (source code stays local)
noderith push . --api-url https://noderith.com/api --api-key sk_noderith_xxx
```

## Commands

### `noderith analyze <path>`

Run local codebase analysis. Parses every file with Tree-sitter, builds a dependency graph, calculates health scores, and evaluates architecture rules.

```bash
noderith analyze .
noderith analyze ./my-project --format json
noderith analyze . --threshold 70 --fail-on-cycles --fail-on-deny
noderith analyze . --json | jq '.topIssues'
noderith analyze . --format md > report.md
noderith analyze . --threshold 60 --silent
```

| Flag | Description |
|------|-------------|
| `--format <json\|text\|md>` | Output format (default: `text`) |
| `--json` | Shorthand for `--format json` |
| `--threshold <number>` | Fail (exit 1) if health score is below this value (0-100) |
| `--fail-on-cycles` | Fail (exit 1) if circular dependencies are found |
| `--fail-on-deny` | Fail (exit 1) if any deny-level architecture rules are violated |
| `--silent` | Only output on failure |

### `noderith push <path>`

Analyze locally and push **only metadata** to the Noderith platform. Your source code never leaves your machine.

**What gets uploaded:** file names, import/export relationships, complexity scores, health warnings, function signatures, dependency graph structure.

**What stays local:** source code, file contents, implementation details, comments, API keys, environment variables.

```bash
noderith push . --api-url https://noderith.com/api --api-key sk_noderith_xxx
noderith push ./my-project --name my-service --url https://github.com/org/repo
```

| Flag | Description |
|------|-------------|
| `--api-url <url>` | Noderith API URL (or env `NODERITH_API_URL`) |
| `--api-key <key>` | API key (or env `NODERITH_API_KEY`) |
| `--org-id <id>` | Organization ID (or env `NODERITH_ORG_ID`) |
| `--name <name>` | Repo name override (default: directory name) |
| `--url <url>` | Optional GitHub URL to associate with the push |

### `noderith help`

Show usage information and examples.

## Architecture Rules

Create `.noderith/rules.json` in your repo root to define architecture constraints:

```json
{
  "rules": [
    { "name": "No circular dependencies", "deny": { "cycles": true } },
    { "name": "Max 500 lines per file", "warn": { "max_lines": 500 } },
    { "name": "No frontend-to-api imports", "deny": { "from": "frontend/**", "to": "api/**" } },
    { "name": "Max complexity 15", "warn": { "max_complexity": 15 } }
  ]
}
```

| Rule | Description |
|------|-------------|
| `cycles: true` | Flags circular dependency chains |
| `max_lines: N` | Flags files exceeding N lines |
| `max_complexity: N` | Flags functions exceeding cyclomatic complexity N |
| `from` / `to` (glob) | Flags imports crossing the specified boundary |

**Severity levels:**
- **deny** — hard failures; blocks CI with `--fail-on-deny`
- **warn** — advisory; reported but does not cause a non-zero exit code

## CI/CD Usage

### GitHub Actions

```yaml
name: Noderith Analysis
on:
  pull_request:
    branches: [main]

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '22'

      - name: Install Noderith
        run: npm install -g @noderith/cli

      - name: Run Analysis
        run: noderith analyze . --threshold 60 --fail-on-cycles --fail-on-deny --json

      - name: Push to Noderith
        if: github.ref == 'refs/heads/main'
        run: noderith push . --name ${{ github.event.repository.name }}
        env:
          NODERITH_API_URL: https://noderith.com/api
          NODERITH_API_KEY: ${{ secrets.NODERITH_API_KEY }}
          NODERITH_ORG_ID: ${{ secrets.NODERITH_ORG_ID }}
```

### Environment Variables

| Variable | Description |
|----------|-------------|
| `NODERITH_API_URL` | Default API URL for `push` command |
| `NODERITH_API_KEY` | Default API key for `push` command |
| `NODERITH_ORG_ID` | Default organization ID for `push` command |

## Exit Codes

| Code | Meaning |
|------|---------|
| `0` | Analysis passed all checks |
| `1` | Threshold, cycle, or deny-rule check failed |
| `2` | Analysis error (e.g., no parseable files found) |

## JSON Output Fields

When using `--format json`, the output includes:

| Field | Description |
|-------|-------------|
| `repoPath` | Resolved absolute path |
| `healthScore` | Overall score 0-100 |
| `totalFiles` | Number of parsed files |
| `totalEdges` | Number of import relationships |
| `totalCycles` | Number of circular dependency chains |
| `languages` | File count by language |
| `warnings` | Counts by severity (critical, warning, info) |
| `warningDetails` | Full list with type, severity, file, message |
| `ruleViolations` | Architecture rule violations |
| `topIssues` | Top 20 unhealthiest files |
| `fileScores` | Per-file health scores |

## Supported Languages

- JavaScript (.js, .jsx)
- TypeScript (.ts, .tsx)
- Python (.py)
- Rust (.rs)
- Go (.go)
- Java (.java)
- Ruby (.rb)
- PHP (.php)
- C/C++ (.c, .cpp, .h, .hpp)

## Links

- **Website:** [noderith.com](https://noderith.com)
- **Documentation:** [noderith.com/docs](https://noderith.com/docs)
- **Get an API Key:** [noderith.com/app/api-keys](https://noderith.com/app/api-keys)

## License

MIT