# bigfish, an Electron shell that vendors its backend and picks a port at launch

> Bigfish wraps a local coding agent's web backend in a native desktop window so that a user never opens a terminal, never learns a port number, and never installs a runtime. The cost of that convenience is visible in the manifest: an empty dependency list, the agent shipped as a committed tree of installed modules, a plugin market that writes npm packages into a directory outside the app, and three packaging scripts of which two only work on the machine they are named after.

**turtle2209/Bigfish** — Bigfish —— DeepSeek Harness 的第三方桌面端，内置 Node 运行时，双击即用，附带桌面萌宠。

- Repository: https://github.com/turtle2209/Bigfish
- Stars: 319 · Forks: 15
- Language: JavaScript
- License: MIT
- Published: 2026-09-18 · Updated: 2026-09-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/turtle2209-bigfish

## The agent arrives as a committed tree of installed modules

The manifest declares no runtime dependencies at all. The dependency object is empty, and the two development dependencies are the build tools:

```json
"dependencies": {},
"devDependencies": {
  "electron": "^33.2.0",
  "electron-builder": "^25.1.8"
}
```

The agent itself is supposed to be an npm package, and the readme names it. It is not in that list. Instead the build configuration copies a directory called dsh-bundle/node_modules into the packaged app and renames it on the way, so the harness ships as a pre-installed module tree that was captured at some point and committed. Its version is whatever that snapshot was, nothing in the manifest pins it, and npm install on a fresh clone fetches nothing for it.

That is why the two development commands are the whole setup, and why they are also insufficient on their own. They start the desktop shell, which then looks for a harness that has to be in the tree already. The published version is 0.1.2, and the three tags that reached it were published on three consecutive days in mid August 2026, so this is a young project whose newest release is older than its newest commit.

## The port is found at launch instead of being fixed

The readme's diagram of the main process is five steps, and the first one is the reason the application exists. The shell finds a free port on the loopback address, starts the backend as a child process pointed at a web profile, polls until that backend answers, and only then loads the address into a native window. The user never sees a port number, which is the whole problem the project set out to remove.

The sequence has a window in it. A port is found to be free, then a child process is started, and the two are separate actions with a process launch in between. Anything else on the machine that binds that port in the gap wins it, and the polling step has no timeout, no port, and no error described for the case where the child process exits instead of answering.

The security argument is also borrowed rather than implemented here. The readme's justification for the local-only binding is that the backend's own source forbids listening on all interfaces, which makes the boundary already present. That is a reasonable thing to rely on, and it leaves one question the readme does not answer: a local HTTP backend with no authentication described, reachable by any process running as the same user, including the transparent always-on-top pet window's own web content.

## Plugins are npm packages written outside the app directory

The plugin system is not an extension format invented here. A plugin is an npm package that declares two manifest keys, one for the backend bundle and one for the client, and installing it means copying it into a profile directory inside the user's home folder. Settings for an installed plugin then appear inside the agent's own settings screen after a restart, so a third party package gains a panel in the application's own interface.

The install engine is a single bundled copy of a package manager shipped inside the app, so nothing has to be installed on the host to add a plugin. The catalogue is fetched live from a community site that is described as the largest such listing with a thousand entries, and if that fetch fails the app falls back to a curated copy stored in its own JSON file. There is also a directory of plugins that ship with the app and install without a network round trip.

What is not described is any verification step. The two manifest keys are all a package has to declare, the destination is a directory the user owns, and the effect is immediate on restart. That is the widest door in the project, and it is opened by a menu item in the system tray.

## Three screenshot cells are empty and one shows an unexplained window

The readme has a screenshots section made of two tables. The first has two columns captioned with the desktop pet and a redemption shop. The second has one column captioned with mode selection. All three cells are empty. There are no images, so the section that would tell a first time user what the application looks like tells them nothing, while the rest of the file spends a paragraph on each feature.

The redemption shop is the more interesting half. A window for it exists in the repository, with its own markup, its own script, and its own preload file, and all three are named in the build manifest's file list, so it ships. It appears in no feature list, in no directory description, and in no troubleshooting note. Neither does mode selection. A user who sees the window in a screenshot has no way to learn what opens it or what it does.

That mismatch is a symptom of the documentation strategy. The feature list is written for a reader deciding whether to install, the directory section names a handful of paths for someone hacking on the source, and neither is a description of the interface. The three unlinked text files at the top of the repository are where that gap is meant to be covered, and nothing in the readme says so.

## The user documentation is four files the readme never opens

The readme's navigation bar links to four documents: version notes, usage instructions, a known issues and troubleshooting file, and a third party notices file. All four are in the repository root, and all four carry Chinese names except the last one. None of them is summarised, quoted, or even characterised in the readme itself, so the front page is a marketing summary that points at the manual.

The directory section makes the same gap measurable. It names nine things: the main process, three files for the market window, the fallback catalogue, the bundled plugin directory, three files for the pet window, the pet animation frames, the bundled package manager, and the manifest. The root holds thirty nine entries. Not named are the two shell scripts that create a Linux desktop entry and set up Linux, the two download scripts that fetch the bundled runtime and the build tool, the two scripts that maintain the pet's image assets, the version manifest used for updates, the packaging hook, the icon generator, a background image, and the vendored harness tree.

Only the icon generator has a script entry in the manifest. Everything else in that second list is either run by a human by hand or run by the build, and the readme explains which for none of them.

## Development runs on system Node and the packaged app does not

There are two runtimes and the choice between them is silent. A table in the readme assigns one to development and the other to everything after packaging: a development session executes the agent with whatever Node is on the machine, and an installed copy executes it with a runtime carried inside the app. An environment variable overrides the first.

```bash
npm install
npm start
```

The repository contains the two scripts that fetch those bundled runtimes, one for Node and one for the build tool, and neither has an entry in the manifest's script list, so npm run cannot start either of them. A contributor reads the readme, runs the two commands above, and gets a shell with no harness and no pet, because the vendored module tree is not something npm will fetch for them.

The asymmetry has a second edge. The same code path that finds a free port and polls for readiness runs in both modes, so a behaviour that reproduces only on one runtime, for instance because a native module was rebuilt for the other, is invisible in the mode most contributors use.

## Three packaging targets and two of them need the machine they are named after

The manifest exposes three platform scripts and one generic one, and the readme annotates two of the three with the same warning: the macOS disk image has to be built on macOS, and the Linux AppImage and package have to be built on Linux. The Windows installer is the only target that builds anywhere.

```bash
npm run dist:win      # Windows NSIS 安装包
npm run dist:mac      # macOS dmg（需在 macOS 上构建）
npm run dist:linux    # Linux AppImage + deb（需在 Linux 上构建）
```

The reason given is a list of native dependencies that have to be compiled on the machine they will run on. The build configuration is consistent with that: native rebuilds are switched off, so the packer will not recompile anything for the target, and the archives are unpacked rather than packed into a single binary container, so the shipped JavaScript and the shipped module tree are both readable on disk.

The feature list blurs the platform story in the same way it blurs everything else. Launch on system start-up and a right-click entry in the file manager are named as features without a platform label on the first and an explicit Windows label on the second, while a single global shortcut is given for all three systems with no alternative and no note that the same key combination is unusual on a Mac.

## The desktop pet was contributed back by a fork of this repository

The acknowledgements section is worth reading closely, because the credit runs in a circle. The approach behind the desktop pet is attributed to a separate community project whose name combines the agent's short name with this project's own name. That project, in turn, is described as a fork of this repository, modified by an author with a different account name, under the same licence, with details in the notices file.

So the feature that gives the application its name and its character was implemented elsewhere, in a fork, and imported back. The shipped files are three for the transparent window and a directory of animation frames, and the fork's version is referred to as a plugin, which suggests the feature arrived through the same plugin path a third party would use. That is a reasonable way to work and an unusual thing to see written down plainly.

The notices file is the only place the licence relationship is spelled out, and the readme links to it from the navigation bar and from the acknowledgements, which is the correct handling. What the readme does not offer is a version number for the imported work, so there is no way to tell from this page which state of the fork is running.

## Conclusion

Use bigfish if you want a local coding agent with a desktop interface and you would rather not manage a terminal, a runtime, or a port. Before you install it, check four things. That you trust the plugin market, because plugins are npm packages installed into a profile directory in your home folder and take effect on the next restart, with no signature check described anywhere. That you know which build you downloaded, because the release page carries three platform targets and two of them only build correctly on the matching operating system. That the harness version is one you accept, since it arrives as a pre-installed module tree rather than as a pinned dependency. And that the screenshots are not what you are buying, because all three image cells in the readme are empty and one of them advertises a window the feature list never mentions.

## FAQ

### What is bigfish and what does it wrap?

bigfish is an Electron desktop shell for a local coding agent. It packages the agent's local backend and its web interface into a native window, finds a free loopback port at launch, starts the backend as a child process, and loads the address into the window. The backend is the same npm package the command line version uses, and the readme states the current version is 0.1.2 for Windows, macOS, and Linux.

### Does bigfish need Node.js installed on my computer?

Not for the packaged application, which carries its own Node runtime. A development checkout does use the system Node, with an environment variable available to override which one is used. The two build tools the project needs are declared as development dependencies and are pinned to caret ranges rather than exact versions.

### How does the bigfish plugin market work?

A plugin is an npm package declaring two manifest keys, and installing it copies the package into a profile directory in the user's home folder, taking effect after a restart. The app bundles its own copy of a package manager so nothing has to be installed on the host, fetches the online catalogue from a community site, falls back to a curated local copy if that fails, and can also install plugins bundled with the app offline.

### Is bigfish open source and what licence does it use?

The manifest declares the MIT licence and the repository root contains a licence file. The readme also credits a separate community project for the desktop pet approach, notes that it is a fork of this repository by a different author under the same licence, and points to a third party notices file for details.

## Sources

- [Issues](https://github.com/turtle2209/Bigfish/issues)
- [License: MIT](https://github.com/turtle2209/Bigfish/blob/main/LICENSE)
- [README](https://github.com/turtle2209/Bigfish/blob/main/README.md)
- [Releases](https://github.com/turtle2209/Bigfish/releases)
- [turtle2209/Bigfish on GitHub](https://github.com/turtle2209/Bigfish)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/turtle2209-bigfish
