Ship code that passes CI on the first try.
Project description
FirstTry
FirstTry makes sure your pull request is green on the first push.
It runs the same checks as your GitHub Actions CI, locally, in seconds — and tells you exactly which step would fail and how to fix it.
Pass CI on the first try.
FirstTry is a pre-commit quality gate that runs the same checks your CI does, locally, before you push. No more "fix lint" commits.
Security Gate: Blocks unsafe shell execution patterns and secret leaks before you ever push to GitHub. This is what your CI wishes it did locally.
FirstTry — Ship Green On The First Try ✅
Quick Start
- Install:
pip install -e .orpip install firsttry - Run the pre-commit gate locally:
firsttry run --gate pre-commit - Install hooks:
firsttry install-hooks
Pro vs Free
- Free: local gating (
firsttry gates) that prevents obviously broken commits and surfaces failing steps. - Pro:
firsttry mirror-ci --runexecutes your CI steps locally (safe sandbox, denies destructive commands) and requires a license key.
VS Code flow (one-click onboarding)
- Click the extension
Protect this repoaction. - Extension runs:
firsttry init,firsttry install-hooks,firsttry run --gate pre-commit. - Extension writes
.firsttry.jsonwith install metadata and coverage threshold and surfaces PASS/FAIL inline in the editor.
Quick Start
# Install
pip install firsttry
# Run checks before commit
firsttry run --gate pre-commit
# Install git hooks for automatic checking
firsttry install-hooks
# See what your CI will run
firsttry mirror-ci --root .
Trying FirstTry locally (no install)
You can run FirstTry directly from the repo using Python:
# Check version
python -m firsttry.cli --version
# See if your repo is clean to push (lint, typecheck, etc.)
python -m firsttry.cli gates --json --root .
# Simulate CI locally (requires a license key for --run)
python -m firsttry.cli mirror-ci --root . --run --json --license-key TEST-KEY-OK
python -m firsttry.cli uses the same engine and returns the same JSON you'd get from the packaged firsttry command.
This absolutely matters for onboarding. It means you don’t have to ship wheels or publish to PyPI before giving someone value. You can just DM them the repo and a license key.
And critically: that block makes it crystal clear that `mirror-ci` is gated behind a key. That’s how you start charging.
Fast start — one-command activation
If you want a single command to install hooks, run an initial autofix pass, and finish onboarding, use the
activate command we added to the CLI. This is the smoothest way to get FirstTry protecting a repo.
# Install
pip install firsttry
# One-command activation (installs hooks + runs autofix scan)
python -m firsttry.cli activate
What this does:
- Installs
pre-commitandpre-pushgit hooks for FirstTry. - Runs the
pre-commitgate once in non-interactive autofix mode (applies safe fixes). - Prints onboarding instructions and next steps.
If the initial scan finds issues that require manual attention, activate will still install hooks and
print guidance on how to review and finish onboarding.
FirstTry — ship green on the first push
FirstTry runs all your quality gates (lint, typecheck, formatting, etc.) and even simulates your GitHub Actions pipeline locally — safely — so you don't spam PRs with "fix lint lol" commits.
1. Repo Health (Free)
Check if your repo is clean before you push.
firsttry gates --json
or
python -m firsttry.cli gates --json
What this does:
Runs your "pre-commit" / "pre-push" style gates (ruff, mypy, tests, etc.).
Captures returncode, stdout, and stderr from each check.
Never crashes — even if a tool explodes, the result comes back as a structured failure entry.
Returns a single JSON report:
{
"ok": false,
"results": [
{
"gate": "pre-commit",
"ok": false,
> **Public Beta (v0.1.0-beta)**
> You can start using FirstTry right now:
>
> 1. **CLI setup & workflow** → [GET_STARTED.md](./GET_STARTED.md)
> 2. **VS Code extension install** → [INSTALL_VSCODE_EXTENSION.md](./INSTALL_VSCODE_EXTENSION.md)
> 3. **Download the extension (.vsix)** → Check the latest Release tagged `v0.1.0-beta`
>
> FirstTry = ship code that passes CI on the first try. No more "fix lint lol" commits.
````markdown
# FirstTry
**FirstTry makes sure your pull request is green on the first push.**
It runs the same checks as your GitHub Actions CI, locally, in seconds — and tells you exactly which step would fail and how to fix it.
**Pass CI on the first try.**
FirstTry is a pre-commit quality gate that runs the same checks your CI does, locally, before you push. No more "fix lint" commits.
<!-- ci-trigger: touch to run CI workflows -->
## Quick Start
```bash
# Install
pip install firsttry
# Run checks before commit
firsttry run --gate pre-commit
# Install git hooks for automatic checking
firsttry install-hooks
# See what your CI will run
firsttry mirror-ci --root .
```
"failed_at": {
"workflow": "ci.yml",
"job": "build",
"step": "Run tests",
"cmd": "pytest -q",
"stderr": "E AssertionError: 1 != 0\n",
"duration_s": 3.24
}
}
}
Want early access to Pro? Reach out to our team to request an early access key — we'll enable --run for your account.
Option B: via flag
firsttry mirror-ci --root . --run --json --license-key YOUR-LICENSE-KEY
What this does:
Reads .github/workflows/*.yml
Builds your CI plan (jobs, steps, run commands)
Executes allowed steps locally in order
Blocks obviously dangerous commands with a safety denylist
e.g. rm -rf /, fork bombs, shutdown
Captures stdout / stderr / return codes per step
Returns a structured JSON summary so you know exactly what will fail in PR
If no valid license key is provided:
You still get the dry-run plan (visibility)
But Pro execution (--run) is restricted
This is perfect for:
Senior engineers who are sick of red PRs
Juniors who don't want to look bad on review
Teams that want “CI green on first try”
- Safety
We will not run destructive commands. Known-dangerous patterns (like rm -rf /) are denied up front. Blocked steps are reported as:
{ "job": "build", "step": "cleanup", "cmd": "rm -rf /", "status": "blocked", "reason": "blocked_for_safety", "returncode": null, "stdout": "", "stderr": "Command blocked by safety policy" }
So you get transparency without wrecking your machine.
- Quality Gates on FirstTry itself
Before we ship anything, we run one command:
AUTOFIX=1 bash local_ci.sh
That enforces:
Ruff + Black formatting
Mypy (0 errors, repo-wide)
Pytest (currently 70+ tests)
Coverage (75%+ across core modules like gates, mirror-ci, licensing, safety)
Node-side checks for supporting extensions / dashboard code
JSON contract tests for both gates and mirror-ci CLI commands
If any of that fails, we don't ship.
This isn’t a toy script. This is production posture.
That block:
- Teaches what you do in under 2 minutes.
- Shows off that you're serious (mypy, coverage, safety).
- Draws a clean pricing line between Free and Pro without using the ugly word "paywall".
- Gives you screenshots you can post.
Add that to README.md and commit it. That is step one toward onboarding pilot teams.
2. Tiny UX/sales tweaks you should do next
These are easy wins that make demos way more convincing:
(a) Human output mode for firsttry gates
Right now --json prints JSON, which is perfect for your VS Code / Codespaces panel and tests.
For humans (no --json flag), you're already printing a readable summary like:
FirstTry Gates Report
---------------------
[pre-commit] ok=False status=fail returncode=1
[pre-push] ok=True status=pass returncode=0
OVERALL OK: False
Keep that. That’s a screenshot candidate. That goes in README too, as a second example.
(b) Add “Suggested next step”
At the end of that human-readable print in cmd_gates, append something like:
if not all_ok:
print("\nTip: Run firsttry gates --json to see exact stdout/stderr for each failed gate.")
else:
print("\n✓ Repo is clean. You’re safe to push.")
That one line does two things:
It teaches people how to self-diagnose without DMing you.
It markets your JSON format (which is your dashboard API) right inside the CLI.
(c) Screenshot those two commands for marketing:
firsttry gates (failing repo)
firsttry mirror-ci --run --json (with one failing step and one blocked dangerous step)
The second one especially is money because you can say:
“We blocked a destructive command from your CI and still told you what else passed. Your laptop is safe.”
That’s how you close teams.
Roadmap
- Security baseline noise reducer (group known test/tool files instead of flooding output)
Screenshots / GIFs
Saved example placeholders (replace with real images):
docs/screenshots/gates_failure.png— screenshot offirsttry gateswith one gate failingdocs/screenshots/mirror_ci_failed_at.gif— GIF showingfirsttry mirror-ci --run --jsonhighlightingfailed_at
Visual demos
We're capturing real CI runs and hook failures and will publish anonymized screenshots and GIFs here after a short private beta. For now, the forensic failed_at JSON block above is the canonical proof of value.
Workflow timing (why devs actually use it)
FirstTry runs in three layers so you don't get slowed down:
pre-commitgate (auto-installed git hook)
- ~1-3 seconds
- Lint, imports, basic safety checks
- Blocks dumb mistakes from even entering your history
pre-pushgate
- ~5-10 seconds (depends on repo)
- Type-check, smoke tests, DB drift sanity
- Blocks "oops broke tests" from hitting origin
firsttry mirror-ci --run(Pro)
- Runs the actual steps from your GitHub Actions locally
- Stops at the first failing step
- Gives you a forensic
failed_atblock with job, step, stderr, and a suggested quick-fix when available - Use this before opening a PR so your PR goes green on first try
This three-tier story sells both speed and workflow: quick developer feedback at commit time, broader checks on push, and a full confidence check before your PR.
Local dev requirements
To run pytest -q and to run the Pro CI mirror locally:
- Python 3.11+
pip install -e .from repo rootruff,mypy,pytestinstalled in your venv (our tests assume they're available)- For Pro mode (
firsttry mirror-ci --run):- set
FIRSTTRY_LICENSE_KEY=TEST-KEY-OKfor local testing - some steps in your GitHub Actions may assume tools you haven't installed locally yet (example:
ruff check .). FirstTry will report that failure and stop instantly on that step.
- set
Why this matters: we're honest about local assumptions. If a CI step requires a tool you don't have, FirstTry will tell you quickly so you can install it and re-run.
30-second smoke test
- Create and activate a venv and install:
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
- Quick health report:
firsttry doctor --json
- Preview your CI plan:
firsttry mirror-ci --root .
- (Pro preview) simulate running those steps locally:
FIRSTTRY_LICENSE_KEY=TEST-KEY-OK firsttry mirror-ci --root . --run
If step 4 stops with a JSON block that includes "failed_at", that's exactly what would have broken your PR.
Features
🚀 Pre-Commit/Pre-Push Gates
Run quality checks before commits hit CI:
**Output:**
Lint.......... PASS ruff
FirstTry security gate & baseline
FirstTry includes a local CI gate you can run with python -m firsttry.cli run --gate pre-push.
It executes linting, type checks, security scans (bandit), and tests with coverage. Findings are grouped into
two buckets: (1) unreviewed high-risk security files which will block a push, and (2) baselined files
that are known noisy/test/tool paths and are shown for information only. Use python -m firsttry.cli baseline add <glob>
to add a path or glob to the baseline and immediately re-run the full gate to see its effect.
Format........ PASS black-check
Types......... PASS mypy
Tests......... PASS pytest
Coverage XML.. PASS coverage_xml
Coverage Gate. PASS coverage_gate
Verdict: SAFE TO COMMIT ✅
Everything looks good. You'll almost certainly pass CI on the first try.
### 🔍 Mirror CI Locally
See exactly what your GitHub Actions workflows will run:
```bash
firsttry mirror-ci --root .
Example Output:
Workflow: ci.yml
Job: qa
Step: Lint
Run:
ruff check .
Step: Test
Run:
pytest -q
Step: Type Check
Run:
mypy .
This is your CI plan as a dry-run checklist.
⚙️ Environment Variables
FIRSTTRY_USE_REAL_RUNNERS
Toggle between stub runners (fast, no dependencies) and real analysis tools:
# Use lightweight stubs (default)
firsttry run --gate pre-commit
# Use real ruff, black, mypy, pytest
FIRSTTRY_USE_REAL_RUNNERS=1 firsttry run --gate pre-commit
Why this matters:
- Stubs: Fast feedback loop during development
- Real runners: Serious analysis before pushing
- One env var to flip between "quick sanity" and "CI-grade checks"
Perfect for CI pipelines, pre-push hooks, or when you want confidence.
Installation
pip install firsttry
Or from source:
git clone https://github.com/arnab19111987-ops/Firstry.git
cd Firstry
pip install -e .
Commands
firsttry run
Run a quality gate (pre-commit or pre-push).
firsttry run --gate pre-commit
firsttry run --gate pre-push
firsttry run --gate pre-commit --require-license
When something fails, FirstTry explains exactly what broke and how to fix it.
Example:
--- Format (black) FAILED ---
Fix:
Run: black .
--- Lint (ruff) FAILED ---
Fix:
Run: ruff --fix .
Options:
--gate: Which gate to run (pre-commit|pre-push)--require-license: Fail if license check fails
firsttry install-hooks
Install git hooks that automatically run FirstTry before commits/pushes.
firsttry install-hooks
Creates:
.git/hooks/pre-commit- Runspre-commitgate.git/hooks/pre-push- Runspre-pushgate
firsttry mirror-ci
Show what CI workflows will run, locally.
firsttry mirror-ci --root .
Options:
--root: Project root containing.github/workflows(default:.)
Runners API (Semi-Stable)
FirstTry's runner interface is semi-stable. You can build alternate runner packs by implementing:
from types import SimpleNamespace
def run_ruff(args) -> SimpleNamespace:
"""Run ruff linter."""
return SimpleNamespace(
ok=True, # bool: did the check pass?
name="ruff", # str: runner name
duration_s=0.5, # float: how long it took
stdout="", # str: command stdout
stderr="", # str: command stderr
cmd=("ruff", ...") # tuple: command that ran
)
def run_black_check(args) -> SimpleNamespace:
"""Run black formatter check."""
# Same signature as above
def run_mypy(args) -> SimpleNamespace:
"""Run mypy type checker."""
# Same signature as above
Why you'd want this:
- Ship alternate tool sets (ruff → pylint, black → yapf)
- Add company-specific checks
- Integrate proprietary analysis tools
Place your runners in tools/firsttry/firsttry/runners.py and set FIRSTTRY_USE_REAL_RUNNERS=1.
Development
# Run tests
pytest -q
# Run with real runners
FIRSTTRY_USE_REAL_RUNNERS=1 pytest -q
# Install in editable mode
pip install -e .
License
MIT
Tags & Branches
firsttry-core-v0.1: First stable release, 42/42 tests passing, hardened runner loaderfeat/firsttry-stable-core: Development branch for stable core features
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file arnab_firsttry-0.1.0-py3-none-any.whl.
File metadata
- Download URL: arnab_firsttry-0.1.0-py3-none-any.whl
- Upload date:
- Size: 78.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3803aab923a2bfd50c1aef022dcb7f632cfcf2b185475ebebf4a454e2318cf29
|
|
| MD5 |
b637e1d9daaef8948ea652588ae3fa82
|
|
| BLAKE2b-256 |
13cef910665c43d44dad8a11499bfa746ae5b3ae39a00bacff2324edc2f1e952
|