Files
obs-tools/CLAUDE.md
T
2026-10-19 22:51:31 +02:00

7.0 KiB

CLAUDE.md

Style

  • Keep everything short: replies, explanations, comments, docs.
  • Use simple English: short sentences, common words.
  • Avoid em dashes (—). Do not just swap them for "-" either. Rewrite the sentence instead, for example with a comma, a colon, brackets or two sentences.

Commits

  • English only.
  • Conventional Commits prefix: feat:, fix:, chore:, docs:, refactor:, ci:, build:, test:.
  • Subject as short as possible. Imperative, lowercase, no trailing period.
  • Body only when something genuinely cannot be inferred from the diff.
  • Never add Co-Authored-By, "Generated with" or any other AI attribution to commits or PR descriptions.
  • Do not commit or push before I have checked the changes locally and said they are fine. Then commit and push. Several attempts at the same thing make one commit, and attempts that did not work make none. Different things done in one session get a commit each. This also goes for releases and tags.

Project

  • The plugin is Rust (src/) and talks to OpenDeck through the openaction crate. It runs on one thread: every event is a task of its own (tokio LocalSet). Never hold a RefCell borrow across an .await. Settings come from the settings pages as loose JSON ("5" for 5, null for ""). Each action reads them into its own struct with k.settings::<T>() (#[derive(Deserialize, Default)] and #[serde(default, rename_all = "camelCase")]): src/settings.rs reads every field the way JavaScript would. Use String, bool, f64 or serde_json::Value fields, nothing that can fail.
  • make package builds for x86_64 and aarch64 with an old glibc (2.28), so it runs on older distributions too. It needs zig, cargo-zigbuild and the Rust library for aarch64 (Arch: rust-aarch64-gnu). make install only builds for this PC. Dev tools are Rust too: cargo xtask lists them.
  • Plugin ID is de.felitendo.obs-tools (folder de.felitendo.obs-tools.sdPlugin), like the Feishin plugin. Do not change it again: OpenDeck keys profiles and settings by it.
  • manifest.json, de.json, pi/lib/shared.js and the icons in images/ are generated. Change the actions in src/manifest.rs or the glyphs in src/icons.rs, then run make manifest or make icons. make icons first measures every glyph (cargo xtask fit-glyphs, needs ImageMagick), so all icons end up the same optical size and optically centered (halfway between the middle of the box and the center of mass, so a play triangle does not look too far left). The action order in src/manifest.rs is the order in OpenDeck: most used first.
  • The settings pages stay JavaScript (pi/): they run in OpenDeck's web view. What they share with the plugin (German texts, glyphs) comes from Rust through pi/lib/shared.js. pi/lib/render.js draws the same key pictures as src/render.rs: change both, make check compares them.
  • Settings pages come from pi/schemas.js. A new setting needs a default in the defaults of the action (its Kind in src/actions/), a field in its settings struct and a field in the schema. The test every_setting_has_a_default checks that each field has a default. The status line is on top. Its "Change" button opens the connection settings right below it, and they open by themselves while OBS cannot be reached. The settings of the key follow in sections (section in pi/schemas.js): what the key is about, Controls, On the key, and closed sections for the rest. Use the own dropdown(), checkbox() and number stepper in pi/pi.js, never native <select> or checkboxes: OpenDeck's WebKitGTK draws those in the GTK style.
  • An action that can do more than one thing lists it in ops of its Kind (the press choice is in the setting press_key), and its schema uses gestures(). Press, hold and double press then offer the same choices, and src/actions/key/ does the key handling.
  • Settings a key cannot work without go in required, so the key shows the setup image (gray glyph, yellow dot) until they are set. Errors an action returns show up on its settings page: write them as short English sentences and add the German text.
  • Everything a user can read comes in English and German. Write the English text in the code and wrap it in t() (src/i18n.rs, or pi/lib/i18n.js on a settings page), then add the German text to src/i18n/de.rs and run make manifest. Action names and tooltips for the OpenDeck list are in src/manifest.rs (it writes de.json). Messages the plugin sends to a settings page stay English, the page translates them with translateMessage(). make check fails when a German text is missing.
  • Keys look like the other FeloDeck plugins too: no background, bold white glyph in the middle, gray when off. Dials with their own touch strip layout use layouts/*.json.
  • Test in the real apps. First check if a real Stream Deck is plugged in (lsusb | grep -i 0fd9, Elgato's USB vendor ID). If one is, test on it, but only in new profiles of its own, with a name that is not taken yet (for example "OBS Tools Test"). Never change or delete the profiles that are already on it, they are in use. Note which profile was selected before (~/.config/opendeck/profiles/<device>.json) and select it again when done. cargo xtask profile only writes profiles for the virtual deck.
  • Without a real Stream Deck, use the virtual deck: make install install-virtual-deck, restart OpenDeck, put actions on keys with cargo xtask profile test/e2e/layout-<suite>.json (OpenDeck must be stopped), then run cargo xtask e2e <suite>. The suites need the test scenes and media: cargo xtask make-video and cargo xtask setup-obs.
  • make check runs the tests, also of the settings pages (in boa, a JavaScript engine in Rust, so no Node is needed). OBS that is busy encoding (a weak VM) can make the end-to-end tests flaky, run them again before hunting a bug.

Releases

  1. Read git log <last tag>..HEAD and pick the version: only fixes → patch, something new → minor, something that breaks or needs the user to act → major.
  2. Bump VERSION, run make manifest and add the entry at the top of CHANGELOG.md, in one commit (chore: 1.4.0).
  3. Push, then push the tag: git tag v1.4.0 && git push origin main v1.4.0.
  4. make package (both CPUs in one file), then gh release create v1.4.0 with the entry from CHANGELOG.md and a short install part as notes, and only the plugin file, named OBS-Tools-v1.4.0.streamDeckPlugin. Never attach a .zip as well: the plugin store of OpenDeck then asks which file to download.

A minor or major release starts with a welcome sentence and has a ### Highlights list. A patch release is just a sentence or two. Write for users: what they notice, not how the code does it.

README

  • The virtual deck is a test tool. The README does not mention it.
  • New UI (a key, a settings page) gets a screenshot in the README, next to the text about it. A real screenshot of it running, in English.
  • When a screen changes, take its screenshot again. The README never shows an old one.