# How Coco App Configures and Persists Autostart and Global Shortcuts

> Discover how Coco App configures and persists autostart and global shortcuts using Tauri. Learn about its React UI and Rust-native OS integrations and data storage.

- Repository: [INFINI Labs/coco-app](https://github.com/infinilabs/coco-app)
- Tags: internals
- Published: 2026-03-04

---

**Coco App leverages Tauri's plugin architecture to bridge React UI commands with Rust-native OS integrations, persisting autostart preferences to a plain-text file and global shortcuts to a JSON-backed key-value store in the application config directory.**

Coco App, an open-source search utility built by Infinite Labs, relies on Tauri's hybrid architecture to manage system-level behaviors. The application configures **autostart** (launch at login) and **global shortcuts** (system-wide hotkeys) through a deterministic flow that persists user preferences across restarts. This implementation spans TypeScript frontend handlers in [`src/commands/system.ts`](https://github.com/infinilabs/coco-app/blob/main/src/commands/system.ts) and Rust backend commands in [`src-tauri/src/autostart.rs`](https://github.com/infinilabs/coco-app/blob/main/src-tauri/src/autostart.rs) and [`src-tauri/src/shortcut.rs`](https://github.com/infinilabs/coco-app/blob/main/src-tauri/src/shortcut.rs).

## Architecture Overview

Coco App runs on **Tauri**, which bridges a React-based UI with native Rust code. Two system-level features—autostart and global shortcuts—are handled through dedicated Tauri plugins and a tiny key-value store. The required plugins are declared in [`src-tauri/Cargo.toml`](https://github.com/infinilabs/coco-app/blob/main/src-tauri/Cargo.toml): `tauri-plugin-autostart` for login-launch management, `tauri-plugin-global-shortcut` for hotkey registration, and `tauri-plugin-store` for JSON persistence.

## Autostart Configuration and Persistence

### Frontend Toggle Flow

When a user toggles autostart in the *General Settings* page, the UI invokes the `change_autostart` command. In [`src/components/Settings/GeneralSettings.tsx`](https://github.com/infinilabs/coco-app/blob/main/src/components/Settings/GeneralSettings.tsx), the toggle handler calls `change_autostart(true)` or `change_autostart(false)` via Tauri's `invoke` API. This reaches the backend through the thin wrapper in [`src/commands/system.ts`](https://github.com/infinilabs/coco-app/blob/main/src/commands/system.ts), which forwards the boolean state to the Rust command layer.

### Rust Backend Implementation

The `change_autostart` command in [`src-tauri/src/autostart.rs`](https://github.com/infinilabs/coco-app/blob/main/src-tauri/src/autostart.rs) interacts directly with the OS via **tauri-plugin-autostart**. The function retrieves the autolaunch manager using `app.autolaunch()`, then calls `manager.enable()` or `manager.disable()` based on the `open` parameter. This immediately updates the OS-level login item or registry entry without requiring a restart.

### Persistence Mechanism

To survive app restarts and OS-level changes, the desired state is written to a plain-text file named [`autostart.txt`](https://github.com/infinilabs/coco-app/blob/main/autostart.txt) in the application config directory (`app_config_dir()`). The Rust code uses `std::fs::write(cfg_dir.join("autostart.txt"), open.to_string())` to persist the boolean. On subsequent launches, the `current_autostart` function reads this file to restore the user's choice, ensuring the UI reflects the persisted state even if the OS modified it externally.

### Startup Consistency Check

During early startup, the setup module in [`src-tauri/src/setup/mod.rs`](https://github.com/infinilabs/coco-app/blob/main/src-tauri/src/setup/mod.rs) calls `autostart::ensure_autostart_state_consistent(&tauri_app_handle)`. This function compares the OS-reported autostart status against the value stored in [`autostart.txt`](https://github.com/infinilabs/coco-app/blob/main/autostart.txt) and reconciles any mismatch, guaranteeing that the actual OS behavior aligns with the user's saved preference.

## Global Shortcut Configuration and Persistence

### Shortcut Management Flow

The shortcuts UI in [`GeneralSettings.tsx`](https://github.com/infinilabs/coco-app/blob/main/GeneralSettings.tsx) provides three primary operations: retrieving the current hotkey, updating it, and unregistering it. These map to `get_current_shortcut`, `change_shortcut`, and `unregister_shortcut` in [`src/commands/system.ts`](https://github.com/infinilabs/coco-app/blob/main/src/commands/system.ts). Each function uses `invoke` to communicate with the Rust backend, passing the shortcut string (e.g., `"ctrl+shift+space"`) for validation and registration.

### Backend Registration and Storage

In [`src-tauri/src/shortcut.rs`](https://github.com/infinilabs/coco-app/blob/main/src-tauri/src/shortcut.rs), the `change_shortcut` command validates the input using `key.parse::<Shortcut>()`, then persists it via **tauri-plugin-store**. The store writes to a JSON file in the config directory using the key `coco_global_shortcut`. After storing, the command calls `_register_shortcut` to activate the hotkey through **tauri-plugin-global-shortcut**, which binds the system-wide listener. The `unregister_shortcut` command removes the active registration without deleting the stored preference.

### Default Shortcuts and Initialization

On first launch, `shortcut::enable_shortcut` checks the store for an existing entry. If none exists, it writes a platform-specific default: `command+shift+space` on macOS, or `ctrl+shift+space` on Windows and Linux. This initialization occurs in [`src-tauri/src/setup/mod.rs`](https://github.com/infinilabs/coco-app/blob/main/src-tauri/src/setup/mod.rs) during `backend_setup`, ensuring the global shortcut is active immediately when the app starts.

## Storage Locations and File Formats

**Autostart preferences** live in a plain-text file at `<app_config_dir>/autostart.txt`, containing the literal string `"true"` or `"false"`. **Global shortcuts** persist as a JSON entry within `<app_config_dir>/coco-app.store.json` (managed by `tauri-plugin-store`) under the key `coco_global_shortcut`. Both paths resolve via `tauri::api::path::app_config_dir()`, making them portable across macOS, Windows, and Linux.

## Implementation Examples

### Toggle Autostart from the Frontend

```typescript
import { change_autostart } from '@/commands/system';

// Enable launch at login
await change_autostart(true);

// Disable launch at login
await change_autostart(false);

```

### Manage Global Shortcuts

```typescript
import {
  get_current_shortcut,
  change_shortcut,
  unregister_shortcut,
} from '@/commands/system';

// Read persisted shortcut
const current = await get_current_shortcut();   // "ctrl+shift+space"

// Update to a new hotkey
await change_shortcut('alt+space');

// Clear current registration
await unregister_shortcut();

```

### Rust Autostart Logic

```rust
// src-tauri/src/autostart.rs
pub async fn change_autostart(app: tauri::AppHandle, open: bool) -> Result<(), String> {
    let manager = app.autolaunch();
    if open { 
        manager.enable()?; 
    } else { 
        manager.disable()?; 
    }

    // Persist to autostart.txt
    let cfg_dir = app.path().app_config_dir()?;
    std::fs::create_dir_all(&cfg_dir)?;
    std::fs::write(cfg_dir.join("autostart.txt"), open.to_string())?;
    Ok(())
}

```

### Rust Shortcut Registration

```rust
// src-tauri/src/shortcut.rs
pub async fn change_shortcut(
    app: AppHandle,
    _window: tauri::Window,
    key: String,
) -> Result<(), String> {
    let shortcut = key.parse::<Shortcut>()
        .map_err(|_| format!("invalid shortcut {}", key))?;

    // Persist to tauri-plugin-store
    let store = app.get_store(COCO_TAURI_STORE)?;
    store.set(COCO_GLOBAL_SHORTCUT, JsonValue::String(key));

    // Register with tauri-plugin-global-shortcut
    _register_shortcut(&app, shortcut);
    Ok(())
}

```

## Summary

- **Autostart** uses `tauri-plugin-autostart` for OS-level toggling and a custom [`autostart.txt`](https://github.com/infinilabs/coco-app/blob/main/autostart.txt) file for state persistence, with `ensure_autostart_state_consistent` reconciling drift during startup.
- **Global shortcuts** rely on `tauri-plugin-global-shortcut` for hotkey registration and `tauri-plugin-store` for JSON persistence using the key `coco_global_shortcut`.
- All configuration data lives in the Tauri application config directory, ensuring cross-platform portability.
- The initialization sequence in [`src-tauri/src/setup/mod.rs`](https://github.com/infinilabs/coco-app/blob/main/src-tauri/src/setup/mod.rs) restores both autostart and shortcut states immediately when the backend launches.

## Frequently Asked Questions

### Where does Coco App store autostart settings?

Coco App writes the autostart boolean to a plain-text file named [`autostart.txt`](https://github.com/infinilabs/coco-app/blob/main/autostart.txt) inside the Tauri application config directory, typically located at `~/.config/coco-app/` on Linux, `~/Library/Application Support/coco-app/` on macOS, or `%APPDATA%\coco-app\` on Windows.

### How does Coco App handle global shortcut conflicts?

If the requested shortcut is already registered by another application, the `change_shortcut` command in [`src-tauri/src/shortcut.rs`](https://github.com/infinilabs/coco-app/blob/main/src-tauri/src/shortcut.rs) will fail during the `_register_shortcut` call, returning an error to the frontend. The UI can then prompt the user to select a different combination.

### What happens if the OS removes autostart permission?

During startup, `ensure_autostart_state_consistent` in [`src-tauri/src/autostart.rs`](https://github.com/infinilabs/coco-app/blob/main/src-tauri/src/autostart.rs) detects the mismatch between the OS state and the [`autostart.txt`](https://github.com/infinilabs/coco-app/blob/main/autostart.txt) file. If the OS has disabled autostart (e.g., via system settings), the function reconciles the file to match the actual OS state, ensuring the UI remains accurate.

### Can users customize the default shortcut on first launch?

Yes. If no prior value exists in the store, `enable_shortcut` in [`src-tauri/src/shortcut.rs`](https://github.com/infinilabs/coco-app/blob/main/src-tauri/src/shortcut.rs) writes a platform-specific default (`command+shift+space` on macOS, `ctrl+shift+space` elsewhere) and immediately registers it. Users can override this default at any time through the General Settings UI, which updates the store and re-registers the hotkey dynamically.