ValetFS addresses the security problem of local AI agents using API keys. Traditional approaches typically write keys into shell config files, environment variables, or dotfiles, which can easily be read by subsequent prompt injection attacks. ValetFS keeps keys on the phone side (protected by Face ID); when a tool or AI agent on the computer needs a key, the valetfs daemon temporarily borrows it into memory and returns it once use is complete. After the app is closed, a grace timer starts, and after it times out, the daemon unmounts and wipes itself, leaving no plaintext on disk.
Main capabilities
- Zero backend, peer-to-peer, in-memory virtual filesystem: exposes short-lived tokens and keys to AI agents only when the paired mobile app allows it.
- Provides a Go daemon and a Cloudflare Worker signaling stub.
- Supports FUSE mounting, and automatically falls back to a local WebDAV endpoint if unavailable.
- Provides local CLI commands: ls, status, cat, exec, cp, mv, rm, mkdir, rmdir, and more.
- Keys exist only in the daemon's heap memory; on Ctrl-C, remote lock/unmount, or the app forgetting the session, the daemon unmounts and zero-wipes memory; when unclaimed, it automatically locks after a grace period.
- The connection key itself contains the signaling URL, so there is no need to additionally specify --signaling.
- Uses WebSocket transport (Cloudflare Durable Object) with end-to-end encryption by default, and also supports the legacy P2P path via --transport webrtc.
- Supports Vault pairing between two devices via the CLI, without the need for a mobile app.
Usage
AI agents can access the in-memory filesystem through the local CLI. The secure usage is to use valetfs exec, injecting keys as environment variables into a child process, rather than using cat to print keys to stdout (which would otherwise enter agent records, shell history, and logs). exec passes through the child process's stdout, stderr, and exit code as-is, and can be embedded into existing pipelines or && chains. --as-file materializes a key as a 0600 permission file in a memory-backed directory, zeroing and deleting it on exit. Multiple options can be repeated to inject multiple keys at once. ls and status only report names, sizes, and daemon status, without showing contents, and can safelyCall.
If using an agent such as Claude Code that intercepts valetfs cat, a command must be run manually to merge the valetfs-related permissions into the user-level settings file ($CLAUDE_CONFIG_DIR/settings.json or ~/.claude/settings.json), preserving other keys and their order, backing up the original file as settings.json.valetfs-backup; running it repeatedly has no side effects. Writes and deletions (cp, mv, rm) are not granted by default, and cat also requires explicit addition via --allow-cat.
Steps for an AI agent to quickly connect to a session:
- Install the valetfs CLI (Linux x86_64 / arm64); no root, drivers, or FUSE required; if FUSE is unavailable, the daemon serves files via a loopback WebDAV endpoint. Installation without sudo: ... | INSTALL_DIR=$HOME/.local/bin bash, and ensure that directory is in PATH. On macOS/Windows or unsupported architectures, build from source: git clone https://github.com/winm2m/valet-fs && cd valet-fs && go build -o valetfs ./cmd/valetfs. 1b. Install the agent skill (Claude Code and other agents that support skills) by placing the valetfs skill into ~/.claude/skills/. Setting SKILL_DIR= allows installation into a single project.
- Join the session using the connection key provided by the user; this command connects as a daemon, publishes the E2EE public key, and starts an in-memory filesystem. Keep it running, then the user pushes the key from the app, and it can be read with the local CLI.
Vault paths require the fs: prefix; a bare /keys will be treated as a local path. ls/cat/exec reject bare paths, while cp/mv accept both paths and infer direction; omitting the prefix will silently write plaintext to disk.
Use cases
- A local AI agent or coding assistant needs temporary access to an API key but wants to avoid the key touching disk.
- You want to keep keys centralized on your phone and lend them out temporarily after biometric authorization.
- You need to manage keys securely in local environments without cloud workload identity federation (laptops, home servers, containers).
Limitations and security guarantees
- On each startup, the daemon first performs an unmount (fusermount -uz or Windows net use /delete) before remounting, ensuring idempotent mounting.
- Graceful shutdown on SIGINT/SIGTERM: after unmounting, all file contents in memory are erased.
- No plaintext on disk: the diff repository under $VALETFS_GIT_DIR contains only sha256, size, and path manifest lines, with no token contents.
- Quota enforcement: MemFS rejects writes exceeding the configured cluster quota (--quota-mb, default 5MB).
- exec does not write key values into its own output; keys are passed to child processes via environment variables; on failure it reports only the vault path, and malformed env files report only the line number, never outputting file contents. --as-file materializes in an memory-backed directory with 0600 permissions, and is zeroed and deleted on all exit paths (including signal termination).
- The internal vfs and sync packages have headerless unit tests covering memory wiping, quota enforcement, path traversal rejection, and manifest non-leakage.
The project's current implementation is optimized for first controller pairing per session; if rejoin times out, a new serve session must be created. TURN credentials are not embedded in source code or binaries; short-lived credentials are issued by a Cloudflare Worker using a secret.