blob: b12092b419263dc425f3349ff7a97b50c23df34e [file] [view]
# AI Coding Agent Tooling (`fx agents`)
## Overview
`fx agents` is a Fuchsia developer tool that manages tool configurations, permissions, and
local state for AI coding assistants (such as Gemini CLI, Claude, and IDE plugins) operating
within the Fuchsia source tree.
Its primary command is `fx agents setup`, which handles:
- **Permission Profiles**: Presets for different workflows (e.g. read-only inspection vs.
local editing).
- **Command Expansion**: Translates command names into regex patterns that match flags and
environment variables.
- **Atomic Updates & Backups**: Writes configuration atomically and creates a backup before
making changes.
- **State Tracking**: Tracks managed rules in `~/.local/share/Fuchsia/agents/setup/state.json`
(respecting `$XDG_STATE_HOME` / `$XDG_DATA_HOME`) so custom rules you manually add aren't lost
when switching profiles.
- **Status & Rollback**: Inspect active rules (`--status`), roll back previous changes
(`--rollback [N]`), or reset to a clean baseline (`--reset`).
- **Daemon Restarts**: Automatically restarts background daemons across `//` and `//vendor/*`.
- **Git Hooks**: Installs and manages modular `.git/hooks/<hook_name>.d/` hooks across all
checkout repositories (`//`, `//vendor/*`) to format staged code and check commit message
formatting.
---
## Quickstart
### Apply Default Permission Profile
Run `fx agents setup` to configure the default `local-changes` profile:
```bash
fx agents setup
```
### Apply a Specific Profile
```bash
fx agents setup --profile read-only
```
### Dry Run Mode
Preview calculated grant modifications, Git hook actions, and daemon restarts without touching
`config.json` or installing hooks:
```bash
fx agents setup --profile full-access --dry-run
```
---
## Permission Profiles
`fx agents setup` provides four tiered permission profiles:
| Profile | Purpose | Allowed (`allow`) | Denied (`deny`) | Prompt on Exec (`ask`) |
| ------------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ----------------- | ---------------------------------------------------------------------------------------- |
| **`read-only`** | Safe workspace inspection and build/test verification. | `read_only.txt` | `never_allow.txt` | `external_changes.txt`, `device_ops.txt`, `cache_destruction.txt`, `batch_execution.txt` |
| **`local-changes`** *(Default)* | Workspace editing, formatting, local commits, emulators, and device management. | `read_only.txt`, `local_changes.txt`, `device_ops.txt` | `never_allow.txt` | `batch_execution.txt`, `external_changes.txt`, `cache_destruction.txt` |
| **`external-changes`** | Local changes plus upstream code reviews, pushes, and remote infra. | `read_only.txt`, `local_changes.txt`, `external_changes.txt`, `device_ops.txt` | `never_allow.txt` | `batch_execution.txt`, `cache_destruction.txt` |
| **`full-access`** | Unrestricted developer operations across all local, external, device, and cache tools. | `read_only.txt`, `local_changes.txt`, `external_changes.txt`, `device_ops.txt`, `cache_destruction.txt`, `batch_execution.txt` | `never_allow.txt` | *(none)* |
### Permission Rule Files
Rules are stored in plain text files under `.agents/config/permissions/`:
- **`read_only.txt`**: Safe inspection (`git status`, `git diff`, `fx build`, `fx test`, `cat`,
`grep`, `rg`, `fd`).
- **`local_changes.txt`**: In-tree editing and local VCS (`git add`, `git commit`, `git checkout`,
`git branch`, `git stash`, `git rebase`, `fx format-code`).
- **`external_changes.txt`**: Upstream publishing and review (`git push`, `jiri upload`,
`fx gh pr ...`).
- **`device_ops.txt`**: Target device controls (`ffx target ...`, `fx ota`, `fx reboot`).
- **`cache_destruction.txt`**: Build directory cleans and cache wipes (`fx clean`,
`fx clean-build`).
- **`batch_execution.txt`**: Batch traversal and pipeline tools (`find`, `xargs`).
- **`never_allow.txt`**: Prohibited dangerous commands (`git reset --hard`, `git clean -fdx`,
`rm -rf /`).
---
## Safety Guarantees
1. **`never_allow.txt` Enforcement**: Dangerous commands (like `rm -rf /` or `git reset --hard`)
are denied across every profile.
2. **Force-Push Detection**: Detects force-push flags (`--force`, `-f`, `+<ref>`) anywhere in `git
push` arguments, preventing accidental remote history overwrites.
3. **Preserves Custom Rules**: Custom rules you manually added to `config.json` outside of
`fx agents` are preserved when switching profiles.
4. **Atomic JSON Writes**: Modifications are written to `.config.json.tmp` and renamed into place
atomically to prevent corrupted files if interrupted.
5. **Pre-Modification Backups**: Every write creates a timestamped backup in
`~/.local/share/Fuchsia/agents/setup/backups/` before modifying existing configuration.
6. **Safe Staged Formatting**: The `pre-commit` hook isolates staged changes before formatting so
unstaged edits are never modified or accidentally committed.
---
## Git Hooks Integration
`fx agents setup` automatically manages Git hooks across all checkout repositories discovered in the
Fuchsia source tree (including `//` and `//vendor/*`).
Hooks are installed into `.git/hooks/<hook_name>.d/10-fuchsia-agent.sh`, integrating cleanly with
the Jiri universal hook dispatcher without overwriting custom developer or team hooks.
### What the Hooks Do
- **`pre-commit` (Safe Formatting & Staging Isolation)**:
- **Fully Staged Files**: Automatically formatted using `fx format-code` and re-staged
(`git add`).
- **Partially Staged Files**: Checked in read-only mode under stash isolation. If formatting
issues exist, the commit is blocked with instructions on how to fix them so unstaged edits
aren't overwritten.
- **Fast Path**: Skips invoking `fx format-code` entirely if no formattable files are staged.
- **`commit-msg` (Commit Message Standards)**:
- Validates subject line length ($\le 50$ chars recommended, $> 65$ warned), 72-character body
wrapping, and mandatory footers (`Bug:`, `Test:`, `Change-Id:`) via
`scripts/shac/commit_msg_checker.py`.
### Human vs. AI Agent Commit Behavior
The hooks check whether a commit is run by a human or an AI agent (via environment variables):
| Commit Invocation | Commit Message Style | Formatting Behavior |
| ---------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------ |
| **Human Developer** (Interactive) | **Advisory Warnings**: Non-blocking warnings for style/length; commits succeed. | Fully staged files auto-formatted and re-staged. |
| **AI Coding Agent** (`GEMINI_CLI`, etc.) | **Strict Rejection**: Non-compliant commit messages fail (`--strict`). | Auto-formatting strictly enforced. |
### Opt-Outs & Bypasses
1. **Skip Hooks During Setup**:
```bash
# Configure permissions without installing Git hooks:
fx agents setup --no-git-hooks
# Reset permissions while leaving Git hooks installed:
fx agents setup --reset --no-git-hooks
```
2. **Per-Commit Bypass**:
```bash
# Standard Git flag (skips pre-commit and commit-msg natively):
git commit -n
# or
git commit --no-verify
```
3. **Environment Variable Bypass (Scripts / CI)**:
```bash
FUCHSIA_SKIP_HOOKS=1 git commit ...
```
---
## Status, Rollback, and Reset
### Status Inspection (`--status`)
Inspect active configuration, rule counts, Git hook status, and history:
```bash
fx agents setup --status
```
Example output:
```text
=== AI Coding Agent Configuration Status ===
Active Profile : local-changes
Last Updated : 2026-08-26 21:00:00
Fuchsia Root : /usr/local/google/home/username/fuchsia
Config File : /home/username/.gemini/config/config.json [exists]
State File : /home/username/.local/share/Fuchsia/agents/setup/state.json [exists]
Rule Breakdown:
[ALLOW] : 58 total ( 55 managed, 3 custom)
[DENY ] : 8 total ( 8 managed, 0 custom)
[ASK ] : 12 total ( 12 managed, 0 custom)
Recent History (2 transactions):
1. [2026-08-26 21:00:00] Profile: local-changes | Backup: config.20260826_210000.bak
2. [2026-08-26 20:30:00] Profile: read-only | Backup: config.20260826_203000.bak
Git hooks: Configured across 12/12 repositories.
```
### Multi-Step Rollback (`--rollback [N]`)
Revert `config.json` to the state prior to N setup operations:
```bash
# Roll back to previous configuration (N=1)
fx agents setup --rollback
# Roll back 3 setups prior
fx agents setup --rollback 3
```
### Reset Configuration (`--reset`)
Remove all permissions configured by `fx agents setup`, reverting to a clean baseline while
preserving any custom developer-authored rules in `config.json`:
```bash
fx agents setup --reset
```
> **Note:** Unlike `--rollback` (which steps backward through previous profile changes using backup
> snapshots), `--reset` removes all Fuchsia-managed grants and clears the local state file
> (`state.json`) without modifying custom permissions or non-permission IDE settings you manually
> configured. To reset permissions while preserving Git hooks, pass `--no-git-hooks`
> (`fx agents setup --reset --no-git-hooks`).
---
## Ad-Hoc Grants and Custom Lists
You can customize any profile by passing ad-hoc commands (`--allow`, `--deny`, `--ask`) or custom
list files (`--allow-list`, `--deny-list`, `--ask-list`):
```bash
fx agents setup \
--profile local-changes \
--allow "fx test //custom:target" \
--deny "git push upstream main" \
--deny-list ~/my_denylist.txt \
--allow-list path/to/extra_allowed.txt
```
### Rule Evaluation Precedence & Conflicts
When an AI coding assistant attempts to execute a command, rules are evaluated in strict priority
order:
```text
Incoming Agent Command
┌─────────────────────┐
│ Matches DENY rule? │ ───► YES ───► [BLOCKED]
└──────────┬──────────┘
│ NO
┌─────────────────────┐
│ Matches ASK rule? │ ───► YES ───► [PROMPT USER]
└──────────┬──────────┘
│ NO
┌─────────────────────┐
│ Matches ALLOW rule? │ ───► YES ───► [AUTO-RUN]
└──────────┬──────────┘
│ NO
[DEFAULT PROMPT]
```
- **`DENY` Always Wins**: If a command matches both an `allow` and a `deny` rule, the command is
blocked immediately.
- **Overlapping Rules in Configuration**: If you specify an ad-hoc `--deny` or `--deny-list` for a
command that is already in the selected profile's `allow` list (e.g. denying `git commit` under
`local-changes`), both rules will appear in `config.json`. Because `DENY` has highest priority,
the command is safely blocked at runtime.
- **Persistence Across Runs**: Ad-hoc flags only apply to that specific `setup` run. Running
`fx agents setup` later without those flags reverts to the profile defaults. Keep your custom
list files (e.g. `my_denylist.txt`) so you can pass them when re-running setup.
---
## Multi-Repository Overlays
In multi-repo setups (e.g. `//` with `//vendor/*`), `fx agents` automatically discovers and merges
configuration:
1. `.agents/config/permissions/` (Public Fuchsia tree)
2. `vendor/*/.agents/config/permissions/` (Internal & vendor overlays)
3. `services.txt` daemon declarations across all repository roots.
---
## Architecture & Further Reading
For in-depth documentation on the architecture and implementation of `fx agents`:
- **[Permissions & Configuration Architecture](docs/permissions.md)**: Deep dive into tiered
profiles, partitioned manifests, regex expansion mechanics, and three-way set reconciliation.
- **[Git Staging & Commit Hooks Guide](docs/git_hooks.md)**: Deep dive into staging partition
isolation, the `StashGuard` ($S^2 \to S$) algorithm, modular `.d/` hook dispatchers, and
troubleshooting.
- **[Developer & Contributor Guide](DEVELOPMENT.md)**: Guide for contributing to `tools/agents`,
including directory structure, building, testing, and adding new subcommands.