Show HN: PushCI — Catch broken AI-generated code before production
The problem
We build OpenSyber, a security platform for AI agents. Our codebase has 31K TypeScript files, 103 database tables, and 263 API routes. About 60% of our PRs now contain AI-generated code from Cursor, Claude Code, or Copilot. And we keep finding the same failure modes.
The AI writes code that looks correct but is not. It imports modules that do not exist. It calls API methods that were removed two versions ago. It adds database columns without defaults and breaks every downstream service. It installs packages that were registered by attackers under typosquatted names. It generates Terraform with iam:* permissions because the docs example used them. These are not hypotheticals. We caught all of these in the last 3 months.
What PushCI does
PushCI is a GitHub Action that runs on every PR. It does three things:
Semantic validation — not syntax checking, semantic checking. PushCI resolves every import, function call, and type reference in the diff against the actual codebase. If the AI hallucinated a module or called a function that does not exist, PushCI flags it inline on the PR. It also checks schema changes against downstream consumers to catch breaking migrations.
Dependency safety — every new or changed dependency is checked against typosquat databases, known-vulnerability feeds, and package age heuristics. A package registered 3 days ago with an install script that reads .env is blocked before it reaches your lockfile.
Infrastructure drift — Terraform, Kubernetes, and Docker configs in the PR are compared against your declared baseline. PushCI catches overly permissive IAM, missing resource limits, public-facing services that should be internal, and images pinned to mutable tags.
How it works
Two lines in your GitHub Actions workflow:
- name: PushCI uses: opensyber/pushci@v1
That is the entire setup. PushCI runs on every PR, annotates findings inline, and exits with a pass, warn, or block status. Median check time is 340ms. Average false positive rate is 0.3 per repo per day.
What it catches that linters do not
- Imports of modules that were hallucinated — the package exists nowhere, but the AI wrote import { parse } from "csv-autoparse" with full confidence.
- Function calls to APIs that do not exist — the AI read old docs and generated client.billing.syncInvoices(), but that method was removed two versions ago.
- Schema changes that break downstream consumers — a migration adds a NOT NULL column without a default, and three services depend on inserts to that table.
- Packages that were typosquatted by the AI — it suggested expres instead of express, and npm has a malicious package registered under that name.
- Terraform resources with overly permissive IAM — the AI generated iam:* because the docs example used it, and your baseline policy does not allow that.
- Docker images pinned to :latest — the AI copied from a blog post and your base image now runs as root with no resource limits.
Honest limitations
- It does not catch logic bugs. If the AI writes a sorting algorithm that sorts in the wrong direction, PushCI will not flag it. That is what tests are for.
- It does not replace your test suite. PushCI catches structural failures — broken references, dangerous dependencies, drifted infrastructure. It is not a substitute for unit or integration tests.
- It does not do full program analysis. PushCI runs in 340ms because it does targeted semantic checks, not whole-program symbolic execution. It trades completeness for speed and low false positives.
Pricing
Free for open source. For private repos, free up to 100 checks per month, then $29/month for unlimited. We would rather every open source repo have this than optimize for revenue on day one.