fremkit.app · Download · brew install --cask fdussert/fremkit/fremkit
Fremkit turns the Corsair Xeneon Edge — a 2560 × 720 touch strip — into a widget dashboard for
your Mac. Pages of tiles show the clock, the machine's load, your calendar, your build pipelines,
your 3D printer, your smart home; you arrange them by dragging them around in a browser-based
admin, and you drive them by touch through a native macOS helper. Widgets are plain HTML folders,
so writing one takes a manifest and an index.html — no build step, no framework.
No iCUE, no third-party driver, no kernel extension. The helper talks to the Edge's touch panel over USB HID itself. Quit iCUE and Touchscreen Gestures if you run them — Fremkit replaces them, it does not sit beside them.
The name is the Fremen survival kit from Dune.
- Pages of tiles on a 64 × 16 grid, switched from a navigation bar, with optional auto-rotation.
- A live editor at
/admin: the real page rendered with real widgets, drag and resize with snapping, overlap refused, keyboard nudges, undo/redo and autosave. - Thirty-nine widgets — clock, weather, a pomodoro timer, CPU, memory, disks, a disk map, network throughput, batteries, processes, volume, Spotify, Dock badges, a clipboard history, shortcut buttons, service status checks, published calendars, Claude Code sessions and limits; and, from the registry, meeting controls, CleanShot X actions, Azure DevOps builds, GitHub notifications and Actions, a Bambu Lab printer, Homey devices and flows, a Synology NAS. Twenty-two ship with Fremkit; the rest are one press away in the admin.
- An iPad app that shows a screen of the dashboard from your Mac over the local network, paired by QR code and revocable from the admin. See docs/devices.md.
- A browser extension — Fremkit Companion sends the video of a Chromium tab to the Fremplay widget on the Edge, with touch controls. See docs/companion.md.
- Compact widgets in the navigation bar, with a full-size popover on touch.
- Per-tile appearance — background colour, opacity, background image, accent colour and how much of the tile the accent paints.
- Connections — named credential sets for outside services, with secrets kept in the macOS keychain rather than in the config file.
- A native helper — a menu bar app that drives the Edge's touch panel with its own HID driver, fences the mouse out of the display, shows the dashboard in a kiosk window and supervises the server.
- A widget marketplace — Sietch in the admin installs widgets from a curated registry, showing what each one will be allowed to do and asking again when an update wants more.
- Backup and restore of the whole dashboard, as a zip that never carries a secret, and a history of every saved version for the last month, each one a click away from coming back.
- Shareable layouts — a page, a screen or the whole setup as one file to post and load in a click, without your accounts in it.
- Themes — the palette, the fonts and the text size, as a folder with one JSON file: two ship with it, four more are on the registry, and yours sits beside them. The dashboard, the editor and the widgets all wear the one you pick — or a second one at night, switching at sunset or at the time you choose.
- Two languages — the whole interface is French or English, switched in the admin.
- A widget SDK that is a folder, a JSON file and an HTML page.
- Optional local operations show Docker containers and Ollama/MLX models through registry widgets. See docs/local-operations.md.
Nothing from Corsair: no iCUE, no driver. The helper opens the touch panel itself, so iCUE and Touchscreen Gestures must not be running (the panel takes one owner).
- macOS 13 or later, Apple silicon
- a Corsair Xeneon Edge — everything except the touch driver works on any display
jq, only for the Claude Code status lineffmpeg, only for the chamber camera of an X1 or H2 printer- to build from source only: Xcode Command Line Tools, Node 22 or later, and pnpm
| Install the app | Build from source |
|---|---|
| For using Fremkit. One signed, notarized app that carries everything it needs, Node included, and updates itself. | For working on Fremkit. A checkout, the developer helper pointed at it, and your changes live on the Edge. |
Download the DMG and drag Fremkit to Applications — or brew install --cask fdussert/fremkit/fremkit |
git clone + pnpm run setup, below |
Data in ~/Library/Application Support/Fremkit |
Data in the checkout's data/ |
-
Download
Fremkit-<version>.dmgfrom the latest release, open it and drag Fremkit onto Applications — or, with Homebrew:brew install --cask fdussert/fremkit/fremkit
-
Quit iCUE and Touchscreen Gestures, if you use them — see step 3 of the source install below for the launchd agent that relaunches Touchscreen Gestures.
-
Open Fremkit. It lives in the menu bar (the F), starts its own server and opens the dashboard on the Edge. macOS then asks for two permissions for Fremkit, one after the other: Input Monitoring (to read the touch panel), then Accessibility (to post the touch panel's clicks and scrolls, and read the Dock's badges). A permission still missing shows as a line in the menu bar menu; clicking it opens the right pane of System Settings → Privacy & Security. Touch starts on its own once Input Monitoring is granted, or the menu says "Touch: allowed — quit and reopen Fremkit…" and clicking it does that.
-
Allow Local Network when macOS asks — the first time the server reaches a device on your LAN, a printer or a Homey.
-
Full Disk Access, optionally, for the disk map to measure the folders macOS protects: Privacy & Security → Full Disk Access → "Fremkit". See step 8 of the source install below.
Updates arrive by themselves (Sparkle, signed by the project), or with Check for Updates… in
the menu. Your dashboard, connections and backgrounds live in
~/Library/Application Support/Fremkit, never inside the app, so an update or a reinstall keeps
them. The Claude Code hook and status line ship inside the app: see
docs/claude-code.md for the path to put in ~/.claude/settings.json.
Already running the developer helper from a checkout? Nothing changes until you choose to move; docs/troubleshooting.md says how.
-
Clone and set up.
git clone https://github.com/fdussert/fremkit.git cd fremkit pnpm run setuppnpm run setupchecks the prerequisites, installs dependencies, builds the UI and the server, offers to create the code-signing identity, then builds and installs the helper into~/Applicationsand points it at your checkout.pnpm run setup --checkruns the checks only. Type therun:pnpm setupon its own is pnpm's own command, which edits your shell's profile and does not set Fremkit up. -
Say yes to the signing identity when it asks. The helper is signed ad hoc unless a stable code-signing identity exists, and macOS ties Input Monitoring and Accessibility grants to the signature — so with an ad-hoc signature every rebuild would drop the permissions you just granted.
scripts/create-signing-identity.shcreates a local self-signed "Fremkit Helper Dev" certificate in your login keychain. It asks for your login password and is idempotent. -
Quit Touchscreen Gestures, if you use it. It holds the touch controller exclusively, so the helper's driver cannot open the panel while it runs — the helper replaces it, it does not coexist with it. Quitting the app is not enough while its launchd agent relaunches it:
launchctl bootout "gui/$UID" ~/Library/LaunchAgents/<its agent>.plist
-
Grant Input Monitoring. System Settings → Privacy & Security → Input Monitoring → add "Fremkit Helper". Required to read the touch panel's raw HID reports.
-
Grant Accessibility. Same place → Accessibility → add "Fremkit Helper". Required to post the synthetic mouse and scroll events the touch driver generates, and to read the Dock's badges.
-
Relaunch the helper if it asks. Touch starts on its own once Input Monitoring is granted; when macOS wants the helper reopened first, the menu bar F says "Touch: allowed — quit and reopen Fremkit…", and clicking it does that.
-
Allow Local Network when macOS asks. It asks the first time the server reaches a device on your LAN — a Bambu printer, a Homey. The app to allow is "Fremkit Helper".
-
Full Disk Access, optionally. The disk map measures your home folder; without Full Disk Access the folders macOS protects (Mail, Messages, other apps' containers) are shown as unreadable, and macOS asks once for Desktop, Documents and Downloads. Grant it under Privacy & Security → Full Disk Access → "Fremkit Helper" to measure everything — see troubleshooting. It is a broad grant: the server the helper runs can then read every file.
-
Launch at login, optionally, from the menu bar menu. There is no
KeepAlive: if the helper crashes, open it again by hand.
Rebuilding the helper later (pnpm helper:build && pnpm helper:install) is what registers changes
to its bundle, including the fremkit:// URL scheme the dashboard's long press uses to open the
admin window: an older copy ignores it.
The dashboard then opens by itself on the Edge. If you would rather not run the helper at all,
pnpm start serves everything and pnpm kiosk opens a full-screen Chrome window on the Edge,
signed in through a one-time link — you lose the touch driver, the mouse fence and the Dock
badges.
- Open the admin — from the menu bar F menu: in its own window, or in your browser with
Open the admin in the browser. The server answers only callers holding its access secret,
so typing http://127.0.0.1:4242/admin by hand shows a page saying how to get in instead
(see Security); from a checkout,
pnpm open /admindoes the same as the menu. - Add a page with the + in the Pages list, and name it.
- Add widgets — click a card in the widget library to drop it in the first free spot, or drag it onto the canvas. Drag it to move it, pull a handle to resize it.
- Set it up — with a widget selected, the right column shows its title, appearance and its own settings. A widget that needs a service asks for a connection; create one with Connections in the top bar.
- Switch to Test to use the widgets for real. Everything saves on its own; the chip in the top bar says saved, saving or not saved.
A fresh install starts on one page with a clock and the wallpaper that ships with Fremkit. That wallpaper is an ordinary entry in the background library, so Settings → your screen → Screen background → Remove the image leaves the screen with no background at all rather than putting it back.
The admin's middle column is the real page, rendered with live widgets and scaled to fit, with the navigation bar below it exactly as the Edge shows it.
A dashboard can have several screens — the Edge, an iPad — each with its own pages and bar, and each edited on its own: pick it above the canvas. The widgets are shared, so one shown on two screens is the same widget, with the same settings.
- Edit / Test — in Edit, an overlay captures the mouse: click to select, drag to move, eight handles to resize. While a widget moves, alignment guides show where its edges or its centre line up with another widget's or with the screen's edges and centre (the grid already snaps, so the guides only show; they never pull). Shift- or Cmd-click adds a widget to the selection (or takes it out), a drag on the empty canvas draws a rectangle that selects every widget it touches, Cmd+A selects the whole page, and a click on the empty canvas or Escape lets go. Several selected widgets move together — by the mouse or the arrows, locked ones staying put — and are duplicated, copied and pasted (in the same arrangement), locked, restyled, moved to another page or removed together, each as one undo step; the inspector then shows how many and what they share. In Test the overlay steps aside and the widgets are usable, and the preview behaves like the screen: a horizontal swipe on the navigation bar or on free board space changes page, wrapping around at either end.
- Right click — on a widget: settings, show title, appearance (opacity presets, colours, background image, reset), copy and paste its style, duplicate, copy and paste, move to another page or screen, also show it on another screen, default or minimum size, lock its position (a locked widget is neither dragged nor resized), open its connection, about, reload, remove. On the empty canvas: paste, select all, add a widget, new page, page background, screen settings, reload the dashboard. On a page in the list: rename, duplicate, page background, copy to another screen, move, delete. On a library card: add to a page or to the bar, and for a Sietch widget show it there, update or uninstall it. On a group of selected widgets: show title, opacity, duplicate, copy and paste, move to page, lock, remove. On a bar widget: settings, move left or right, remove. On a screen above the canvas: rename, screen settings, reload the dashboard, export, import, delete. The menus work from the keyboard too (arrows, Enter, Escape, type-ahead).
- Command palette — Cmd+K (Ctrl+K, or Commands in the top bar) searches everything the editor can do and runs it from the keyboard: add a widget, go to a page or a screen, select a widget, open a connection, jump to a setting, fix a widget that needs attention, and every item of the right-click menus — the selected widget's included, submenus and all. Its commands are the menus' own, so a new menu item is in the palette too. The last commands run come first.
- Keyboard — Tab and Shift+Tab select the next or previous widget of the page, Cmd+A all of
them, arrows move the selection — one widget or several — by one cell (a held arrow is one undo step), Shift+arrows resize it from the south-east
corner — never through another widget, never a locked one — Delete or Backspace removes it,
Cmd+D duplicates it, Cmd+C and Cmd+V copy it and paste a new one with the same settings on the
page you are on (any page, any screen), Escape deselects. Cmd+Z and Cmd+Shift+Z undo and redo
anywhere, up to 50 steps.
?shows every shortcut; the sheet, the key handler and the menus' hints all read the one table inui/src/admin/shortcuts.ts. - Left column — the pages (drag to reorder, double-click to rename, the rest in their menu or
behind the "…" on hover) and the widget library, with a
rescan button that re-reads the
widgets/folder without restarting the server. Each card says in a line what that widget asks for, so a folder dropped intowidgets/cannot ask for anything quietly. - Right column — Widget: title, whether the frame draws it, background, accent, the widget's own settings, position and size, and what the widget asks for — the channels it reads, the ones it can command, the hosts it may reach. With no widget selected, Page: its own background (a colour or an image shown instead of the screen's, or the screen's). Screen: language, grid (read-only), navigation bar height and opacity, which gesture opens the admin, auto-rotation delay, the bar's compact widgets, the screen background, the kiosk URL, the history of saved versions, backup and restore, and privacy.
- Move to page — a tile can be sent to another page from the Widget tab: it keeps everything it carries and lands in the largest free spot there, or the move is refused when nothing fits.
- Copy settings from… — where the same widget already exists elsewhere, a drop-down above its settings copies the configuration of another of its instances, tile or navigation bar, in one step.
- Saving — every change saves on its own, grouped over 300 ms, as a
PUT /api/configof the whole configuration. A refusal shows the message in a toast and reloads from the server. Two admin tabs open at once are last-writer-wins.
Pages. A dashboard is any number of pages, each a full screen of tiles. You switch between them by swiping, by tapping the dots in the navigation bar, or automatically after a delay you set (auto-rotation, off by default).
The grid. A page is 64 columns by 16 rows of 40 px cells — the Edge's 2560 × 720, less the navigation bar. A 40 px bar leaves 17 rows instead of 16. Every position and size is in whole cells: placement snaps to them, and a drop that would leave the screen or overlap a neighbour is refused with a red ghost rather than silently adjusted.
Tiles and sizes. A tile is one instance of a widget, with its own settings, position and size. Each widget declares a minimum size the editor will not go below and a default size it is dropped at; between the two the size is free, and a well-written widget reflows.
Appearance. Every tile carries its own look: a background colour, an opacity from 0 to 1 that lets the screen background show through (0 makes the tile, border included, fully see-through — the selection outline keeps it findable while editing), a background image with a dimming overlay, an accent colour, and an accent mode saying how much of the tile that accent paints: none leaves it to the widget's own highlights, frame colours the title bar and the border, fill colours the whole tile. The screen itself has a background colour and image too, and a page can have its own, shown instead of the screen's while that page is on screen.
The navigation bar. The strip at the bottom of every page, 80 px or 40 px tall, as opaque as you like. Its middle shows page dots by default. In Settings → your screen → Layout → Pages in the bar, each screen can show scrolling names instead. The sides stay available for compact widgets. Hold or double-tap a page button to open the admin — the Edge has no keyboard, so this is the way in from the screen. Settings → your screen → Layout → Open the admin from the bar chooses between the two gestures, or accepts both, which is the default. When both gestures are enabled, a page tap waits briefly for a possible double tap. With only long press enabled, the page opens on release. The admin prevents a named-page layout that would hide compact widgets. A single page keeps its button so the admin shortcut remains available.
Compact widgets. Widgets can live in the bar, in a left or a right cluster, in the order
you set, as many as fit beside the page buttons. A compact rendering is one readable line, as wide
as the widget's manifest asks for and as tall as the bar; the bar is its surface, so it has no
title and no tile of its own. Ten of the built-ins have one: clock, weather, pomodoro,
cpu, memory, network, battery, calendar, claude-usage and service-status. Registry
widgets bring their own — github-inbox, homey-devices and the two Synology ones have one too.
Full widget on touch. A bar widget can be marked for a popover: touching it opens the same widget at its full default size above the bar. It closes on a second touch, on a touch outside it, on a page change, or after fifteen seconds.
Connections. A widget that talks to an outside service — Azure DevOps, GitHub, a Bambu
printer, a Homey, a NAS, a published calendar — reads its credentials from a named connection,
configured once in the admin and referenced by the widget. The connection types are part of
Fremkit; the widgets for these live on the registry, which is why creating one lists them.
Several widgets can share one, and one service can have several. Non-secret fields live in data/fremkit.json; secrets go to the macOS keychain
(or, with the file backend, to a mode-600 data/secrets.json) and are never returned by the
API, logged, written to the config or sent on the WebSocket.
Brightness. Settings → your screen → Brightness sets the level of the selected screen and how it changes
on its own, per screen: a day / night pair of levels switched at sunrise and sunset (computed
on the Mac from a latitude and longitude — typed, or found with Search for a city, which asks
Open-Meteo for that name only when you press it) or at fixed times, with a gradual
change of a few minutes; and follow the Mac, where the screen follows the Mac's built-in display
and its light sensor, through a scale and an offset. With both on, the screen follows the Mac and
day / night is a ceiling at night. A change by hand — the brightness widget, this panel, or the
slider in the helper's F menu — holds until the next day / night switch or until the Mac's
brightness moves noticeably; Back to automatic ends it at once. It works over DDC/CI on Apple
silicon, needs the helper, and only drives the display the kiosk is on; a display that does not
answer says so (see troubleshooting).
Language. French or English, switched in the admin's Settings → General. It changes the interface, the widget library and the widgets themselves, live, without a reload.
The helper, or a browser. The dashboard is a web page: any browser can show it. The native helper adds what a browser cannot — its own HID driver for the Edge's touch panel, a fence that keeps the mouse cursor on your other displays, a kiosk window with no chrome and no cursor, the Dock's notification badges, the brightness of the Edge (DDC/CI), and supervision of the server. Its menu bar F shows what is running: Open the admin, Admin in the browser, Hide the dashboard / Show the dashboard, Reload the dashboard, a brightness slider for the kiosk's display, the Touch / Mouse fence / Notifications / Manage the server / Launch at login toggles, Log… and Quit, above state lines such as "Server: running" and "Touch: active".
| Widget | Shows | Connection | Compact |
|---|---|---|---|
battery |
The Mac's battery and its Bluetooth peripherals | — | ● |
brightness |
The brightness of the screen it is on: a slider to slide, in the bar too, and what drives it (day/night, follow the Mac) | — | ● |
calendar |
The next events of one or more published calendars | ICS calendar | ● |
claude-sessions |
Live Claude Code sessions; a touch goes to the session's window, and it can chime when one starts waiting | — | — |
claude-usage |
Claude 5 h / 7 day limits and today's tokens | — | ● |
clipboard |
Recent clipboard entries, tap to copy back | — | — |
clock |
Time, date and other cities | — | ● |
cpu |
CPU load and temperature | — | ● |
disk |
Disk usage and available space | — | — |
disk-map |
What fills the disk, as rings you drill into; long press shows it in Finder | — | ● |
memory |
Memory usage, available RAM and swap | — | ● |
uptime |
Time since the Mac last booted | — | — |
network |
Live network throughput, with a sparkline | — | ● |
notifications |
Unread badges read from the Dock | — | — |
pomodoro |
A work and break timer, driven by touch | — | ● |
processes |
Top processes | — | — |
service-status |
A green, amber or red dot per service it pings | — | ● |
shortcuts |
Big touch buttons that open apps, links and shortcuts | — | — |
spotify |
Current track and transport | — | — |
volume |
System volume | — | — |
weather |
Current weather and forecast, from Open-Meteo | — | ● |
Published on the widget registry rather than shipped, because each one only does anything with a printer, a hub, a NAS or an account behind it. Install them from Sietch in the admin’s top bar; the provider or connection type each one reads is already part of Fremkit, so there is nothing else to set up. A tile placed on a screen whose widget is not installed offers the install where it stands.
| Widget | Shows | Connection | Compact |
|---|---|---|---|
ado-pipelines |
Azure DevOps runs in progress and recent history | Azure DevOps | — |
bambu-job |
A printer's current job, AMS and chamber camera | Bambu Lab | — |
cleanshot |
Big touch buttons for captures, needs CleanShot X with its URL scheme API allowed | — | — |
github-actions |
Running and finished GitHub Actions workflows | GitHub | — |
github-inbox |
GitHub notifications, review requests and pull requests | GitHub | ● |
homey-devices |
Lights, plugs and sensors of a Homey Pro | Homey Pro | ● |
homey-flows |
Buttons that run a Homey Pro's flows | Homey Pro | — |
mutedeck |
Meeting controls through MuteDeck | — | — |
synology-storage |
Volumes, disk health and temperature of a NAS | Synology | ● |
synology-system |
CPU, memory, network and uptime of a NAS | Synology | ● |
Every setting of every widget is listed in docs/widgets.md. To write your
own, see docs/writing-widgets.md: pnpm widget:new my-widget starts
one that works, pnpm dev reloads it on every save, and pnpm widget:check runs the registry's
rules before you publish it. To change how all of it looks,
see docs/themes.md.
What the installer checks, what a consent record is and how an update asks again: docs/marketplace.md.
How to obtain each credential, what is stored where, and what is never logged: docs/connections.md.
The optional Codex provider reads selected local account and chat data after an explicit opt-in. Its dashboard widgets are distributed separately.
A setup worth a photo is worth a file. Export page… (a page's right-click menu),
Export screen… (a screen's), or Settings → Share → Export the whole setup… write a
.fremkit-layout.json: the pages, the bar, each tile's place, look and settings, the theme, and
the background images. The dialog shows what is in the file before you download it (or copy it,
where a download is not possible) and what was left out.
Never in it: connections and their secrets, host names, e-mail addresses, device names, privacy choices, install consents, brightness schedules. A setting that points at a connection is blanked; one typed as free text — a label, a link, a note — goes in only if you tick it. Post the file with a photo in the repository's Discussions → Show and tell.
To load one, drop it onto the editor, or use Import a layout…. The dialog lists the widgets it uses, offers to install from the Sietch the ones you do not have (with the usual consent dialog), asks which of your connections a widget should use, and adds the pages or screens beside yours — replacing only if you choose to. One ⌘Z undoes the whole import. Details, and the file format, in docs/sharing.md.
/admin → Settings → History & backup → Backup downloads the whole dashboard — the configuration and the background
library — as fremkit-backup-<date>.zip, and Restore… takes one back.
Secrets are never in it: they live in the macOS keychain, and the point of keeping them there is that a file copied to a USB stick does not carry them. Because they are keyed by connection id and a restore keeps those ids, restoring onto the same Mac finds them and everything works at once; on another Mac the admin lists the connections whose secret has to be entered again.
A restore replaces the dashboard — pages, widgets, connections and backgrounds — and refuses to write at all while the configuration on disk cannot be read. It keeps this Mac's own security choices whatever the archive says: where secrets are kept, the privacy switches, and what each installed widget was granted. Details in docs/contributing.md.
/admin → Settings → History & backup (or the clock-arrow button next to undo) lists every saved version of the dashboard for the last 30 days, up to 100, grouped by day, each with what changed: pages added, removed or renamed, widgets added, removed, moved or edited, screens, theme. Continuous editing is kept as one version per two minutes, the last state winning. Open a version to see its pages, and Restore this version to put it back. A restore is a save like any other, so the version it replaced is the next line down and restoring that one undoes it. The version before a backup restore, a setup import or a Fremkit update that converts the file is always kept.
Like a backup restore, putting a version back keeps this Mac's secrets backend, privacy switches
and widget permissions, and a connection keeps its stored secret only if it comes back unchanged.
The versions live in data/history/, private to your account, hold no secret (the configuration
never does), and are not part of a backup: a backup is meant to travel, the history keeps what you
deleted on purpose.
Fremkit is a dashboard of your own machine, so several widgets read things that belong to you. The list is short and it is all of it.
| What | Who reads it | When |
|---|---|---|
~/.claude/projects/ — Claude Code's session transcripts |
the claude-sessions and claude-usage widgets, for the session list and the token counts |
whenever one of those widgets is on the dashboard |
The Claude Code-credentials keychain item — Claude Code's OAuth token |
the account usage behind the claude-usage gauges. The token is presented to api.anthropic.com and nowhere else; it is never stored, never logged, never in an error message |
off for a new install. Turn it on in /admin → Settings → Privacy. A dashboard that already showed the Claude widget before this setting existed keeps it on, so the gauges do not go blank on an upgrade — turn it off there if you would rather. The endpoint (/api/oauth/usage) is not documented by Anthropic and may disappear |
| Where a Claude Code session lives — its terminal application, pane and tty, read by the hook inside the session | the claude-sessions widget's ↗, to raise that window again |
whenever the Claude Code hooks are installed. It stays on the server: the dashboard is told which kind of application it is and what to call it, never the pane key or the tty |
The clipboard, through pbpaste |
the clipboard widget |
whenever that widget is on the dashboard |
| The Dock's badge counts and the icons of installed applications | the notifications and shortcuts widgets, through the helper |
whenever one of those widgets is on the dashboard |
| The brightness of the kiosk's display (DDC/CI over its cable) and of the Mac's built-in display | the helper, for the brightness widget and Settings → your screen → Brightness; it changes only the display the kiosk is on |
while the helper runs |
| The volume, the battery, the disks, the processes, the network | those widgets, through pmset, df, ps and friends |
whenever one of them is on the dashboard |
| The names and sizes of the folders and files under your home folder or a volume — never their contents | the disk-map widget, through fremkit-scan or du; the last scan is kept in data/disk-map/ |
only when you tap Scan (the first time) or ↻ on that widget — never on its own, never on a timer |
A widget that shows an account — its plan, how you signed in — never gets the account's e-mail address unless you tick /admin → Settings → Privacy → Show the account e-mail address. It is off by default, and the server leaves the address out of what it sends, so no widget can show it or pass it on. Once on, every widget that reads that account's channel receives it, one installed from the marketplace included, and it is on the screen.
Everything else Fremkit knows, you typed into it: the connections of the table above, whose
secrets live in the macOS keychain (see docs/connections.md). Nothing is
sent to any server other than the ones you configured, there is no telemetry, and the server
listens on 127.0.0.1 only. The one exception is the app's update check: once a day it
downloads appcast.xml from this project's GitHub releases, sending nothing but the request
itself (Sparkle's system profile is off).
| Symptom | Fix |
|---|---|
| "Fremkit can't be opened" or "is damaged" | Download the DMG again from the release page; see the Gatekeeper section of the troubleshooting guide |
| Permissions asked again after moving to the app | Expected once: the app is signed differently from the developer helper. Grant them to "Fremkit" |
| "Touch: Input Monitoring missing — open Settings…" | Click the line, turn "Fremkit" (or "Fremkit Helper" for a source install) on in the Input Monitoring list it opens. Touch starts within seconds, or the line asks you to reopen Fremkit — click it |
| "Touch: taken by another driver" | Quit Touchscreen Gestures and unload its launchd agent |
| Permissions reset after every rebuild | Run scripts/create-signing-identity.sh and rebuild |
A LAN device answers ping but not Fremkit |
Allow Local Network for the app running the server |
| "Server: external" | Something else answers port 4242 — expected under pnpm dev |
| The browser shows "Open Fremkit from the F menu" | The server asks for its access secret. Use Open the admin in the browser in the F menu, or pnpm open |
| A shortcut button to a NAS or a router has no icon | Expected: favicons of private and local addresses are not fetched. The button still works |
| The admin shows an old version of itself | Reopen it, or Cmd+R in its window; it keeps one web view for the helper's lifetime |
| Widgets break after pulling a new version | Restart the server: the widget bridge is read once, at start |
| The iPad app does not list the Mac | The network may not relay Bonjour: scan the QR code the admin shows, or put both on the same Wi-Fi — details |
| The disk map shows locked folders | Give "Fremkit" (or "Fremkit Helper" for a source install) Full Disk Access, or leave them unmeasured |
| The disk map says "du (no helper)" | Expected under pnpm dev: the bundled fremkit-scan is only there under the helper |
The rest, with the reasoning: docs/troubleshooting.md.
pnpm dev # server on 4242 + Vite on 5173; then pnpm open --dev [/admin] to sign in
pnpm open # opens http://127.0.0.1:4242 signed in (pnpm open /admin for the admin)
pnpm demo # a demo server on :4250, invented data only: see docs/demo-mode.md
pnpm build # ui + server
pnpm start # production: http://127.0.0.1:4242 and /admin
pnpm test # vitest, server + ui
pnpm typecheck
pnpm e2e # Playwright end-to-end tests, after pnpm --filter ui build (docs/contributing.md)
pnpm helper:build # native/dist/Fremkit Helper.app
pnpm helper:install
pnpm helper:test
bash scripts/build-app.sh # native/dist/Fremkit.app: the self-contained app, see docs/releasing.md| Folder | What is in it |
|---|---|
server/ |
Fastify 5 on 127.0.0.1:4242 — config, widget catalog, providers, connections, secrets, the bridge, the WebSocket |
ui/ |
Vue 3 — the dashboard, the admin, and the code they share |
e2e/ |
Playwright end-to-end tests of the admin and the dashboard, each worker on a throwaway server |
native/ |
The Swift helper — kiosk window, HID touch driver, mouse fence, admin window, Dock badges, server supervision, and fremkit-scan, the disk map's scanner |
widgets/ |
One folder per widget |
scripts/ |
Setup, dev, the helper's build and tests, the app's build, notarization and release, the signing identity, kiosk, the Claude Code hooks |
packaging/ |
The Homebrew cask and Sparkle's public key |
data/ |
Your configuration and its assets. Git-ignored |
brand/ |
Icon, menu bar glyph, favicons, social image — see brand/README-assets.md |
docs/ |
This documentation |
A second checkout can run beside a live one by giving it another port: FREMKIT_PORT=4301 pnpm start.
FREMKIT_DATA_DIR=/tmp/fremkit-fresh pnpm start points the config, the background library and the
caches somewhere else — a from-scratch install on the live checkout, without moving anything
aside. Your keychain secrets are keyed by connection id, so a fresh config never names them.
Writing a widget for the registry: pnpm widget:new <id>, then pnpm widget:check <folder> —
docs/writing-widgets.md.
Working on Fremkit itself — the helper build, the configuration files:
docs/contributing.md.
Working on it with a coding agent — layout, conventions, the gotchas: AGENTS.md.
Building, notarizing and publishing a release: docs/releasing.md.
Feeding the Claude Code widgets: docs/claude-code.md.
The server answers only callers holding a secret made at each launch: the helper's windows get
it on their own, a browser through a one-time link (the F menu, pnpm open), and scripts read
it from ~/Library/Application Support/Fremkit/access-4242.token and send it as
Authorization: Bearer. For example:
curl -X POST -H @<(printf "Authorization: Bearer %s" "$(cat ~/Library/Application\ Support/Fremkit/access-4242.token)") http://127.0.0.1:4242/api/widgets/rescanThe threat model, what a widget can and cannot do, what the helper's permissions mean, the known limits, and how to report a problem: SECURITY.md.
Fremkit is written by usul, with
FlorianBruniaux, mcouzinet and
LivioGama.
The widgets and themes on the registry name their own authors on their cards. The admin's
Settings → About lists the same people, from ui/src/shared/credits.ts.
The icons are a subset of Lucide (ISC licence, © Lucide Contributors),
inlined in ui/src/shared/icons.ts so the interface takes no runtime icon dependency.
Corsair and Xeneon are trademarks of Corsair Gaming, Inc. Bambu Lab, Homey, Spotify, GitHub, Azure DevOps and Claude are trademarks of their respective owners. Fremkit is an independent project and is not affiliated with, endorsed by or sponsored by any of them; the names are used only to say what it talks to.
MIT — see LICENSE.





