How Settings Are Managed and Accessed in the Modly Application

Modly stores configuration paths and tokens in a JSON file inside Electron’s user-data directory, exposing them via pure functions (getSettings, setSettings) and IPC handlers for secure cross-process access.

The lightningpixel/modly repository implements a centralized configuration system for its Electron-based AI image generation workflow. Understanding how settings are managed and accessed in the Modly application reveals a robust pattern that separates storage logic from business concerns while maintaining synchronization between the main process, renderer, and Python backend.

Central Settings Store

The foundation of Modly’s configuration system resides in electron/main/settings-store.ts, which defines the data structures and persistence logic.

The AppSettings Interface and Defaults

The module exports an AppSettings interface that type-safely declares configurable paths for models, workspace, workflows, extensions, and dependencies, plus optional values like the Hugging Face token. The store generates default directory values dynamically using Electron’s app.getPath('userData'), ensuring platform-appropriate locations across Windows, macOS, and Linux.

Reading and Writing Configuration

Two pure functions handle all disk access:

  • getSettings(userData: string): AppSettings – Reads settings.json from the user-data directory if it exists, merges persisted values with defaults, and safely migrates legacy keys (specifically converting outputsDir to workspaceDir).
  • setSettings(userData: string, patch: Partial<AppSettings>): AppSettings – Writes the updated JSON back to disk and returns the complete new settings object.

The actual file location is determined by settingsPath(userData), which simply joins the user-data folder with settings.json.

IPC Exposure for Cross-Process Access

Since Electron’s renderer process cannot directly access the filesystem, Modly exposes settings through secure IPC channels defined in electron/main/ipc-handlers.ts.

Registering IPC Handlers

The main process registers two handlers during initialization:

ipcMain.handle('settings:get', () => getSettings(app.getPath('userData')));

ipcMain.handle('settings:set', async (_event, patch) => {
  const updated = setSettings(app.getPath('userData'), patch);
  // Synchronize environment variables when HF token changes
  return updated;
});

These endpoints allow the UI to request current configuration or persist partial updates without knowing the underlying file path.

Renderer Process Usage

React components in the renderer invoke these handlers through the preload script:

// Retrieve current configuration
const settings = await window.ipc.invoke('settings:get');
console.log(settings.modelsDir, settings.workspaceDir);

// Update a specific path
await window.ipc.invoke('settings:set', {
  workspaceDir: '/custom/path/to/workspace',
});

Consuming Settings Throughout the Application

Core modules running in the main process import getSettings directly to obtain directory locations or authentication tokens, ensuring they always read the latest on-disk values.

Python Environment Setup

In electron/main/python-setup.ts, the virtual environment path is constructed by joining the dependenciesDir from settings with 'venv':

import { getSettings } from './settings-store';
import { join } from 'path';

const venvPath = join(
  getSettings(userData).dependenciesDir, 
  'venv'
);

Model Download Authentication

electron/main/model-downloader.ts and electron/main/python-bridge.ts both access getSettings(userData).hfToken to authenticate Hugging Face downloads. The token is passed to download routines or exposed to Python subprocesses via environment variables.

Workspace and Extension Management

Various IPC handlers—handling model lists, exports, workspace utilities, and extension installation—resolve their target directories by calling getSettings(app.getPath('userData')) and accessing the specific path properties (.modelsDir, .extensionsDir, etc.).

Runtime Synchronization and Safety

Modly implements additional safeguards and synchronization mechanisms beyond simple file storage.

HF Token Propagation

When the Hugging Face token changes via the settings:set IPC handler, the system immediately updates process.env['HF_TOKEN'] and notifies the FastAPI backend through a POST request to /settings/hf-token. This guarantees that child processes spawned after the change inherit the new token without requiring an application restart.

Filesystem Security Validation

The fs:deleteDirectory IPC handler validates deletion requests against a whitelist of allowed roots derived from the current settings (models, workspace, extensions, and cache directories). This prevents the application from accidentally or maliciously manipulating arbitrary filesystem locations outside its managed scope.

Summary

  • Storage: All settings live in a JSON file inside Electron’s userData directory, managed by deterministic functions in electron/main/settings-store.ts.
  • Access: The renderer communicates via IPC (settings:get, settings:set) while main-process modules import getSettings directly.
  • Synchronization: HF token changes propagate immediately to environment variables and the FastAPI server.
  • Security: Filesystem operations validate paths against whitelist roots defined in the current settings.

Frequently Asked Questions

Where does Modly store its configuration file?

Modly stores configuration in settings.json inside Electron’s userData directory (typically %APPDATA%/Modly on Windows, ~/Library/Application Support/Modly on macOS, or ~/.config/Modly on Linux). The exact path is computed at runtime by joining app.getPath('userData') with settings.json.

How does Modly handle changes to the Hugging Face token?

When updated via IPC, the settings:set handler immediately writes the token to disk, updates process.env['HF_TOKEN'], and sends a notification to the FastAPI server at /settings/hf-token. This ensures both the current process and any subsequently spawned Python subprocesses use the updated authentication credentials.

Can the renderer process directly access the settings file?

No. The renderer process must use IPC invocations (window.ipc.invoke('settings:get') and window.ipc.invoke('settings:set')) to interact with configuration. This isolation prevents the UI from accessing sensitive filesystem locations directly and ensures all changes pass through validation logic in the main process.

How does Modly prevent deletion of arbitrary directories?

The fs:deleteDirectory IPC handler validates requested paths against a whitelist of allowed roots derived from the current AppSettings (models, workspace, extensions, and cache directories). The operation only proceeds if the target path resolves within one of these authorized locations.

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 →