File Mirrors
File mirrors let you keep copies of files in sync across multiple locations with one-way synchronization from source to target.
The Main Use Case: AI Context Files
If you’re using AI coding assistants, you’ve likely created context files:
- CLAUDE.md — Claude Code (docs)
- AGENTS.md — OpenAI Codex, emerging standard (agents.md)
- .cursorrules — Cursor AI (or
.cursor/rules/) - .github/copilot-instructions.md — GitHub Copilot
- .windsurfrules — Windsurf (or
.windsurf/rules/) - GEMINI.md — Google Gemini CLI
The industry is converging on AGENTS.md as the standard — GitHub Copilot, Codex, and others now read it automatically alongside their native formats.
The problem? You end up maintaining the same instructions across multiple projects. Update one, forget the others, and your AI context drifts out of sync.
File mirrors solve this. Create one master context file, mirror it to all your projects, and sync with a single keystroke.
Best Practice: Use a Dedicated Source File
Don’t use CLAUDE.md as your source. Instead, create a dedicated file
like context.md as your single source of truth, then mirror it to all the
AI tool files.
Why? The source file contains strayfiles tracking metadata (frontmatter or HTML comments). When you mirror, that metadata is automatically stripped from the targets. Your AI tools see clean files without any strayfiles markup.
Master file: ~/dotfiles/context.md (with frontmatter)
↓ (metadata stripped)
Mirror targets: ~/projects/frontend/CLAUDE.md
~/projects/backend/CLAUDE.md
~/projects/mobile/AGENTS.md
~/work/client-app/.cursor/rules
Edit your master context.md once, press S to sync all, and every project
gets clean files with no frontmatter clutter.
Cross-Tool Synchronization
Different AI tools use different filenames, but often need similar context. Mirrors let you maintain one source of truth:
Source: ~/dotfiles/ai-context.md
↓
Targets:
~/project-a/CLAUDE.md
~/project-a/AGENTS.md
~/project-a/.cursorrules
~/project-b/.github/copilot-instructions.md
~/project-c/.windsurfrules
Your coding standards, project conventions, and AI instructions stay consistent across every tool and every project.
Pro tip: Since AGENTS.md is becoming the standard and is now read by Copilot, Codex, and others, you might only need to mirror to AGENTS.md plus any tool-specific files for tools that don’t support it yet.
What Are File Mirrors?
Sometimes you need the same file content in multiple places:
- A
CLAUDE.mdcontext file shared across several projects - A
README.mdthat needs to appear in multiple directories - Documentation that should be mirrored to a backup location
File mirrors solve this by creating a source → target relationship. When you sync, the source content is copied to all targets.
Key difference from note sync: Mirrors work on ANY file, whether or not it’s tracked by Strayfiles. They’re purely file-to-file copying.
Creating a Mirror
From File Discovery
- Press
/to open file discovery - Navigate to the file you want to mirror
- Press
mto open the mirror action menu - Select “Create Mirror”
- Enter the target file path
From the Mirrors Dialog
- Open Settings (
sfrom notebook view) - Navigate to Mirrors section
- Select “Manage Mirrors”
- Press
nto create a new mirror - Enter source and target paths
How Mirroring Works
The Sync Process
When you sync a mirror:
- Read source — The source file content is read
- Strip metadata — Strayfiles tracking metadata is removed
- Atomic write — Content is written to target (crash-safe)
- Update timestamp — Last sync time is recorded
Metadata Stripping
When a source file contains Strayfiles tracking metadata, it’s automatically stripped during sync. This is critical to prevent UUID conflicts — without stripping, the target file would have the same UUID as the source, causing Strayfiles to treat them as the same note.
Why this matters:
- Each tracked file needs a unique UUID
- If you mirror a tracked file without stripping, you’d have duplicate UUIDs
- Strayfiles would get confused about which file is which
- Edits to either file could overwrite the other unexpectedly
Stripped content:
- YAML frontmatter
strayfiles:section (the tracking block) - HTML comment metadata
<!-- strayfiles: {...} -->
Preserved content:
- All user frontmatter (title, tags, custom fields)
- The entire document body
- HTML comments that aren’t Strayfiles metadata
Example with YAML frontmatter:
Source file:
---
title: My Project README
strayfiles:
enabled: true
id: "019abc12-3456-7890-abcd-ef1234567890"
workspaces: ["work"]
tags: [documentation]
---
# My Project
...
After mirroring (target file):
---
title: My Project README
---
# My Project
...
Example with HTML comment:
Source file:
<!-- strayfiles: {"enabled":true,"id":"019abc12-..."} -->
# My README
...
After mirroring (target file):
# My README
...
The target file is now a clean copy with no Strayfiles tracking. If you want to track the target file separately, you can add it to Strayfiles and it will get its own unique UUID.
Managing Mirrors
The Mirrors Dialog
Access via Settings → Mirrors → Manage Mirrors.
The dialog shows all configured mirrors with:
- Source file path
- Target file path
- Enabled/disabled status
- Last sync timestamp
- Any sync errors
Keyboard Shortcuts
| Key | Action |
|---|---|
j / k | Navigate mirrors |
e | Toggle enabled/disabled |
s | Sync selected mirror |
S | Sync all enabled mirrors |
d | Remove mirror (with confirmation) |
Esc | Close dialog |
Enabling and Disabling
Toggle a mirror’s enabled state with e. Disabled mirrors:
- Won’t sync when you press
S(sync all) - Preserve the target file as-is
- Can be re-enabled later
Auto-Sync
Auto-sync automatically keeps your mirrors updated when source files change. Enable it in Settings → Mirrors → Auto-Sync.
When enabled:
- Mirrors sync automatically when you save changes to a source file
- Only enabled mirrors are synced (disabled mirrors are skipped)
- Syncing happens silently in the background
- You can still sync manually with
sorSat any time
Auto-sync uses the file watcher to detect changes, so there may be a brief delay (typically under a second) before mirrors update.
Removing Mirrors
When you remove a mirror (d), you’ll be asked whether to:
- Keep target file — Only removes the mirror relationship
- Delete target file — Removes both the relationship and the target
Constraints and Limits
| Constraint | Limit |
|---|---|
| Mirrors per source | 20 maximum |
| Target uniqueness | Each target path must be unique per source |
| Source existence | Source file must exist when creating |
| Path overlap | Source and target must be different files |
Use Cases
AI Context Distribution
Keep your AI context synced across multiple projects using a dedicated source:
Source: ~/dotfiles/context.md
Target 1: ~/projects/app-backend/CLAUDE.md
Target 2: ~/projects/app-frontend/AGENTS.md
Target 3: ~/projects/shared-lib/.cursor/rules
When you update your master context.md, sync to propagate clean files everywhere.
README Duplication
Mirror a README to appear in multiple package directories:
Source: ~/monorepo/README.md
Target 1: ~/monorepo/packages/core/README.md
Target 2: ~/monorepo/packages/cli/README.md
Documentation Backup
Keep important docs backed up:
Source: ~/projects/app/docs/architecture.md
Target: ~/Dropbox/backups/app-architecture.md
What Happens If You Edit a Target File?
Your changes will be lost on the next sync.
Mirrors are strictly one-way. When you sync:
- The source file content is read
- The target file is completely overwritten
There’s no merge, no conflict detection, no warning. The target becomes an exact copy of the source (minus Strayfiles metadata).
If You Accidentally Edit a Target
If you realize you edited a target file instead of the source:
- Before syncing: Copy your changes from the target to the source
- After syncing: Your changes are gone — check version history if the target was a tracked note
Best Practices
- Use a dedicated source file — Create
context.mdinstead of usingCLAUDE.mddirectly, so metadata is stripped from all targets - Always edit the source — Train yourself to go to the master file
- Disable before editing — If you need to customize a target temporarily, disable its mirror first to prevent accidental overwrites
Why No Two-Way Sync?
Mirrors are intentionally simple. Two-way sync introduces:
- Conflict resolution complexity
- Race conditions between devices
- Unexpected merge results
If you need bidirectional sync, use Strayfiles’ note sync feature instead, which has proper version tracking and conflict resolution.
Tips
-
Disabled mirrors preserve targets — Use disable instead of remove if you want to pause syncing without affecting the target file
-
Mirrors work on untracked files — You don’t need to track a file with Strayfiles to mirror it
-
Metadata stripping is automatic — You don’t need to manually remove Strayfiles metadata before mirroring
-
Atomic writes are crash-safe — If sync is interrupted, the target won’t be left in a corrupted state
-
Auto-sync keeps targets updated — Enable Auto-Sync in Settings → Mirrors to automatically sync mirrors when source files change. You can also sync manually with
sorSat any time