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 causeset_boot_persistence in commands.rs called launchctl unload without 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
  • Fixset_boot_persistence now captures daemon_is_running() before the launchctl operation. If the daemon was alive before and is dead after, it restarts it standalone via start_daemon_background() with a 300ms grace period for launchctl to finish
  • Toggle ON case — Also covered: launchctl load with RunAtLoad=true spawns 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 calling atlas_gui::run(), checks if start --foreground was passed. If so, creates an engine and calls run_foreground() (PID file, signal handling, blocking watcher) without ever initializing the GUI
  • run_foreground made publiccli::tracking::run_foreground() changed from fn to pub fn so the GUI binary can call it directly, reusing all existing PID file management and signal handling
  • No new dependenciesctrlc and libc are already dependencies of the atlas crate where run_foreground lives

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 checks Path::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 handleruseDaemonEvents hook handles the connectivity_changed event type by calling updatePathConnectivity() in WorkspaceContext, updating the status indicator within ~2-4 seconds of mount/unmount
  • Daemon decoupled — Removed connectivity_changed event emissions from watcher.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_run command — Tauri command exposing the engine’s pattern-based entity matching. Returns matching entities with name, path, status
  • ignore_and_purge command — Single Tauri command that adds an ignore rule and optionally purges matching entities in one call
  • removeLogEntriesByEntityIds — 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-opener added — New dependency in Cargo.toml and package.json, plugin registered in lib.rs
  • opener:allow-reveal-item-in-dir — Permission added to capabilities
  • DirectoryRow — Switched from open() (shell plugin) to revealItemInDir() (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 to Cargo.toml. main.rs now calls atlas::cli::run() instead of re-declaring every module
  • Exposed CLI module — Added pub mod cli to lib.rs so the binary can import it from the library
  • Removed dead code — Deleted get_entity_name_at() from storage.rs (genuinely unused everywhere)
  • Cleaned up #[allow(dead_code)] — Removed the suppression on Engine::config() since it’s now visible to the compiler as used
  • Fixed non-mcp build bugcli/connect.rs referenced stdio instead of _stdio in 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/10 bar 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 scanscan_directory_path and watch_directory Tauri commands run via spawn_blocking, allowing progress events to stream to the webview during execution
  • ProgressEvent serialization — Added #[derive(Serialize, Clone)] with #[serde(tag = "type")] to the engine’s ProgressEvent enum for Tauri event emission
  • Event pipeline — Backend emits "scan-progress" events with { path, event } payload via app.emit(). Frontend listens via @tauri-apps/api/event and 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 is text-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_path against 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 overrideatlas watch --cloud <path> / atlas watch --no-cloud <path> for explicit control
  • Schema — New cloud_backed boolean on watched_paths table (migration 17→18). Existing cloud paths are backfilled during migration
  • Deletion pipelineprocess_deletion_cloud() and reconcile_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
  • CLIatlas status shows ☁ indicator on cloud-backed paths. atlas watch prints [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.

  • CLIatlas status shows [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 existing ConnectVisibility pattern: a parallel Record<string, boolean> map delivered alongside watched paths
  • Backend — New PathConnectivity struct, compute_path_connectivity() helper, and get_path_connectivity Tauri command for on-demand refresh. InitialData includes path_connectivity field
  • FrontendpathConnectivity state in WorkspaceContext, connected prop threaded through DirectoriesSectionDirectoryRow

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 objects
  • journalAttr.*, 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 stale watched_paths timestamp)
    • Watch status and Connect visibility indicators with tooltips
    • Toggle Connect visibility from context menu (writes to config.toml scope 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 LogEntry struct from current_state.current_path
    • Fetches 50 entries, deduplicates, shows top 20
  • 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-tauri member
  • Mutex<Engine> pattern for thread-safe Tauri state (same as MCP server)
  • atlas dependency with default-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.ts for 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, rewrites current_state paths to the new prefix, records path changes in path_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 namespace column to watched_paths with a unique partial index.
  • All namespace commands support --json output.
  • 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 noticeatlas agent-setup now 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 status and last_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, update last_seen_at only (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

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_to parameters — Added to atlas_query, atlas_find, atlas_edges, and atlas_log. Accepts RFC 3339 timestamps. Filters on the entity’s created_at (when Atlas first recorded the entity).
  • witnessed_only parameter — 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.
  • witnessed field in log outputatlas_log entries now include a witnessed: bool field indicating whether Atlas observed the event in real-time.
  • ~ prefix on CLI timestamps — Unwitnessed timestamps in atlas log are displayed with a ~ prefix (e.g., ~Dec 12 2025 22:51) to indicate the date is approximate.
  • Design doc updatedplans/temporal-queries-and-historical-timestamps.md updated 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 limit type coercion — All limit, offset, and depth parameters 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 resultsatlas_query with group_by: "source" now includes name and path alongside the entity UUID. Previously required N+1 atlas_history lookups to resolve every grouped result row.
  • Consistent offset + limit on all list-returning endpoints — Every tool that returns a list now supports pagination. Added offset to atlas_query, atlas_edges, atlas_log. Added both limit and offset to atlas_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. Supports group_by (reference_path, source, edge_type, pack) and count_only mode. 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_find enhanced — Added extension, path_contains, exclude (LIKE pattern), limit, and offset parameters. Prevents oversized results (previously 17.7M characters for a simple extension search).
  • atlas_inputs / atlas_outputs enhanced — 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 for CLAUDE.md, .cursorrules, or .github/copilot-instructions.md in the current directory. Supports --format flag: claude, cursor, copilot, generic, mcp. The mcp format 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 --json filters.
  • atlas audit summary — Grouped activity summary with Unicode bar chart. --days <N> controls the window (default 7).
  • audit_cli config option — When set to true in ~/.atlas/config.toml, CLI --json calls are also logged to the audit table with source = "cli". Default: false.
  • Schema v12 → v13 — Adds agent_audit_log table with indexes on timestamp and tool_name.
  • mcp feature flag — MCP dependencies (rmcp, tokio, schemars, axum) are gated behind the mcp feature, enabled by default. Build with --no-default-features to 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 --confirm and shows a safety warning. Re-enabling a pattern shows a count of matching entities already in the database with a hint to use atlas forget --pattern to clean them up. Schema v10 → v11 adds enabled column.
  • Directory-scoped ignore patterns — Patterns can now be scoped to specific directories using --scope. atlas ignore add "dist/*" --scope ~/projects/myapp ignores dist/ 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 adds scope_path column with compound unique index.
  • Pattern-based mass forgetatlas forget --pattern "*.log" permanently deletes all entities whose current path matches the glob. Dry run by default showing blast radius (active/deleted/disconnected counts), --confirm to execute. Uses the same CompiledIgnoreSet matching engine as ignore patterns — no divergence between “what gets ignored” and “what gets forgotten.” Each entity is logged to forget_log via the existing forget_entity path.
  • atlas ignore list updated — 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 .atlasignore files — 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.
  • forget extended with --pattern flag 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) — Extracts assetPath property and resolves to the actual audio file in the project’s Assets/ directory (input edge). Traits: frequency_khz, channels, length_seconds.
  • Event XMLs (Metadata/Event/{uuid}.xml) — Extracts SingleSoundaudioFile UUID references as input edges to AudioFile XMLs. Extracts banks relationship UUIDs as input edges to Bank XMLs. Handles nested MultiSound containers with multiple SingleSound children. Trait: fmod_event_name.
  • Bank XMLs (Metadata/Bank/{uuid}.xml) — Extracts bank name and resolves to compiled .bank file in Build/Desktop/ (output edge). Trait: fmod_bank_name.
  • Lineage chain — Event XML → AudioFile XML → .wav file 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.

  • disconnected state — When a watched path disappears (external drive ejected, cloud folder removed), all entities under it are marked disconnected instead of deleted. This preserves the semantic that the files aren’t gone — they’re just unreachable.
  • Stale watch detectionsync_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 reconciliationatlas scan now 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 reconciliationatlas start now 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 history offline 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 to inactive, records removed_at). Historical entity data is fully retained.
  • atlas watch on a previously inactive path — Reactivates it (sets status to active, updates added_at, clears removed_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 --inactive flags. Shows added_at, removed_at, and last_activity_at timestamps 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 the bankchain array and categorization fields. NKS preview audio linking.
  • NKS Snapshot (.nksn) — NI DSIN container with 4KIN marker. Extracts library product ID (input edge) and NKS preview audio (output edge). Reuses ni_container.rs for 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 requiring komplete.db3.
  • Reaktor Ensemble (.nrkt) — NI DSIN container. Extracts product ID (input edge) and file:// URI content references to dependent resources like .rkplr files (input edges).
  • Bitwig Preset (.bwpreset) — BtWg binary 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>.ogg when the preview file exists on disk. Shared nks_preview_ref() helper in ni_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) skip extract_traits() — the file_type/is_text/byte_size traits 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 capMAX_HASH_THREADS increased 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_THREADS constant (4) with a dedicated rayon::ThreadPoolBuilder for 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 scansPRAGMA cache_size = -262144 set 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::Immediate instead of the default Deferred. 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.”

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 — dependenciesedges

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:

  1. FILE directives → audio source paths (input edges)
  2. ORIGINAL_FILENAME → import provenance (sets source_path on target entity)
  3. <VST> blocks → plugin name, vendor, and format (input edges)
  4. Kontakt deep extraction → base64-decode VST state blob, parse NI container, resolve product ID via komplete.db3 to library name and path (input edges)

Added: Kontakt .nki extractor

Binary NI container parsing for Kontakt instrument files:

  • Product ID from AUTHORING_APPkomplete.db3 resolution to library name and path
  • Instrument metadata from SOUNDINFO
  • Sample paths via FastLZ decompression + FILENAME_LIST_EX parsing (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:

  • HTMLsrc, href, <link>, <script>, <img>, <video>, <audio>, <source> attributes
  • CSSurl() values, @import paths
  • Markdown — image references ![](path), link references [](path)
  • JSON/YAML — heuristic detection of path-like string values
  • SVGxlink: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 need
  • atlas outputs <file> — what does this entity produce
  • atlas broken [file] — unresolved or missing references
  • atlas orphans [--type <ext>] — files not referenced by anything
  • atlas impact <file> — transitive cascade analysis
  • atlas 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.