跪拜 Guibai
← Back to the summary

A Service Manager Born from a Rant: One Afternoon, 49M Tokens, and a Tauri Desktop App That Ships

A few days ago, it happened again: starting a new project, port was occupied. Checked with lsof, and there sat a java process with a long jar name that I couldn't identify which project it belonged to. Kill it? Afraid it might be a service still in use. Don't kill it? My project couldn't start. Went back and forth for ten minutes, finally discovered it was an old project from debugging half a month ago that I'd forgotten to shut down.

As a full-stack developer, I have not only company projects but also plenty of my own: a Vue admin dashboard, Spring Boot APIs, Go utilities, services started by Python scripts — all piled onto one Mac. I can't even tell which ones are running and which ports they're occupying. And with many Node versions managed via nvm, sometimes I don't know which version a project uses until a startup error reveals it.

So I'd wanted to build this management tool for a long time. The idea is simple: scan, list, one-click start/stop, and view logs. But actually writing it myself was still somewhat difficult. I'd thought about using Claude before but kept forgetting. This time I happened to subscribe to Volcano Engine's Agent Plan, which connects directly to Claude Code and lets you configure doubao-seed-evolving. I looked up this model and found one setting particularly appealing: the ID carries no version number; the official team iterates weekly, and the subscriber's configuration doesn't need a single change. This upgrade brings 1M context and a 256k output limit.

First, check out the effect: Scanning running projects

Setup, about ten minutes, two things to watch

The subscription process isn't complicated, but two spots are easy to trip on. Let me be clear.

Subscribe to a plan

Find Agent Plan in the console, subscribe as needed. Entry here: Subscription address. Details on each tier's benefits are in the official docs: Plan details. I bought the Medium tier, 49.9 per month, with a quota of 5 hours 10000 AFP, 35000 weekly, 100000 monthly — enough for personal development.

Subscribe as needed

There are many model types available, including the Seed series and mainstream domestic models like GLM, Minimax, DeepSeek, and Kimi.

Plan details

Watch point one: The Key is not that Key

The plan has a dedicated API Key, different from the usual pay-as-you-go key. Using the wrong one still charges you by usage, wasting the subscription. I almost configured it with the old key.

Select plan key

Watch point two: Base URL is also separate

Two protocols, two addresses. Anthropic protocol uses https://ark.cn-beijing.volces.com/api/plan, OpenAI protocol uses /api/plan/v3. If you slip and configure /api/v3, congratulations, you're back on pay-as-you-go.

Protocol support

