1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# Bashkit core library
# Sandboxed bash interpreter for multi-tenant environments
[]
= "bashkit"
= true
= true
= true
= true
= true
= true
= true
= true
= "../../README.md"
[]
# Async runtime
= { = true }
= { = true }
# futures-core / tower are only pulled in by the LLM `BashTool` wrapper
# (and the `scripted_tool` layer on top of it). Optional, gated under `bash_tool`.
= { = true, = true }
= { = true }
= { = true, = true }
# Error handling
= { = true }
= { = true }
# Serialization
= { = true }
= { = true }
= { = true, = true }
# Regex
= { = true }
= { = true }
# Date/Time
= { = true }
= { = true, = true }
# HTTP client (for curl/wget) - optional, enabled with http_client feature
= { = true, = true }
# Direct rustls dep so we can install the crypto provider ourselves at runtime
# (paired with reqwest's `rustls-no-provider` feature). Optional, gated under
# http_client. The backend is chosen by the `ring` (default) / `aws-lc-rs`
# features, not pinned here.
= { = true, = true }
# SSH client (for ssh/scp/sftp) - optional, enabled with ssh feature
= { = true, = true }
# Fault injection for testing (optional)
= { = true, = true }
# URL parsing
= "2"
# Compact flag bitsets used by the interpreter for variable attributes
# (readonly/integer/lower/upper) and shell options (set -e/-u/-x/-o pipefail).
# Stays the format!()-based `_READONLY_X`/`SHOPT_*` keys off the hot path.
= "2"
# JSON processing (jq) - optional, enabled with jq feature
= { = true, = true }
= { = true, = true }
= { = true, = true }
# Compression (for gzip/gunzip and bzip2/bunzip2)
= { = true }
= { = true }
# Base64 encoding (for base64 builtin and HTTP basic auth)
= { = true }
# Ed25519 signing for bot-auth request signing (optional)
= { = true, = true }
= { = true, = true }
= { = true, = true }
# CSPRNG for credential placeholder generation
= { = true }
# Checksums (for md5sum, sha1sum, sha256sum builtins)
= { = true }
= { = true }
= { = true }
= "0.13"
# Logging/tracing (optional)
= { = true, = true }
# CLI-style argument parsing for custom builtins and ported coreutils
# argument surfaces. Always on — see knowledge/runtimes/coreutils-args-port.md.
= { = true }
# Pinned to uutils' workspace versions. Used by the vendored
# uucore::format module (see crates/bashkit/src/builtins/generated/format)
# that backs `printf`. Kept platform-clean — no rustix / errno
# transitive deps — so wasm32 stays buildable.
= "0.4"
= "0.2"
= "0.5"
= "0.1.3"
# Embedded Python interpreter (optional).
# Registry dep since monty 0.0.19 — the first version published to crates.io.
# Keeps `python` usable for downstream crates and lets the publish workflow
# ship the feature instead of stripping it.
#
# Important decision (security): held at 0.0.19. Cargo treats `0.0.z` as its own
# compatibility range (`^0.0.19` == `>=0.0.19, <0.0.20`), so this is already an
# exact pin; the matching `ignore` entries in .github/dependabot.yml stop the
# bump PRs from being regenerated.
#
# 0.0.21 moves `max_memory` enforcement from host-side accounting to a probe of
# the `LIVE_MEMORY`/`BASELINE_MEMORY` globals, which only the separate
# `monty-alloc` crate writes — and only when installed as the process-wide
# global allocator. Bashkit is an embeddable library (and bashkit-python is a
# CPython extension module), so it cannot impose a global allocator on its
# hosts. Without one, `probe_memory()` is `0.saturating_sub(usize::MAX)` == 0
# and the Python sandbox's memory ceiling silently stops being enforced.
# See knowledge/runtimes/python-builtin.md § Upgrade blocker.
= { = "0.0.19", = true }
= { = "0.0.19", = true }
# Embedded TypeScript interpreter (optional)
= { = "1.5.1", = true }
# Embedded SQLite engine via Turso (optional, BETA upstream).
# Pulls a multi-MB transitive dep tree only when the `sqlite` feature is active.
= { = true, = true }
[]
= ["bash_tool", "ring", "tzdata"]
# Named IANA timezone support for the `date` builtin's `TZ=` handling, via the
# chrono-tz database. On by default.
#
# Important decision: this is a feature, not an unconditional dep, because
# chrono-tz compiles the whole IANA database in -- by far the largest single
# artifact in the tree (an 18.6 MB rlib) -- to serve three lines of use in
# builtins/date.rs. Builds that do not need named zones (the slim browser wasm
# package) should not carry it.
#
# Turning it off does not open a hole. `SandboxTimezone` closes to UTC alone and
# `date` reports that it cannot honour a named zone, exiting 1 rather than
# formatting in UTC and returning a plausible-looking wrong time. The
# fail-closed direction of THREAT[TM-INF-018] is unchanged: host timezone state
# is still never consulted. `TZ=UTC`, unset, empty, and path-style values are
# unaffected.
= ["dep:chrono-tz"]
# Enable the LLM-facing `BashTool` wrapper: the `Tool` trait, `ToolExecution`,
# OpenAI tool-definition/JSON-schema helpers, and the `tower::Service` bridge.
# On by default. Disable with `--no-default-features` to compile just the
# embeddable `Bash` interpreter and drop the `tower` / `futures-core` deps.
# Usage: cargo build --no-default-features [--features <others>]
= ["dep:tower", "dep:futures-core"]
# Route getrandom at JS (`crypto.getRandomValues`) on wasm32-unknown-unknown.
# Needed by JS hosts (browsers, workers, Node); must stay off for non-JS wasm
# embedders, which supply their own getrandom backend via
# `--cfg getrandom_backend="custom"`.
# Usage: cargo build --target wasm32-unknown-unknown --features wasm_js
= [
"getrandom/wasm_js",
"chrono/wasmbind",
"dep:web-time",
"dep:gloo-timers",
"dep:send_wrapper",
]
# Enable jq builtin via embedded jaq interpreter
# Usage: cargo build --features jq
= ["dep:jaq-core", "dep:jaq-std", "dep:jaq-json", "dep:serde_yaml_ng"]
# HTTP client (curl/wget) over rustls. Does NOT imply a crypto backend: pick
# `ring` (on by default) or `aws-lc-rs`. Enabling neither is a compile error.
= ["reqwest", "rustls"]
# Crypto backend for the rustls-based HTTP client. Exactly one is used at
# runtime; `ring` wins when both are on, which keeps Cargo's additive feature
# unification sound (a consumer asking for `aws-lc-rs` still compiles and still
# installs exactly one provider when something else re-enables `ring`).
#
# Important decision: `ring` is the default because it keeps the dependency
# tree free of C-compiled crypto (no aws-lc-sys), which is what keeps
# cross-compiled aarch64 manylinux wheel builds green — that cross sysroot is
# missing `AT_HWCAP2` and aws-lc-sys trips over it. `aws-lc-rs` exists for
# consumers who need a FIPS-capable backend or who already link aws-lc-rs and
# want to avoid shipping two crypto libraries.
= ["rustls?/ring"]
= ["rustls?/aws-lc-rs"]
# Enable Ed25519 request signing per RFC 9421 / web-bot-auth profile
= ["http_client", "dep:ed25519-dalek", "dep:rand", "dep:zeroize"]
# Enable fail points for security/fault injection testing
# Usage: FAILPOINTS="fail_point_name=action" cargo test --features failpoints
= ["fail/failpoints"]
# Enable structured logging via tracing crate
# Usage: cargo build --features logging
= ["tracing"]
# Enable git builtin for sandboxed git operations
# Phase 1: Local operations (init, config, add, commit, status, log)
# Phase 2 will add gix dependency for remote operations
# Usage: cargo build --features git
= []
# Enable ssh/scp/sftp builtins for remote command execution and file transfer
# Usage: cargo build --features ssh
= ["russh"]
# Enable ScriptedTool: compose ToolDef+callback pairs into a single Tool
# Builds on the `BashTool` contract, so it pulls in the `bash_tool` feature.
# Usage: cargo build --features scripted_tool
= ["bash_tool"]
# Enable python/python3 builtins via embedded Monty interpreter
# Usage: cargo build --features python
= ["dep:monty", "dep:monty-types"]
# Enable ts/node/deno/bun builtins via embedded ZapCode TypeScript interpreter
# Usage: cargo build --features typescript
= ["dep:zapcode-core"]
# Enable sqlite/sqlite3 builtins backed by Turso (pure-Rust SQLite-compatible
# engine). Phase 1 uses turso's `MemoryIO` with a load/flush against the VFS
# at command boundaries; Phase 2 plugs the bashkit VFS in via a custom `IO`
# implementation. Both paths share the same builtin and dot-command surface.
# See knowledge/runtimes/sqlite-builtin.md.
#
# Turso is BETA upstream — keep this off by default and document the risk.
# Requires the multi-threaded tokio runtime so the sync `IO` trait can bridge
# back to the async VFS via `block_in_place`.
# Usage: cargo build --features sqlite
= ["dep:turso_core", "tokio/rt-multi-thread"]
# Enable RealFs backend for accessing host filesystem directories
# WARNING: This intentionally breaks the sandbox boundary.
# Usage: cargo build --features realfs
= ["dep:rand"]
# Enable native-extension interop contracts such as bashkit::interop::fs.
= ["tokio/rt-multi-thread"]
[]
= true
= ["--cfg", "docsrs"]
[]
= { = true }
= { = true }
= { = true }
= { = "0.8", = ["async_tokio"] }
= { = true }
= "3"
= { = true }
# Important decision: consolidate the bulk of integration tests into one
# binary. Cargo's auto-discovery makes every `tests/*.rs` its own crate,
# statically linking the world (monty, zapcode, turso, russh, jaq,
# reqwest+rustls, ed25519-dalek) — 80+ link steps blew CI runner disk.
# This single `[[test]]` rolls them up. Tests that need their own binary
# (process-global env mutation, `--test-threads=1`, ssh-only feature
# isolation) remain as siblings at `tests/<name>.rs`. See
# `knowledge/operations/testing.md` for the convention.
[[]]
= "integration"
= "tests/integration/main.rs"
[[]]
= "parallel_execution"
= false
[[]]
= "hotpath"
= false
[[]]
= "file_ops"
= false
[[]]
= "awk_regex"
= false
[[]]
= "snapshot_history"
= false
[[]]
= "sqlite"
= false
= ["sqlite"]
[[]]
= "agent_tool"
= ["http_client"]
[[]]
= "git_workflow"
= ["git"]
[[]]
= "ssh_supabase"
= ["ssh"]
[[]]
= "show_tool_output"
= ["bash_tool"]
[[]]
= "scripted_tool"
= ["scripted_tool"]
[[]]
= "python_scripts"
= ["python"]
[[]]
= "python_external_functions"
= ["python"]
[[]]
= "typescript_scripts"
= ["typescript"]
[[]]
= "typescript_external_functions"
= ["typescript"]
[[]]
= "realfs_readonly"
= ["realfs"]
[[]]
= "realfs_readwrite"
= ["realfs"]
[[]]
= "sqlite_basic"
= ["sqlite"]
[[]]
= "sqlite_workflow"
= ["sqlite"]
# Additional tokio features needed only on native (not WASM)
[]
= { = "1", = ["rt-multi-thread", "fs"] }
# std::time::{Instant,SystemTime} panic on wasm32-unknown-unknown; see
# time_compat/mod.rs. Only pulled in for wasm32 — everywhere else time_compat
# re-exports std::time directly with zero overhead.
#
# These three are JS-backed (wasm-bindgen imports), so they are optional and
# pulled in by `wasm_js`. A non-JS wasm embedder gets time_compat::host_clock
# instead and links none of them: their imports would be unresolvable in a
# runtime with no JS engine.
[]
= { = true, = true }
[]
= { = "0.4", = ["futures"], = true }
= { = "0.6", = ["futures"], = true }
# Vendored uucore modules (e.g. generated/format/human.rs) carry upstream
# `#[cfg(feature = "i18n-decimal")]` gates. bashkit has no i18n surface —
# the port tool hard-errors on Fluent/translate imports — so this feature
# is never defined here and the gated branch is always compiled out. Declare
# it as a known cfg so `unexpected_cfgs` (denied via -D warnings in CI) does
# not flag the vendored code. See knowledge/runtimes/coreutils-args-port.md.
[]
= { = "warn", = ['cfg(feature, values("i18n-decimal"))'] }