Skip to content

Rename project: deckd → deskestra #145

Description

@jonocodes

Why

The app has outgrown its original framing. It's no longer "an app controller" — it's a full desktop control surface that drives apps, windows, the desktop, and the GNOME/KDE/macOS sessions around them. The name deckd was a nod to Stream Deck and reads narrowly. We want a name that:

  • keeps desk (drives home "you control a screen, not a server"),
  • carries the conducting thread (you conduct your desktop, you don't just press buttons),
  • reads as one natural word with one obvious spelling,
  • is coined enough to be brand-/domain-/product-safe.

The recent layoutdeck cutover (issue #105) already gave us internal vocabulary room. Now we want the project itself to move.

Decision: deskestra

desk + orche·stra → you conduct your desktop. Three syllables, one spelling, easy to say aloud.

Across every candidate we researched, deskestra is the only one that came back genuinely unclaimed — no product, package, org, or app. The desk- sound space is occupied by Deskera (funded cloud ERP) and DeskRoll (a remote-desktop product), but deskestra is far enough from both (extra syllable, different ending) to stand apart.

Service name: deskestra (no -d suffix — agreed that <name>d feels dated).
GNOME extension UUID: deskestra-focus@local.
KWin script ID: deskestra-focus.
Password file: ~/.config/deskestra/password.
Python distribution / entry points: deskestra, deskestra-dev, deskctl (keeping deckctl — it's a CLI for the daemon, not the daemon itself; rename candidate TBD).

Names considered

Clustered by approach. Each entry: name → one-line verdict → why.

A. Keep deckd (reposition instead of rename) — rejected

  • deckd → keep, reframe positioning. Cheapest path. Rejected because we explicitly said the cutover doesn't scare us and we want the broader positioning baked into the name itself.

B. Generic conducting/control surface — rejected, all taken or weak

  • Helm → "you steer the desktop from it." Strong, but collides with Kubernetes Helm.
  • Maestro → conducting metaphor, distinctive. Prior art: Mobile "Maestro" test tool. Rejected as overused.
  • Conductor → conducting + dispatch. conductord ugly. Rejected as overused.
  • Conduit → routing metaphor. Rejected: reads as internal plumbing, not conducting.
  • Podium → fresh, low collision. Rejected: you don't want "pod."
  • Panel / Console / Dispatch / Relay / Pilot → various. Rejected for over-use or vibe mismatch.

C. desk + fused coined suffix (the vein we liked)

  • Deskpit (cockpit) → rejected, you don't like "pit."
  • Deskata → taken-ish (deskata.com exists; risks Deskera echo).
  • Deskra → basically a homophone of Deskera ERP (funded, 80k+ users). Hard no.
  • Deskira / Deskora / Deskana / Deskyra / Deskade → variations. Most share the Deskera phonetic overlap; none meaningfully better than deskestra.
  • Deskomand / Deskommand / Deskrix / Deskrex / Deskura / Deskept → control-rooted variants. Various fatal flaws (skept-adjacent, "command" doesn't fuse, etc.).
  • Deskrol → direct collision with DeskRoll (existing remote-desktop product). Hard no.
  • Deskrola → deskrol + softened; Polish "deskorolki" + Deskera echo. Compromised.
  • Deskestra ✅ → clean, conducting-fused, no collision. Winner.

D. control family, no desk — rejected, all crowded

  • Controlla → near-identical open-source "phone-as-keyboard/mouse-for-desktop" project already uses the name (okekedev/controlla). Plus CAREL Controlla (HVAC controllers). Hard no.
  • Controla → spread thin across active apps (Controla cybersecurity, ControlA university mgmt, Controla.ai org). Diluted.
  • Kontroll / Kontrol → stylized bare spelling. Rejected earlier: dated, un-searchable.
  • Ctrl / Ctrla → literal keyboard modifier, on-theme. Rejected: ambiguous to say aloud.
  • Controlla / Drake collision → also a Drake song. Bonus reason not to.

E. Less-literal control roots (Latin / Greek / French) — rejected, all occupied

  • Dirigo (Latin "I direct") → several active software cos (Dirigo Software accident reconstruction, etc.).
  • Regie (French "control room") → Regie.ai dominates.
  • Kyber (kubernan root) → saturated. KDE has a "Kyber" cross-platform remote-control product, plus post-quantum crypto, plus k8s deploy tool.
  • Imperia (imperare "to command") → Imperia SCM + Imperia Online game.

Pattern: anything that obviously means control/command/steer has been claimed, usually more than once. Coined fusions (deskestra) escape the saturation.


Rename blast-radius plan: deckddeskestra

Generated by an exhaustive inventory of the repo. Hard references are listed explicitly. Soft references (comments, prose, generic "deck" usage as a product concept like "button deck") are not listed and should not be mechanically renamed.

Naming decisions (commit these first)

Old New
Project name deckd deskestra
Python distribution deckd deskestra
Python package daemon/deckd/ daemon/deskestra/
Executable deckd deskestra
Executable deckd-dev deskestra-dev
Executable deckctl deskctl (keep, but see open question below)
Service unit deckd.service deskestra.service
LaunchAgent com.deckd.daemon com.deskestra.daemon
NixOS module services.deckd-spike services.deskestra-spike
NixOS script deckd-spike-start deskestra-spike-start
udev rules 70-deckd-uinput.rules 70-deskestra-uinput.rules
GNOME UUID deckd-focus@local deskestra-focus@local
KWin script ID deckd-focus deskestra-focus
D-Bus bus org.deckd.Focus org.deskestra.Focus
D-Bus path /org/deckd/Focus /org/deskestra/Focus
D-Bus interface org.deckd.Focus org.deskestra.Focus
Env DECKD_PASSWORD DESKESTRA_PASSWORD
Env DECKD_FAKE_MPRIS DESKESTRA_FAKE_MPRIS
Env DECKD_TLS_DIR / DECKD_TLS_HOST DESKESTRA_TLS_DIR / DESKESTRA_TLS_HOST
Env VITE_DECKD_WS VITE_DESKESTRA_WS
Password file ~/.config/deckd/password ~/.config/deskestra/password
LaunchAgent log @PROJECT_DIR@/deckd.log @PROJECT_DIR@/deskestra.log
Browser localStorage key deckd.password deskestra.password
HTTP header X-Deckd-Password X-Deskestra-Password
GitHub Pages base /deckd/ /deskestra/
Pages URL jonocodes.github.io/deckd/ jonocodes.github.io/deskestra/
Client PWA name / short_name deskestra
HTML <title> Deskestra
macOS PWA apple-mobile-web-app-title Deskestra
Auto-ignore logic: window titled "deckd" window titled "deskestra"
Test fixture suffix deckd-smoke-* etc. deskestra-smoke-*
CLI metric prefix deckd_ (e.g. deckd_actions_total) deskestra_
Class DeckdFocusDBusService DeskestraFocusDBusService
Class DeckdFocusCache DeskestraFocusCache
Class DeckdFocusExtension DeskestraFocusExtension
Class attr Server._is_deckd_window Server._is_deskestra_window
Setuptools include pattern deckd* deskestra*
Repo URL github.com/jonocodes/deckd github.com/jonocodes/deskestra

Open question on deckctl: it's the CLI, not the daemon. Options: rename to deskctl (consistent), rename to deskestractl (verbose), or rename to something functional like deskestra-cli. Leaning toward deskctl for symmetry. Worth a quick opinion before the cutover.

Mechanical order of operations

Do these in order so the tree is never in a half-renamed state for more than a commit.

  1. Pre-flight: confirm availability — deskestra.com/.app, github.com/deskestra, npmjs.com/package/deskestra, PyPI deskestra, and that no new project has appeared in the past 24h. (Last check during research came back clean, but registries move fast.)
  2. Lock the new identifiers by editing these in one commit:
    • pyproject.tomlname, [project.scripts] (deskestra, deskestra-dev), deskctl decision, package include pattern.
    • daemon/deckd/daemon/deskestra/ (rename the package directory itself; every internal import updates accordingly).
    • All from deckd… / import deckd… (the directory rename takes care of most; touch up external references).
    • All DECKD_* and VITE_DECKD_WS env var names.
    • ~/.config/deckd/password~/.config/deskestra/password in auth.py, systemd unit, launchd plist, README, docs.
    • D-Bus: org.deckd.Focus, /org/deckd/Focus, interface name — in platform.py, GNOME extension.js, KWin main.js, all scripts/* and tests/*.
    • Class names Deckd*Deskestra* (DBus service, cache, extension class, _is_deckd_window).
    • Auto-ignore logic: "deckd" literal → "deskestra" (and case-insensitive match).
  3. Packaging: rename and update these files/paths:
    • packaging/systemd/deckd.servicepackaging/systemd/deskestra.service; rename Description, ExecStart, WorkingDirectory references.
    • packaging/launchd/com.deckd.daemon.plistpackaging/launchd/com.deskestra.daemon.plist; label, program, log path, password path.
    • packaging/nixos/deckd-spike.nixpackaging/nixos/deskestra-spike.nix; module name, generated script name, executable path, service name.
    • packaging/udev/70-deckd-uinput.rulespackaging/udev/70-deskestra-uinput.rules.
    • packaging/gnome-shell/deckd-focus@local/packaging/gnome-shell/deskestra-focus@local/; metadata.json uuid + name + description; extension.js bus/path/interface; wire-shape.js import path.
    • packaging/kwin-script/deckd-focus/packaging/kwin-script/deskestra-focus/; metadata.json Id + Name; main.js bus/path/interface + comment header.
  4. Justfile: update every recipe that invokes deckd, deckd-dev, deckctl, references the extension UUID, or hardcodes paths. (See "Justfile" in the inventory — this is one of the larger files to edit.) Also update the GNOME pack/install recipe (packaging/gnome-shell/...@local) and the KWin install recipe ($HOME/.local/share/kwin/scripts/deskestra-focus/...).
  5. Client (client/):
    • package.json: namedeskestra-client (or just deskestra).
    • index.html: <title> and apple-mobile-web-app-title.
    • vite.config.ts: VITE_DECKD_WSVITE_DESKESTRA_WS.
    • public/manifest.json and public/icon.svg: display name + aria-label.
    • src/socket.ts: localStorage key deckd.passworddeskestra.password; any error text containing deckd.
    • playwright.config.ts: DECKD_FAKE_MPRIS env var name.
  6. Scripts (scripts/): every file that imports deckd.* or references deckd-focus@local / org.deckd.Focus / DECKD_FAKE_MPRIS / ~/.config/deckd/password.
  7. Tests (tests/):
    • Update all from deckd… imports.
    • Update all D-Bus name assertions (org.deckd.Focus).
    • Update Deckd* class assertions.
    • Rename tests/test_deckd_window.pytests/test_deskestra_window.py and update test names + the tests/.pytest_cache nodeids will regenerate.
    • Rename e2e client/e2e/daemon-log.ts references if any contain the binary name.
  8. Docs: sweep README.md, CONTEXT.md, AGENTS.md, docs/ONBOARDING.md, docs/REFERENCE.md, docs/TESTING.md, docs/SPIKES.md, docs/ARCHITECTURE.md, docs/research/landscape.md, docs/research/issue-56-macos-nowplaying.md, all docs/adr/*.md. Do not mechanically replace generic "deck" usage — that word is now the product concept (a "deck" is a control surface) and stays. Only the project identifier deckd / Deckd changes.
  9. GitHub-side:
    • Rename the repo (github.com/jonocodes/deckdgithub.com/jonocodes/deskestra) — GitHub redirects old URLs but update local git remote after.
    • .github/workflows/deploy-pages.yml: Pages base path /deskestra/, build env VITE_BASE_PATH: /deskestra/.
    • .github/workflows/ci.yml: any commands invoking deckd / deckctl / deckd-dev.
  10. Cleanup: delete daemon/deckd.egg-info/, client/dist/, .pytest_cache/, .mypy_cache/, __pycache__/. Rebuild from clean state. Run just lint test (or the equivalent) and verify.

Behavioral / data migration concerns

  • Existing user password file: anyone currently running deckd has ~/.config/deckd/password. On first run of deskestra, either (a) auto-migrate by reading the old path and writing the new one, or (b) require re-running the install/setup to generate a new password. Option (a) is nicer and one-line.
  • Browser localStorage key: a returning client will not find deskestra.password and will treat the user as unauthenticated. Acceptable for a personal/OSS project with no users yet.
  • GitHub Pages redirect: GitHub preserves redirects on repo rename, but the Pages site itself is tied to the new repo path — there will be a brief window where old links 404. Acceptable since no users yet.
  • D-Bus name conflict: since org.deckd.Focus and org.deskestra.Focus are different bus names, there is no risk of two instances colliding on the session bus during a transition. But anyone with the old GNOME extension installed will be publishing to the old name — uninstall the old extension before installing the new one.

Verification ladder (run in order)

  1. just lint — type/format/lint.
  2. just test — Python suite, including the renamed test_deskestra_window.py.
  3. Build the GNOME extension zip from packaging/gnome-shell/deskestra-focus@local and confirm the UUID in the metadata matches what the daemon expects.
  4. Build the client (just client-build or whatever it is) and load it against a running daemon. Confirm:
    • WebSocket connects (uses the new env var).
    • localStorage key is deskestra.password.
    • HTML title is Deskestra.
  5. just client-e2e (Playwright) — confirms the daemon spawn command, env var, and auth header.
  6. Live smoke: python scripts/smoke_focus_live.py — confirms D-Bus round-trip on the new bus name.
  7. Live smoke: python scripts/smoke_mpris_live.py — same.
  8. Manual: load a layout that includes raise-window / focus actions, verify the extension is publishing to org.deskestra.Focus.

What I deliberately did not put in this plan

  • Renaming the product concept of a "deck" (a deck of controls, a button deck, deck layout, deck grid) — those stay.
  • Renaming third-party product references (Stream Deck, Macro Deck, WebDeck, Deckboard, OpenDeck, Loupedeck) — those are third parties.
  • Renaming Git history — git log will still show the old name. A git filter-repo could rewrite history but it's not worth it pre-launch.

Open questions for the human reviewer

  1. deckctldeskctl (recommended), or something else?
  2. Do we keep the daemon binary name as deskestra, or use deskestrad/deskestra-service after all? (You said you don't like the -d suffix; I agree.)
  3. Repo rename on GitHub happens before, during, or after the code cutover?
  4. Old-password-file auto-migration on first run, or fresh setup?
  5. Anything else in the inventory I missed — deckd.egg-info style build artifacts are covered by step 10, but double-check the GitHub deploy-pages flow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or requestneeds-triageMaintainer needs to evaluate this issue

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions