{"record":{"id":"488f4c6e95e55ad8","repo":"zeroclaw-labs/zeroclaw","slug":"allowed-tool-is-only-supported-with-prompt-cro","errorCode":null,"errorMessage":"--allowed-tool is only supported with --prompt cron jobs","messagePattern":"--allowed-tool is only supported with --prompt cron jobs","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/cron/mod.rs","lineNumber":225,"sourceCode":"                );\n                println!(\n                    \"{}\",\n                    get_required_cli_string_with_args(\n                        \"cli-cron-next\",\n                        &[(\"v\", &job.next_run.to_rfc3339())]\n                    )\n                );\n                println!(\n                    \"{}\",\n                    get_required_cli_string_with_args(\n                        \"cli-cron-prompt\",\n                        &[(\"v\", job.prompt.as_deref().unwrap_or_default())]\n                    )\n                );\n                print_delivery_line(&job);\n            } else {\n                if !allowed_tools.is_empty() {\n                    bail!(\"--allowed-tool is only supported with --prompt cron jobs\");\n                }\n                let job = add_shell_job_with_approval(\n                    config,\n                    &agent_alias,\n                    None,\n                    schedule,\n                    &command,\n                    delivery,\n                    false,\n                )?;\n                println!(\n                    \"{}\",\n                    get_required_cli_string_with_args(\"cli-cron-added\", &[(\"id\", &job.id)])\n                );\n                println!(\n                    \"{}\",\n                    get_required_cli_string_with_args(\"cli-cron-expr2\", &[(\"v\", &job.expression)])\n                );","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/src/cron/mod.rs#L207-L243","documentation":"In the expression-based cron creation path (cron add with --expression), a tool allowlist only exists for agent prompt jobs: --allowed-tool constrains which tools an agent may use while executing its prompt. A shell job (created without --prompt) runs a fixed command string, so an allowlist has no meaning and is rejected before the job is stored.","triggerScenarios":"`zeroclaw cron add <alias> --expression '...' --command 'backup.sh' --allowed-tool bash` — i.e. the Add path without --prompt while one or more --allowed-tool values are present.","commonSituations":"Copy-pasting a prompt-job command line and swapping --prompt for --command; scripts templating one flag set over all job types; assuming allowlists gate shell commands the way approval prompts do.","solutions":["Remove the --allowed-tool flags; shell jobs are gated by the approval flow instead (add_shell_job_with_approval).","Or switch the job to an agent prompt job by passing --prompt so the allowlist applies.","If you need to constrain a shell job, put the constraint inside the command itself (full path, sandboxing wrapper) rather than an agent allowlist."],"exampleFix":"# before\nzeroclaw cron add bot --expression '0 3 * * *' --command 'backup.sh' --allowed-tool bash\n# after (shell job: drop the flag)\nzeroclaw cron add bot --expression '0 3 * * *' --command 'backup.sh'\n# after (agent job: keep the flag, add --prompt)\nzeroclaw cron add bot --expression '0 3 * * *' --prompt 'run the backup' --allowed-tool bash","handlingStrategy":"validation","validationCode":"fn validate_cron_add(is_prompt: bool, allowed_tools: &[String]) -> Result<(), String> {\n    if !is_prompt && !allowed_tools.is_empty() {\n        Err(\"--allowed-tool requires --prompt on cron add\".into())\n    } else {\n        Ok(())\n    }\n}\n// run before shelling out to `zeroclaw cron add ...`","typeGuard":"enum JobSpec<'a> {\n    Prompt { allowed_tools: &'a [String] },\n    Shell,\n}\n// constructing JobSpec::Shell forces the caller to drop allowed_tools;\n// only JobSpec::Prompt can carry them, making the bad state unrepresentable","tryCatchPattern":"match run_cron_add(args).await {\n    Err(e) if e.to_string().contains(\"only supported with --prompt\") => {\n        // strip --allowed-tool or re-issue with --prompt; never retry unchanged\n    }\n    other => other,\n}","preventionTips":["In scripts, emit --allowed-tool flags only on the --prompt branch of the command builder.","Treat allowlists as an agent-job concept; for shell jobs rely on the approval flow.","Test cron-creation wrappers once against a scratch config to catch flag-combination errors early."],"tags":["cron","cli","argument-validation","allowed-tool"],"backgroundTag":"invalid-cli-flag-combination","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}