Show HN: Crock – secure P2P file transfer desktop companion

1 month ago 4

Crock logo

A polished Electron + React desktop companion for croc that makes peer-to-peer file and text transfers friendly, observable, and configurable without touching the CLI.

Crock UI wraps the battle-tested croc CLI in a modern desktop experience. It bundles croc binaries for the current platform, keeps them up to date, and exposes common workflows through a visual interface. Beneath the surface it uses a hardened Electron main process, a React + Vite renderer, Zustand for state, Tailwind/shadcn components for styling, and a dedicated IPC layer that mirrors the behaviours of the CLI.

  • Instant send & receive — Queue files or plain text, choose a relay, and kick off croc transfers with a single click.
  • Code phrase ergonomics — Generate, copy, paste, or scan QR codes for session codes; the UI keeps clipboard and form state in sync.
  • Transfer observability — Track real-time progress, inspect structured logs, and revisit prior sessions via the built-in history viewer.
  • Configurable defaults — Adjust send/receive flags, destinations, and automation toggles across General, Advanced, Misc, and About tabs.
  • Relay & proxy health checks — Test the configured relay, proxy, and croc binary; receive live relay status events streamed from the main process.
  • Binary lifecycle management — Download, install, or pin croc releases directly from GitHub without leaving the app.
  • Theming & localisation — Light, dark, and system themes plus English, Vietnamese, and Japanese translations out of the box.
  • Browser-friendly mock API — In non-Electron contexts a safe mock window.api keeps the renderer functional for design previews.

Additional previews reside in ./screenshots.

The application is split across three collaborating layers:

  • Bootstrapped by src/main.tsx, rendering App.tsx into the DOM.
  • Uses Zustand stores (src/stores) to model UI, settings, history, and transfer state.
  • Interfaces with Electron via a typed window.api bridge (src/lib/window-api.ts).
  • Tailwind CSS and shadcn-inspired primitives (src/components/ui) drive design consistency.
  • Internationalisation is powered by react-i18next with JSON resource bundles in src/locales.
  • electron/preload.ts exposes a whitelisted, type-safe API to the renderer.
  • Bridges file dialogs, clipboard, window controls, croc lifecycle commands, history access, and settings mutations.
  • Provides an event bus (events.on) for streaming relay status and progress updates to the UI.
  • electron/main.ts configures the BrowserWindow, single-instance lock, external link handling, and lifecycle integration.
  • Services in electron/services manage croc binaries, build commands, spawn processes, monitor relays, and persist history/settings via electron-store.
  • IPC handlers in electron/ipc/modules wrap those services into cohesive request/response channels.
  • vite-plugin-electron builds and hot-reloads the main/preload code alongside the renderer during development.
crock/ ├─ electron/ # Main-process code, preload bridge, IPC modules, services ├─ public/ # Static assets bundled at runtime (logo, icons) ├─ src/ # React renderer (components, stores, hooks, contexts) │ ├─ components/ # UI elements grouped by feature (transfer, settings, history) │ ├─ lib/ # Utilities (i18n, window API, helpers) │ ├─ locales/ # i18next resource bundles (en, ja, vi) │ ├─ providers/ # Theme provider & shared contexts │ └─ stores/ # Zustand stores synchronised via IPC ├─ dist/ # Renderer production build output (generated) ├─ dist-electron/ # Compiled main & preload bundles (generated) ├─ electron-builder.json5 # Packaging configuration for installers ├─ package.json # Scripts, dependencies, electron-builder metadata └─ pnpm-lock.yaml # Deterministic dependency lockfile
  • Node.js ≥ 18.17 (Electron 30 runtime)
  • pnpm ≥ 9 (matching the checked-in pnpm-lock.yaml)
  • macOS, Windows, or Linux desktop environment

The Vite dev server and Electron process will launch together. Changes to renderer, main, or preload code hot-reload automatically.

