How the Modly Settings Store Persists Configuration Across Sessions

Modly persists configuration by storing settings in a JSON file inside Electron's user-data directory, reading it on startup and writing updates synchronously via getSettings and setSettings in electron/main/settings-store.ts.

The Modly application is an Electron-based tool for AI model management, and reliable configuration persistence is critical for a smooth user experience. The settings store ensures that user preferences—including API tokens, directory paths, and workflow settings—survive application restarts. This article explains exactly how the settings store persists configuration across sessions, with full reference to the implementation in the lightningpixel/modly repository.

Where Settings Are Stored

Settings are saved to a file named settings.json located in Electron's user-data directory. This directory is platform-specific—typically ~/Library/Application Support/Modly on macOS, %APPDATA%/Modly on Windows, and ~/.config/Modly on Linux.

The settingsPath function constructs this location:

// From electron/main/settings-store.ts
settingsPath(userData) => join(userData, 'settings.json')

Because Electron's app.getPath('userData') returns a consistent path across sessions, the same file is read every time the application launches.

How Settings Are Loaded on Startup

The getSettings(userData) function handles configuration retrieval. It implements a robust loading strategy with graceful degradation:

  1. Defaults first – A base configuration object is created with sensible defaults for modelsDir, workspaceDir, workflowsDir, extensionsDir, and dependenciesDir, all relative to userData.

  2. File check – If settings.json exists, it is read synchronously using readFileSync.

  3. Legacy migration – Old configuration keys like outputsDir are automatically mapped to the current workspaceDir naming.

  4. Merge strategy – Parsed file values are spread over defaults: { ...defaults, ...parsed }.

  5. Corruption handling – If parsing fails for any reason, the function returns defaults rather than crashing.

// Retrieve configuration (creates defaults if file missing or corrupt)
const userData = app.getPath('userData');
const config = getSettings(userData);

console.log(config.modelsDir);  // '/Users/.../Application Support/Modly/models'

How Settings Are Saved

The setSettings(userData, patch) function persists changes atomically:

  1. Merge incoming changes with current settings: { ...getSettings(userData), ...patch }.

  2. Write to disk using writeFileSync for immediate, blocking persistence.

  3. Pretty-print with 2-space indentation for human readability and debugging.

// Update and persist the Hugging Face token
setSettings(userData, { hfToken: 'hf_...' });

// Change models directory location
setSettings(userData, { modelsDir: '/mnt/large-disk/models' });

Every UI action that modifies settings calls setSettings, ensuring the disk file always reflects the current state.

Configuration Structure and Defaults

The default settings object in electron/main/settings-store.ts defines these keys:

Key Default Value Purpose
modelsDir ${userData}/models Local model storage
workspaceDir ${userData}/workspace Project outputs and artifacts
workflowsDir ${userData}/workflows Saved workflow definitions
extensionsDir ${userData}/extensions Extension modules
dependenciesDir ${userData}/dependencies Dependency packages
hfToken undefined Hugging Face API authentication

Users can override any default through setSettings, and their choices persist indefinitely.

Cross-Session Persistence Guarantees

The synchronous file operations (readFileSync/writeFileSync) provide immediate consistency:

  • No data loss on crash – writes complete before function returns
  • No stale reads – every getSettings call reads fresh from disk
  • Atomic updates – the merge-then-write pattern prevents partial configuration states

This design prioritizes durability over performance, appropriate for a desktop application where configuration changes are infrequent.

Summary

  • Settings persist to settings.json in Electron's user-data directory
  • getSettings loads, migrates, and merges with defaults; survives corruption gracefully
  • setSettings writes updates synchronously with pretty-printed JSON
  • All paths are relative to userData, ensuring portability across machines
  • Legacy key migration (outputsDir → workspaceDir) maintains backward compatibility

Frequently Asked Questions

What happens if settings.json is deleted?

Modly regenerates defaults automatically. On next launch, getSettings will find no file, return the default configuration, and subsequent setSettings calls will create a fresh settings.json.

Where exactly is the settings file located?

The path is join(app.getPath('userData'), 'settings.json'). On macOS this resolves to ~/Library/Application Support/Modly/settings.json; on Windows %APPDATA%/Modly/settings.json.

Can multiple Modly instances corrupt the settings?

Potentially yes. The implementation uses readFileSync and writeFileSync without file locking or atomic rename operations. Concurrent modifications from multiple processes could lead to race conditions, though this is uncommon for a single-user desktop application.

How do I programmatically reset all settings to defaults?

Delete settings.json while the application is closed, or call setSettings(userData, getDefaults(userData)) if you have access to the internal getDefaults helper (currently private in the source).

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →