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
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.
- 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.
| 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:
- tsc validates TypeScript types for both renderer and Electron code.
- Vite emits production bundles under dist/.
- 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.
- 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.
- 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:
- Install dependencies with pnpm install.
- Ensure linting passes (pnpm lint).
- 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.
.png)
