Skip to main content

AgentAdapter

Trait AgentAdapter 

Source
pub trait AgentAdapter {
Show 37 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 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 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_workflow( &self, capability: &ResolvedCapability, 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 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 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_workflow( &self, capability: &ResolvedCapability, 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§