Skip to main content

AgentAdapter

Trait AgentAdapter 

Source
pub trait AgentAdapter {
Show 40 methods // Required methods fn id(&self) -> &'static str; fn display_name(&self) -> &'static str; fn dir_prefix(&self) -> &'static str; fn mcp_config_relpath(&self) -> &'static str; fn supported_agents(&self) -> &[&'static str]; fn hook_compatibility(&self) -> &'static CompatibilityMatrix; fn hook_settings_relpath(&self) -> &'static str; fn hook_settings_shape(&self) -> HookSettingsShape; fn scaffold_hook_event(&self) -> &'static str; fn detect(&self, repo_root: &Path) -> bool; fn kinds_supported(&self) -> &[CapabilityType]; // Provided methods fn hook_filename(&self) -> &'static str { ... } fn hook_file_content(&self, hook_cfg: &HookConfig) -> Result<Vec<u8>> { ... } fn render_standard_hook( &self, context: HookRenderContext<'_>, ) -> Result<HookRenderPlan> { ... } fn command_hook_fragment(&self, native_event: &str, command: &str) -> Value { ... } fn merge_hook_fragment( &self, existing: Option<&[u8]>, fragment: &Value, ) -> Result<Vec<u8>> { ... } fn remove_hook_settings( &self, repo_root: &Path, managed_hooks: &[ManagedHook], ) -> Result<()> { ... } fn policy_compatibility(&self) -> Vec<PolicyCoverageEntry> { ... } fn permissions_settings_relpath(&self) -> Option<&'static str> { ... } fn permission_relpath_for( &self, _subject: PolicySubjectKind, ) -> Option<&'static str> { ... } fn policy_rule_gap(&self, _rule: &PolicyRule) -> Result<Option<String>> { ... } fn native_permission_rules( &self, _rule: &PolicyRule, ) -> Result<Option<Vec<String>>> { ... } fn supports(&self, capability_type: CapabilityType) -> bool { ... } fn native_hook_event(&self, raw_event: &str) -> Result<&'static str> { ... } fn canonical_hook_event(&self, raw_event: &str) -> Result<&'static str> { ... } fn ensure_project_dir(&self, repo_root: &Path) -> Result<()> { ... } fn mcp_env_reference(&self, var: &str) -> String { ... } fn mcp_server_entry(&self, server: &McpServerConfig) -> Value { ... } fn mcp_http_declares_type(&self) -> bool { ... } fn mcp_server_entry_checked( &self, server: &McpServerConfig, ) -> Result<Value> { ... } fn install_note(&self, _kind: CapabilityType) -> Option<&'static str> { ... } fn plan( &self, capability: &ResolvedCapability, repo_root: &Path, ) -> Result<Vec<PlannedFile>> { ... } fn remove( &self, primitive_id: &str, repo_root: &Path, managed_hooks: &[ManagedHook], ) -> Result<()> { ... } fn plan_skill( &self, capability: &ResolvedCapability, repo_root: &Path, ) -> Result<Vec<PlannedFile>> { ... } fn plan_tool( &self, capability: &ResolvedCapability, repo_root: &Path, ) -> Result<Vec<PlannedFile>> { ... } fn plan_hook( &self, capability: &ResolvedCapability, repo_root: &Path, ) -> Result<Vec<PlannedFile>> { ... } fn plan_native_hook( &self, capability: &ResolvedCapability, native: &NativeHookConfig, repo_root: &Path, ) -> Result<Vec<PlannedFile>> { ... } fn plan_mcp_server( &self, capability: &ResolvedCapability, repo_root: &Path, ) -> Result<Vec<PlannedFile>> { ... } fn plan_policy( &self, capability: &ResolvedCapability, repo_root: &Path, ) -> Result<Vec<PlannedFile>> { ... } fn remove_dir( &self, repo_root: &Path, base: &str, kind: &str, primitive_id: &str, ) -> Result<()> { ... }
}
Expand description

What a harness adapter declares, and what Tuff does with it.

An adapter is a declaration: where the harness keeps its files, which hook events it has and how they map onto Tuff’s, the shape of its hook settings file, and how to recognise a project that uses it. Everything else, planning files, rendering hooks, merging into and removing from the settings file, is a default method here, so there is one implementation of each and an adapter overrides one only when its harness genuinely differs (Cursor’s ${env:VAR} spelling, say).

Required Methods§

Source

fn id(&self) -> &'static str

Source

fn display_name(&self) -> &'static str

Source

fn dir_prefix(&self) -> &'static str

Source

fn mcp_config_relpath(&self) -> &'static str

Source

