Omahub
← All plugins
T

Neopolitan

by tpelicano

Neapolitan dough calculator in the bar: baker's-percentage batch math, yeast scaled for ferment temperature, time and type, saved presets, the procedure, clipboard copy and a printable export.

Security review

Review recommended · 1 finding

Deterministic scan — not a security guarantee

Medium
Risk level
Medium
Analyzed commit
dcab986
Scanned
1 month ago
  • medium external_hosts …/workflows/test.yml:26

    Downloads or connects to an external HTTP(S) host.

    git clone --depth 1 --branch quattro https://github.com/basecamp/omarchy /tmp/omarchy

Automated analysis only — not a security guarantee.

AI advisory review

No obvious issues detected

Language-model assessment · ~deepseek/deepseek-v4-flash-latest — advisory only

Low
AI risk level
Low
Recommendation
install
Model
~deepseek/deepseek-v4-flash-latest
Analyzed commit
dcab986
Reviewed
1 month ago

The plugin is a self-contained QML dough calculator with no install-time code execution, no network access at runtime, and no destructive operations; the only external-host finding is a CI workflow that clones the upstream Omarchy repo for testing, which is not part of the installed plugin. The code is well-structured, escapes user-provided text in HTML/Text sinks, and limits file writes to its own state directory and the user-selected export directory.

  • The deterministic scan flagged .github/workflows/test.yml for cloning https://github.com/basecamp/omarchy, but that is CI-only and never runs on a user's machine during install or use.
  • The Export feature invokes headless Chromium to print a generated HTML file; this is user-initiated and writes only to the configured export directory, so it is acceptable but worth noting as the only subprocess execution.
  • The plugin writes to ~/.local/state/omarchy/neopolitan/presets.json and can open it in the user's editor; this is documented, user-visible behavior with no hidden persistence.
How this check works

This review combines the deterministic scan (the rule-based results above) with an independent look at the plugin's code by a language model. The model reads a trimmed sample of the repository's files, the manifest, and the README, then gives a plain-language risk level and a recommendation: install (no notable danger), review (look closer first), or avoid (clearly dangerous).

It runs on the same analyzed commit as the deterministic scan and is strictly advisory — it is not a security guarantee and never blocks a plugin by itself. A human moderator still reviews plugins before they are listed.

AI advisory only — automated analysis, not a security guarantee.

Install
$ omarchy plugin add https://github.com/tpelicano/neopolitan --enable
Widgets #bar #quickshell

Neopolitan

A Neapolitan dough calculator that lives in the Omarchy bar. Baker's percentages, yeast scaled for how warm and how long you ferment, and the weights for the whole batch — without leaving the desktop for a spreadsheet.

Click the bread-loaf glyph in the status bar: batch weights on top, the inputs underneath, and the results recalculate as you type.

What it computes

Standard baker's-percentage back-solve. Total dough is fixed by doughball count × ball weight, and flour is the unknown that makes the percentages add up:

totalDough = count × ballWeight
flour      = totalDough / (1 + hydration + saltRatio + yeastRatio)
water      = flour × hydration
salt       = flour × saltRatio
yeast      = flour × yeastRatio

The yeast percentage you enter is calibrated at 70 °F over 1410 total ferment minutes on active dry yeast. The calculator scales away from that reference using the accepted rules of thumb:

Factor Rule
Temperature Activity doubles per 17 °F rise, so a colder ferment needs more yeast
Time Inversely proportional to total ferment minutes (bulk rest + balled)
Type Instant yeast is ~25% more potent by weight — 0.75× active dry

At exactly the reference conditions all three factors are 1.0 and the entered percentage passes through untouched. That invariant is asserted in the tests.

With the shipped defaults (8 × 280 g, 62% hydration, 2.6% salt, 0.06% ADY, 70 °F ferment, 30 min bulk rest, 23 h balled) you get:

Flour (00)   1360.4 g
Water         843.4 g
Salt           35.37 g
Active dry     0.82 g
Total dough  2240.0 g

Water temperature feeds the procedure only — it never moves a gram.

Features

  • Live batch weights, rounded to the precision each ingredient is weighed at
  • Every variable that moves a number, with plain labels
  • The five-step procedure, with your temps and times interpolated (folded away by default, since the popup is already tall — click the header to open it)
  • Saved presets — name a batch setup, click to recall, delete with a confirm
  • A user-owned default batch, editable as JSON with live reload (see Settings)
  • Copy puts the whole recipe on the clipboard as plain text (wl-copy)
  • Export writes a printable recipe to ~/Downloads

Install

omarchy plugin add https://github.com/tpelicano/neopolitan.git --enable --yes

Or, to develop against a local clone:

make link     # symlink this repo into ~/.config/omarchy/plugins/ and rescan
make enable   # add the widget to the bar

The widget lands in the bar's right section; move it with omarchy bar move tpelicano.neopolitan --section center.

Requirements

Omarchy 4 (Quattro) or newer — the plugin runs inside omarchy-shell, the Quickshell host. Nothing needs to be installed to build or package it.

