Skip to main content

Command-line client for freelancer-payment-protection: automated invoice escalation, legal document generation, and client risk scoring for freelancers.

Project description

freelancer-payment-protection-cli

Command-line client for freelancer-payment-protection: automated invoice escalation, legal document generation, and client risk scoring for freelancers. This package wraps the project's FastAPI backend (apps/api/app/routers/*.py) so the same clients, invoices, escalations, and risk-scoring data you'd otherwise reach through the dashboard or the raw HTTP API is scriptable from a terminal or an agent.

Login and first command

Install

pip install freelancer-payment-protection-cli

Or with uv / pipx:

uvx freelancer-payment-protection-cli --help
pipx install freelancer-payment-protection-cli

Requires Python 3.10+. The console command is installed as both fpp (short form) and freelancer-payment-protection (full form), the same entry point either way.

Configuration

The CLI needs to know two things: which backend API to talk to, and which Supabase project issues your login tokens.

Variable Purpose Default
FPP_API_URL Backend API base URL http://localhost:8000
FPP_SUPABASE_URL (or SUPABASE_URL) Your Supabase project URL none, required for login
FPP_SUPABASE_ANON_KEY (or SUPABASE_ANON_KEY) Your Supabase project's anon key none, required for login

The anon key is the same public key the web app's Supabase client uses. It is not a secret, and it's the key already in apps/web/.env.example as NEXT_PUBLIC_SUPABASE_ANON_KEY.

Login and authentication

export FPP_SUPABASE_URL="https://your-project.supabase.co"
export FPP_SUPABASE_ANON_KEY="your-anon-key"
fpp login

fpp login prompts for your email and password, then calls Supabase's own REST auth endpoint directly:

POST {SUPABASE_URL}/auth/v1/token?grant_type=password
Header: apikey: <anon key>
Body:   {"email": ..., "password": ...}

This is the same call the web dashboard's Supabase client makes. The CLI never talks to a login endpoint of its own, because the backend (apps/api/app/middleware/auth.py) doesn't mint tokens; it only validates Supabase-issued JWTs. On success, the returned access_token and refresh_token are cached to ~/.config/freelancer-payment-protection-cli/credentials.json (mode 600). Every later command reads the JWT's workspace_id claim the same way get_current_workspace() does server-side, and transparently refreshes the access token with the cached refresh token once it expires.

Run fpp logout to delete the cached credentials, or fpp whoami to see which workspace and email the cached token resolves to.

Commands

Every data-returning command supports --json for scripting and agent use.

fpp login                                   Log in (prompts for email/password)
fpp logout                                  Remove cached credentials
fpp whoami [--json]                         Show cached workspace/session info

fpp invoice list [--status] [--client-id] [--page] [--page-size] [--json]
fpp invoice create --client-id --invoice-number --amount --due-date [...] [--json]
fpp invoice show <invoice-id> [--json]
fpp invoice set-status <invoice-id> <status> [--json]

fpp escalation list [--json]                Active escalations, grouped by stage
fpp escalation status <invoice-id> [--json] Current stage + full history
fpp escalation advance <invoice-id> [--json] AI-draft the next stage's email

fpp client list [--risk-level] [--search] [--page] [--page-size] [--json]
fpp client show <client-id> [--json]
fpp client risk <client-id> [--json]        Compute/refresh the AI risk score

Run fpp --help or fpp <command> --help for full flag references.

Filtering invoices, scoring a client, and checking escalation status

A note on escalation advance

The backend's escalation router (apps/api/app/routers/escalations.py) exposes exactly three routes: list active escalations, draft the next stage's email, and read history. There is no route that persists a stage change. draft_escalation_email in escalation_service.py computes and returns what the next stage's email would say, but never writes escalation_stage back to the database. fpp escalation advance calls that draft endpoint and shows you the preview; it does not claim to move the invoice to the next stage, because the API it wraps doesn't do that either.

JSON output for agents/scripts

fpp invoice list --status overdue --json | jq '.[] | {id, invoiceNumber, daysPastDue}'
fpp client risk "$CLIENT_ID" --json | jq '.level'

Field names in --json output match the backend's actual Pydantic response models exactly (camelCase, e.g. invoiceNumber, daysPastDue, escalationStage) since the CLI passes the API's response straight through rather than remapping it.

FAQ

