Safe Project Initialization¶
agentguard init [PATH] prepares an existing repository for AgentGuard without
running repository code, installing dependencies, or changing Git state. It is
included in the production agentguard-evals==0.3.0 package:
Start With A Dry Run¶
From the repository to initialize:
Or provide the repository path from its parent directory:
The plan reports the resolved project root, detected project type, files that would be created or replaced, files already current, conflicts, the next local command, and the next CI step. Dry-run planning does not change project files.
After reviewing the plan, initialize the project:
Command Interface¶
agentguard init [PATH] [--dry-run] [--force]
[--ci github | --no-ci]
[--preset minimal|recommended|strict]
[--test-command TEXT]
PATH defaults to the current directory. CI generation is opt-in; use
--ci github to create the maintained workflow or --no-ci to state that no
workflow should be generated. --test-command takes precedence over detected
commands. --preset defaults to recommended; omitting it preserves the
Phase 44A generated configuration. See CI policy presets
for the exact effective settings and tradeoffs.
Generated Files¶
| Path | Purpose |
|---|---|
agentguard.yaml |
Tracked strict-schema CI configuration using the selected policy preset. |
.gitignore |
Preserves existing content and adds one .agentguard/ runtime-artifact entry when missing. |
.github/workflows/agentguard.yml |
Optional pull-request gate generated by --ci github. |
The tracked configuration is deliberately not placed under .agentguard/.
That directory is reserved for generated reports, manifests, history, and
other runtime artifacts.
A separate benchmark or suite is not needed for the first project check. CI mode evaluates the existing repository and its current Git diff:
Python, Node.js, And Go Detection¶
Phase 44A recognizes common Python signals such as pyproject.toml,
setup.py, setup.cfg, pytest configuration, conftest.py, and requirements
files. It reads these as text only and never imports them or executes setup,
hooks, package managers, test commands, or repository code during
initialization.
When maintained pytest configuration is present, the initializer selects:
For this conservatively detected case, the optional GitHub workflow also adds
an explicit Python test-environment step. It always installs pytest rather
than relying on runner-preinstalled packages. Safe root-level conventional
requirements files (requirements.txt, requirements-test.txt, and
requirements-dev.txt) are installed with pip --requirement, without
installing the repository itself. A [project] table in pyproject.toml, a
packaging [metadata] or [options] table in setup.cfg, or a regular
root-level setup.py conservatively identifies an installable root project;
the workflow then installs that checkout in editable mode so its declared
runtime dependencies and source tree are available to its tests. A bare
[build-system] table or pytest-only setup.cfg does not imply that the root
is installable. These operations run later in GitHub Actions, not during
initialization.
This is intentionally a small setup model, not universal Python environment
inference. Unrecognized requirements*.txt names and symlinked, unreadable, or
oversized dependency metadata require explicit customization instead of
emitting a guessed installation step. Pytest-only roots without packaging or
requirements metadata receive only the explicit pytest installation. An
explicit --test-command takes precedence and suppresses all inferred project
setup; add the reviewed setup required by that command to the workflow.
An explicit command is preserved as a single YAML string:
AgentGuard later splits this value into an argument vector; it does not pass it through a shell. Quotes and shell metacharacters therefore do not become shell fragments. Review any explicit command before running the gate.
Node.js detection is deliberately narrower. The initializer reads only safe,
root-level regular files. It parses at most 1 MiB of package.json as strict
UTF-8 JSON, rejects duplicate keys and non-standard constants, and requires a
top-level JSON object. Lockfiles are treated only as untrusted presence signals;
their contents are never parsed or executed.
The only automatically selected Node.js command is the fixed native runner:
AgentGuard selects that fixed value only when all of these conditions hold:
package.jsonhas an exact string value ofnode --testatscripts.test;- no
workspacesfield is present; - at most one of
package-lock.json,npm-shrinkwrap.json,yarn.lock,pnpm-lock.yaml,bun.lock,bun.lockbis present; and - when
packageManageris present, it namesnpm,yarn,pnpm, orbunwith a non-whitespace version/reference and agrees with the detected lockfile.
The script is used only as a conservative signal. Its contents are not copied
into configuration, and initialization never invokes npm test, another
package script, a lifecycle hook, a package manager, Node.js, a local binary,
or repository code. Commands such as jest, vitest, npm test, yarn test,
and values containing arguments or shell operators require an explicit
--test-command; AgentGuard does not try to quote or rewrite them.
The following cases also require customization: mixed Python/Node.js roots,
workspaces and monorepos, conflicting lockfiles, a packageManager mismatch,
lockfile-only projects, and missing, unreadable, malformed, oversized,
duplicate-key, non-object, or symlinked package.json metadata. Root-level
signals are intentional; recursive package discovery could guess the wrong
workspace. Symlinked detection inputs are ignored rather than followed.
An explicit --test-command still takes precedence for every recognized or
ambiguous project. It is stored as one value and later split without a shell.
That protects argument boundaries, but it does not make the selected executable
or repository tests trusted.
Go detection is similarly conservative and reads only safe root-level regular
files. go.mod, go.work, and go.sum are presence signals; their contents
are untrusted. AgentGuard reads at most 1 MiB of go.mod as strict UTF-8 and
requires exactly one supported simple, unquoted module directive. Missing,
duplicate, or malformed module directives fail closed. AgentGuard deliberately
does not parse or validate go, toolchain, require, replace, exclude,
retract, or other remaining content; it treats those lines as opaque untrusted
data and never copies them into generated files. It never invokes go, parses
command output, follows symlinked metadata, or reads go.sum contents during
initialization.
For an otherwise unambiguous root module with no go.work, the initializer
selects the fixed command:
The module path is only a conservative signal and is never copied into a
command. Workspaces, mixed Python/Node.js/Go roots, go.sum without a supported
go.mod, and missing, malformed, or unsupported module directives require
customization, as do unreadable, oversized, NUL-containing, non-UTF-8, or
symlinked metadata. Other go.mod content can still be invalid because the
initializer does not implement Go's module-file parser. An explicit
--test-command still takes precedence in these cases. The Go toolchain
validates the complete module file only during later user-authorized execution.
Initialization itself never runs go test, go list, go env, go generate,
other Go tooling, repository code, module downloads, scripts, or project
binaries. The generated test command is intended for a later, reviewed
AgentGuard run. During that later execution, go test ./... executes repository
test code and the Go toolchain may download modules named by repository
metadata. Review the module and test sources and configure dependency policy or
an appropriate execution boundary before running it. AgentGuard CI performs
post-execution validation; it does not contain hostile code.
The isolated test environment assigns Go build and module caches beneath the
ignored .agentguard/cache/ directory, disables the per-user Go environment
file, and disables automatic toolchain switching. This avoids dependence on a
user home directory and prevents host Go cache state from being inherited. It
does not prevent the selected Go runtime from downloading modules during the
later test execution.
If no safe command can be inferred, the generated configuration contains a
deterministic placeholder that prints an edit instruction and exits nonzero.
Replace test_command before treating the configuration as a working CI gate.
AgentGuard does not guess a command for unknown ecosystems.
Select A Validation Preset¶
The initializer supports three post-execution CI validation postures:
minimalkeeps every check but uses wider limits for trusted local work.recommendedis the balanced default and preserves Phase 44A behavior.stricttightens limits, makes scope and diff findings blocking, and enables supported built-in secret-content detectors.
Inspect definitions before initializing:
These presets do not contain coding-agent or test-command execution. They omit
Docker, command-policy, and filesystem-watcher settings because the current CI
path does not enforce those controls. No untrusted-agent preset is exposed;
contained execution is tracked separately in
issue #157.
Overwrite And Idempotency Model¶
The initializer computes and validates the complete plan before writing:
- Missing known targets are created atomically where practical.
- Byte-identical targets are reported as already current and left untouched.
- A non-identical target is a conflict, produces a nonzero exit status, and prevents all planned writes.
--forcereplaces only the three known targets listed above. It never deletes directories, recursively replaces content, or changes unrelated files.- Existing
.gitignorecontent is retained and.agentguard/is not duplicated. - Symlink targets and parent directories that escape the selected root are
rejected, including with
--force. - Selecting a different preset changes
agentguard.yaml, so it conflicts by default and requires an intentional--forcereplacement. An identical workflow and.gitignoreremain current.
The command never stages, commits, pushes, installs, or executes the generated configuration. Inspect the diff yourself:
GitHub Actions Security¶
The optional workflow:
- runs for
pull_request, notpull_request_target; - grants only
contents: read; - installs
agentguard-evals==0.3.0for a reproducible gate; - for a safely auto-detected pytest root, installs allowlisted requirements, installs an identified project editably when applicable, and explicitly installs pytest;
- pins
actions/checkoutv5.0.1 andactions/setup-pythonv6.2.0 to maintained immutable full commit SHAs; - for a detected Node.js root, pins
actions/setup-nodev6.5.0 to its immutable full commit SHA and selects supported Node.js 24; - for a detected Go root, pins
actions/setup-gov7.0.0 to its immutable full commit SHA, selects supported Go 1.26, and disables setup caching so setup does not inspect or restore module dependencies; - passes the pull request base SHA through a quoted environment variable;
- uses no secrets, OIDC, long-lived credentials, or repository write access;
- runs the real
agentguard ci --config agentguard.yamlcommand and preserves its failing exit status.
Review the workflow, commit it on your branch, and open a pull request to run
the first CI evaluation. The exact agentguard-evals==0.3.0 pin is available
from production PyPI.
The generated workflow does not install Node.js dependencies. Dependency-free
native tests can run immediately. If the selected test command needs installed
packages, add a reviewed installation step yourself. Package-manager installs
may download dependencies and execute lifecycle hooks on the GitHub runner;
that later execution is outside agentguard init, and AgentGuard CI remains
post-execution validation rather than hostile-code containment.
Python dependency installation is likewise later, user-authorized CI
execution. Requirement processing and editable installation can download
packages and execute package build backends or setup hooks from the checked-out
repository. agentguard init only inspects bounded root-level regular-file
metadata and writes the workflow; it never invokes pip, imports the project, or
executes those hooks. Review dependency and build metadata before enabling the
generated workflow. Projects needing constraints, lock tooling, non-editable
installation, extras, multiple environments, or another setup sequence should
replace the generated step explicitly.
For Go projects, setup prepares the supported runtime with dependency caching
disabled; the generated workflow has no module installation or metadata-probe
step. The later AgentGuard test step runs the configured go test ./...; that
command can download modules and execute repository test code. Review go.mod,
replacements, dependencies, and tests before enabling the gate.
Customize Or Remove¶
Edit agentguard.yaml to match the repository's source paths, test paths,
expected diff size, and test command. Strict validation rejects unknown fields
instead of silently weakening policy. See GitHub Actions
for CI behavior, CI policy presets for preset details, and
Architecture for the trust model.
To remove initialization manually, delete agentguard.yaml, optionally delete
.github/workflows/agentguard.yml, and remove the .agentguard/ line from
.gitignore if no other AgentGuard workflows use it. The initializer never
performs removal.