mallcop.yaml is the primary, zero-flag config path. mallcop init
scaffolds it; mallcop config set connector / autonomy write into it
(strict-validated, atomic). Command-line flags and environment variables still work for anything
you'd rather not put in the file, and take precedence over it when both are set. This page covers
every knob.
mallcop init scaffolds mallcop.yaml — the one file mallcop
reads. Run mallcop scan with no flags and it discovers that file: connector,
store path, inference mode, detector config, learning autonomy, sovereignty, and budgets all
resolve from it. Flags on mallcop scan and a handful of environment variables
(inference endpoint + key, GitHub App auth) still work and take precedence over the file for
any value you set explicitly — the flag-only path from earlier mallcop versions hasn't
gone away, it's just no longer the primary one. mallcop config prints the effective
merged configuration a scan would pick up right now. Before mallcop init has run
(no mallcop.yaml discovered), it falls back to built-in defaults:
$ mallcop config mallcop effective config Config file: (none found — built-in defaults; run `mallcop init` to create mallcop.yaml) Version: 1 Inference mode: offline Inference URL (MALLCOP_INFERENCE_URL): (unset — scans force-escalate every finding, the fail-safe) Inference key (MALLCOP_API_KEY): (unset) Model (MALLCOP_MODEL): mallcop-default Store path: ./store Connectors: 1 configured - local-events kind=file Builtin detectors: enabled=true disabled=[] Sidecar detectors: dir=./detectors/bin Learning dir: detectors (autonomy=non, enforce_pin=false) Sovereignty: tier=open contribute_back=false Budgets: max_findings=25 scan_timeout=10m selfext_spend_cap_usd=25
After mallcop init, the same command reports Config file:
<dir>/mallcop.yaml instead — the rest of the output reflects whatever that
file (plus any environment overrides) resolves to. See
Quick Start § Initialize for the full
mallcop init transcript.
Here is the exact mallcop.yaml that mallcop init writes on a fresh
machine — every top-level key mallcop reads, at its default value. Nothing is hidden or
summarized: add a connector or flip the autonomy dial and only the value you touched changes.
# mallcop.yaml — the one file mallcop reads. Generated by `mallcop init`. # Run the scan with no flags: mallcop scan # Add a source by editing connectors: below. version: 1 inference: mode: offline endpoint: "" key_env: MALLCOP_API_KEY model: mallcop-default store: path: ./store baseline: "" connectors: - kind: file id: local-events path: ./events.jsonl org: "" source: "" args: [] since: "" env: [] binary: "" detectors: builtin: enabled: true disable: [] sidecars: dir: ./detectors/bin learning: dir: detectors autonomy: non enforce_pin: false sovereignty: tier: open contribute_back: false budgets: max_findings: 25 scan_timeout: 10m selfext_spend_cap_usd: 25
This exact file is checked byte-for-byte against the real mallcop init output in
CI (test/docdemo) — it cannot silently drift from what the binary actually
writes.
config set
mallcop config set connector and mallcop config set autonomy write
strict-validated changes directly into mallcop.yaml — atomic writes, no
inline secrets, no duplicate ids. These are the shared primitives any driver of a config change
(this CLI, a chat surface) calls; they're what makes the reconfiguration dial in
self-improvement a config-file operation rather than
hand-editing YAML.
$ mallcop config set connector --kind=github --id=my-org --org=my-org mallcop config set connector: added "my-org" (kind=github) to <dir>/mallcop.yaml — takes effect on the next `mallcop scan` $ mallcop config set autonomy semi mallcop config set autonomy: learning.autonomy=semi in <dir>/mallcop.yaml
config set connector rejects a duplicate id, an unknown --kind, or an
inline secret passed via --env. config set autonomy accepts exactly
non, semi, or fully — the self-extension autonomy
dial (see Self-Improvement).
mallcop's AI cascade runs against whatever inference endpoint your key points at. Bring your own key and mallcop costs you nothing — you pay only your model provider. Point it at Anthropic, OpenAI, Bedrock, any OpenAI-compatible endpoint, or the mallcop managed endpoint.
export MALLCOP_INFERENCE_URL=https://api.anthropic.com # or https://api.mallcop.app for managed export MALLCOP_API_KEY=sk-... # your vendor key, or a mallcop-sk-* key export MALLCOP_MODEL=mallcop-default # optional model override
The --base-url flag on mallcop scan overrides
$MALLCOP_INFERENCE_URL per run. With no inference URL set at all, mallcop still runs
and every finding force-escalates to you — the documented fail-safe, no key required.
The built-in GitHub connector reads org events through a GitHub App. Install the app on your org with read access to organization administration and audit events, then export its credentials:
export GITHUB_APP_ID=... export GITHUB_APP_PRIVATE_KEY=... # the app's private key (PEM) export GITHUB_INSTALLATION_ID=...
Two connectors are built in. Add one to mallcop.yaml with
mallcop config set connector (shown above) so a bare mallcop scan
picks it up, or pass it as a flag for a one-off run:
# file connector (default): read normalized events from a JSONL file or stdin mallcop scan --events events.jsonl --store ./store # github connector: pull org events via the GitHub App above mallcop scan --connector github --github-org my-org --store ./store
Cloud sources (AWS, Azure, GCP, M365, Okta) are separate binaries that emit JSONL
you feed into the file connector — see the
Connector Catalog for the two-step flow and the roadmap.
Every scan writes findings, resolutions, events, and directives to the git-native store you pass
with --store (required). It is a plain git repo — git log is your
audit trail. mallcop scan runs git init on the store directory the first
time if it isn't already a repo.
mallcop scan --connector github --github-org my-org --store ./store mallcop status --store ./store # counts by source and status
Detection is baseline-relative and learns from your activity automatically — no manual
configuration required. You can optionally widen coverage with a widen-only
tuning overlay passed via --tuning. The overlay can only make mallcop
more watchful; narrowing is inexpressible (see
Self-Improvement).
# detectors/tuning.yaml — widen-only extra_* knobs priv_escalation: extra_elevated_keywords: - poweruser mallcop scan --events events.jsonl --store ./store --tuning detectors/tuning.yaml
Your rulings on findings (mallcop feedback) are written back to the store as suppress
directives the next scan honors — there is no separate self-improvement config block to manage.
A volume circuit breaker protects you from runaway spend during a finding storm. Pass
--max-findings: a scan that produces more findings than the ceiling force-escalates a
single critical meta-finding to a human instead of running the AI cascade on every one.
mallcop scan --connector github --github-org my-org --store ./store --max-findings 25
Default ceiling is 25. Events are always collected and stored; only the AI investigation is short-circuited when the breaker trips.