Skip to content
Development
Skill

/desktop-and-build-footguns

Desktop JVM and build traps: JNA natives, bundling, memory, packaging, code signing, R8, deep links, Gradle and CI releases. Use when a desktop build fails packaged, signed, on another OS or arch, or in CI.

BOOST
From plugin
kotlin-footguns
1.3k10 skills
Install
$ npx -y skills add maxrave-dev/kotlin-footguns --skill desktop-and-build-footguns --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/desktop-and-build-footguns

Context preview

The summary Claude sees to decide when to auto-load this skill.

Desktop JVM and build traps: JNA natives, bundling, memory, packaging, code signing, R8, deep links, Gradle and CI releases. Use when a desktop build fails packaged, signed, on another OS or arch, or in CI.

SKILL.md

desktop-and-build-footguns.SKILL.md
name: desktop-and-build-footguns
description: "Desktop JVM and build traps: JNA natives, bundling, memory, packaging, code signing, R8, deep links, Gradle and CI releases. Use when a desktop build fails packaged, signed, on another OS or arch, or in CI."

Desktop JVM and build footguns

24 traps mined from a production Kotlin and Compose Multiplatform app, one short file each under `references/`. Every file gives the working pattern, the **Traps** (the specific ways it fails in practice, and why), and a **Verifying it** section with commands to run against the user's own tree.

**How to use this index.** Match the code about to be written, or the symptom being chased, against the entries below: each names its topic and the symptom that should send you to it. Read every file that plausibly applies with the Read tool before proposing code or a fix; each is under 150 lines. Where a Verifying command names the source project's paths, substitute the equivalent paths in the user's tree.

**Cross-references.** A backticked trap name inside a file that is not listed here lives in a sibling area skill: glob `../*/references/<name>.md` to open it.

Native code on the desktop JVM

  • [`jna-native-binding-traps`](references/jna-native-binding-traps.md) — Hand-writing a JVM binding for a C library with JNA (Java Native Access) — the open-flags option that means something else on Windows, structs read by raw offset, callbacks the binding holds weakly, search paths registered too late, and proving which file was actually opened. Reach for it when a binding works on every developer machine and fails on a clean one, or when the very first symbol lookup fails with "the specified module could not be found" while the library is sitting right there.
  • [`native-artifact-for-embedding`](references/native-artifact-for-embedding.md) — Producing a native shared library a JVM app can actually load and ship — why a prebuilt portable bundle usually is not a loadable library at all, building on the oldest base system you support, run-path choice, which libraries to deliberately leave out of the bundle, and gating the build on a load-and-initialize smoke test. Reach for it when the bundled native works on every developer machine and fails on a clean one, or when you discover the app has been quietly using a system-wide copy instead of yours.
  • [`bundled-native-soname-conflict`](references/bundled-native-soname-conflict.md) — A native library you bundle with a desktop app drags its own copy of a general-purpose base library along, that copy claims the shared-object name for the whole process the moment your native loads, and an unrelated platform API then fails with a missing-symbol message naming a third library. Use when a feature that opens links or system dialogs works on your machine but silently does nothing on users' machines, when a platform API reports itself unsupported at runtime, when deciding what a native bundle may contain, or when a merged fix for exactly this bug does not seem to have changed anything for users.
  • [`macos-codesign-sidecar-strip`](references/macos-codesign-sidecar-strip.md) — Strip the `._*` companion files that macOS archiving writes beside files carrying extended attributes, after unpacking anything into a macOS app bundle and before the bundle is signed, because the signer seals those companions as ordinary bundle members and the OS deletes them the first time the file manager touches the app. Use when a signed macOS app launches fine on the build machine but users are told it is damaged and can't be opened, or when signature verification reports a sealed resource missing.
  • [`jvm-desktop-memory-footprint`](references/jvm-desktop-memory-footprint.md) — Judge and reduce a desktop JVM application's memory honestly — read the heap-to-footprint ratio rather than the resident figure, run the one experiment that separates a leak from an allocator holding idle pages, and understand why per-thread allocator arenas make the footprint depend on the user's core count. Use when a desktop app settles near a gigabyte or keeps climbing over a long session, when users on big machines report far worse memory than you can reproduce, or before tuning any allocator or garbage-collector flag.
  • [`embed-media-engine-desktop`](references/embed-media-engine-desktop.md) — Embedding a native C media engine in a JVM desktop app — one handle per media item, a dedicated event-pump thread, pinning the output driver and creating the render context in the right order, confining every property write to the thread that also releases handles, feature-detecting optional engine options, and formatting numbers the way the engine parses them. Reach for it when the app stops while setting a property, when the engine opens a window of its own, or when a value the app clearly sets is silently ignored.
  • [`merge-split-av-streams-desktop`](references/merge-split-av-streams-desktop.md) — Playing a separate audio-only stream and video-only stream as ONE source on JVM desktop through the media engine's edit-list URL form — the desktop counterpart of a merging media source — including length-prefixed quoting of stream URLs and why a merged two-URL item must not be prepared in the middle of a crossfade. Reach for it when desktop video plays back completely silent with nothing in the log, when a stream URL is truncated at the first semicolon, or when fading into a video track cuts the outgoing song short.
  • [`compose-desktop-video-no-swingpanel`](references/compose-desktop-video-no-swingpanel.md) — Rendering video frames from a native media engine in Compose Desktop without embedding a heavyweight AWT panel — publish finished frames as immutable snapshots on a StateFlow and draw them with a plain Image, convert off the UI thread, match the engine's pixel byte order, and let the engine decide the fit. Reach for it when embedded video sits on top of everything regardless of z-order, lags a frame behind while scrolling, goe
Read more
Ships withkotlin-footguns

By maxrave-dev — creator and maintainer of SimpMusic, the 10.8k-star cross-platform music app every lesson in this repository was mined from.

Get the whole plugin
Stats
1,305
Stars
6
Forks
Active
Maintenance
Python
Language
GPL-3.0
License
20d ago
Last commit
1mo ago
Created
5h ago
Added

Repo: maxrave-dev/kotlin-footguns

Other skills on kotlin-footguns.