The docs list connection methods for tools like Claude Code, Codex, OpenCode, and TRAE — just copy them (but make sure to select the plan's key).

Detailed integration docs

After configuration, switch with /model doubao-seed-evolving and get started.

Opening with a rant

There was no requirements document. I typed my rant verbatim, essentially the opening paragraph: a pile of Vue, Java, Go, Python services, forgotten which ones are running, version mismatches, script-started ones nowhere to be found — build me something to manage it all.

After sending it, it pondered for about a minute. I thought it would just start writing, but it didn't. Instead, it asked me: do you want something light or heavy? A menu bar utility, a full desktop manager — three options, each with pros and cons listed for me to choose.

Throwing out my pain points

I wanted the full version. It recommended Tauri + Vue3 as the tech stack, citing small bundle size and low memory usage, suitable for a background resident. I already write Vue, so no objections.

Giving suggestions

Then it broke down the features into seven items and confirmed each with me: auto-detect project type, read version numbers, one-click start/stop, reverse-scan running services, log collection, SQLite for config storage, dark interface. I give this step high marks — without confirmation, it easily goes off on its own and builds things you don't want.

Confirming architecture and feature points

Setting rules, then letting it spin on its own

Before starting, I did two things.

First, I fed it my coding standards: no large classes, no large files, reference my own project skills, split Rust modules by responsibility. Second, I turned on /loop to let it iterate on its own — finish one round, check itself, then continue, without me feeding it line by line.

It laid out a nine-step plan and started running. I genuinely slacked off in between, occasionally glancing at the terminal.

Setting standards and starting the project

Optimization, three rounds

It wasn't a one-shot deal, honestly.

White screen

It said the frontend build was done. I opened it — black screen. I pressed it with "Are you sure the frontend is fine?" It went back to recheck and found that MainLayout.vue used the h function without importing it from Vue, and a store was called outside setup. After fixing, it created an eight-item checklist and ticked each one off. This self-checking behavior surprised me more than the bug fix itself.

Frontend build issue - follow-up

Continuing loop after fix

Clicking did nothing

The first version of the interface appeared. Clicked "Scan Directory" — nothing happened. No error, no loading, as if it were dead. I described the symptom, and it added loading states and success/failure prompts, conveniently replacing a fragile component.

First version - click unresponsive

Overlapping modals

The third round was styling: modals and lists overlapping, spacing a mess. This kind of "looks wrong" it genuinely can't detect — it can't see the screen. I described what was off, and it fixed it. After one round, hover states, spacing, and left-right alignment were all smooth.

Gradual polish - styling issues

Optimization - display

So logic-layer errors it can handle on its own; UI oddities need human eyes. This step can't be skipped.

Hands-on testing

Started around 4-5 PM, by 8 PM I was testing with real projects.

Scan directory first

In settings, added the path of a Vue project to the scan directory, clicked scan. It recognized it: Vue, Node 22.12.0, port 18100, start command npm run dev — all correct, no guessing.

Scanning directory project

Then reverse scan

I had another Java archive service, previously started in the terminal, not in any scan directory at all. Clicked "Scan Running Services," and it scanned all listening port processes system-wide, reverse-looked up working directories. electronic-archives was caught just like that, port 18881, check it to include in the list. This is exactly the effect I wanted most — terminal-started, IDE-started, none can hide.

Scanning running projects

Start/Stop

Tried starting and stopping several rounds. Response was quick — status changed immediately after clicking, no waiting for the process to slowly exit. Port numbers are clickable; clicking one opens the browser directly. This is handy.

Start - Stop

Logs

Services started through it can view logs directly. Opened the web project's logs — Vite's output was all there as-is, ready in 259 ms, no different from running in the terminal, plus timestamps.

Viewing running logs

Settings, removal, and other corners

The settings page can configure multiple scan directories. Switches for auto-start on boot and auto-restart on crash are there. NVM, terminal, and editor paths are also customizable.

Settings

Removing a project from the list triggers a secondary confirmation dialog, and it specifically added the line "will not delete local files." It added this on its own; I didn't mention it. That's very user-friendly.

Removing from list

Glanced at the code

A working interface isn't enough; I plan to use this long-term, so I had to review the code.

The structure is well-separated: the commands layer only forwards parameters, detectors are one file per language, managers handle processes, database, and nvm separately. To add recognition for a new language later, just drop a new file into detectors — no need to touch anything else.

Noted a few things while browsing. Reading the Node version checks .nvmrc, .node-version, and package.json's engines in descending priority — exactly my manual troubleshooting habit. The start command guesses among dev, serve, start in scripts — a priority I never taught it. Before starting a process, it stuffs the bin directories of all Node versions under nvm into PATH — crude, but the "npm not found" problem just disappears. Stopping a process sends TERM first, waits two seconds, then force-kills — no orphan processes left behind. "Open project directory" didn't wrestle with Tauri's shell plugin permissions; it directly calls open on Mac and explorer on Windows. This workaround is very old-school developer; I chuckled when I saw it.

I won't paste the specific implementation into the article. Once I clean up the rough edges, the code will be open-sourced.

Settling accounts

At the end, I sent "scan our project and see how many lines of code."

Rust backend: 2004 lines. Vue/TS frontend: 1343 lines. Total: 3347. The breakdown also matches the standards: process management 492, database 298, language detectors 301, nvm management 173, IPC layer 242. No two-thousand-line mega-files grew. It also casually reported the packaged installer is about 5MB — I haven't verified this number myself yet, just noting it.

Code scan

Then I asked it to summarize, verbatim: "I hope you summarize from the beginning of our conversation, mainly summarizing what I asked you to do and the optimization matters." In 14 seconds, it sorted through the entire process: seven requirements, every modification I raised in each round, how the architecture was split — all matching my memory. After an afternoon of back-and-forth, it still remembered that opening rant. The 1M context wasn't wasted.

Asking it to summarize the project

Let's also show the token bill. For doubao-seed-evolving, writing this project on July 21st consumed a total of over 49 million tokens. I think the effect was very good — at the very least, it solved my needs and pain points.

Final project token usage

Finally

This tool now resides permanently on my Mac. Which service is running? Open it, glance, and you know — no more checking lsof one by one.

Looking back at the cost, from ranting in the afternoon to testing with real projects in the evening — just one afternoon. Most of the time, it spun in its own loop while I did my own thing. Tokens burned: over 49 million — a scary number, but the plan's 5-hour usage warning never popped once. The 49.9 ticket was more than enough.

For me, the most practical thing is that this isn't a demo built for a screenshot and then discarded. These past couple of days, I've been starting and stopping my current projects right inside it. A tool I'd been thinking about for over half a year just landed like that.

Next, I plan to have it go through Windows adaptation on a real machine. Once those small code issues are cleaned up, it'll be open-sourced. Anyway, the model iterates weekly, and the ID doesn't even need changing. Next time I work, let's see how much it has improved.