Script Purpose
pnpm dev Launch Vite + Electron in development mode with hot reload.
pnpm build Type-check, build renderer bundles, and package Electron via electron-builder.
pnpm lint Run ESLint across .ts and .tsx sources.
pnpm preview Serve the built renderer for inspection without Electron.
pnpm format Format project sources with Prettier using the configured glob.

The build pipeline performs the following:

  1. tsc validates TypeScript types for both renderer and Electron code.
  2. Vite emits production bundles under dist/.
  3. electron-builder packages the application using electron-builder.json5, producing platform-specific installers in the dist/ directory.

Adjust icons, app identifiers, update channels, and signing options inside electron-builder.json5 to fit your distribution strategy.

Configuration & data storage

  • Settings and history are persisted with electron-store in the user-specific app.getPath('userData') directory (varies by OS).
  • Croc binaries are cached under <userData>/bin with an accompanying manifest to track versions.
  • Transfer logs and relay health are streamed from the main process; background monitors stop automatically when the window closes.
  • Relay status updates originate from RelayStatusMonitor and arrive via the relay:status event channel.
  • Default language is Vietnamese (vi), with English (en) and Japanese (ja) translations bundled.
  • Translation resources live in src/locales/<lang>/translation.json and are loaded by src/lib/i18n.ts.
  • To add a new language, duplicate an existing locale file, add the language code to supportedLanguages, and update UI copy as needed.
  • Deep link handling – Restore and harden application-level deep link support so incoming croc:// URIs populate the receive flow automatically.
  • Keyboard shortcuts – Wire global accelerator handling for opening history (Ctrl+H) and settings (Ctrl+,) from both renderer and main process.
  • Transfer history polish – Refresh the history data table, improving column layout, empty states, and accessibility affordances.
  • Settings redesign – Simplify copy and grouping across the Settings dialog tabs, removing redundant controls and tightening spacing.
  • Type cleanup – Prune duplicate or unused TypeScript definitions in src/types and electron/types to reduce maintenance overhead.

Known issues & limitations

  • ESLint TypeScript warning – Running pnpm lint emits a warning because @typescript-eslint/typescript-estree only supports TypeScript < 5.6 while this project currently pins 5.9 (see the lint output in this repo). Aligning the compiler version or upgrading the lint tooling will resolve it.
  • Proxy diagnostics are shallow – ConnectionDiagnostics (electron/services/ConnectionDiagnostics.ts) only reports whether proxy URLs are configured; it does not attempt any connectivity checks, so proxy misconfiguration goes unnoticed.
  • No SOCKS5 proxy UI – The backend understands SOCKS5 (electron/services/CrocCommandBuilder.ts, electron/services/SettingsStore.ts), but the settings dialog only exposes HTTP/HTTPS fields. Users cannot currently edit SOCKS5 relay defaults from the UI.
  • Renderer requires Electron bridge – getWindowApi() (src/lib/window-api.ts) throws when window.api is absent. Serving the renderer with plain Vite (without the preload script) will break as soon as settings or transfer actions touch the bridge. A lightweight browser mock is not yet implemented.
  • History size column bug – The transfer history table occasionally omits or misformats file sizes, so long-running sends lack accurate totals until this renderer formatting issue is fixed.
  • TypeScript warnings about unsupported versions come from @typescript-eslint if you use a newer compiler; either align the TypeScript version or pin a supported range.
  • When running outside Electron (e.g., pnpm preview), certain bridge features are mocked. Use the full Electron runtime for transfer tests.
  • If relay checks fail, confirm network access to your chosen relay, or update the relay settings under Settings → Advanced.

Contributions are welcome! Please open an issue or pull request on GitHub describing the enhancement or fix. When submitting changes:

  1. Install dependencies with pnpm install.
  2. Ensure linting passes (pnpm lint).
  3. Describe testing steps and screenshots when UI changes are involved.
  • croc — peer-to-peer transfer utility that powers the underlying protocol.
  • Electron, Vite, and React for the developer experience.
  • UI primitives influenced by shadcn/ui.

This project is distributed under the MIT License. See the license file for full terms and attribution requirements.

Read Entire Article