{"record":{"id":"be3ba4f8b2f5b626","repo":"rtk-ai/rtk","slug":"rtk-find-does-not-support-compound-predicates-or-a","errorCode":null,"errorMessage":"rtk find does not support compound predicates or actions (e.g. -not, -exec). Use `find` directly.","messagePattern":"rtk find does not support compound predicates or actions \\(e\\.g\\. -not, -exec\\)\\. Use `find` directly\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmds/system/find_cmd.rs","lineNumber":89,"sourceCode":"    \"-regex\", \"-iregex\",\n];\n\nfn has_unsupported_find_flags(args: &[String]) -> bool {\n    args.iter()\n        .any(|a| UNSUPPORTED_FIND_FLAGS.contains(&a.as_str()))\n}\n\n/// Parse arguments from raw args vec, supporting both native find and RTK syntax.\n///\n/// Native find syntax: `find . -name \"*.rs\" -type f -maxdepth 3`\n/// RTK syntax: `find *.rs [path] [-m max] [-t type]`\nfn parse_find_args(args: &[String]) -> Result<FindArgs> {\n    if args.is_empty() {\n        return Ok(FindArgs::default());\n    }\n\n    if has_unsupported_find_flags(args) {\n        anyhow::bail!(\n            \"rtk find does not support compound predicates or actions (e.g. -not, -exec). Use `find` directly.\"\n        );\n    }\n\n    if has_native_find_flags(args) {\n        parse_native_find_args(args)\n    } else {\n        parse_rtk_find_args(args)\n    }\n}\n\n/// Parse native find syntax: `find [path] -name \"*.rs\" -type f -maxdepth 3`\nfn parse_native_find_args(args: &[String]) -> Result<FindArgs> {\n    let mut parsed = FindArgs::default();\n    let mut i = 0;\n\n    // First non-flag argument is the path (standard find behavior)\n    if !args[0].starts_with('-') {","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/rtk-ai/rtk/blob/29f9bb7161775cd807565fd3041eb2b7d1be071c/src/cmds/system/find_cmd.rs#L71-L107","documentation":"RTK's find replacement (parse_find_args in src/cmds/system/find_cmd.rs) supports only simple searches: its compact syntax (`rtk find '*.rs' [path] [-m max] [-t type]`) and single-predicate native syntax (`-name`, `-type`, `-maxdepth`, ...). Before parsing it scans argv for UNSUPPORTED_FIND_FLAGS — `-not`, `!`, `-or`, `-o`, `-and`, `-a`, `-exec`, `-execdir`, `-delete`, `-print0`, `-newer`, and friends — and aborts on any exact-token match. This is a deliberate scope limit: silently mishandling compound predicates or side-effecting actions would return wrong or destructive results, so rtk refuses and points you at the real `find`.","triggerScenarios":"Any `rtk find` invocation containing a token from UNSUPPORTED_FIND_FLAGS, e.g. `rtk find . -name '*.rs' -not -name '*_test.rs'`, `rtk find . -exec rm {} \\;`, `rtk find . -newer ref -type f`, `rtk find . -name '*.tmp' -delete`.","commonSituations":"Agents piping every find through rtk by habit; muscle-memory GNU find idioms with -not/-exec; scripts assuming rtk find is a drop-in find replacement.","solutions":["Run the system `find` directly for compound predicates or actions; wrap with `rtk proxy find ...` if you still want it counted in rtk's usage stats.","Rewrite as a simple predicate rtk supports: `rtk find '*.rs' -t f` or `rtk find . -name '*.rs' -type f -maxdepth 3`.","For -exec/-delete effects, use find itself or a small shell loop — rtk deliberately avoids reproducing side-effecting actions."],"exampleFix":"# before\nrtk find . -name '*.tmp' -not -name '*.keep' -delete\n\n# after — use the real find (rtk supports neither -not nor -delete)\nfind . -name '*.tmp' -not -name '*.keep' -delete\n# or keep it in rtk usage stats:\nrtk proxy find . -name '*.tmp' -not -name '*.keep' -delete","handlingStrategy":"validation","validationCode":"# bash — pre-check the tokens rtk find rejects before invoking it\nUNSUPPORTED='-not ! -or -o -and -a -exec -execdir -delete -print0 -newer'\nfor a in \"$@\"; do\n  case \" $UNSUPPORTED \" in\n    *\" $a \"*) exec find \"$@\" ;;   # compound predicate -> real find\n  esac\ndone\nrtk find \"$@\"","typeGuard":"rtk_find_safe() {\n  # returns 0 when no argv token is in rtk find's unsupported-flag set\n  local a\n  for a in \"$@\"; do\n    case \" $a \" in\n      ' -not '|' ! '|' -or '|' -o '|' -and '|' -a '|' -exec '|' -execdir '|' -delete '|' -print0 '|' -newer ') return 1 ;;\n    esac\n  done\n  return 0\n}","tryCatchPattern":"out=$(rtk find \"$@\" 2>&1) || {\n  case \"$out\" in\n    *'compound predicates'*) exec find \"$@\" ;;  # deliberate scope limit -> raw find\n  esac\n  printf '%s\\n' \"$out\" >&2; exit 1\n}\nprintf '%s\\n' \"$out\"","preventionTips":["Keep a mental split: rtk find for quick simple lookups, system find for anything with -not/-exec/-delete/-newer.","In agent prompts, state that compound find predicates must call find directly (or via rtk proxy find).","When in doubt, `rtk proxy find ...` always works and still records usage."],"tags":["find","file-search","cli","unsupported-flag"],"backgroundTag":"unsupported-cli-flag","analyzedSha":"29f9bb7161775cd807565fd3041eb2b7d1be071c","analyzedAt":"2026-08-20T15:54:42.457Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}