Propose a change
Name Last commit message Last updated
install.sh Add adompkg installer files 1mo ago
package.json Add adompkg installer files 1mo ago
page.json Remove internal identifiers from page.json 10d ago
README.md Initial commit: skill/carbon-preferences 1mo ago
SKILL.md Add adompkg installer files 1mo ago
uninstall.sh Add adompkg installer files 1mo ago

Carbon Preferences API

Store and retrieve per-user key-value pairs via the Carbon hydrogen_preferences object. Adrian built this for Hydrogen's theme/UI settings, but it works for any lightweight per-user config (adom-desktop flags, feature toggles, timestamps, etc.).

Hard limit

10 MB total per user. Keep individual values small. Don't dump logs, blobs, or large JSON objects into preferences.

Data model

GET /user returns the authenticated user. The hydrogen_preferences field contains three sections:

hydrogen_preferences: {
  settings:    Record<string, string | number | boolean>
  keybindings: Record<string, string>
  extensions:  Record<string, { version: string, enabled: boolean }>
}

Reading preferences

Read via GET /user and extract the hydrogen_preferences field.

CLI

# Full user profile (hydrogen_preferences is a top-level field)
adom-cli carbon user get

# Extract just settings with jq
adom-cli carbon user get | jq '.hydrogen_preferences.settings'

# Get a single setting
adom-cli carbon user get | jq -r '.hydrogen_preferences.settings["general.appearance.theme"]'

curl (from container)

API_KEY=$(cat /var/run/adom/api-key)
curl -s -H "Cookie: session_token=$API_KEY" https://carbon.adom.inc/user \
  | jq '.hydrogen_preferences'

JavaScript (Hydrogen web)

const user = await get(`${API_BASE_URL}/user`);
const theme = user.hydrogen_preferences.settings['general.appearance.theme'];

Tauri (Hydrogen Desktop)

const { invoke } = await import('@tauri-apps/api/core');
const result = await invoke('auth_proxy', { path: '/user', method: 'GET' });
const settings = result.data.hydrogen_preferences.settings;

Writing settings

Endpoint

PATCH /user/hydrogen/settings
Content-Type: application/json

Request body

{ "key": "dotted.key.name", "value": "<string | number | boolean | null>" }
  • key -- dotted lowercase string matching ^(?:[a-z0-9_]+)(?:\.[a-z0-9_]+)*$
  • value -- string, number (f64), boolean, or null to delete

One key per request. Returns { "status": 200 } on success.

CLI

# Set a boolean
adom-cli carbon user hydrogen-settings '{"key":"desktop.enabled","value":true}'

# Set a string
adom-cli carbon user hydrogen-settings '{"key":"desktop.last_slug","value":"john-myproject-abc123"}'

# Set a number
adom-cli carbon user hydrogen-settings '{"key":"desktop.last_connect_epoch","value":1747612800}'

# Delete a key (set value to null)
adom-cli carbon user hydrogen-settings '{"key":"desktop.enabled","value":null}'

curl (from container)

API_KEY=$(cat /var/run/adom/api-key)
curl -s -X PATCH https://carbon.adom.inc/user/hydrogen/settings \
  -H "Cookie: session_token=$API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"key":"desktop.enabled","value":true}'

JavaScript (Hydrogen web)

await patch(`${API_BASE_URL}/user/hydrogen/settings`, {
  key: 'general.appearance.theme',
  value: 'adom-light'
});

Tauri (Hydrogen Desktop)

await invoke('auth_proxy', {
  path: '/user/hydrogen/settings',
  method: 'PATCH',
  body: { key: 'desktop.enabled', value: true }
});

Writing keybindings

Endpoint

PATCH /user/hydrogen/keybindings
Content-Type: application/json

CLI

adom-cli carbon user hydrogen-keybindings '{"key":"editor.save","value":"Ctrl+S"}'

Key naming conventions

Use dotted namespaces to avoid collisions. Third-party tools (adom-desktop, CLI tools, etc.) MUST use their own namespace prefix so they never clobber keys the Hydrogen frontend uses.

Namespace Owner Examples
general.* Hydrogen frontend general.appearance.theme, general.developer_mode
schematic.* Hydrogen schematic editor schematic.nudge_amount.small
3d.* Hydrogen 3D viewer 3d.control_style
code.* Hydrogen code editor code.vim_emulation_mode
simulator.* Hydrogen simulator simulator.code_editor_position
desktop.* adom-desktop / HD desktop.enabled, desktop.last_connect_epoch, desktop.last_slug

Rule: Never write to general.*, schematic.*, 3d.*, code.*, simulator.*, or extensions.* -- those belong to the Hydrogen frontend. Pick a unique prefix for your tool (e.g., desktop.*, chipfit.*, tsci.*).

Known Hydrogen settings (defined in settings tree)

These have schema definitions with types, defaults, and validation:

Key Type Default Description
general.developer_mode boolean false Developer mode
general.pane_focus_mode boolean true Only focused pane is active
general.appearance.theme string adom-dark Theme
general.appearance.user_interface_style string standard UI density (standard, compact)
schematic.nudge_amount.small number 1 Arrow key nudge (px)
schematic.nudge_amount.large number 8 Shift+arrow nudge (px)
schematic.invert_zoom_direction boolean false Invert scroll zoom
schematic.default_cursor string crosshair Default cursor
3d.control_style string fusion 3D controls (fusion, solidworks, blender)
3d.invert_zoom_direction boolean false Invert 3D scroll zoom
code.appearance.font.family string DM Mono Code font
code.line_numbers.enabled boolean true Show line numbers
code.line_numbers.style string absolute Line number style
code.vim_emulation_mode boolean false Vim mode
simulator.code_editor_position string right Code panel position

Custom keys (like desktop.*) are not in this schema -- they are stored and returned as-is with no server-side validation.

Behavior notes

  • Setting a value to null deletes the key entirely (not stored as null)
  • Setting a value equal to the schema default in the Hydrogen frontend also deletes it (clean storage)
  • Keys not in the schema are accepted and stored -- no server-side key validation
  • One key per PATCH request; batch by issuing multiple requests
  • Auth: same as all Carbon endpoints -- session token cookie or X-Api-Key header
  • The full preferences object is returned inline with every GET /user call, so there's no separate GET endpoint for just preferences