What is this, and how is it different from just calling the API with curl? It's a typed command-line wrapper around the same backend the web dashboard uses (invoices, escalations, and client risk scoring), with persistent login (so you're not re-attaching a bearer token to every request), human-readable tables by default, and a --json flag on every data command for piping into jq, scripts, or an agent's tool-calling loop. The differentiator versus curl is session handling (login once, silent token refresh after) and consistent, documented output shapes instead of hand-rolled request construction.

What platforms and Python versions does it support? Python 3.10 through 3.13, on any OS pip/uvx/pipx runs on (Linux, macOS, Windows). It has no compiled dependencies; the only runtime dependencies are click and httpx, both pure-Python-installable wheels.

How do I log in, and where are my credentials stored? Run fpp login, enter your email and password when prompted. The CLI calls Supabase's password-grant token endpoint directly (see "Login and authentication" above) and caches the resulting access and refresh tokens to ~/.config/freelancer-payment-protection-cli/credentials.json with file mode 600 (owner read/write only). Nothing is sent anywhere except Supabase's own auth endpoint and the backend API you configure via FPP_API_URL.

I ran a command and got Error: Internal Server Error. Is that a CLI bug? Usually not. The CLI's error handling surfaces whatever the backend returned; a 500 means the backend itself failed. Two real, backend-side causes to check first: (1) fpp client risk and fpp escalation advance both trigger AI calls through packages/legal_ai/client.py. If ANTHROPIC_API_KEY isn't a real key on the server, client risk falls back to a heuristic score automatically, but escalation advance has no such fallback and will 500. (2) Confirm you're running a backend build that includes the packages/legal_ai module-name fix and the risk_scoring.py request-parameter fix, both real bugs in this repo (a hyphenated packages/legal-ai directory that the code imports as packages.legal_ai, and a rate-limiter/parameter-name collision on /api/v1/risk/score) that this CLI's own end-to-end testing surfaced and this same change fixed. A plain 401 means your cached token expired and couldn't refresh. Run fpp login again.

Does fpp escalation advance actually send the escalation email or move the invoice to the next stage? No. It calls the backend's /api/v1/escalations/{id}/draft endpoint, which only returns an AI-drafted preview of what the next stage's email would say. The backend has no endpoint today that persists a stage change or sends the email. See "A note on escalation advance" above.

Can I point this at a self-hosted or non-default backend? Yes. Set FPP_API_URL to your backend's base URL (default is http://localhost:8000, matching the FastAPI dev server's default port). Every command reads that variable at call time, so switching environments is just re-exporting it.

What's the licensing situation? Can I use or modify this commercially? This CLI ships from the same repository as, and under the same license as, freelancer-payment-protection itself: a proprietary license, copyright Rudrendu Paul and Sourav Nandy, all rights reserved. Personal, academic, commercial, or scheduled use requires explicit written permission from both owners. See the LICENSE file. This is not an MIT/Apache-style open-source license; publishing it to PyPI makes it installable, not freely reusable.

Why isn't there a hosted/default API URL I can just start using? freelancer-payment-protection is self-hosted software, not a hosted multi-tenant SaaS with a public API endpoint today. You (or whoever operates your workspace) runs the backend; the CLI just needs its URL.

Development

cd packages/cli
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest

All HTTP calls (to Supabase and to the backend API) are mocked in tests with respx; the test suite makes no live network calls.

Contributing

This package lives inside the freelancer-payment-protection monorepo. See the repository root for contribution guidelines.

License

Proprietary. See LICENSE. Contact the owners (see LICENSE) before any use beyond installing and running the package as published.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

freelancer_payment_protection_cli-0.1.2.tar.gz (19.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file freelancer_payment_protection_cli-0.1.2.tar.gz.

File metadata

File hashes

Hashes for freelancer_payment_protection_cli-0.1.2.tar.gz
Algorithm Hash digest
SHA256 fbefb7106715945469de132bb8a5e4b6e489800831056ad6c1ce74ed9df8d2cc
MD5 1e63945a9855349a3d2cb343c01cc7b8
BLAKE2b-256 4398eae60b386a3e59517f3b313a46de8b60d37b6fc0da94464668e65d5c2773

See more details on using hashes here.

File details

Details for the file freelancer_payment_protection_cli-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for freelancer_payment_protection_cli-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 660e1c65cdf4f0ddab6d93eb618643edce8bf783e6fa64e9df8e7da16d491df4
MD5 d21bcec4c11f8473e789f0eddeb4ec23
BLAKE2b-256 f3395b8e7041b3fa564899b1a5206832cba941d4898382ecd2240a4efd0f2cea

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page