pub enum Agent {
ClaudeCode,
Codex,
Droid,
Copilot,
Pi,
}Expand description
Which agent to run, by name.
It used to be a free argv, and that was the wrong shape. The grouping stage does not merely spawn a process: it hands the agent a tool allowlist, a fetch command and a prompt written for what that agent can do (ADR 0022). An arbitrary argv gets the prompt and none of the rest, so it was a knob that looked like it worked. A name selects an invocation this crate builds whole, and adding an agent is adding a variant here.
The name also answers what a reviewer is shown while they wait — the argv never could, at four times the width of the line it had.
Four of the five keep the model read-only; Pi does not (ADR 0033).
Read Agent::read_only and ReadOnly::is_enforced before choosing one.
Variants§
ClaudeCode
Headless claude, read-only by tool allowlist (ADR 0022).
Codex
Headless codex exec, read-only by OS sandbox (Seatbelt, bubblewrap).
Droid
Headless droid exec, read-only by default — the tier is what we do
not pass.
Copilot
Headless copilot, read-only by tool allowlist and an explicit deny.
Pi
Headless pi, read-only is NOT enforced (ADR 0033).
Pi ships no sandbox and no per-command allowlist, and its -t flag
toggles whole tools. The model needs bash to run the fetch command
and git diff, and bash also lets it write, commit and push. Nothing
but the prompt stops it. Choose this agent only knowing that.
Implementations§
Source§impl Agent
impl Agent
Sourcepub const ALL: [Agent; 5]
pub const ALL: [Agent; 5]
Every agent, so a lister does not keep its own copy of the list.
The array is exhaustive by hand, which a match would enforce and an
array cannot. all_agents_are_listed in this module is that check.
Sourcepub fn key(self) -> &'static str
pub fn key(self) -> &'static str
The name this agent answers to in [grouping].agent.
Hand-written rather than derived, because serde renames on the way IN
and there is no way to ask it for the string on the way out without a
second derive. The match is the guard: a new variant does not compile
until it has a name here.
Sourcepub fn proven(self) -> bool
pub fn proven(self) -> bool
Whether anyone has ever run this agent’s command line.
Not a quality judgement — a claim about provenance, and the only honest one this crate can make. Every argv here is written from its agent’s documentation, and a test can assert the string this crate builds but never that the CLI on the other end accepts it. CI cannot either: the binary is not installed and its flags move between releases.
true means dfr agents --probe passed all four checks against the
real CLI, and the argv is in this repository because of that run.
false means likely wrong, not merely unchecked. Of the three
checked so far, two were broken: Claude Code’s allowlist did not bind
without --permission-mode default, and Codex was passing
--ask-for-approval, which its exec subcommand rejects outright. Both
came from documentation that was accurate about the product and wrong
about the entry point. Nothing suggests the unchecked two are better.
A caller that offers a user this list must say so, for the same reason
it must say what Agent::read_only answers: the person choosing is
the person who carries it.
This flips when someone runs the probe and the argv lands — never because it looks right.
Sourcepub fn read_only(self) -> ReadOnly
pub fn read_only(self) -> ReadOnly
What stops this agent writing, if anything.
A caller that shows a user the list of agents MUST show this too. The
person picking a name is the person who needs to know, and exactly one
answer here is ReadOnly::NotEnforced.
Trait Implementations§
impl Copy for Agent
Source§impl<'de> Deserialize<'de> for Agent
impl<'de> Deserialize<'de> for Agent
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for Agent
impl StructuralPartialEq for Agent
Auto Trait Implementations§
impl Freeze for Agent
impl RefUnwindSafe for Agent
impl Send for Agent
impl Sync for Agent
impl Unpin for Agent
impl UnsafeUnpin for Agent
impl UnwindSafe for Agent
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.