Needs For If missing
wl-copy (wl-clipboard) Copy Ships with Omarchy. Copy does nothing without it
Chromium or Chrome Export → PDF Button becomes Export HTML; the HTML is still written
omarchy-launch-config-editor ⚙ settings button Ships with Omarchy
Node.js Running the test suite only Not needed to use the plugin

No fonts are installed. The bar glyph is a Nerd Font bread loaf; if your font lacks it, set barLabel to doughballs or flour for a text label instead.

Uninstall

omarchy plugin remove tpelicano.neopolitan

That removes the widget from the bar and deletes the plugin directory. It does not touch your saved batches, so reinstalling picks up where you left off. To remove those too:

rm -rf ~/.local/state/omarchy/neopolitan

If you installed with make link, use make unlink (or delete the symlink at ~/.config/omarchy/plugins/tpelicano.neopolitan) instead.

Nothing else is left behind: the plugin writes only its own state directory and its entry in ~/.config/omarchy/shell.json, which omarchy plugin remove clears.

Settings

Your default batch

The ⚙ button in the panel opens presets.json in your editor (whatever omarchy is set to use). Saving it reloads the panel immediately — no restart, no reopening.

The defaults block is your own baseline: what ↻ returns to. Set it once to your house recipe and reset always brings you home:

{
  "defaults": { "doughballCount": 16, "doughballWeightG": 250, "hydrationPercent": 65 },
  "lastInput": { "...": "where you left off" },
  "presets": []
}

Any key you leave out falls back to the shipped value, and anything out of range or unparseable is clamped rather than trusted — so a bad hand-edit degrades instead of producing NaN g.

Don't want to edit JSON? Right-click ↻ to make the batch currently on screen your default.

lastInput is just where you left off; it is written for you as you work and is independent of defaults.

Widget preferences

Two keys on the widget's entry in ~/.config/omarchy/shell.json. Omarchy 4.0.1 ships no UI that renders a plugin's settings schema yet, so these are hand-edited for now (shell.json hot-reloads on save):

Key Default What it does
barLabel icon icon, doughballs (8×280 beside the glyph), or flour (the flour weight)
exportDir ~/Downloads Where Export writes

Scripting

The plugin registers a neopolitan IPC target, so the recipe is reachable from a script or a keybinding without opening the panel:

omarchy-shell neopolitan recipe        # print the current batch as plain text
omarchy-shell neopolitan copy          # same, onto the clipboard
omarchy-shell neopolitan exportRecipe  # write the printable files
omarchy-shell neopolitan toggle        # open/close the panel

Where state lives

Widget preferences live in shell.json like any bar widget. The recipe itself — the current batch and every saved preset — lives in its own file:

~/.local/state/omarchy/neopolitan/presets.json

That split is deliberate. The bar-widget settings schema has no float type, so 62.5% hydration and 0.06% yeast have no faithful representation in it; and a settings write-back replaces a widget's layout entry wholesale, which would silently drop any recipe keys smuggled in alongside. Presets also want to be an array of up to 50 objects, which has no business in a bar layout entry.

The file is plain JSON and safe to hand-edit — anything malformed, truncated or from a future schema version degrades to the defaults rather than throwing. It is watched, so an edit from any source lands live; the panel ignores the echo of its own writes so editing and using it at the same time is safe.

Export

Export renders the recipe to a self-contained HTML file (no external assets, so nothing to fetch) and then prints it to PDF with headless Chromium, which is already on an Omarchy box. Both land in exportDir:

~/Downloads/dough-recipe-8x280g.html
~/Downloads/dough-recipe-8x280g.pdf

If no Chromium/Chrome is found the button reads Export HTML and stops after the HTML — open it and press Ctrl+P. If Chromium is present but fails, the HTML is still on disk and the status line says so. It never silently does nothing.

Development

make test     # node unit tests + omarchy plugin validate + qmllint
make watch    # restart the shell on every save (see below)
make reload   # one-shot shell restart

Model.js holds the entire data layer — the math, the formatting, the procedure, the renderers, and the preset-store shape — as plain functions with no QML types, so QML and node --test load the same file and the tests test what ships.

On reloading a symlinked checkout: the shell hot-reloads plugin code by watching ~/.config/omarchy/plugins with inotifywait -r, which does not traverse symlinks. A symlinked working tree is discovered and mounted fine, but saves inside it never reach that watcher.

Measured on Omarchy 4.0.0.alpha, neither omarchy-shell shell rescanPlugins nor re-creating the symlink swaps the code of an already-mounted bar widget — the watcher logs the reload, but the running instance keeps the old QML. Only omarchy restart shell reliably applies an edit, so that is what make watch and make reload do. Installing the plugin normally (omarchy plugin add, a real directory) is not affected.

Layout

File What it is
manifest.json The plugin contract the shell and omarchy-plugin-validate enforce
Model.js All the math, formatting and store logic — pure, testable, no QML
BarWidget.qml The bar button; loads the panel eagerly and hands it the bar
Panel.qml The popup and the state machine: results, inputs, procedure, presets, export
DecimalField.qml Fractional number entry — the kit's NumberField is int-only
ResultTile.qml One batch-weight card
SectionHeader.qml Section header with an optional fold chevron

License

MIT