Skip to main content

kaish_kernel/tools/
mod.rs

1//! Tool system for kaish.
2//!
3//! Tools are the primary way to perform actions in kaish. Every command
4//! is a tool — builtins and user-defined tools all implement
5//! the same `Tool` trait.
6//!
7//! # Architecture
8//!
9//! ```text
10//! ToolRegistry
11//! ├── Builtins (echo, ls, cat, ...)
12//! └── User Tools (defined via `tool` statements)
13//! ```
14
15mod builtin;
16mod clap_schema;
17mod context;
18mod global_flags;
19mod registry;
20mod traits;
21// Wrapped commands run external programs, so the module only exists on the
22// `subprocess` axis; a sandbox build has no `wrapped` module at all.
23#[cfg(feature = "subprocess")]
24pub mod wrapped;
25
26pub use builtin::register_builtins;
27#[cfg(feature = "subprocess")]
28pub use builtin::{resolve_in_path, virtual_cwd_error};
29pub use clap_schema::{params_from_clap, schema_from_clap, schema_tree_from_clap};
30pub use context::{
31    external_commands_unavailable_error, ExecContext, ExternalCommandsUnavailable,
32    GateExpectations, OutputContext, OverwriteExpectation, DEFAULT_KILL_GRACE,
33};
34pub(crate) use context::{cas_overwrite, is_trash_excluded, ExternalCommandOutcome};
35pub use global_flags::GlobalFlags;
36pub use registry::ToolRegistry;
37pub use traits::{ArgBinding, global_flag_value_is_truthy, is_global_output_flag, validate_against_schema, Tool, ToolArgs, ToolCtx, ToolSchema, ParamSchema};
38
39/// Commands that consume bareword `key=value` argv (Arg::WordAssign) as
40/// shell-assignment pairs and route them through `tool_args.named`. For every
41/// other command, `key=value` lands as a positional `"key=value"` string —
42/// matching bash (`cat foo=bar` opens a file named `foo=bar`).
43///
44/// Add to this list only for builtins that have a documented shell-assignment
45/// argv contract (`export FOO=bar`, `alias greet='echo hi'`). Long-flag
46/// `--key=value` is a separate AST node (`Arg::Named`) and routes through
47/// `tool_args.named` regardless — except past `--`, where both spellings
48/// become literal positionals.
49pub const WORD_ASSIGN_BUILTINS: &[&str] = &["export", "alias", "unalias"];
50
51pub fn accepts_word_assign(name: &str) -> bool {
52    WORD_ASSIGN_BUILTINS.contains(&name)
53}