# async-fs-io
[](https://crates.io/crates/async-fs-io)
[](https://docs.rs/async-fs-io)
[](https://github.com/legra-ai/async-fs-io/actions/workflows/ci.yml)
[](LICENSE-APACHE)
Async-first filesystem primitives for Tokio applications that must keep file
I/O centralized, bounded, and observable.
The crate provides:
- `AsyncFile`, an async low-level file handle for sequential and random-access
operations;
- bounded whole-file reads that require an explicit byte ceiling;
- streaming directory traversal with one directory entry in flight;
- atomic writes that stream through a temporary file;
- explicit asynchronous temporary-directory cleanup;
- typed filesystem errors with path and operation context.
Large files and directories are never implicitly loaded into memory. Use
`AsyncFile` or the streaming helpers for unbounded data and use bounded reads
only when the caller has an explicit size contract.
## Enforcing the filesystem boundary
The crate is designed to be the single filesystem boundary for an application.
Do not call `std::fs`, `tokio::fs`, blocking filesystem APIs, or private wrappers
around them anywhere else in the repository.
Run the repository lint with:
```text
./.scripts/lint-fs-io.sh --allow-path src
```
Copy that command into CI and the repository's pre-commit hook (this
repository runs it in both). In a consuming repository, omit
`--allow-path src`; the consumer has no filesystem backend allowlist. The
lint scans production code, tests, benchmarks, and private helpers, and it
matches both fully-qualified paths (`std::fs::read`) **and** the import
statements themselves (`use std::fs;`, `use tokio::fs as t;`), so aliasing
cannot slip a call past it. Its only allowlist in this repository is the
audited backend implementation under `src`.
## License
Licensed under either of:
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE));
- MIT License ([LICENSE-MIT](LICENSE-MIT)).