mirror of
https://github.com/openai/codex.git
synced 2026-05-14 08:12:36 +00:00
add trust hooks CLI flag
This commit is contained in:
@@ -566,6 +566,7 @@ impl CatalogRequestProcessor {
|
||||
};
|
||||
let hooks = codex_hooks::list_hooks(codex_hooks::HooksConfig {
|
||||
feature_enabled: config.features.enabled(Feature::CodexHooks),
|
||||
trust_hooks: config.trust_hooks,
|
||||
config_layer_stack: Some(config.config_layer_stack),
|
||||
plugin_hook_sources: plugin_outcome.effective_plugin_hook_sources(),
|
||||
plugin_hook_load_warnings: plugin_outcome.effective_plugin_hook_warnings(),
|
||||
|
||||
@@ -1421,6 +1421,7 @@ async fn run_debug_prompt_input_command(
|
||||
main_execve_wrapper_exe: arg0_paths.main_execve_wrapper_exe,
|
||||
show_raw_agent_reasoning: shared.oss.then_some(true),
|
||||
ephemeral: Some(true),
|
||||
trust_hooks: shared.trust_hooks.then_some(true),
|
||||
additional_writable_roots: shared.add_dir,
|
||||
..Default::default()
|
||||
};
|
||||
@@ -2254,6 +2255,16 @@ mod tests {
|
||||
assert_eq!(interactive.resume_session_id, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resume_merges_trust_hooks_flag() {
|
||||
let interactive = finalize_resume_from_args(["codex", "resume", "--trust-hooks"].as_ref());
|
||||
|
||||
assert!(interactive.trust_hooks);
|
||||
assert!(interactive.resume_picker);
|
||||
assert!(!interactive.resume_last);
|
||||
assert_eq!(interactive.resume_session_id, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fork_picker_logic_none_and_not_last() {
|
||||
let interactive = finalize_fork_from_args(["codex", "fork"].as_ref());
|
||||
|
||||
@@ -6992,6 +6992,7 @@ async fn test_precedence_fixture_with_o3_profile() -> std::io::Result<()> {
|
||||
startup_warnings: Vec::new(),
|
||||
history: History::default(),
|
||||
ephemeral: false,
|
||||
trust_hooks: false,
|
||||
file_opener: UriBasedFileOpener::VsCode,
|
||||
codex_self_exe: None,
|
||||
codex_linux_sandbox_exe: None,
|
||||
@@ -7251,6 +7252,7 @@ async fn test_precedence_fixture_with_gpt3_profile() -> std::io::Result<()> {
|
||||
startup_warnings: Vec::new(),
|
||||
history: History::default(),
|
||||
ephemeral: false,
|
||||
trust_hooks: false,
|
||||
file_opener: UriBasedFileOpener::VsCode,
|
||||
codex_self_exe: None,
|
||||
codex_linux_sandbox_exe: None,
|
||||
@@ -7409,6 +7411,7 @@ async fn test_precedence_fixture_with_zdr_profile() -> std::io::Result<()> {
|
||||
startup_warnings: Vec::new(),
|
||||
history: History::default(),
|
||||
ephemeral: false,
|
||||
trust_hooks: false,
|
||||
file_opener: UriBasedFileOpener::VsCode,
|
||||
codex_self_exe: None,
|
||||
codex_linux_sandbox_exe: None,
|
||||
@@ -7552,6 +7555,7 @@ async fn test_precedence_fixture_with_gpt5_profile() -> std::io::Result<()> {
|
||||
startup_warnings: Vec::new(),
|
||||
history: History::default(),
|
||||
ephemeral: false,
|
||||
trust_hooks: false,
|
||||
file_opener: UriBasedFileOpener::VsCode,
|
||||
codex_self_exe: None,
|
||||
codex_linux_sandbox_exe: None,
|
||||
|
||||
@@ -660,6 +660,11 @@ pub struct Config {
|
||||
/// When true, session is not persisted on disk. Default to `false`
|
||||
pub ephemeral: bool,
|
||||
|
||||
/// Whether enabled hooks should run without requiring persisted hook trust for this session.
|
||||
///
|
||||
/// This is a runtime-only knob populated from invocation overrides, not from config files.
|
||||
pub trust_hooks: bool,
|
||||
|
||||
/// Optional URI-based file opener. If set, citations to files in the model
|
||||
/// output will be hyperlinked using the specified URI scheme.
|
||||
pub file_opener: UriBasedFileOpener,
|
||||
@@ -1884,6 +1889,7 @@ pub struct ConfigOverrides {
|
||||
pub show_raw_agent_reasoning: Option<bool>,
|
||||
pub tools_web_search_request: Option<bool>,
|
||||
pub ephemeral: Option<bool>,
|
||||
pub trust_hooks: Option<bool>,
|
||||
/// Additional directories that should be treated as writable roots for this session.
|
||||
pub additional_writable_roots: Vec<PathBuf>,
|
||||
}
|
||||
@@ -2152,6 +2158,7 @@ impl Config {
|
||||
show_raw_agent_reasoning,
|
||||
tools_web_search_request: override_tools_web_search_request,
|
||||
ephemeral,
|
||||
trust_hooks,
|
||||
additional_writable_roots,
|
||||
} = overrides;
|
||||
|
||||
@@ -3072,6 +3079,7 @@ impl Config {
|
||||
config_layer_stack,
|
||||
history,
|
||||
ephemeral: ephemeral.unwrap_or_default(),
|
||||
trust_hooks: trust_hooks.unwrap_or_default(),
|
||||
file_opener: cfg.file_opener.unwrap_or(UriBasedFileOpener::VsCode),
|
||||
codex_self_exe,
|
||||
codex_linux_sandbox_exe,
|
||||
|
||||
@@ -3359,6 +3359,7 @@ async fn build_hooks_for_config(
|
||||
Hooks::new(HooksConfig {
|
||||
legacy_notify_argv: config.notify.clone(),
|
||||
feature_enabled: config.features.enabled(Feature::CodexHooks),
|
||||
trust_hooks: config.trust_hooks,
|
||||
config_layer_stack: Some(config.config_layer_stack.clone()),
|
||||
plugin_hook_sources,
|
||||
plugin_hook_load_warnings,
|
||||
|
||||
@@ -155,6 +155,7 @@ fn mark_exec_global_args(cmd: clap::Command) -> clap::Command {
|
||||
.mut_arg("dangerously_bypass_approvals_and_sandbox", |arg| {
|
||||
arg.global(true)
|
||||
})
|
||||
.mut_arg("trust_hooks", |arg| arg.global(true))
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Subcommand)]
|
||||
|
||||
@@ -265,6 +265,7 @@ pub async fn run_main(cli: Cli, arg0_paths: Arg0DispatchPaths) -> anyhow::Result
|
||||
config_profile,
|
||||
sandbox_mode: sandbox_mode_cli_arg,
|
||||
dangerously_bypass_approvals_and_sandbox,
|
||||
trust_hooks,
|
||||
cwd,
|
||||
add_dir,
|
||||
} = shared;
|
||||
@@ -423,6 +424,7 @@ pub async fn run_main(cli: Cli, arg0_paths: Arg0DispatchPaths) -> anyhow::Result
|
||||
show_raw_agent_reasoning: oss.then_some(true),
|
||||
tools_web_search_request: None,
|
||||
ephemeral: ephemeral.then_some(true),
|
||||
trust_hooks: trust_hooks.then_some(true),
|
||||
additional_writable_roots: add_dir,
|
||||
};
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ struct HookHandlerSource<'a> {
|
||||
key_source: String,
|
||||
source: HookSource,
|
||||
is_managed: bool,
|
||||
trust_hooks: bool,
|
||||
hook_states: &'a HashMap<String, HookStateToml>,
|
||||
env: HashMap<String, String>,
|
||||
plugin_id: Option<String>,
|
||||
@@ -50,6 +51,7 @@ pub(crate) fn discover_handlers(
|
||||
config_layer_stack: Option<&ConfigLayerStack>,
|
||||
plugin_hook_sources: Vec<PluginHookSource>,
|
||||
plugin_hook_load_warnings: Vec<String>,
|
||||
trust_hooks: bool,
|
||||
) -> DiscoveryResult {
|
||||
let mut handlers = Vec::new();
|
||||
let mut hook_entries = Vec::new();
|
||||
@@ -98,6 +100,7 @@ pub(crate) fn discover_handlers(
|
||||
key_source: source_path.display().to_string(),
|
||||
source: hook_source,
|
||||
is_managed,
|
||||
trust_hooks,
|
||||
hook_states: &hook_states,
|
||||
env: HashMap::new(),
|
||||
plugin_id: None,
|
||||
@@ -115,6 +118,7 @@ pub(crate) fn discover_handlers(
|
||||
&mut display_order,
|
||||
plugin_hook_sources,
|
||||
&hook_states,
|
||||
trust_hooks,
|
||||
);
|
||||
|
||||
DiscoveryResult {
|
||||
@@ -150,6 +154,7 @@ fn append_managed_requirement_handlers(
|
||||
key_source: source_path.display().to_string(),
|
||||
source: hook_source_for_requirement_source(managed_hooks.source.as_ref()),
|
||||
is_managed: true,
|
||||
trust_hooks: false,
|
||||
hook_states,
|
||||
env: HashMap::new(),
|
||||
plugin_id: None,
|
||||
@@ -165,6 +170,7 @@ fn append_plugin_hook_sources(
|
||||
display_order: &mut i64,
|
||||
plugin_hook_sources: Vec<PluginHookSource>,
|
||||
hook_states: &HashMap<String, HookStateToml>,
|
||||
trust_hooks: bool,
|
||||
) {
|
||||
for source in plugin_hook_sources {
|
||||
let PluginHookSource {
|
||||
@@ -198,6 +204,7 @@ fn append_plugin_hook_sources(
|
||||
),
|
||||
source: HookSource::Plugin,
|
||||
is_managed: false,
|
||||
trust_hooks,
|
||||
hook_states,
|
||||
env,
|
||||
plugin_id: Some(plugin_id),
|
||||
@@ -444,10 +451,11 @@ fn append_matcher_groups(
|
||||
trust_status,
|
||||
});
|
||||
if enabled
|
||||
&& matches!(
|
||||
trust_status,
|
||||
HookTrustStatus::Managed | HookTrustStatus::Trusted
|
||||
)
|
||||
&& (source.trust_hooks
|
||||
|| matches!(
|
||||
trust_status,
|
||||
HookTrustStatus::Managed | HookTrustStatus::Trusted
|
||||
))
|
||||
{
|
||||
handlers.push(ConfiguredHandler {
|
||||
event_name,
|
||||
@@ -579,6 +587,7 @@ mod tests {
|
||||
use codex_config::HookStateToml;
|
||||
use codex_config::MatcherGroup;
|
||||
use codex_config::TomlValue;
|
||||
use codex_protocol::protocol::HookTrustStatus;
|
||||
|
||||
fn source_path() -> AbsolutePathBuf {
|
||||
test_path_buf("/tmp/hooks.json").abs()
|
||||
@@ -597,6 +606,24 @@ mod tests {
|
||||
key_source: path.display().to_string(),
|
||||
source: hook_source(),
|
||||
is_managed: true,
|
||||
trust_hooks: false,
|
||||
hook_states,
|
||||
env: std::collections::HashMap::new(),
|
||||
plugin_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn unmanaged_hook_handler_source<'a>(
|
||||
path: &'a AbsolutePathBuf,
|
||||
hook_states: &'a std::collections::HashMap<String, HookStateToml>,
|
||||
trust_hooks: bool,
|
||||
) -> super::HookHandlerSource<'a> {
|
||||
super::HookHandlerSource {
|
||||
path,
|
||||
key_source: path.display().to_string(),
|
||||
source: HookSource::User,
|
||||
is_managed: false,
|
||||
trust_hooks,
|
||||
hook_states,
|
||||
env: std::collections::HashMap::new(),
|
||||
plugin_id: None,
|
||||
@@ -685,6 +712,64 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trust_hooks_allows_enabled_untrusted_handlers() {
|
||||
let mut handlers = Vec::new();
|
||||
let mut hook_entries = Vec::new();
|
||||
let mut warnings = Vec::new();
|
||||
let mut display_order = 0;
|
||||
let source_path = source_path();
|
||||
let hook_states = std::collections::HashMap::new();
|
||||
|
||||
append_matcher_groups(
|
||||
&mut handlers,
|
||||
&mut hook_entries,
|
||||
&mut warnings,
|
||||
&mut display_order,
|
||||
&unmanaged_hook_handler_source(&source_path, &hook_states, /*trust_hooks*/ true),
|
||||
HookEventName::PreToolUse,
|
||||
vec![command_group(Some("Bash"))],
|
||||
);
|
||||
|
||||
assert_eq!(warnings, Vec::<String>::new());
|
||||
assert_eq!(handlers.len(), 1);
|
||||
assert_eq!(hook_entries.len(), 1);
|
||||
assert_eq!(hook_entries[0].trust_status, HookTrustStatus::Untrusted);
|
||||
assert_eq!(hook_entries[0].enabled, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trust_hooks_respects_disabled_handlers() {
|
||||
let mut handlers = Vec::new();
|
||||
let mut hook_entries = Vec::new();
|
||||
let mut warnings = Vec::new();
|
||||
let mut display_order = 0;
|
||||
let source_path = source_path();
|
||||
let hook_states = std::collections::HashMap::from([(
|
||||
format!("{}:pre_tool_use:0:0", source_path.display()),
|
||||
HookStateToml {
|
||||
enabled: Some(false),
|
||||
trusted_hash: None,
|
||||
},
|
||||
)]);
|
||||
|
||||
append_matcher_groups(
|
||||
&mut handlers,
|
||||
&mut hook_entries,
|
||||
&mut warnings,
|
||||
&mut display_order,
|
||||
&unmanaged_hook_handler_source(&source_path, &hook_states, /*trust_hooks*/ true),
|
||||
HookEventName::PreToolUse,
|
||||
vec![command_group(Some("Bash"))],
|
||||
);
|
||||
|
||||
assert_eq!(warnings, Vec::<String>::new());
|
||||
assert_eq!(handlers, Vec::<ConfiguredHandler>::new());
|
||||
assert_eq!(hook_entries.len(), 1);
|
||||
assert_eq!(hook_entries[0].trust_status, HookTrustStatus::Untrusted);
|
||||
assert_eq!(hook_entries[0].enabled, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_tool_use_treats_star_matcher_as_match_all() {
|
||||
let mut handlers = Vec::new();
|
||||
|
||||
@@ -106,6 +106,7 @@ pub(crate) struct ClaudeHooksEngine {
|
||||
impl ClaudeHooksEngine {
|
||||
pub(crate) fn new(
|
||||
enabled: bool,
|
||||
trust_hooks: bool,
|
||||
config_layer_stack: Option<&ConfigLayerStack>,
|
||||
plugin_hook_sources: Vec<PluginHookSource>,
|
||||
plugin_hook_load_warnings: Vec<String>,
|
||||
@@ -125,6 +126,7 @@ impl ClaudeHooksEngine {
|
||||
config_layer_stack,
|
||||
plugin_hook_sources,
|
||||
plugin_hook_load_warnings,
|
||||
trust_hooks,
|
||||
);
|
||||
Self {
|
||||
handlers: discovered.handlers,
|
||||
|
||||
@@ -111,6 +111,7 @@ with Path(r"{log_path}").open("a", encoding="utf-8") as handle:
|
||||
|
||||
let engine = ClaudeHooksEngine::new(
|
||||
/*enabled*/ true,
|
||||
/*trust_hooks*/ false,
|
||||
Some(&config_layer_stack),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
@@ -126,6 +127,7 @@ with Path(r"{log_path}").open("a", encoding="utf-8") as handle:
|
||||
let listed = crate::list_hooks(crate::HooksConfig {
|
||||
legacy_notify_argv: None,
|
||||
feature_enabled: true,
|
||||
trust_hooks: false,
|
||||
config_layer_stack: Some(config_layer_stack.clone()),
|
||||
plugin_hook_sources: Vec::new(),
|
||||
plugin_hook_load_warnings: Vec::new(),
|
||||
@@ -208,6 +210,7 @@ fn unknown_requirement_source_hooks_stay_managed() {
|
||||
|
||||
let engine = ClaudeHooksEngine::new(
|
||||
/*enabled*/ true,
|
||||
/*trust_hooks*/ false,
|
||||
Some(&config_layer_stack),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
@@ -219,8 +222,12 @@ fn unknown_requirement_source_hooks_stay_managed() {
|
||||
|
||||
assert_eq!(engine.handlers.len(), 1);
|
||||
assert_eq!(engine.handlers[0].source, HookSource::Unknown);
|
||||
let discovered =
|
||||
super::discovery::discover_handlers(Some(&config_layer_stack), Vec::new(), Vec::new());
|
||||
let discovered = super::discovery::discover_handlers(
|
||||
Some(&config_layer_stack),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
/*trust_hooks*/ false,
|
||||
);
|
||||
assert_eq!(discovered.hook_entries.len(), 1);
|
||||
assert_eq!(discovered.hook_entries[0].source, HookSource::Unknown);
|
||||
assert_eq!(discovered.hook_entries[0].enabled, true);
|
||||
@@ -281,6 +288,7 @@ fn user_disablement_filters_non_managed_hooks_but_not_managed_hooks() {
|
||||
|
||||
let engine = ClaudeHooksEngine::new(
|
||||
/*enabled*/ true,
|
||||
/*trust_hooks*/ false,
|
||||
Some(&config_layer_stack),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
@@ -292,8 +300,12 @@ fn user_disablement_filters_non_managed_hooks_but_not_managed_hooks() {
|
||||
|
||||
assert_eq!(engine.handlers.len(), 1);
|
||||
assert_eq!(engine.handlers[0].source, HookSource::CloudRequirements);
|
||||
let discovered =
|
||||
super::discovery::discover_handlers(Some(&config_layer_stack), Vec::new(), Vec::new());
|
||||
let discovered = super::discovery::discover_handlers(
|
||||
Some(&config_layer_stack),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
/*trust_hooks*/ false,
|
||||
);
|
||||
assert_eq!(discovered.hook_entries.len(), 2);
|
||||
assert_eq!(discovered.hook_entries[0].key, managed_disabled_key);
|
||||
assert_eq!(discovered.hook_entries[0].enabled, true);
|
||||
@@ -338,6 +350,7 @@ fn user_disablement_does_not_filter_managed_layer_hooks() {
|
||||
|
||||
let engine = ClaudeHooksEngine::new(
|
||||
/*enabled*/ true,
|
||||
/*trust_hooks*/ false,
|
||||
Some(&config_layer_stack),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
@@ -352,8 +365,12 @@ fn user_disablement_does_not_filter_managed_layer_hooks() {
|
||||
engine.handlers[0].source,
|
||||
HookSource::LegacyManagedConfigFile
|
||||
);
|
||||
let discovered =
|
||||
super::discovery::discover_handlers(Some(&config_layer_stack), Vec::new(), Vec::new());
|
||||
let discovered = super::discovery::discover_handlers(
|
||||
Some(&config_layer_stack),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
/*trust_hooks*/ false,
|
||||
);
|
||||
assert_eq!(discovered.hook_entries.len(), 1);
|
||||
assert_eq!(discovered.hook_entries[0].key, managed_key);
|
||||
assert_eq!(discovered.hook_entries[0].enabled, true);
|
||||
@@ -421,6 +438,7 @@ fn trusted_plugin_hook_stack(
|
||||
/*config_layer_stack*/ None,
|
||||
plugin_hook_sources.to_vec(),
|
||||
Vec::new(),
|
||||
/*trust_hooks*/ false,
|
||||
);
|
||||
let state = discovered
|
||||
.hook_entries
|
||||
@@ -489,6 +507,7 @@ fn requirements_managed_hooks_warn_when_managed_dir_is_missing() {
|
||||
|
||||
let engine = ClaudeHooksEngine::new(
|
||||
/*enabled*/ true,
|
||||
/*trust_hooks*/ false,
|
||||
Some(&config_layer_stack),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
@@ -598,6 +617,7 @@ fn discovers_hooks_from_json_and_toml_in_the_same_layer() {
|
||||
|
||||
let engine = ClaudeHooksEngine::new(
|
||||
/*enabled*/ true,
|
||||
/*trust_hooks*/ false,
|
||||
Some(&config_layer_stack),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
@@ -688,6 +708,7 @@ print(json.dumps({
|
||||
);
|
||||
let engine = ClaudeHooksEngine::new(
|
||||
/*enabled*/ true,
|
||||
/*trust_hooks*/ false,
|
||||
Some(&config_layer_stack),
|
||||
plugin_hook_sources.clone(),
|
||||
Vec::new(),
|
||||
@@ -715,6 +736,7 @@ print(json.dumps({
|
||||
let listed = crate::list_hooks(crate::HooksConfig {
|
||||
legacy_notify_argv: None,
|
||||
feature_enabled: true,
|
||||
trust_hooks: false,
|
||||
config_layer_stack: None,
|
||||
plugin_hook_sources,
|
||||
plugin_hook_load_warnings: Vec::new(),
|
||||
@@ -796,6 +818,7 @@ fn plugin_hook_sources_expand_plugin_placeholders() {
|
||||
);
|
||||
let engine = ClaudeHooksEngine::new(
|
||||
/*enabled*/ true,
|
||||
/*trust_hooks*/ false,
|
||||
Some(&config_layer_stack),
|
||||
plugin_hook_sources,
|
||||
Vec::new(),
|
||||
@@ -839,6 +862,7 @@ fn plugin_hook_sources_expand_plugin_placeholders() {
|
||||
fn plugin_hook_load_warnings_are_startup_warnings() {
|
||||
let engine = ClaudeHooksEngine::new(
|
||||
/*enabled*/ true,
|
||||
/*trust_hooks*/ false,
|
||||
/*config_layer_stack*/ None,
|
||||
Vec::new(),
|
||||
vec!["failed plugin hook".to_string()],
|
||||
|
||||
@@ -30,6 +30,7 @@ use crate::types::HookResponse;
|
||||
pub struct HooksConfig {
|
||||
pub legacy_notify_argv: Option<Vec<String>>,
|
||||
pub feature_enabled: bool,
|
||||
pub trust_hooks: bool,
|
||||
pub config_layer_stack: Option<ConfigLayerStack>,
|
||||
pub plugin_hook_sources: Vec<PluginHookSource>,
|
||||
pub plugin_hook_load_warnings: Vec<String>,
|
||||
@@ -66,6 +67,7 @@ impl Hooks {
|
||||
.collect();
|
||||
let engine = ClaudeHooksEngine::new(
|
||||
config.feature_enabled,
|
||||
config.trust_hooks,
|
||||
config.config_layer_stack.as_ref(),
|
||||
config.plugin_hook_sources,
|
||||
config.plugin_hook_load_warnings,
|
||||
@@ -215,6 +217,7 @@ pub fn list_hooks(config: HooksConfig) -> HookListOutcome {
|
||||
config.config_layer_stack.as_ref(),
|
||||
config.plugin_hook_sources,
|
||||
config.plugin_hook_load_warnings,
|
||||
config.trust_hooks,
|
||||
);
|
||||
HookListOutcome {
|
||||
hooks: discovered.hook_entries,
|
||||
|
||||
@@ -865,6 +865,7 @@ pub async fn run_main(
|
||||
codex_linux_sandbox_exe: arg0_paths.codex_linux_sandbox_exe.clone(),
|
||||
main_execve_wrapper_exe: arg0_paths.main_execve_wrapper_exe.clone(),
|
||||
show_raw_agent_reasoning: cli.oss.then_some(true),
|
||||
trust_hooks: cli.trust_hooks.then_some(true),
|
||||
additional_writable_roots: additional_dirs,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -47,6 +47,10 @@ pub struct SharedCliOptions {
|
||||
)]
|
||||
pub dangerously_bypass_approvals_and_sandbox: bool,
|
||||
|
||||
/// Run enabled hooks without requiring persisted hook trust for this invocation.
|
||||
#[arg(long = "trust-hooks", default_value_t = false)]
|
||||
pub trust_hooks: bool,
|
||||
|
||||
/// Tell the agent to use the specified directory as its working root.
|
||||
#[clap(long = "cd", short = 'C', value_name = "DIR")]
|
||||
pub cwd: Option<PathBuf>,
|
||||
@@ -68,6 +72,7 @@ impl SharedCliOptions {
|
||||
config_profile,
|
||||
sandbox_mode,
|
||||
dangerously_bypass_approvals_and_sandbox,
|
||||
trust_hooks,
|
||||
cwd,
|
||||
add_dir,
|
||||
} = self;
|
||||
@@ -79,6 +84,7 @@ impl SharedCliOptions {
|
||||
config_profile: root_config_profile,
|
||||
sandbox_mode: root_sandbox_mode,
|
||||
dangerously_bypass_approvals_and_sandbox: root_dangerously_bypass_approvals_and_sandbox,
|
||||
trust_hooks: root_trust_hooks,
|
||||
cwd: root_cwd,
|
||||
add_dir: root_add_dir,
|
||||
} = root;
|
||||
@@ -102,6 +108,9 @@ impl SharedCliOptions {
|
||||
*dangerously_bypass_approvals_and_sandbox =
|
||||
*root_dangerously_bypass_approvals_and_sandbox;
|
||||
}
|
||||
if !*trust_hooks {
|
||||
*trust_hooks = *root_trust_hooks;
|
||||
}
|
||||
if cwd.is_none() {
|
||||
cwd.clone_from(root_cwd);
|
||||
}
|
||||
@@ -128,6 +137,7 @@ impl SharedCliOptions {
|
||||
config_profile,
|
||||
sandbox_mode,
|
||||
dangerously_bypass_approvals_and_sandbox,
|
||||
trust_hooks,
|
||||
cwd,
|
||||
add_dir,
|
||||
} = subcommand;
|
||||
@@ -149,6 +159,9 @@ impl SharedCliOptions {
|
||||
self.dangerously_bypass_approvals_and_sandbox =
|
||||
dangerously_bypass_approvals_and_sandbox;
|
||||
}
|
||||
if trust_hooks {
|
||||
self.trust_hooks = true;
|
||||
}
|
||||
if let Some(cwd) = cwd {
|
||||
self.cwd = Some(cwd);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user