---
name: file-system
description: Safe filesystem operations for agents, including path normalization vs resolution, temp file handling, atomic replacement, and spooled buffers. Use when reading/writing user-supplied paths, staging outputs, or managing temporary files; triggers: filesystem, os.path, tempfile, path normalization, realpath, atomic write.
---

# File System Operations

## Overview
Apply safe path handling and temporary file patterns so reads and writes are reliable, even with untrusted input or large intermediate data.

## When to Use
- Use this skill only after the frontmatter triggers; otherwise start with a simple read/write path.

## Decision Tree
1. Normalize or resolve the path?
   - Normalize only: use `os.path.normpath()` for lexical cleanup.
   - Resolve + check existence: use `os.path.realpath(path, strict=True)`.
2. Are you writing to a target path that may already exist?
   - Yes: write to a temp file in the same directory and replace.
3. Is the file size unknown or potentially large?
   - Yes: use `tempfile.SpooledTemporaryFile` to avoid unnecessary disk writes.

## Workflows

### 1. Normalize vs Resolve Paths
1. Normalize user input with `os.path.normpath()` to collapse redundant segments.
2. Resolve real paths with `os.path.realpath(path, strict=True)` when you must confirm the file exists.
3. Reject paths that fail resolution or escape your allowed base directory.

### 2. Atomic Replace Write
1. Create a temporary file in the destination directory.
2. Write and flush content to the temp file.
3. Replace the destination with `os.replace`/`os.rename` after the write completes.
4. Ensure the temp file and destination are on the same filesystem.

### 3. Spooled Temporary Buffer
1. Create `tempfile.SpooledTemporaryFile(max_size=...)`.
2. Stream data into the spooled file as you process it.
3. Call `.rollover()` to force the buffer onto disk when needed.

## Non-Obvious Insights
- `normpath` is lexical only and can change the meaning of a path with symlinks.
- `realpath(..., strict=True)` raises `FileNotFoundError` when the path does not exist.
- `os.rename` is atomic on POSIX when successful; keep temp and destination on the same filesystem.
- Temporary files may not have a visible name; do not rely on name visibility.
- Spooled temp files can be forced to disk with `rollover()` when a file grows.

## Evidence
- "Normalize a pathname by collapsing redundant separators and up-level references so that A//B, A/B/, A/./B and A/foo/../B all become A/B. This string manipulation may change the meaning of a path that contains symbolic links." - [Python Docs](https://docs.python.org/3/library/os.path.html)
- "FileNotFoundError is raised if path does not exist, or another OSError if it is otherwise inaccessible." - [Python Docs](https://docs.python.org/3/library/os.path.html)
- "If successful, the renaming will be an atomic operation (this is a POSIX requirement)." - [Python Docs](https://docs.python.org/3/library/os.html#os.rename)
- "Rename the file or directory src to dst. If dst exists and is a file, it will be replaced silently if the user has permission. The operation may fail if src and dst are on different filesystems." - [Python Docs](https://docs.python.org/3/library/os.html#os.replace)
- "TemporaryFile, NamedTemporaryFile, TemporaryDirectory, and SpooledTemporaryFile are high-level interfaces which provide automatic cleanup and can be used as context managers." - [Python Docs](https://docs.python.org/3/library/tempfile.html)
- "should not rely on a temporary file created using this function having or not having a visible name in the file system." - [Python Docs](https://docs.python.org/3/library/tempfile.html)
- "rollover() ... causes the file to roll over to an on-disk file regardless of its size." - [Python Docs](https://docs.python.org/3/library/tempfile.html)

## Scripts
- `scripts/file-system_tool.py`: CLI for resolve, atomic write, copy, and safe reads.
- `scripts/file-system_tool.js`: Node.js CLI equivalents.

## Dependencies
- Python standard library (`os`, `tempfile`, `pathlib`, `shutil`) or Node standard library (`fs`, `path`, `os`).

## References
- [references/README.md](references/README.md)
