Changelog
All notable changes to Atlas are documented here. Entries are grouped by date, with the most recent changes first.
2026-03-19
Fixed: Boot persistence toggle killing the daemon
Toggling “Start on login” OFF in the GUI’s DaemonPopover unexpectedly killed the running daemon. remove_boot_persistence_inner() calls launchctl unload, which kills the managed process — the user only wanted to disable auto-start, not stop the daemon.
- Root cause —
set_boot_persistenceincommands.rscalledlaunchctl unloadwithout checking whether the daemon needed to survive. If the daemon was launchd-managed (from boot or from a previous toggle ON), unloading killed it with no restart - Fix —
set_boot_persistencenow capturesdaemon_is_running()before the launchctl operation. If the daemon was alive before and is dead after, it restarts it standalone viastart_daemon_background()with a 300ms grace period for launchctl to finish - Toggle ON case — Also covered:
launchctl loadwithRunAtLoad=truespawns a new daemon that kills the old one (stale PID cleanup). The was-running/is-running check catches this too if the new process hasn’t started yet
Technical: The explicit stop_daemon() path in tracking.rs is unaffected — it intentionally unloads boot persistence before killing, which is correct for an explicit stop.
Fixed: GUI daemon start (dual-mode binary)
When the GUI called start_daemon_background(), it spawned current_exe() with start --foreground — but current_exe() resolves to Atlas.app/Contents/MacOS/atlas-gui, which opened another GUI window instead of running the watcher. The fix makes atlas-gui a dual-mode binary: if launched with start --foreground args, it skips Tauri and runs the watcher loop directly.
- Arg check in
main.rs— Before callingatlas_gui::run(), checks ifstart --foregroundwas passed. If so, creates an engine and callsrun_foreground()(PID file, signal handling, blocking watcher) without ever initializing the GUI run_foregroundmade public —cli::tracking::run_foreground()changed fromfntopub fnso the GUI binary can call it directly, reusing all existing PID file management and signal handling- No new dependencies —
ctrlcandlibcare already dependencies of theatlascrate whererun_foregroundlives
Technical: The dual-mode approach means boot persistence (launchd) and GUI-spawned daemons both work identically — atlas-gui start --foreground runs as a headless watcher process. CLI users with the standalone atlas binary are unaffected.
Fixed: Live drive connectivity updates in GUI
The GUI now reactively updates the connected/disconnected status of watched paths when external drives are mounted or ejected. Previously, path connectivity was only computed on app launch — reconnecting a drive required restarting the GUI to see the status change.
- GUI-side connectivity polling — The Tauri poller thread (
gui/src-tauri/src/lib.rs) now checksPath::exists()for all active watched paths every 2 seconds, alongside its existing daemon event polling - Change detection — A
HashMap<String, bool>tracks last-known connectivity per path. Only state transitions emit events — the first poll cycle seeds the map silently to avoid a startup flood - Frontend handler —
useDaemonEventshook handles theconnectivity_changedevent type by callingupdatePathConnectivity()in WorkspaceContext, updating the status indicator within ~2-4 seconds of mount/unmount - Daemon decoupled — Removed
connectivity_changedevent emissions fromwatcher.rs. The GUI detects connectivity independently, so it works even when the daemon isn’t running or hasn’t been rebuilt
Technical: Reuses the existing DaemonEventPayload struct and "daemon-event" Tauri event channel. No daemon changes required — connectivity is fully self-contained in the GUI process.
2026-03-18
Added: Ignore & purge flow from Recent activity feed
The Recent activity feed on the Home page is now interactive. Each row has a three-dot menu (hover-reveal, same pattern as Directories) that lets you create ignore rules directly from the activity you’re seeing.
- Three-dot menu on activity rows — Appears on hover, also triggered by right-click. Shows “Show in Finder”, a separator, then ignore actions
- “Ignore this file” — Opens the ignore modal pre-filled with the exact filename (e.g.,
debug.log) - “Ignore files like this…” — Opens the ignore modal pre-filled with an extension-based pattern (e.g.,
*.log). Only shown when the file has an extension - IgnorePatternModal component — New inline panel (
gui/src/components/shared/IgnorePatternModal.tsx) with: editable pattern input (monospace), reason field, scope selector (auto-detects watched directory from entity path), debounced dry-run preview showing matching entity count with expandable list, purge toggle with destructive warning, and Add Rule / Cancel actions forget_pattern_dry_runcommand — Tauri command exposing the engine’s pattern-based entity matching. Returns matching entities with name, path, statusignore_and_purgecommand — Single Tauri command that adds an ignore rule and optionally purges matching entities in one callremoveLogEntriesByEntityIds— New WorkspaceContext helper that filters purged entities from the log state after a successful purge
Technical: ForgetPatternPreview and ForgetPatternMatch in engine.rs gained #[derive(Serialize)] to support the new Tauri commands. The dry-run uses the same CompiledIgnoreSet matching as the production ignore pipeline.
Added: Show in Finder (directories + activity feed) — in progress
“Show in Finder” is wired up in both the directory context menu and the activity feed context menu. Currently migrating from tauri-plugin-shell (whose open() scope validation silently blocks local file paths) to tauri-plugin-opener (which has a dedicated revealItemInDir API using NSWorkspace on macOS).
tauri-plugin-openeradded — New dependency inCargo.tomlandpackage.json, plugin registered inlib.rsopener:allow-reveal-item-in-dir— Permission added to capabilities- DirectoryRow — Switched from
open()(shell plugin) torevealItemInDir()(opener plugin) - Home.tsx — “Show in Finder” calls
revealItemInDir(entity_path)for activity feed entries - Status — Work in progress; verifying the opener plugin resolves the silent failure of the shell plugin’s
open()with local paths
Changed: Directory context menu — reordered and simplified
Reordered the right-click context menu for directory rows to put the most common actions first, and merged the namespace actions into a single “Rename” item.
- New order — Show in Finder → Scan → Rename → Cloud toggle → Connect toggle → separator → Unwatch
- Single “Rename” item — Replaces the conditional “Set namespace” / “Edit namespace” + “Remove namespace” items. Always opens the inline input regardless of whether a namespace exists
- Empty-string removal — Clearing the rename input and confirming removes the namespace (calls
setNamespace(path, null)), eliminating the need for a separate “Remove namespace” menu item
Fixed: Eliminated all 10 dead_code compiler warnings
The atlas binary was declaring its own module tree in main.rs instead of importing from the library crate. This meant the Rust compiler couldn’t see that the Tauri GUI (a separate crate) was using functions from storage.rs and engine.rs, producing 10 false-positive dead_code warnings on every build.
- Split binary from library — Added explicit
[lib]and[[bin]]sections toCargo.toml.main.rsnow callsatlas::cli::run()instead of re-declaring every module - Exposed CLI module — Added
pub mod clitolib.rsso the binary can import it from the library - Removed dead code — Deleted
get_entity_name_at()fromstorage.rs(genuinely unused everywhere) - Cleaned up
#[allow(dead_code)]— Removed the suppression onEngine::config()since it’s now visible to the compiler as used - Fixed non-mcp build bug —
cli/connect.rsreferencedstdioinstead of_stdioin the#[cfg(not(feature = "mcp"))]block, previously hidden because the binary always compiled with mcp enabled
Added: Scan directory from GUI with progress bar
Directories can now be rescanned directly from the Home page via the three-dot context menu (“Scan”), equivalent to atlas scan /path on the CLI. Both rescan and initial directory watch show a smooth progress bar behind the directory row.
- “Scan” menu item — Added to the directory context menu between visibility options and “Show in Finder”
- Progress bar — Subtle
bg-accent/10bar fills left-to-right behind the directory row during scan. All 6 engine phases (walk, filter, hash, commit, reconcile, reference scan) are mapped to weighted segments of a single 0→100% bar - Walking phase pulse — The indeterminate “Walking directory” phase pulses to indicate activity before determinate progress begins
- Completion animation — Bar fills to 100%, flashes green (
bg-status-active/25), then fades out over 600ms - Non-blocking scan —
scan_directory_pathandwatch_directoryTauri commands run viaspawn_blocking, allowing progress events to stream to the webview during execution ProgressEventserialization — Added#[derive(Serialize, Clone)]with#[serde(tag = "type")]to the engine’sProgressEventenum for Tauri event emission- Event pipeline — Backend emits
"scan-progress"events with{ path, event }payload viaapp.emit(). Frontend listens via@tauri-apps/api/eventand maps phase-level events into a unified progress fraction
Technical: New emit_progress() helper in commands.rs creates a ProgressCallback that bridges the engine’s callback system to Tauri’s event system. Phase weights: Walking 0–10%, Filtering 10–20%, Hashing 20–70%, Committing 70–85%, Reconciling 85–92%, Scanning 92–100%.
Improved: Home page — Directories section redesign
Redesigned the Directories section layout:
- Status indicators moved left — Both watch status (green dot) and Connect visibility (blue dot) now appear to the left of the namespace and path, creating a clear “status | identity | data” reading order
- Namespace/path hierarchy — Namespace text is now
font-medium(primary), path istext-xs text-text-tertiary(subordinate) - Smart path truncation — Paths use
~/prefix and mid-path collapse (~/Library/…/Dropbox/_Projects) instead of clipping from the start - Tooltips on all elements — Watch status, Connect visibility, entity count, last activity, and namespace all have descriptive hover tooltips
- ”+ Watch a directory” row — Add button moved from header to below the directory list as a clickable row
- Connect toggle in context menu — Three-dot menu now includes “Show to Atlas Connect” / “Hide from Atlas Connect” toggle
- Tighter row spacing — Reduced vertical padding for Linear-style density
Improved: Home page — Recent activity section redesign
Redesigned the Recent activity feed as a straight chronological log:
- Event type indicators — Color-coded dot on the left of each row: green (created/tracked), yellow (modified), red (deleted), orange (forked), gray (moved/renamed)
- Connect visibility indicator — Second dot shows whether the file is under a Connect-visible directory (blue) or not (gray), determined by matching
entity_pathagainst watched paths - Layout restructured — Filename (bold) + parent directory path (secondary) on the left, verb right-aligned in the count column position, timestamp on the far right
- Parent directory only — Path column shows the containing directory, not the full path with redundant filename
- Chronological log — Raw event history with no deduplication or count badges; each row is one event
- Section alignment — Directory count column, timestamp column, and section header counts now align vertically between Directories and Recent sections
Added: Cloud storage awareness — smart eviction handling
Directories under cloud storage (Dropbox, Google Drive, OneDrive, iCloud) are now automatically detected. When files are removed locally from a cloud-backed directory (e.g., Dropbox evicts local copies to free space), Atlas marks them as “disconnected” instead of “deleted” — recognizing that the files still exist in the cloud.
- Auto-detection — Paths under
~/Library/CloudStorage/(macOS) and common cloud mount points are automatically flagged as cloud-backed at watch time - Manual override —
atlas watch --cloud <path>/atlas watch --no-cloud <path>for explicit control - Schema — New
cloud_backedboolean onwatched_pathstable (migration 17→18). Existing cloud paths are backfilled during migration - Deletion pipeline —
process_deletion_cloud()andreconcile_directory_cloud()check parent directory existence: if the directory still exists but files are gone, entities are marked “disconnected” with mtime/size preserved for fast reconnection - CLI —
atlas statusshows ☁ indicator on cloud-backed paths.atlas watchprints[cloud-backed]when cloud storage is detected - GUI — Cloud-backed directories show a ☁ icon. Tooltips differentiate “files may exist in cloud storage” from “drive disconnected”. Bulk eviction (5+ files) triggers an inline banner notification that auto-dismisses after 8 seconds
- Reconnection — Uses the same fast-reconnect path as external drives. Re-syncing a cloud folder stat-checks and reconnects without rehashing unchanged files
Added: Disconnected directory indicators (CLI + GUI)
Watched directories on external drives or cloud storage that become unreachable now show a visual indicator at the directory level, not just on individual entities.
- CLI —
atlas statusshows[disconnected]tag on active paths whose directory no longer exists on disk (e.g., ejected drive) - GUI — Watch status dot changes from green to amber when a directory is unavailable. Path text dims to 50% opacity. Tooltip reads “Directory unavailable”
- Computed at query time — Connectivity is transient state checked via
Path::exists(), not persisted. Follows the existingConnectVisibilitypattern: a parallelRecord<string, boolean>map delivered alongside watched paths - Backend — New
PathConnectivitystruct,compute_path_connectivity()helper, andget_path_connectivityTauri command for on-demand refresh.InitialDataincludespath_connectivityfield - Frontend —
pathConnectivitystate inWorkspaceContext,connectedprop threaded throughDirectoriesSection→DirectoryRow
Improved: Batch entity count query optimization
Replaced N separate SELECT COUNT(*) ... LIKE queries (one per watched directory) with a single SQL query using SUM(CASE WHEN ... THEN 1 ELSE 0 END) expressions. On a 1M-entity database with 6 watched directories, this scans the table once instead of 6 times.
Fixed: Glob patterns not matching nested paths
The glob-match crate treats * as NOT matching / (directory separator). Existing ignore patterns like */target/* and */.git/* only matched one directory level deep, failing to catch files in subdirectories (e.g., target/debug/deps/foo).
Added ** glob patterns that cross directory boundaries: **/target/**, **/.git/**, **/.fingerprint/**, **/node_modules/**, **/dist/**. The old single-* patterns are retained for backward compatibility but the ** versions are what actually filter deeply nested paths.
Added: macOS system file ignore patterns
Added ignore patterns for macOS system files that were cluttering the activity feed:
**/.fseventsd/**— macOS filesystem event tracking**/.Spotlight-V100/**,*Store-V2*,tmp.spotlight.state— Spotlight index files**/.DocumentRevisions-V100/**— macOS document revisions cache*.rcgu.o— Rust compiler intermediate objectsjournalAttr.*,db.sqlite-wal,db.sqlite-shm— SQLite journal/WAL files
Fixed: Font readability regression
After switching from system fonts to website fonts (Inter, DM Mono, Montserrat Alternates), body text was too thin. DM Mono at weight 400 renders thinner than system monospace fonts. Reverted to using Inter (sans-serif) for all UI text (nav items, labels, data text) and reserving DM Mono only for technical data (timestamps, counts, paths). Montserrat Alternates retained for the Atlas wordmark.
2026-03-17
Added: Tauri v2 desktop GUI — Home/Dashboard view
Atlas now has a native desktop app built with Tauri v2, React 19, TypeScript, and Tailwind CSS v4. Designed with colors and fonts from the fileatlas.app website (Inter, DM Mono, Montserrat Alternates).
- App shell — Sidebar with Atlas wordmark, navigation (Home, Inspect, Graph, Activity), and daemon status indicator showing entity count. Linear-inspired dark theme.
- Directories section — Fully interactive directory management panel:
- Watch/unwatch directories via native OS folder picker or context menu
- Inline namespace editing (click to edit, Enter to confirm, Escape to cancel)
- Per-directory entity count via optimized single-pass SQL query
- Last activity timestamps from
current_state.last_seen_at(real data, not stalewatched_pathstimestamp) - Watch status and Connect visibility indicators with tooltips
- Toggle Connect visibility from context menu (writes to
config.tomlscope rules) - Show in Finder from context menu
- Collapsible ignore patterns sub-section with enable/disable toggles
- Smart path display:
~/prefix, mid-path truncation (~/Library/…/Dropbox/_Projects) - Keyboard navigation (arrow keys)
- Recent activity section — Deduplicated activity feed:
- Consecutive entries with same filename+verb collapsed with count badge (e.g.,
engine.rs ×3) - Parent directory shown instead of full path (no filename repetition)
- File path added to
LogEntrystruct fromcurrent_state.current_path - Fetches 50 entries, deduplicates, shows top 20
- Consecutive entries with same filename+verb collapsed with count badge (e.g.,
- Loading states — Skeleton loaders for all sections, non-blocking data fetches
- Tooltips — All interactive elements have descriptive tooltips
Technical details:
- Cargo workspace: root crate (CLI + lib) +
gui/src-taurimember Mutex<Engine>pattern for thread-safe Tauri state (same as MCP server)atlasdependency withdefault-features = false(no MCP in GUI binary)- 16 Tauri commands wrapping Engine methods
- Optimized batch SQL queries for entity counts and last activity (single table scan instead of N queries)
vite-env.d.tsfor TypeScript CSS import support
Fixed: Watcher not respecting ignore patterns
The filesystem watcher (watcher.rs) was processing all Create, Modify, and debounced events without checking ignore patterns. Files matching ignore rules (e.g., */target/*) were tracked by the daemon despite being in the ignore list. The ignore check only ran during initial directory scans in tracker.rs.
Added tracker::should_ignore() checks to all three event processing paths in the watcher: Create handler, Modify handler, and debounce flush handler.
Fixed: forget_entity foreign key constraint failure
Batch pattern-based forget (atlas forget --pattern) failed with FOREIGN KEY constraint failed when deleting entities that other entities forked from. The forked_from_entity_id reference on child entities blocked parent deletion.
Fixed by nullifying forked_from_entity_id references and deleting inbound edges before deleting the entity row.
Added: Batch entity forget (forget_entities_batch)
Pattern-based forget was extremely slow — each entity was deleted in its own transaction with a WAL checkpoint, making 32K deletions take hours. Added forget_entities_batch() that wraps all deletions in a single transaction. Also added config_mut() accessor on Engine for GUI config writes.
Added: Common ignore patterns
Added user ignore patterns for common build artifacts and generated files:
*/target/*— Rust/Cargo build artifacts*/node_modules/*— Node.js dependencies*/.git/*— Git internals*/dist/*— Build output*/.DS_Store— macOS metadata
Added: Directory namespaces
Watched directories can now be given a human-friendly name. Namespaces provide cleaner display in atlas status, stable identity for path portability, and the ability to remap directories to new paths when migrating drives.
atlas namespace add <name> <path>— Assign a name to a watched directory. Auto-watches the path if not already tracked. Validates that the name isn’t taken and the path doesn’t already have a namespace.atlas namespace remove <name>— Remove a namespace. The directory stays watched.atlas namespace remap <name> <new-path>— Move a namespace to a new directory path. Uses the existing drive reconnect system: disconnects entities under the old path, rewritescurrent_statepaths to the new prefix, records path changes inpath_history, then runs fast reconnection (mtime/size match → no rehash, mismatch → rehash). Makes drive migration seamless.atlas namespace list— Show all named directories with their paths.atlas status— Now shows[namespace-name]tag next to named directories.- Schema v13 → v14 — Adds nullable
namespacecolumn towatched_pathswith a unique partial index. - All namespace commands support
--jsonoutput. - Foundation for future team features (shared namespaces, cross-user lineage). See
plans/design-council-teams.md.
Added: Connect Scope
Control which watched paths are visible to AI agents through Connect. Scope rules live in [connect.scope] in config.toml with allow/deny lists. Deny always wins over allow. Glob patterns supported in deny entries.
- Default deny entries seeded on first run:
~/.ssh,~/.gnupg,~/.aws,~/.config/gh,**/credentials*,**/.env,**/secrets* - CLI management:
atlas connect scope(show),scope allow,scope deny,scope remove,scope reset - Dry-run by default — all scope commands show what would change without
--confirm - Invisible filtering — scoped-out data is absent from results, not redacted
- SQL-level enforcement for aggregate queries (
atlas_query) ensures correct counts - Agent setup notice —
atlas agent-setupnow shows scope status
Fixed: Fast volume reconnection for external drives
After unmounting and remounting an external drive, Atlas was leaving up to 89% of entities stuck as disconnected despite the volume being available. Root cause: mark_entities_disconnected_under_path was destroying stored file_size, mtime_secs, and mtime_nsecs by setting them to NULL, making smart reconnection impossible. The only recovery path was a full rescan with rehashing every file — hours for large volumes over USB.
Two changes fix this:
- Preserved mtime/size on disconnect — The disconnect SQL now only updates
statusandlast_seen_at, keeping the last known file metadata intact. reconnect_directory()function — When a volume reappears, Atlas iterates all disconnected and deleted entities under the path prefix, stats each file, and compares stored mtime/size against on-disk values:- Match → fast reconnect: flip to
live, updatelast_seen_atonly (no rehash) - Mismatch → rehash the file, then update hash + mtime/size + status
- NULL stored mtime (legacy disconnect) → trust file existence, fast reconnect
- File gone → leave as-is
- Match → fast reconnect: flip to
Performance: ~550K stat calls + ~0 hashes (typical case) completes in 30–60 seconds, down from hours. Files modified on another machine while the drive was away are correctly rehashed.
Also fixes ~31K entities incorrectly marked deleted (not disconnected) by previous daemon runs — reconnect_directory now handles both statuses.
Added: --status flag on atlas find
Filter entities by their current status: live, deleted, or disconnected.
atlas find --status deleted # Show all deleted entities
atlas find --status disconnected # Show all disconnected entities
atlas find --status live # Show all live entities
Can be combined with other find criteria (--hash, --name, --path) to narrow results. Limited to 1000 results.
2026-03-16
Added: Temporal queries and witnessed indicator
Date-range filtering on MCP tools, where an agent couldn’t ask “what plugins did I use in 2025 vs 2026?”
date_from/date_toparameters — Added toatlas_query,atlas_find,atlas_edges, andatlas_log. Accepts RFC 3339 timestamps. Filters on the entity’screated_at(when Atlas first recorded the entity).witnessed_onlyparameter — Restricts results to entities Atlas observed in real-time (via the watcher), excluding entities discovered during initial directory scans. Scan-discovered entities have timestamps reflecting scan time, not original file creation time.witnessedfield in log output —atlas_logentries now include awitnessed: boolfield indicating whether Atlas observed the event in real-time.~prefix on CLI timestamps — Unwitnessed timestamps inatlas logare displayed with a~prefix (e.g.,~Dec 12 2025 22:51) to indicate the date is approximate.- Design doc updated —
plans/temporal-queries-and-historical-timestamps.mdupdated with the simplified witnessed/not-witnessed model, replacing the original three-tier timestamp proposal. Informed by testing representative Dropbox-synced files (RPP, WAV, FMOD) which showed that only 1 of 3 formats had internal timestamps, and filesystem timestamps were disrupted by cloud sync.
Fixed: ignore_scoped_pattern test failure on macOS
The test compared raw TempDir paths (/var/folders/...) against canonicalized paths (/private/var/folders/...), failing because macOS has a /var → /private/var symlink. Fixed by canonicalizing test paths before comparison.
Improved: MCP agent usability — type coercion, readable names, pagination
- Fixed
limittype coercion — Alllimit,offset, anddepthparameters now accept both string ("20") and number (20) values. MCP clients are inconsistent about parameter types; previously string values caused deserialization errors. - Human-readable names in grouped results —
atlas_querywithgroup_by: "source"now includesnameandpathalongside the entity UUID. Previously required N+1atlas_historylookups to resolve every grouped result row. - Consistent
offset+limiton all list-returning endpoints — Every tool that returns a list now supports pagination. Addedoffsettoatlas_query,atlas_edges,atlas_log. Added bothlimitandoffsettoatlas_search,atlas_inputs,atlas_outputs,atlas_broken.
Added: MCP server optimization — aggregate queries, edge search, filtering
Based on real-world testing where a cross-project plugin analysis required 85+ individual tool calls, added 2 new MCP tools and enhanced 2 existing ones. The same query now completes in 1 call.
atlas_query— Aggregate query tool. Filters entities by path prefix, name pattern (LIKE), and exclude pattern, then traverses their edges filtered by type and reference path pattern, groups results, and returns counts. Supportsgroup_by(reference_path, source, edge_type, pack) andcount_onlymode. Turns multi-file analysis from 85+ calls into 1.atlas_edges— Edge search tool. Searches edges directly by reference_path LIKE pattern, edge type, source entity path prefix, and/or pack name. Makes plugin references, import paths, and other edge metadata directly queryable.atlas_findenhanced — Addedextension,path_contains,exclude(LIKE pattern),limit, andoffsetparameters. Prevents oversized results (previously 17.7M characters for a simple extension search).atlas_inputs/atlas_outputsenhanced — Now accept directory paths and return aggregated results for all entities under that directory, using batch queries instead of per-entity calls.- MCP server now exposes 14 tools (up from 12).
Added: Atlas Connect — MCP server and agent integration
Atlas now exposes its lineage engine to AI agents via two paths: CLI with --json output and a Model Context Protocol (MCP) server. Built on the rmcp crate with full MCP compliance.
atlas agent-setup— Generates agent configuration snippets. Auto-detects agent format by checking forCLAUDE.md,.cursorrules, or.github/copilot-instructions.mdin the current directory. Supports--formatflag:claude,cursor,copilot,generic,mcp. Themcpformat outputs a JSON config block for MCP clients.atlas connect start --stdio— Runs an MCP server on stdin/stdout. MCP clients launch this as a subprocess. Exposes 14 read-only tools:atlas_status,atlas_history,atlas_search,atlas_find,atlas_log,atlas_trace,atlas_inputs,atlas_outputs,atlas_impact,atlas_broken,atlas_compare,atlas_tree,atlas_query,atlas_edges.atlas connect start --port <N>— Runs an MCP server over Streamable HTTP, daemonized in the background. PID and port written to~/.atlas/connect.pid. Logs to~/.atlas/connect.log.atlas connect stop— Stops the HTTP daemon (SIGTERM with 3s graceful shutdown, then SIGKILL).atlas connect status— Shows server state, transport type, PID, and total queries served. Supports--json.atlas audit— View the agent query audit log. Every MCP tool call is logged with timestamp, tool name, arguments, result count, and duration. Supports--today,--agent <id>,--tool <name>,-n <limit>, and--jsonfilters.atlas audit summary— Grouped activity summary with Unicode bar chart.--days <N>controls the window (default 7).audit_cliconfig option — When set totruein~/.atlas/config.toml, CLI--jsoncalls are also logged to the audit table withsource = "cli". Default:false.- Schema v12 → v13 — Adds
agent_audit_logtable with indexes ontimestampandtool_name. mcpfeature flag — MCP dependencies (rmcp,tokio,schemars,axum) are gated behind themcpfeature, enabled by default. Build with--no-default-featuresto exclude them.
2026-03-15
Added: Ignore system v2 — toggle, scoped patterns, pattern-based forget
Complete overhaul of the ignore system with three new capabilities, designed with the Design Council.
- Toggle (enable/disable) — Ignore patterns can now be disabled without deleting them.
atlas ignore disable "*.log"stops the pattern from being applied;atlas ignore enable "*.log"reactivates it. Disabling a sensitive pattern (secrets, credentials, keys) requires--confirmand shows a safety warning. Re-enabling a pattern shows a count of matching entities already in the database with a hint to useatlas forget --patternto clean them up. Schema v10 → v11 addsenabledcolumn. - Directory-scoped ignore patterns — Patterns can now be scoped to specific directories using
--scope.atlas ignore add "dist/*" --scope ~/projects/myappignoresdist/only within that project. Scoped patterns are additive — they can never override global defaults. Any subdirectory within a watched tree is a valid scope, not just watched roots. Atlas warns when a scope is outside any watched directory. Same pattern with different scopes coexist independently. Scope data is stored in the database (not dotfiles) — Atlas maintains a read-only relationship with watched directories. Schema v11 → v12 addsscope_pathcolumn with compound unique index. - Pattern-based mass forget —
atlas forget --pattern "*.log"permanently deletes all entities whose current path matches the glob. Dry run by default showing blast radius (active/deleted/disconnected counts),--confirmto execute. Uses the sameCompiledIgnoreSetmatching engine as ignore patterns — no divergence between “what gets ignored” and “what gets forgotten.” Each entity is logged toforget_logvia the existingforget_entitypath. atlas ignore listupdated — Now shows[disabled]for toggled-off patterns,[~/path]for scoped patterns. Supports--scope <path>to filter to patterns effective at a specific directory.
Design decisions:
- No
.atlasignorefiles — all configuration stays in~/.atlas/database. Atlas never writes to watched directories. - Ignore is prospective (controls future tracking), forget is retroactive (deletes past data). Two intents, two commands.
forgetextended with--patternflag rather than introducing a new verb.
Added: Pack-level ignore pattern registration for extractors
Extractor packs can now declare ignore_patterns alongside their extractors. Patterns are seeded as defaults on engine initialization. The audio pack registers *.reapeaks (Reaper peak cache files) as the first pack-contributed ignore pattern. Custom extractor packs can use this to register domain-specific file types that should be ignored.
2026-03-14
Added: FMOD Studio metadata extractor
Atlas now understands FMOD Studio project structure. The extractor registers for .xml and .fspro files, fast-bailing on non-FMOD content by checking for the serializationModel="Studio header.
- AudioFile XMLs (
Metadata/AudioFile/{uuid}.xml) — ExtractsassetPathproperty and resolves to the actual audio file in the project’sAssets/directory (input edge). Traits:frequency_khz,channels,length_seconds. - Event XMLs (
Metadata/Event/{uuid}.xml) — ExtractsSingleSound→audioFileUUID references as input edges to AudioFile XMLs. Extractsbanksrelationship UUIDs as input edges to Bank XMLs. Handles nestedMultiSoundcontainers with multipleSingleSoundchildren. Trait:fmod_event_name. - Bank XMLs (
Metadata/Bank/{uuid}.xml) — Extracts bank name and resolves to compiled.bankfile inBuild/Desktop/(output edge). Trait:fmod_bank_name. - Lineage chain — Event XML → AudioFile XML →
.wavfile provides full provenance from sound event to source audio.
Added: Default ignore patterns for FMOD build artifacts
Added .user, .unsaved, .cache, .fobj, and .fsb to the default ignore list. These cover FMOD Studio workspace state, unsaved change caches, compiled cache objects, and compiled sound bank caches.
Fixed: Schema migration fixup for leftover is_deleted column
The v9 → v10 migration that replaced is_deleted with status on current_state was guarded behind if version < 10, meaning databases already at v10 (but with the column still present) never had it dropped. The DROP COLUMN is now a standalone fixup that runs unconditionally, matching the existing pattern used for the import_origin_path rename.
Added: Disconnected state for file redownload and drive reconnection
Atlas now distinguishes between a file being intentionally deleted and a file becoming temporarily unreachable. The is_deleted boolean on current_state has been replaced with a status text field supporting three values: live, deleted, and disconnected. Schema v9 → v10.
disconnectedstate — When a watched path disappears (external drive ejected, cloud folder removed), all entities under it are markeddisconnectedinstead ofdeleted. This preserves the semantic that the files aren’t gone — they’re just unreachable.- Stale watch detection —
sync_watch_list()now detects when an actively watched path no longer exists on disk. It removes the watch, marks entities as disconnected, and logs the event. When the path reappears (drive reconnected), the watch is re-established and a full rescan triggers automatic reconnection via hash matching. - Post-scan reconciliation —
atlas scannow checks for live entities whose files no longer exist on disk and marks them as deleted. Watched directories that no longer exist are marked as disconnected. This catches changes that occurred while the watcher wasn’t running. - Startup reconciliation —
atlas startnow reconciles all watched directories during its initial scan. Existing directories are scanned for new files and reconciled for deletions. Missing directories have their entities marked as disconnected. - Reconnection priority — Disconnected entities are preferred over deleted ones when matching by hash during reconnection, since they’re more likely to be the same file returning.
- Path history optimization — When reconnecting a file at the same path (common for drive reconnection), Atlas no longer adds a redundant path history entry.
atlas status— Now shows disconnected entity count alongside active and deleted.atlas history— Timeline now includes Deleted and Disconnected events, showing when a file was removed or became unreachable. Works for both single-file and directory history views.atlas historyoffline directories — History for directories that no longer exist on disk now works correctly instead of erroring. Falls back to database prefix matching when the path can’t be canonicalized.atlas log— Disconnection events appear in the activity log alongside deletions.
Changed: Watched paths now use soft-delete with full history
Removing a watched path no longer deletes the watched_paths row. Paths are marked inactive with a removed_at timestamp, preserving the record that Atlas once tracked that directory. Re-watching a previously inactive path reactivates it. Schema v8 → v9 adds status, removed_at, and last_activity_at columns to watched_paths.
atlas unwatch— Soft-deletes the path (sets status toinactive, recordsremoved_at). Historical entity data is fully retained.atlas watchon a previously inactive path — Reactivates it (sets status toactive, updatesadded_at, clearsremoved_at).last_activity_at— Updated when files under a watched path are scanned. Shows when Atlas last processed data for that path.atlas status— Now supports--all,--active(default), and--inactiveflags. Showsadded_at,removed_at, andlast_activity_attimestamps for each path.- Path subsumption — When watching a parent directory, child directories already in the watch list are automatically inactivated (not deleted). The user is notified of consolidated paths.
2026-03-13
Added: 6 new audio extractors + NKS preview linking
New extractors for Native Instruments and Bitwig formats, plus expanded Kontakt support. Tested against a 3.1TB / 567K file instrument library.
- NKS Sound File (
.nksf) — RIFF/NIKS container with MessagePack metadata. Extracts 11 preset traits (name, author, vendor, plugin, library, types, modes, characters, comment, device type, UUID) via thebankchainarray and categorization fields. NKS preview audio linking. - NKS Snapshot (
.nksn) — NI DSIN container with4KINmarker. Extracts library product ID (input edge) and NKS preview audio (output edge). Reusesni_container.rsfor product ID extraction. - NI Content Registration (
.nicnt) — Binary header + XML ProductHints. Extracts library identity traits: name, UPID, version, type, NKS status. Enables library inventory without requiringkomplete.db3. - Reaktor Ensemble (
.nrkt) — NI DSIN container. Extracts product ID (input edge) andfile://URI content references to dependent resources like.rkplrfiles (input edges). - Bitwig Preset (
.bwpreset) —BtWgbinary container with length-prefixed key-value metadata. Extracts creator, comment, category, device name, and tags as traits. - AIFF Audio (
.aif,.aiff) — FORM/AIFF chunk walking (big-endian). Extracts sample rate (80-bit extended float conversion), channels, bit depth, instrument mapping (base/low/high note from INST chunk), and author (AUTH chunk). - Kontakt extended —
.nbkt(Battery kits) and.nkm(Kontakt multis) now use the existing Kontakt extractor. Same NI DSIN container format, zero new parsing code. - NKS preview audio linking — NKI, NKSF, and NKSN extractors now emit output edges to
.previews/<filename>.oggwhen the preview file exists on disk. Sharednks_preview_ref()helper inni_container.rs.
Added rmpv dependency for MessagePack parsing. Full format documentation in docs/extractors/atlas-audio/.
Optimized: Scan pipeline for large file counts
Targeted at 567K file instrument libraries where ~526K files have no registered extractor. Reduces unnecessary memory allocation and SQL overhead.
- Smart buffering — Files without a registered extractor now use streaming hash (
hash_file()) instead of buffering the entire file into memory. For 526K hash-only files at ~500KB average, this eliminates ~263GB of unnecessary memory allocation per scan. - Skip generic traits for binary audio — Known binary audio formats (
.wav,.aif,.ogg,.ncw,.mwc,.nkx,.nkc,.8dio,.mid,.nka,.ndx,.flac,.mp3) skipextract_traits()— thefile_type/is_text/byte_sizetraits are redundant for these formats. Saves ~1.6M SQL INSERTs per scan. - Thread-local hash buffers — The 1MB BLAKE3 streaming buffer is now
thread_local!instead of heap-allocated per call. Eliminates 567K allocations, one per file. - Raised hash thread cap —
MAX_HASH_THREADSincreased from 4 to 6. Better utilization of SSD/NVMe parallelism while still avoiding excessive I/O contention.
Optimized: Scan performance for large directories
Targeted at first-scan of 250GB+, 16,000+ file directories on external NVME volumes.
- 1MB streaming hash buffer — BLAKE3 read buffer increased from 64KB to 1MB in
hasher.rs. Reduces syscalls ~16x per large file, better aligned with SSD/NVME read granularity. Heap-allocated to avoid stack overflow. - Capped parallel hash threads — New
MAX_HASH_THREADSconstant (4) with a dedicatedrayon::ThreadPoolBuilderfor the hashing phase. Prevents I/O contention from too many concurrent readers on a single disk volume, restoring sequential read patterns and higher effective throughput. - 256MB SQLite cache during scans —
PRAGMA cache_size = -262144set before the batch commit phase, restored to default after. Keeps hot index pages in memory during 1000-file batch inserts, reducing disk reads for index lookups. - BEGIN IMMEDIATE transactions — Batch commits now use
TransactionBehavior::Immediateinstead of the defaultDeferred. Prevents deadlock promotion when a read-started transaction escalates to write. - synchronous = FULL retained — Explicitly decided NOT to downgrade to
synchronous = NORMAL. The atlas.db is the source of truth for all lineage history — not a reconstructable cache. Durability over speed.
2026-03-12
Fixed: Daemon not detecting Finder file operations
The Atlas daemon was not detecting files added via macOS Finder (drag-and-drop, copy-paste). Finder generates a single directory-level rename event (Modify(Name(Any))) when copying folders, with no individual file creation events. The daemon now scans any directory that appears in a filesystem event, catching all variations of how files can arrive.
Fixed: atlas scan not discovering new files
atlas scan only re-processed files already in the database for reference extraction. It now walks all watched directories first to discover untracked files before extracting references, making it a reliable fallback when the daemon misses files.
Fixed: Daemon process leak on atlas stop
atlas stop sent SIGTERM but didn’t wait for the process to exit. Calling atlas stop && atlas start in quick succession could leave orphaned daemon processes competing for the database. Stop now waits up to 3 seconds for graceful exit, then force-kills if needed. The foreground runner also kills any stale daemon before starting.
Added: macOS Full Disk Access guidance
The daemon requires Full Disk Access (granted to the terminal app) to receive filesystem events. Without it, the daemon starts and appears healthy but silently misses all file changes. Added a setup section to docs/getting-started.md explaining how to enable this.
Added: atlas compare command
Content-identity-aware comparison of files and directories. Unlike diff -r, Atlas recognizes renamed files as the same file, detects restructured directories with identical content, and surfaces fork divergence points using lineage data.
Added: Incremental scanning
Schema v7 → v8 added file_size, mtime_secs, and mtime_nsecs to current_state. Files whose mtime and size haven’t changed now skip BLAKE3 hashing entirely, making rescans significantly faster.
Added: .wav metadata extraction and .RPP render path extraction
WAV files now have their metadata extracted as traits. Reaper .RPP files now extract RENDER_FILE and RENDER_PATTERN directives as output edges, completing the lineage picture from source samples through project to rendered output.
Added: Plugin .plist extractor
macOS audio plugin bundles (.vst3, .component, .vst) are now scanned via their Info.plist to extract plugin name, manufacturer, and version as file traits.
Fixed: Rename/move detection regression
Fixed an issue where file renames and moves were not being correctly detected in certain scenarios. Also removed render path extraction from .rpp-bak files (backup files shouldn’t contribute output edges).
Changed: CLI command restructure and documentation overhaul
Revised CLI commands for consistency. Updated all user-facing documentation to reflect current command names and behavior.
Changed: Export format versioning
JSON export output now includes a version header. Fixed stale references to “dependencies” in export output — now correctly labeled “edges.”
Changed: Updated consent language
Consent messaging now mentions extraction and reference tracking alongside the existing file watching disclosure.
Added: Expanded test suite
+15 tests covering edges, compare, incremental scan, and fork chains.
2026-03-11
Added: atlas trace — lineage traversal
The core feature that makes Atlas a lineage engine. atlas trace <file> --forward shows what a file became. atlas trace <file> --backward shows where it came from. Supports --depth, --reaches, and --json flags. Walks fork links, input edges, and output edges to build a complete provenance chain.
Changed: Graph model refactor — dependencies → edges
Redesigned the relationship data model around lineage traversal. The dependencies table became edges. Six ref_type values collapsed into two edge_type values: input (“I need this to work”) and output (“I create this”). import_origin_path became source_path on entities. Schema migrations v4 → v5 → v6 handled data-first, schema-second to preserve provenance data.
Added: Reaper .RPP extractor
Four-pass extraction from Reaper project files:
FILEdirectives → audio source paths (input edges)ORIGINAL_FILENAME→ import provenance (setssource_pathon target entity)<VST>blocks → plugin name, vendor, and format (input edges)- Kontakt deep extraction → base64-decode VST state blob, parse NI container, resolve product ID via
komplete.db3to library name and path (input edges)
Added: Kontakt .nki extractor
Binary NI container parsing for Kontakt instrument files:
- Product ID from
AUTHORING_APP→komplete.db3resolution to library name and path - Instrument metadata from
SOUNDINFO - Sample paths via FastLZ decompression +
FILENAME_LIST_EXparsing (non-DRM files only)
Added: NI container parser (ni_container.rs)
Shared parser for Native Instruments container format used across Kontakt, Reaper VST blobs, and future DAW extractors. Handles hsin/DSIN chunk parsing, product ID extraction, SOUNDINFO decoding, FastLZ level 1 decompression, FILENAME_LIST_EX segment-path decoding, and komplete.db3 product ID resolution (searches Kontakt 8/7/generic paths). Includes a custom base64 decoder (no external dependency).
Added: Audio pack registration
atlas-audio pack with Reaper and Kontakt extractors, registered via audio_pack(). Enabled by default.
2026-03-10
Added: Extractor framework
Extractor trait, ExtractedReference types, and ExtractorRegistry in src/extractors/mod.rs. Extractors are pure functions: bytes in, file path references out. They run during the hash pass on the same byte buffer — no second read. Files under 10MB get full-file buffering for extraction; larger files are hash-only.
Added: Byte-level trait extraction
During the hash pass, Atlas now extracts universal file traits at zero additional I/O cost: file_type (magic byte detection), is_text (UTF-8 validity), byte_size, and line_count. Stored in the file_traits table.
Added: Core pack — 5 extractors
Always-enabled extractors for universal formats:
- HTML —
src,href,<link>,<script>,<img>,<video>,<audio>,<source>attributes - CSS —
url()values,@importpaths - Markdown — image references
, link references[](path) - JSON/YAML — heuristic detection of path-like string values
- SVG —
xlink:href,href, embedded image references
Added: Edge storage and resolution system
edges table records entity-to-entity relationships. Lazy resolution: references resolve automatically as Atlas discovers target files. Query-time broken detection checks if resolved targets have been deleted. Updated forget_entity to clean edge, trait, and extractor log data.
Added: Edge CLI commands
atlas inputs <file>— what files does this entity needatlas outputs <file>— what does this entity produceatlas broken [file]— unresolved or missing referencesatlas orphans [--type <ext>]— files not referenced by anythingatlas impact <file>— transitive cascade analysisatlas scan [path]— re-extract references for tracked files
Added: --json flag on all commands
Every CLI command now supports --json for structured JSON output. Includes existing commands (status, history, find, log, tree, timeline, search, stats, config, ignore) and all new edge commands.
Added: CLI help headings
Commands grouped into categories in --help output: Tracking, Querying, Edges, and Management.
Changed: Schema migration v3 → v4 → v5 → v6
Added file_traits, edges (originally dependencies), and extractor_log tables. v6 refactored the graph model: renamed table and columns, collapsed edge types, added source_path to entities.
Fixed: current_state rebuild from history (M2 deferred)
Added ability to reconstruct current_state from the append-only history tables. Safety net if the denormalized cache ever becomes inconsistent.
Fixed: Batch transaction wrapping for initial scans (M2 deferred)
Initial directory scans now wrap all file processing in a single transaction instead of one transaction per file. Significant performance improvement for large directories.
2026-03-07
Added: Engine API struct
Introduced Engine { conn, config } in engine.rs. The CLI is now a thin consumer of engine methods. Internal modules are pub(crate). This is the API boundary future consumers (GUI, extensions) will build against.
Added: Custom error types
AtlasError enum with 6 variants (Io, Database, NotFound, InvalidInput, AlreadyExists, Watcher) using thiserror. Engine returns structured errors; CLI translates them into user-friendly messages via user_message().
Added: Background daemon
atlas start forks a background process and returns immediately. PID file management with signal handling. atlas stop sends SIGTERM with graceful shutdown. Daemon logs to ~/.atlas/atlas.log.
Added: Boot persistence (macOS)
atlas start --boot generates a launchd plist for automatic startup on login.
Added: Configuration system
AtlasConfig loads from ~/.atlas/config.toml with sensible defaults. atlas config shows effective configuration including config path, database path, and settings.
Added: atlas log command
Reverse-chronological activity feed across all tracked entities. Reconstructed via SQL UNION across history tables. Supports --today, -n (limit), and --entity filters. Queries pushed to SQL for performance.
Added: atlas tree command
Fork visualization with Unicode box-drawing characters. Shows all copies, divergence points, and current status of an entity and its forks.
Added: atlas timeline command
Day-grouped activity summary. Shows per-day modification counts with --path directory filter.
Added: atlas search command
Multi-field search across names, paths, and hash prefixes. Results scored by relevance and recency.
Added: atlas stats command
Database statistics: entity counts, watched paths, database file size.
Added: Entity ID prefix matching
Entity IDs can now be specified by unambiguous prefix instead of full UUID. Errors clearly on ambiguous matches.
Changed: SQL-based queries
atlas log, atlas status, and duplicate detection now use SQL WHERE + LIMIT instead of loading entire tables into memory.
Changed: File permissions
Database (0600), PID file (0600), log file (0600), and directories (0700) are now created with restrictive permissions.
Changed: Expanded default ignore list
32 patterns including .aws/*, .gnupg/*, *.token, .npmrc, .netrc, and other credential/secret files.
Changed: Hasher buffer 8KB → 64KB
BLAKE3 benefits from larger read chunks. Measurable improvement on large files.
Fixed: Transaction-wrapped multi-table writes
process_file, process_rename, process_deletion, and forget_entity now execute within transactions. Partial failure rolls back cleanly.
Fixed: True data erasure in forget
PRAGMA wal_checkpoint(TRUNCATE) after purge ensures forgotten data doesn’t linger in the WAL file. Added forget_log table as a privacy-safe audit trail.
Fixed: --today timezone handling
Local timezone comparison with RFC3339 timestamps. Previously compared naive timestamps, producing incorrect results in non-UTC timezones.
Fixed: debounce_ms wired to watcher
Config value now actually used by the pending-remove flush timer. Previously defined but ignored.
Fixed: Daemon fork safety
setsid and dup2 return values are now checked. Prevents silent failures during daemonization.
Added: atlas watch auto-starts daemon
Watching a path now automatically starts the daemon if it’s not running. atlas unwatch of the last watched path auto-stops it.
Added: Schema migration system
Formalized version-based forward migrations (v1 → v2 → v3) using schema_version in atlas_meta.
Removed: Dead notify-debouncer-mini dependency
Cleaned from Cargo.toml.
Added: Design Council code review
23 items identified across 4 priority tiers. All critical and high-priority items resolved in M2. Review document at plans/milestone-2-code-review.md.
2026-03-06
Added: Filesystem watcher
Real-time monitoring using notify crate with OS-level filesystem events. Handles paired renames (Both mode), split renames (From/To), and macOS FSEvents patterns (Remove+Create for renames and atomic saves). Pending-remove buffer with 200ms/500ms timing windows for rename detection. Initial directory scan on start.
Added: CLI command set
atlas watch, unwatch, start, stop, status, history, find (by hash/name/path/duplicates), ignore (list/add/remove), forget, config. PID-based daemon management. Unified timeline display in history output.
Added: Tracker decision engine
Core logic that determines what happened to a file: new entity, modification, fork detection (known hash at new location), move/rename, deletion, and reconnection (known hash reappearing). Distinguishes “discovered” (pre-existing) from “witnessed” (created while watching) entities.
Added: Default ignore list
21 patterns covering credentials, keys, env files, build artifacts, editor temp files, and OS system files. User-extensible via atlas ignore add/remove. Transparent via atlas ignore list.
Added: Fork tracking
When a file with a known hash appears at a new untracked location, Atlas creates a new entity linked to the original via forked_from_entity_id and forked_at_hash. Both branches share a common ancestor and track independently from the fork point.
Added: atlas forget with dry-run
True deletion of entity history with --confirm gate. Dry-run preview shows what will be removed before committing.
Added: BLAKE3 streaming hasher
Content hashing using BLAKE3 with streaming 8KB buffer (later increased to 64KB in M2). Handles large files without loading them into memory.
Added: Storage layer
Full SQLite schema with WAL mode for concurrent reads. Tables: entities, hash_history, path_history, name_history, watched_paths, current_state, ignore_patterns, plus atlas_meta for self-describing metadata. Append-only history tables with denormalized current_state cache. Indexes for all common query patterns.
2026-03-05
Added: Database structs and CRUD operations
Insert, update, and query functions for all tables. Tracker logic for processing filesystem events into history records.
2026-03-04
Added: Project setup
Rust project initialized with SQLite, notify, BLAKE3, clap, chrono, and whoami dependencies. Database schema designed and implemented.