agent_shell_parser/parse/mod.rs
1//! Shell command parsing and structural analysis.
2//!
3//! This module is **policy-free** — it decomposes shell commands into
4//! structured representations but makes no allow/deny decisions.
5//! Consumers (agent-jj-guard, cc-toolgate) build policy on top.
6//!
7//! ## Entry points
8//!
9//! - [`parse_with_substitutions`] — decompose a compound shell command
10//! into a recursive [`ParsedPipeline`] tree.
11//! - [`parse_command`] — structurally parse a single command into
12//! [`ParsedCommand`] with ordered [`CommandArg`]s (flags and positionals
13//! in source order).
14//! - [`resolve_command`] — strip transparent wrappers (env, sudo, etc.)
15//! and classify unanalyzable patterns (eval, source, shell -c).
16//!
17//! ## Design principles
18//!
19//! - **Parser annotates, consumer decides.** The library classifies
20//! commands; the consumer interprets classifications as policy.
21//! - **Schema-free argument parsing.** `ParsedCommand` identifies flags
22//! syntactically (`-` prefix). Flag-value association requires the
23//! consumer's knowledge of the command's schema. Arguments are kept
24//! in source order so consumers can walk them with schema awareness.
25//! - **Fail-closed on ambiguity.** Parse errors and unresolvable
26//! patterns (dynamic `$cmd`, eval) are surfaced, not hidden.
27
28mod redirect;
29mod resolve;
30pub mod shell;
31mod subst;
32pub mod tokenize;
33pub mod types;
34mod walk;
35
36pub use resolve::{default_command_config, resolve_command, resolve_command_with, strip_with_spec};
37pub use shell::{dump_ast, has_output_redirection, parse_with_substitutions};
38pub use tokenize::{
39 base_command, command_characteristics, env_vars, find_base_command, parse_command, tokenize,
40};
41pub use types::{
42 CommandArg, CommandCharacteristics, CommandConfig, IndirectExecution, Operator, ParseError,
43 ParsedCommand, ParsedFlag, ParsedPipeline, Redirection, ResolvedCommand, ShellSegment,
44 SubstitutionSpan, UnanalyzableCommand, WrapperSpec,
45};