fn supported_agents(&self) -> &[&'static str]

Source

fn hook_compatibility(&self) -> &'static CompatibilityMatrix

Source

fn hook_settings_relpath(&self) -> &'static str

Source

fn hook_settings_shape(&self) -> HookSettingsShape

How the settings file at hook_settings_relpath lays out its registrations. This is the whole of what differs between harnesses in hook handling; the merge and removal follow from it.

Source

fn scaffold_hook_event(&self) -> &'static str

The native event tuff create registers a scaffolded hook under.

Source

fn detect(&self, repo_root: &Path) -> bool

Whether a project already uses this harness.

Source

fn kinds_supported(&self) -> &[CapabilityType]

Provided Methods§

Source

fn hook_filename(&self) -> &'static str

Source

fn hook_file_content(&self, hook_cfg: &HookConfig) -> Result<Vec<u8>>

Source

fn render_standard_hook( &self, context: HookRenderContext<'_>, ) -> Result<HookRenderPlan>

Source

fn command_hook_fragment(&self, native_event: &str, command: &str) -> Value

The hooks-only fragment that registers command under native_event.

Source

fn merge_hook_fragment( &self, existing: Option<&[u8]>, fragment: &Value, ) -> Result<Vec<u8>>

Merge a hooks-only fragment into the settings file’s current bytes.

Source

fn remove_hook_settings( &self, repo_root: &Path, managed_hooks: &[ManagedHook], ) -> Result<()>

Take Tuff’s registrations out of the settings file, leaving the user’s own alone.

Source

fn policy_compatibility(&self) -> Vec<PolicyCoverageEntry>

How this harness enforces each kind of policy rule, one row per effect and subject. The default says, for every row, that Tuff does not compile policies for this harness, so a policy is refused for it rather than reported as installed.

Source

fn permissions_settings_relpath(&self) -> Option<&'static str>

The settings file this harness reads native permission rules from, when it has one a repository can carry.

Source

fn permission_relpath_for( &self, _subject: PolicySubjectKind, ) -> Option<&'static str>

The settings file rules of one subject compile into, for a harness that keeps different kinds of rule in different files. The default is permissions_settings_relpath.

Source

fn policy_rule_gap(&self, _rule: &PolicyRule) -> Result<Option<String>>

Why this harness cannot enforce one rule that its matrix row covers, such as a pattern its native setting has no form for, or None.

Source

fn native_permission_rules( &self, _rule: &PolicyRule, ) -> Result<Option<Vec<String>>>

The native permission rules one policy rule compiles to on this harness, or None when the harness has no such rules. The list the rules go in follows the policy rule’s effect.

Source

fn supports(&self, capability_type: CapabilityType) -> bool

Source

fn native_hook_event(&self, raw_event: &str) -> Result<&'static str>

Source

fn canonical_hook_event(&self, raw_event: &str) -> Result<&'static str>

Source

fn ensure_project_dir(&self, repo_root: &Path) -> Result<()>

Source

fn mcp_env_reference(&self, var: &str) -> String

How this harness spells a reference to an environment variable inside its MCP config. Claude Code and most stdio clients expand ${VAR}.

Source

fn mcp_server_entry(&self, server: &McpServerConfig) -> Value

The mcpServers.<id> entry this harness needs for an external MCP server. Secrets are emitted as env references, never values.

Source

fn mcp_http_declares_type(&self) -> bool

Whether this harness wants an explicit "type": "http" on a remote server entry. Claude Code and Codex do; Cursor infers the transport from url and has no type key for remote servers.

Source

fn mcp_server_entry_checked(&self, server: &McpServerConfig) -> Result<Value>

mcp_server_entry, for a harness whose config cannot express every declaration. The default expresses everything; an override refuses what its harness would silently get wrong, such as a renamed variable, so the install stops before anything is written.

Source

fn install_note(&self, _kind: CapabilityType) -> Option<&'static str>

A note tuff add prints after installing a capability of this kind, for a harness that applies the installed files only under a condition the file itself cannot state, such as Codex loading a project’s .codex/ layer only once the project is trusted.

Source

fn plan( &self, capability: &ResolvedCapability, repo_root: &Path, ) -> Result<Vec<PlannedFile>>

Source

fn remove( &self, primitive_id: &str, repo_root: &Path, managed_hooks: &[ManagedHook], ) -> Result<()>

Source

fn plan_skill( &self, capability: &ResolvedCapability, repo_root: &Path, ) -> Result<Vec<PlannedFile>>

Source

fn plan_tool( &self, capability: &ResolvedCapability, repo_root: &Path, ) -> Result<Vec<PlannedFile>>

Source

fn plan_hook( &self, capability: &ResolvedCapability, repo_root: &Path, ) -> Result<Vec<PlannedFile>>

Source

fn plan_native_hook( &self, capability: &ResolvedCapability, native: &NativeHookConfig, repo_root: &Path, ) -> Result<Vec<PlannedFile>>

Source

fn plan_mcp_server( &self, capability: &ResolvedCapability, repo_root: &Path, ) -> Result<Vec<PlannedFile>>

Emit the canonical server.toml record. The JSON entry in the harness’s MCP config is the artifact the harness reads; this file is what gives the capability a tree to hash, so check/diff/delete work exactly as they do for every other kind.

Source

fn plan_policy( &self, capability: &ResolvedCapability, repo_root: &Path, ) -> Result<Vec<PlannedFile>>

Emit the canonical policy.toml record. The rules the harness reads live in its settings file; this record gives the capability a tree to hash, so check, diff, and delete treat it like every other kind, and update can tell when the policy’s rules changed.

Source

fn remove_dir( &self, repo_root: &Path, base: &str, kind: &str, primitive_id: &str, ) -> Result<()>

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§