Skip to content
Open
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
2 changes: 2 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Changelog

## [0.4.6] - 17/04/2026
- Scans center

## [0.4.5] - 13/04/2026
- Selected commits review
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codeant-cli",
"version": "0.4.5",
"version": "0.4.6",
"description": "Code review CLI tool",
"type": "module",
"bin": {
Expand All @@ -27,7 +27,13 @@
".": "./src/reviewHeadless.js",
"./review": "./src/reviewHeadless.js",
"./push-protection": "./src/utils/installPushProtectionHook.js",
"./config": "./src/utils/config.js"
"./config": "./src/utils/config.js",
"./scans/connection": "./src/scans/connectionHandler.js",
"./scans/list-repos": "./src/scans/listRepos.js",
"./scans/scan-history": "./src/scans/getScanHistory.js",
"./scans/fetch-results": "./src/scans/fetchScanResults.js",
"./scans/fetch-advanced-results": "./src/scans/fetchAdvancedScanResults.js",
"./scans/dismissed-alerts": "./src/scans/fetchDismissedAlerts.js"
},
"files": [
"src"
Expand Down
219 changes: 219 additions & 0 deletions scans.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
# `codeant scans`

Fetch and explore scan results from CodeAnt.

```bash
codeant scans <subcommand> [options]
```

---

## Subcommands

### `scans orgs`

List authenticated organizations.

```bash
codeant scans orgs
```

---

### `scans repos`

List repositories for an organization.

```bash
codeant scans repos [options]
```

**Options:**

| Option | Description |
|--------|-------------|
| `--org <org>` | Organization name (auto-picked when only one is authenticated) |

**Examples:**

```bash
# List repos (auto-selects org if only one)
codeant scans repos

# List repos for a specific org
codeant scans repos --org my-org
```

---

### `scans history`

Show scan history for a repository.

```bash
codeant scans history --repo <owner/repo> [options]
```

**Options:**

| Option | Description |
|--------|-------------|
| `--repo <repo>` | **(required)** Repository in `owner/repo` format |
| `--branch <name>` | Filter by branch name |
| `--since <iso>` | Show scans since ISO date (e.g. `2024-01-01`) |
| `--limit <n>` | Max results (default: `20`) |

**Examples:**

```bash
# Show last 20 scans for a repo
codeant scans history --repo acme/backend

# Filter to a specific branch
codeant scans history --repo acme/backend --branch main

# Show scans since a date
codeant scans history --repo acme/backend --since 2024-06-01

# Show up to 50 results
codeant scans history --repo acme/backend --limit 50
```

---

### `scans get`

Show scan metadata and a severity/category summary. Does not include individual findings.

```bash
codeant scans get --repo <owner/repo> [options]
```

**Options:**

| Option | Description |
|--------|-------------|
| `--repo <repo>` | **(required)** Repository in `owner/repo` format |
| `--scan <sha>` | Specific commit SHA to use |
| `--branch <name>` | Resolve latest scan on this branch |
| `--types <list>` | Comma-separated scan types (default: `all`) |
| `--quiet` | Suppress progress output |

**Examples:**

```bash
# Get latest scan summary for a repo
codeant scans get --repo acme/backend

# Get scan for a specific commit
codeant scans get --repo acme/backend --scan abc1234

# Get latest scan on a branch
codeant scans get --repo acme/backend --branch main

# Only include SAST and secrets types
codeant scans get --repo acme/backend --types sast,secrets

# Suppress progress output
codeant scans get --repo acme/backend --quiet
```

---

### `scans results`

Fetch full scan findings for a repository.

```bash
codeant scans results --repo <owner/repo> [options]
```

**Options:**

| Option | Description |
|--------|-------------|
| `--repo <repo>` | **(required)** Repository in `owner/repo` format |
| `--scan <sha>` | Specific commit SHA to use |
| `--branch <name>` | Resolve latest scan on this branch |
| `--types <list>` | Comma-separated types: `sast`, `sca`, `secrets`, `iac`, `dead_code`, `sbom`, `anti_patterns`, `docstring`, `complex_functions`, `all` (default: `all`) |
| `--severity <list>` | Filter by severity (e.g. `critical,high`) |
| `--path <glob>` | Filter by file path glob |
| `--check <regex>` | Filter by check ID or name (regex) |
| `--include-dismissed` | Include dismissed findings (excluded by default) |
| `--format <fmt>` | Output format: `json`, `sarif`, `csv`, `md`, `table` (default: `json`) |
| `--output <path>` | Write output to file instead of stdout |
| `--fields <list>` | Project findings to a subset of fields (comma-separated) |
| `--limit <n>` | Max findings per page (default: `100`) |
| `--offset <n>` | Pagination offset (default: `0`) |
| `--fail-fast` | Exit `3` on first category fetch failure |
| `--no-color` | Disable ANSI color (auto-disabled when not a TTY) |
| `--quiet` | Suppress progress output on stderr |

**Examples:**

```bash
# Fetch all findings (JSON)
codeant scans results --repo acme/backend

# Fetch only critical and high severity findings
codeant scans results --repo acme/backend --severity critical,high

# Fetch SAST findings only
codeant scans results --repo acme/backend --types sast

# Filter to a specific file path
codeant scans results --repo acme/backend --path 'src/**/*.ts'

# Filter by check name using regex
codeant scans results --repo acme/backend --check 'sql-injection'

# Output as a Markdown table
codeant scans results --repo acme/backend --format md

# Output as SARIF to a file
codeant scans results --repo acme/backend --format sarif --output results.sarif

# Include dismissed findings
codeant scans results --repo acme/backend --include-dismissed

# Paginate through results
codeant scans results --repo acme/backend --limit 50 --offset 100

# Project only specific fields
codeant scans results --repo acme/backend --fields id,severity,message,path
```

**Exit codes:**

| Code | Meaning |
|------|---------|
| `0` | Success |
| `1` | General error |
| `3` | Category fetch failure (with `--fail-fast`) |

---

### `scans dismissed`

List dismissed alerts for a repository.

```bash
codeant scans dismissed --repo <owner/repo> [options]
```

**Options:**

| Option | Description |
|--------|-------------|
| `--repo <repo>` | **(required)** Repository in `owner/repo` format |
| `--analysis-type <type>` | Analysis type: `security` or `secrets` (default: `security`) |

**Examples:**

```bash
# List dismissed security alerts
codeant scans dismissed --repo acme/backend

# List dismissed secrets alerts
codeant scans dismissed --repo acme/backend --analysis-type secrets
```
26 changes: 26 additions & 0 deletions src/commands/scans/dismissed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { fetchDismissedAlerts } from '../../scans/fetchDismissedAlerts.js';

/**
* codeant scans dismissed --repo <repo> [--analysis-type security|secrets]
*/
export async function runDismissed({ repo, analysisType = 'security' } = {}) {
if (!repo) {
const err = new Error('--repo is required');
err.exitCode = 1;
throw err;
}

const result = await fetchDismissedAlerts(repo, analysisType);
if (!result.success) {
const err = new Error(result.error || 'Failed to fetch dismissed alerts');
err.exitCode = 1;
throw err;
}

return {
repo,
analysis_type: analysisType,
total: result.dismissedAlerts.length,
dismissed_alerts: result.dismissedAlerts,
};
}
24 changes: 24 additions & 0 deletions src/commands/scans/formatters/csv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const HEADERS = ['id', 'category', 'severity', 'file_path', 'line_number', 'check_id', 'check_name', 'message', 'cwe', 'cve', 'dismissed'];

function csvCell(val) {
if (val === null || val === undefined) return '';
const s = String(val);
if (s.includes(',') || s.includes('"') || s.includes('\n')) {
return '"' + s.replace(/"/g, '""') + '"';
}
return s;
}

export default {
name: 'csv',
mime: 'text/csv',
extension: '.csv',
render(envelope) {
const { findings = [] } = envelope;
const rows = [HEADERS.join(',')];
for (const f of findings) {
rows.push(HEADERS.map((h) => csvCell(f[h])).join(','));
}
return rows.join('\n');
},
};
12 changes: 12 additions & 0 deletions src/commands/scans/formatters/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Formatter registry.
* Contract: { name, mime, extension, render(envelope) → string }
* Add a new format = drop a file in formatters/ + one line here.
*/
import json from './json.js';
import sarif from './sarif.js';
import csv from './csv.js';
import md from './md.js';
import table from './table.js';

export const FORMATTERS = { json, sarif, csv, md, table };
8 changes: 8 additions & 0 deletions src/commands/scans/formatters/json.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default {
name: 'json',
mime: 'application/json',
extension: '.json',
render(envelope) {
return JSON.stringify(envelope, null, 2);
},
};
Loading