Thanks for considering a contribution to agentgg.
agentgg/
└── packages/
├── core/ Types, Zod schemas (FileRecord, Agent, ScopeConfig)
├── cli/ Commander-based CLI: init, scan, agents, config, view
└── viewer/ Next.js viewer bundled into the CLI dist
Requires Node.js 20+ and pnpm 9+.
git clone https://github.com/agentgg-dev/agentgg.git
cd agentgg
pnpm installThat's the entire setup. No build step is required — the dev runner uses
tsx against TypeScript source.
pnpm agentgg <command> # e.g. pnpm agentgg scan ./some-repopnpm agentgg is wired up in package.json as
tsx packages/cli/src/cli.ts. Edit source, re-run — no rebuild step.
This is the loop most contributors will live in.
The viewer is a Next.js app in packages/viewer/. When you run
pnpm agentgg view <results-dir> from a source checkout, the CLI
spawns the viewer in two modes depending on what's on disk:
- Source dev mode (the default in a fresh clone): runs
next devagainstpackages/viewer/. First page load takes a few seconds (Next compiles on demand), but viewer source edits hot-reload. - Source prod mode: runs
next startifpackages/viewer/.next/has a build (e.g. you ranpnpm --filter @agentgg/viewer build).
So the everyday viewer workflow is:
pnpm agentgg view ./scan-results # boots `next dev`, hot-reloads on editsForce dev mode regardless of whether a build exists:
pnpm agentgg view ./scan-results --devCtrl+C stops the viewer. The default port is 3737, walking forward
to the next free one if taken.
pnpm lint # biome check
pnpm lint:fix # auto-fix what biome can
pnpm test # vitest across all packages
pnpm build # tsc --build across the workspace (type-check + emit per-file dist)pnpm build is required for pnpm test to pass — vitest imports
@agentgg/core through the package's main: ./dist/index.js entry,
so the core's dist must exist. CI runs the same lint → build → test
sequence on PRs.
pnpm test is fully mocked and hermetic. A separate opt-in suite,
packages/cli/__tests__/real-llm.smoke.ts,
makes actual model calls against every provider to catch flag → provider
wiring regressions a mock can't — a flag that silently stops reaching one
backend, or a provider that rejects a request shape the others accept.
pnpm build # core dist must exist, same as pnpm test
pnpm test:smoke # runs vitest against vitest.smoke.config.tsIt never runs automatically:
pnpm testglobs*.test.ts; the smoke file is*.smoke.ts, matched only byvitest.smoke.config.ts— so CI and the normal test run can't pick it up.- Each provider block is credential-gated: it runs only the providers you
have configured, resolved from your saved
agentgg initconfig (~/.agentgg/config.json) or env vars (ANTHROPIC_API_KEY,OPENAI_API_KEY,AGENTGG_SMOKE_OLLAMA_URL,AGENTGG_SMOKE_BEDROCK=1+AWS_REGION,AGENTGG_SMOKE_VERTEX=1+GOOGLE_CLOUD_PROJECT). With nothing configured it's a safe no-op: only an always-on meta test runs and prints which providers are live.
What it does: one small agent over a two-file fixture (a blatant SQL injection
plus a benign file) on the cheapest model per provider, asserting each flag's
observable effect (--exclude, --max-files-per-agent, --max-batches,
--diff, --validate, --score, --effort/--thinking). The structural flag
assertions are deterministic; detection/validate/score depend on the model
actually finding the vuln, so use a capable model — small local Ollama models
(e.g. 7B) can miss it. Override the per-provider model with
AGENTGG_SMOKE_<PROVIDER>_MODEL (e.g.
AGENTGG_SMOKE_OLLAMA_MODEL=qwen2.5-coder:14b).
Filter to one provider or case with vitest's -t (a regex — the describe > test
join is not a literal " > ", so bridge it with .*):
pnpm test:smoke -t "bedrock" # every Bedrock case
pnpm test:smoke -t "openai.*detects" # one caseIf you'd rather type agentgg ... than pnpm agentgg ..., link the
package globally:
pnpm --filter agentgg build # build the bundled dist/cli.js first
pnpm --filter agentgg link --global
agentgg --version # resolves to packages/cli/dist/cli.jsRe-run pnpm --filter agentgg build after every source change. To undo:
pnpm --filter agentgg unlink --global.
You normally don't need this — CI builds the tarball on tag push. But if you're debugging the publish flow, this is the exact pipeline:
pnpm --filter agentgg build:bundle # esbuild + Next.js standalone
cd packages/cli
npm pack # produces agentgg-X.Y.Z.tgz
npm install -g ./agentgg-X.Y.Z.tgz # simulates `npm install -g agentgg`build:bundle runs scripts/bundle-cli.mjs (inlines @agentgg/core
via esbuild) then scripts/bundle-viewer.mjs (Next.js standalone build
copied into dist/viewer/). The prepack hook on the agentgg package
fires the same command automatically during npm pack / npm publish.
Biome handles lint + format. Run pnpm lint:fix
before opening a PR.
TypeScript strict mode is on. Prefer Zod schemas as the source of truth for any shape that crosses a boundary (config files, agent frontmatter) and infer the TS type from the schema.
Agents live in a separate repo: agentgg-dev/agentgg-agents.
That repo is the source of ~/.agentgg/agentgg-agents/ (synced on
first scan and via agentgg agents update). Submit new agents there,
not here.
- Bugs: open a GitHub issue with a minimal repro.
- Feature requests: open a discussion first.
- Security: do not open a public issue. See
SECURITY.mdfor the disclosure process.
Contributions are accepted under the project's license (see LICENSE
and the License section in README.md). By submitting a pull request
you certify that you have the right to license your contribution to
the project.