Metadata-Version: 2.4
Name: flowpatrol-cli
Version: 1.0.0
Summary: Flowpatrol CLI — run security scans from your terminal
Project-URL: Homepage, https://flowpatrol.ai
Project-URL: Documentation, https://github.com/flowpatrol/cli/tree/main/python#readme
Project-URL: Repository, https://github.com/flowpatrol/cli
Project-URL: Issues, https://github.com/flowpatrol/cli/issues
Project-URL: Changelog, https://github.com/flowpatrol/cli/blob/main/python/CHANGELOG.md
Author-email: Flowpatrol Team <team@flowpatrol.ai>
License: MIT
License-File: LICENSE
Keywords: appsec,cli,flowpatrol,scanning,security
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.10
Requires-Dist: click>=8.1
Requires-Dist: httpx>=0.27
Requires-Dist: typing-extensions>=4.0; python_version < '3.11'
Description-Content-Type: text/markdown

# flowpatrol-cli

Command-line interface for [Flowpatrol](https://flowpatrol.ai) — run automated
security scans against your web applications directly from your terminal or CI
pipeline.

## Requirements

- Python 3.10 or later
- A Flowpatrol API key ([sign up](https://flowpatrol.ai))

## Installation

```bash
pip install flowpatrol-cli
# or, recommended for CLI tools:
pipx install flowpatrol-cli
```

## Quick start

```bash
# 1. Save your API key
flowpatrol auth set-key fp_live_abc123

# 2. Run a Surface scan (fast, waits for results)
flowpatrol surface https://myapp.com

# 3. Run a full scan
flowpatrol scan https://myapp.com
```

## Commands

### `flowpatrol auth set-key <key>`

Store your API key in `~/.config/flowpatrol/config.json`. The key is also read
from the `FLOWPATROL_API_KEY` environment variable, which takes precedence.

```bash
flowpatrol auth set-key fp_live_abc123
```

### `flowpatrol auth whoami`

Show the currently active API key (redacted) and API endpoint.

```bash
flowpatrol auth whoami
flowpatrol auth whoami --verify   # also verify the key against the API
```

### `flowpatrol surface <url>`

Run a Surface scan — headers, secrets, fingerprints, RLS, screenshots.

```bash
flowpatrol surface https://myapp.com
flowpatrol surface https://myapp.com --format json
flowpatrol surface https://myapp.com --format sarif
flowpatrol surface https://myapp.com --timeout 300   # 5-minute timeout
```

Exits with code `1` if critical or high findings are found, `0` if clean.

### `flowpatrol scan <url> [options]`

Run a full scan. Waits for completion by default.

```bash
flowpatrol scan https://myapp.com
flowpatrol scan https://myapp.com --mode deep
flowpatrol scan https://myapp.com --no-wait          # fire-and-forget
flowpatrol scan https://myapp.com --format sarif > results.sarif
```

Options:

| Flag | Default | Description |
|------|---------|-------------|
| `-m, --mode` | `deep` | `surface` \| `deep` |
| `-f, --format` | `human` | `human` \| `json` \| `sarif` |
| `--no-wait` | — | Return immediately with the scan ID |
| `--timeout <seconds>` | `3600` | Give up polling after N seconds |

### `flowpatrol status <scan-id>`

Check the current status of a scan.

```bash
flowpatrol status abc-123-def
```

Exit codes: `0` = complete, `1` = still running, `2` = failed/cancelled.

### `flowpatrol report <scan-id> [options]`

Fetch the full report for a completed scan.

```bash
flowpatrol report abc-123-def
flowpatrol report abc-123-def --format json
flowpatrol report abc-123-def --format sarif > results.sarif
flowpatrol report abc-123-def --severity critical,high   # filter output
```

Options:

| Flag | Default | Description |
|------|---------|-------------|
| `-f, --format` | `human` | `human` \| `json` \| `sarif` |
| `--severity` | all | Comma-separated list to filter: `critical,high,medium,low,info` |

## Global flags

| Flag | Description |
|------|-------------|
| `-q, --quiet` | Suppress all human output; rely on exit codes only |
| `-v, --version` | Print CLI version |
| `-f, --format` | Default output format for all commands: `human` \| `json` \| `sarif` |
| `--api-url` | Override the API base URL |
| `--api-key` | Override the API key (takes precedence over config file and env var) |

## Configuration

Configuration is stored at `~/.config/flowpatrol/config.json`:

```json
{
  "apiKey": "fp_live_abc123",
  "apiUrl": "https://api.flowpatrol.ai"
}
```

Environment variables override the config file:

| Variable | Description |
|----------|-------------|
| `FLOWPATROL_API_KEY` | API key |
| `FLOWPATROL_API_URL` | API base URL (useful for self-hosted or local dev) |

## Exit codes

| Code | Meaning |
|------|---------|
| `0` | Success — scan clean or command completed without findings |
| `1` | Findings detected (critical or high severity) |
| `2` | Error — invalid arguments, network failure, auth failure, timeout |

## CI / GitHub Actions example

```yaml
- name: Security scan
  run: |
    pipx install flowpatrol-cli
    flowpatrol scan ${{ env.DEPLOY_URL }} --format sarif > flowpatrol.sarif
  env:
    FLOWPATROL_API_KEY: ${{ secrets.FLOWPATROL_API_KEY }}

- name: Upload SARIF
  uses: github/codeql-action/upload-sarif@v3
  if: always()
  with:
    sarif_file: flowpatrol.sarif
```

## SARIF output

The `--format sarif` flag produces SARIF 2.1.0 output compatible with GitHub
Advanced Security, VS Code SARIF Viewer, and any SARIF-aware tool.

Each finding maps to a SARIF rule with:
- A stable ID derived from the finding type (e.g. `FP-SQL-INJECTION`)
- OWASP and CWE tags when available
- `high` precision for confirmed findings, `medium` for unconfirmed

## Human output example

```
  Flowpatrol — https://myapp.com
  ─────────────────────────────────────────────

  CRITICAL  Supabase service_role key exposed in client JS
            GET / → found in main-abc123.js
            Fix: Move service key to a server-only environment variable
            OWASP A02:2021 · CWE-312

  HIGH      Missing Row Level Security on 'users' table
            /rest/v1/users readable with anon key
            Fix: Enable RLS and add a SELECT policy

  ─────────────────────────────────────────────
  1 critical · 1 high · 0 medium · 0 low
  Scan ID: abc-123-def  |  Duration: 42s
```

## Local development (monorepo)

This package lives in `packages/cli/python/` inside the private
[`flowpatrol/vibecheck`](https://github.com/flowpatrol/vibecheck) monorepo,
alongside its Node sibling at `packages/cli/node/`. Source of truth is the
monorepo; published artifacts live on PyPI, and both CLIs are mirrored into
the public [`flowpatrol/cli`](https://github.com/flowpatrol/cli) repo under
`node/` and `python/` subdirectories.

```bash
cd packages/cli/python
pip install -e ".[dev]"   # or: uv sync

# Run tests
pytest

# Run the CLI directly
python -m flowpatrol_cli --help
```

## Publication mechanics

The CLI is distributed two ways: as a PyPI package (primary) and as a source
mirror on GitHub (secondary, for browsing and issues). The mirror is shared
with the Node CLI — see the top-level README of
[`flowpatrol/cli`](https://github.com/flowpatrol/cli) for the combined layout.

### Release flow

```
conventional commit  →  release-please PR  →  merge PR  →  tag created
                                                               ↓
                                                       publish-cli.yml
                                                        ↓       ↓       ↓
                                        flowpatrol/cli repo   PyPI   (npm if
                                        (node/ + python/)           node bumped)
```

1. Merge a Conventional Commit touching `packages/cli/python/` to `main`.
2. [release-please](https://github.com/googleapis/release-please-action) opens
   a PR titled `chore(main): release cli-python X.Y.Z` that bumps
   `pyproject.toml`, updates `CHANGELOG.md`, and syncs
   `.release-please-manifest.json`.
3. Merging the release-please PR causes the `Release Please` workflow to
   create the tag `cli-python/vX.Y.Z` and call the unified
   [`publish-cli.yml`](../../../.github/workflows/publish-cli.yml) with
   `publish_pypi: true` (and `publish_npm: true` too if the Node CLI was
   bumped in the same batch).
4. `publish-cli.yml` runs three jobs:

   **Job 1 — `mirror`** (always runs)
   - Creates the public `flowpatrol/cli` repo if it does not exist yet
   - Regenerates **both** `node/` and `python/` subdirectories from the
     current monorepo HEAD
   - Generates a top-level README, `.gitignore`, and `CONTRIBUTING.md`
   - Force-pushes `main` and moves the scoped tags `node-vX.Y.Z` and
     `python-vX.Y.Z`

   **Job 2 — `publish-pypi`** (runs if `publish_pypi: true`)
   - Installs `build` and `twine`
   - Bumps the version in `pyproject.toml` to the release version
   - Runs `python -m build` to produce sdist + wheel in `dist/`
   - Runs `twine check dist/*` to validate metadata
   - Runs `twine upload dist/*` to publish `flowpatrol-cli==X.Y.Z` to PyPI

   **Job 3 — `publish-npm`** (runs if `publish_npm: true`)
   - Publishes `@flowpatrol/cli` to npm (only fires if the Node CLI was
     bumped in the same release-please batch)

### Required secrets

| Secret | Where | Required? | Purpose |
|--------|-------|-----------|---------|
| `PYPI_API_TOKEN` | `flowpatrol/vibecheck` → Settings → Actions secrets | Yes | PyPI API token (`pypi-...`) with upload access to the `flowpatrol-cli` project. Used as `TWINE_PASSWORD` with `TWINE_USERNAME=__token__`. |
| `PUBLIC_REPO_TOKEN` | `flowpatrol/vibecheck` → Settings → Actions secrets | Optional | PAT with `repo` scope and permission to create repos under the `flowpatrol` org. If set, the `mirror` job runs; if unset, it is skipped (PyPI is still published). |

### Manual publish (dry run or bootstrap)

```
Actions → Publish CLI (Python) → Run workflow
  version:  (blank → uses packages/cli/python/pyproject.toml)
  dry_run:  true   # build + twine check, no upload
```

Use `dry_run: true` to validate the sdist/wheel build without touching PyPI.

### What users consume

```bash
# Primary: install from PyPI (recommended via pipx for CLI tools)
pipx install flowpatrol-cli
# or
pip install flowpatrol-cli

# Source browsing / issues
https://github.com/flowpatrol/cli             # top-level README covers both CLIs
https://github.com/flowpatrol/cli/tree/main/python  # this package's mirror
```

The `flowpatrol/cli` GitHub repo is a generated mirror — it contains the
source of both CLIs but no `.venv` or `dist`. Do not open PRs against it;
they will be overwritten on the next release. File issues and changes
against `flowpatrol/vibecheck` instead.
