{"slug": "show-hn-app-it-turn-a-local-web-project-into-a-desktop-app-no-electron", "title": "Show HN: App-it – turn a local web project into a desktop app (no Electron)", "summary": "Developer Christian Katzmann released app-it v0.1.0, an open-source tool that wraps local web projects or hosted web apps into native macOS .app bundles without Electron or Tauri. The tool works with Claude Code and Codex, is local-first with no telemetry, and includes an early Windows beta. It is an independent project not affiliated with Anthropic or OpenAI.", "body_md": "Turn a local web project — or any hosted web app — into a macOS Dock-launchable `.app`\n\nbundle — a native window, its own Dock icon, and clean start/stop — **without Electron, Tauri, or a rewrite.**\n\nUnofficial community project— not affiliated with, endorsed by, or sponsored by Anthropic or OpenAI. \"Claude Code\" and \"Codex\" are their respective owners' marks, named here only to say which assistants app-it plugs into. This is an independent open-source tool built by one developer.\n\n*A real app-it build, in motion. Fjord is an ordinary local web project (node server.js); app-it turns it into a native macOS app — double-click launches it, the window opens with its own Dock icon, and ⌘Q quits the app *\n\n**and** frees the dev-server port. The actual generated app, not a mockup.\n\n**Status** — Working, in daily use. The launcher templates are battle-tested across 12+ real projects; `v0.1.0`\n\nis the first standalone, marketplace-installable release. macOS only, by design.\n\n**Windows beta** — macOS is in daily use; Windows is an early beta, now with its first real-hardware fixes but still needing more. A complete sibling plugin (`plugins/app-it-windows/`\n\n), gated by a required `windows-latest`\n\nCI job (build · PowerShell lint · manifest parse · icon round-trip), mirrors the macOS contract with Windows primitives. The author runs only macOS, so for a long time it had never touched real Windows hardware; that changed with [#8](https://github.com/Christian-Katzmann/app-it/pull/8), the first run on an actual Windows machine, and a run of fixes since — a real start, not a finish line. If you're on Windows and want to help harden it, the doorway is [docs/WINDOWS.md](/Christian-Katzmann/app-it/blob/main/docs/WINDOWS.md).\n\n**Local-first** — app-it reads your project *on your machine* to choose a launcher strategy. It uploads nothing, runs no telemetry, adds no runtime dependencies, and never touches your business-logic source. The only thing it produces is an `.app`\n\non your own Dock. For a hosted web app — a published Claude Artifact, a deployed dashboard, an internal tool — the supported networked path is explicit: wrap the hosted URL so the host handles login and keeps usage on each user's own account. See [Privacy](/Christian-Katzmann/app-it/blob/main/PRIVACY.md) and [Terms](/Christian-Katzmann/app-it/blob/main/TERMS.md) for the plain-language policy.\n\n`app-it`\n\nis an assistant-agnostic plugin/skill. It works with **Claude Code** and **Codex**, and builds a small, repeatable launcher around an existing local project or hosted web app so that double-clicking starts the right runtime, opens a native window, keeps the Dock icon as *your* app, and cleans up when you quit.\n\n**Not Electron, Tauri, or a native rewrite.** It wraps your existing dev setup; it doesn't replace it, migrate it, or add a bundler to your dependency tree.**Not a general signed distribution system.** No notarization, no App Store, no auto-update, no installer. A wrapper around a hosted web app is self-contained enough to zip and share, but it is still an ad-hoc-signed local bundle; recipients must trust the bundle and sign in with their own account.**Not cross-platform.** macOS only — and on purpose. Windows is a genuinely different problem (WebView2,`.lnk`\n\n,`.ico`\n\n, SmartScreen), so it belongs in a separate plugin rather than a blurred promise. See[Compatibility](/Christian-Katzmann/app-it/blob/main/docs/COMPATIBILITY.md).**Not a hosted service.** Nothing runs in the cloud and there is no live demo to visit — the proof is the apps on your own Dock (the Stack further down is real).\n\n```\n  WHAT YOU HAVE               WHAT APP-IT DOES           WHAT YOU GET\n  ───────────────────────     ──────────────────────     ───────────────────────────\n  a local web project         inspects it from disk,     YourApp.app on your Dock\n  Vite React, SvelteKit,      picks a strategy, then     · its own icon\n  Astro, Next, static, or ──▶ builds & signs a .app  ──▶ · native window, one click\n  a hosted web app URL        around a WebKit shell      · ⌘Q quits & frees the port\n```\n\nUnder the hood, app-it:\n\n**Inspects before it touches anything**— project type, dev scripts, ports, browser-API needs, icon sources.** Picks a launcher strategy**— a native Swift`WKWebView`\n\nshell by default (so the Dock icon stays*yours*), Chrome`--app`\n\nmode only when a project needs Chromium-only APIs.**Wraps a hosted web app without shared secrets**— set`external_url`\n\nto a hosted link (for example, a published Claude Artifact); each user signs in within the app window and uses their own account.**Copies proven, hard-won templates** into the project rather than re-deriving fragile launcher logic each time.**Builds and ad-hoc-signs a real**— universal (arm64 + x86_64), Gatekeeper-friendly, with a generated`.app`\n\n`.icns`\n\n.**Gets the lifecycle right**— closing the window (⌘W / red-X) leaves the dev server warm for a ~250 ms re-launch; ⌘Q quits the app*and*frees the port.**Writes a report** explaining every change and exactly how to undo it.\n\nFinished app? There's a lighter companion.`app-it`\n\nruns your project's dev server — perfect while you're still building. Once an app isdone, it doesn't need one: thecompanion serves the built output (`app-it-static`\n\n`dist/`\n\n,`build/`\n\n,`out/`\n\n, …) so a finished app costs ~15 MB instead of a dev server's ~300–700 MB. Same native window, same Dock Stack — reach for it only when an app is done.[How it works →]\n\n- macOS.\n- Claude Code or Codex for marketplace installation.\n`swiftc`\n\n(Xcode Command Line Tools) for the native WebKit shell —`xcode-select --install`\n\n.`python3`\n\n(also from the Xcode Command Line Tools) for`app-it-static`\n\n's server mode.- Chrome only if a project needs the Chrome fallback path.\n\n**Claude Code:**\n\n```\nclaude plugin marketplace add Christian-Katzmann/app-it\nclaude plugin install app-it@app-it\n```\n\n**Codex:**\n\n```\ncodex plugin marketplace add Christian-Katzmann/app-it\ncodex plugin add app-it@app-it\n```\n\nThen, from inside any local web project, ask your assistant:\n\n```\n/app-it\n```\n\nNatural triggers work too: *\"make this clickable from the Dock\"*, *\"give this an icon\"*, *\"dockify this\"*, *\"package this as a local app\"*.\n\nTo wrap a hosted web app, point app-it at its URL rather than copied source. A Claude Artifact is the common case: use the hosted artifact link, since a raw `.jsx`\n\nfile works as an ordinary local React app only when it does not depend on Claude's hosted runtime (`window.claude`\n\n, `window.storage`\n\n, MCP prompts, or Claude-provided auth).\n\n*Optional:* for finished apps, also install the lighter companion — `claude plugin install app-it-static@app-it`\n\n(or `codex plugin add app-it-static@app-it`\n\n), then run `/app-it-static`\n\n.\n\n```\nclaude plugin marketplace add /path/to/app-it\nclaude plugin install app-it@app-it\n\ncodex plugin marketplace add /path/to/app-it\ncodex plugin add app-it@app-it\n```\n\nMarketplace install is preferred. To copy just the skill folder:\n\n```\n./install.sh            # auto-detects Claude Code and/or Codex, asks before overwrite\n./install.sh --dry-run  # show what it would do, write nothing\n```\n\nAll additions are additive and reversible:\n\n`scripts/app-it.config.json`\n\n— single source of truth for the app(s)`scripts/desktop-build.sh`\n\n,`desktop-install.sh`\n\n,`desktop-quit.sh`\n\n,`desktop-doctor.sh`\n\n,`desktop-verify.sh`\n\n,`wrapper.swift`\n\n, …`assets/<slug>-icon.png`\n\nor`.svg`\n\n`desktop/<App Name>.app/`\n\n*(gitignored — regenerated by the build)*`docs/desktop-launcher.md`\n\nand an`app-it-report.md`\n\ndecision log`package.json`\n\nscripts:`desktop:build`\n\n,`desktop:install`\n\n,`desktop:quit`\n\n,`desktop:doctor`\n\n,`desktop:verify`\n\nInstalled apps land in `~/Applications/App It/`\n\nby default. Drag that folder to the right side of the Dock once and every future appified app appears in its Stack automatically. Override with `APP_IT_INSTALL_DIR`\n\n.\n\nBy default, generated launchers use `port_mode: \"fallback\"`\n\nso sibling local\napps can coexist by scanning upward from the preferred port. Use\n`port_mode: \"fixed\"`\n\nonly when the app must stay on one exact localhost origin,\nsuch as browser storage or OAuth callbacks.\n\n*A real MyApps Stack, not a mockup. Every icon is an ordinary local web project app-it turned into a native app — its own icon, its own window, one click to launch. Do this a dozen times and your Dock fills itself.*\n\n`app-it`\n\nonly makes additive, reversible changes. It will not rewrite product logic, add runtime dependencies, require a terminal window to stay open, or assume an already-running dev server. It may start and stop local dev-server processes during verification. It never collects telemetry, sends project data anywhere, or handles secrets. See [SECURITY.md](/Christian-Katzmann/app-it/blob/main/SECURITY.md).\n\n```\n./scripts/validate.sh\n```\n\nThis is the one-command check: it validates manifest shape, shell syntax, template presence, plist syntax, Swift typechecking, and Claude plugin validation (when the `claude`\n\nCLI is available). CI runs the same script on `macos-latest`\n\n.\n\nFor launcher/runtime changes, also run the behavioral suite:\n\n```\n./scripts/test-fixtures.sh\n```\n\nIt builds tiny fixture apps and checks the lifecycle app-it promises: bundle shape, runtime ports, ownership, doctor/verify JSON, warm reattach, and cleanup.\n\nThis repo *is* agent tooling, and agents are expected to work in it. Start with [AGENTS.md](/Christian-Katzmann/app-it/blob/main/AGENTS.md) — it names the non-obvious conventions (templates are canonical, trust disk over docs, the macOS-only boundary) and the safe first commands. Architectural decisions and their rejected alternatives live in [docs/decisions/](/Christian-Katzmann/app-it/blob/main/docs/decisions).\n\nThe `app-it-static`\n\ncompanion was inspired by feedback from the r/ClaudeAI launch thread, and the project keeps growing on community help. Thanks to:\n\nfor pointing out that finished apps shouldn't need a full dev server, and that Vercel/PWA-style workflows are far lighter — the nudge that became \"serve the build locally, not a dev server.\"`TechExpert2910`\n\nfor highlighting that deployed/static proof-of-concepts are often the standard workflow and are easier to share.`K_M_A_2k`\n\nfor the corporate-environment caveat: external hosting like Vercel isn't always approved, which is exactly why a`Vo_Mimbre`\n\n*local*static launcher earns its place even for finished projects.for becoming the Windows beta's real-hardware tester — the first proof it actually runs, then a run of fixes each traced and verified on a real Windows 11 box: the window title, the`Firnschnee`\n\n`app-it-host`\n\nlabel stuck in the taskbar right-click menu, and a graceful path when the WebView2 runtime is missing (offer the installer instead of a dead window).for hardening the native window so a restored frame can't open off-screen or postage-stamp sized, adding first-class Vite + React, SvelteKit, and Astro dev recipes, and — most recently — the URL-only launcher that wraps a hosted web app (a published Claude Artifact is the common case) in a Dock window: no local server, no shared secrets, each recipient signed into their own account.`SohamKela`\n\nMIT — see [LICENSE](/Christian-Katzmann/app-it/blob/main/LICENSE).", "url": "https://wpnews.pro/news/show-hn-app-it-turn-a-local-web-project-into-a-desktop-app-no-electron", "canonical_source": "https://github.com/Christian-Katzmann/app-it", "published_at": "2026-06-18 09:58:33+00:00", "updated_at": "2026-06-18 10:23:54.418067+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools"], "entities": ["Christian Katzmann", "app-it", "Claude Code", "Codex", "Anthropic", "OpenAI", "macOS", "Windows"], "alternates": {"html": "https://wpnews.pro/news/show-hn-app-it-turn-a-local-web-project-into-a-desktop-app-no-electron", "markdown": "https://wpnews.pro/news/show-hn-app-it-turn-a-local-web-project-into-a-desktop-app-no-electron.md", "text": "https://wpnews.pro/news/show-hn-app-it-turn-a-local-web-project-into-a-desktop-app-no-electron.txt", "jsonld": "https://wpnews.pro/news/show-hn-app-it-turn-a-local-web-project-into-a-desktop-app-no-electron.jsonld"}}