The Claude Code Session That Changed How AgentDock Connects Its Desktop App
A detailed walkthrough of one AgentDock session in an open-source Electron and local-daemon boilerplate: what broke, how I directed Claude Code, why I rejected the quick fix, and how we verified the safer design.
The most interesting coding-agent session I have had recently happened while I was building AgentDock.
AgentDock is an open-source Electron and local-daemon boilerplate for desktop apps that run work through a user’s existing, signed-in Claude Code or Codex CLI.
It does not ask for provider API keys or read provider login files. The provider’s own command-line tool stays responsible for login.
This article covers one Claude Code session on 28 August 2026. It started with a desktop request that did not work. It ended with a change to how the desktop app talks to the local AgentDock service.
I did not keep a transcript that I can publish. The instructions below are paraphrased from the code, tests, commit notes, and security documentation. I will not present them as exact quotes.
What I was building
AgentDock has a React interface inside Electron. Behind it is a small Fastify service running only on the user’s computer. That service starts Claude Code or Codex and turns their output into one consistent stream of events.
The intended path was:
Desktop interface
→ Electron main process
→ local AgentDock service
→ Claude Code or Codex
The local service uses a private token. Any request without that token is rejected.
The first working version had a problem. The React interface called the local service directly with fetch. Because the request included the private token, the browser layer sent a CORS preflight request first. The service did not allow browser origins, so the real request never happened.
The app built successfully, but the feature did not work when we ran it.
How I used Claude Code
Claude Code was the main coding environment for this session. I first used it to build the request path across the React interface, Electron, the local service, and the provider process.
I do not ask one agent to build something and then accept its own review. I use reviewer agents with a narrow job. In this case, the reviewer was also running inside Claude Code. These reviewer roles are part of my working setup, not part of AgentDock itself.
After the request failed, I asked the reviewer to look beyond the CORS error. The instruction was roughly:
Find why the desktop request fails. Review the browser, token, localhost service, and Electron process boundaries. Give me the smallest fix and the safer long-term fix. Check whether either option would expose the local service to normal web pages.
The agent returned two options.
Option 1: allow the browser request
The quick option was to change the service’s CORS settings so the React interface could call it directly.
That would have made the request work with less code. It would also have kept the private token inside browser-facing code.
This mattered because a normal website can try to send requests to services running on localhost. Binding the service to 127.0.0.1 limits network access, but it does not automatically make browser access safe.
I rejected this option. It fixed the failed request without fixing who was allowed to make that request.
Option 2: let Electron main own the connection
The agent’s second proposal was to move all local-service calls into Electron’s main process.
The React interface would no longer know the service address or private token. Instead, it would receive a small set of allowed actions through Electron’s preload layer, such as:
- list available providers
- start a session
- receive session events
- cancel a session
There would be no general-purpose function that allowed the interface to send any request it wanted.
I chose this option. The agent proposed the design, and I approved it because it solved both problems: the app could complete the request, and browser-facing code no longer held the token.
That distinction is important to me. The agent did not merely follow an architecture I had already written. It found a better option during review. My responsibility was to compare the trade-offs, reject the convenient fix, and decide which result was safe enough to keep.
What the agent changed
I gave Claude Code a direct implementation instruction:
Move the local-service connection and token into Electron main. Expose only the session actions the interface needs through preload. Remove direct service calls from the React code. Update the tests and security documentation to match the new design.
The agent changed the feature across several parts of the app:
- Electron main became responsible for calls to the local service.
- The preload layer exposed a small typed API to the React interface.
- The React code stopped calling localhost directly.
- The private token stayed in the trusted Electron process.
- Tests were updated around the new request path.
- The architecture and security notes were updated so the reason for the design would not be lost later.
This was real engineering work. The change crossed process boundaries, moved a secret, changed how requests and streamed events travelled, and required the types and tests to stay in sync.
Claude Code was useful here because it could carry one decision through all those files without leaving the old path behind in one layer.
How we verified the fix
We did not stop when the project compiled.
The Electron app was run after the change. We used the local Claude Code installation for the real provider flow. The desktop interface started the request through Electron main, received the streamed events, and displayed the result without calling the local service directly.
The automated tests also covered the request path and local-service authentication. Provider fixtures kept the normal test suite independent from a paid Claude or Codex session.
The checks for this session were:
- the real Electron app could start a Claude Code session
- the interface received the streamed result
- the interface no longer called localhost directly
- the private token stayed outside the React interface
- requests without the token were rejected
- the tests passed without requiring a live provider account
The last two points are different. Running the app proved the user path worked. Tests helped protect the rule after the session ended.
I use Browser and Playwright tools for visual checks in my general workflow, but they were not part of this specific session, so I am not counting them as evidence here.
How I choose models without wasting cost
I use Claude Code as my primary coding environment, but I do not force every task through the most expensive model.
For clear implementation work, I usually choose a lower-cost model. For planning, difficult research, or reviews where a wrong assumption could change the design, I use a stronger model. I also switch tools when limits or parallel work make that practical.
I did not keep enough session metadata to say which exact model handled each step on 28 August. I will not reconstruct that detail from memory. What I can say is that I choose the model based on the work instead of using the same model for everything. That keeps the cost lower without treating every task as equally simple.
Codex is part of my wider workflow. For this article, I used it later for a small editing pass on the copy. It was not the engineering agent responsible for the AgentDock change described here.
What I did and what the agent did
Claude Code built the first request path, investigated the failure, produced two possible fixes, proposed the Electron-main design, implemented the chosen change, updated tests, and updated the documentation.
I set the security constraints, asked for a separate review, compared the two options, rejected the quick CORS change, approved the safer design, and required the app to be run before the work was considered complete.
That division is the reason I find the session useful. It was not a story where the agent only filled in code after every decision had already been made. It contributed a better design. It was also not a story where I accepted whatever it generated. The result came from giving the agent room to find options while keeping the final decision and proof with me.
What I would do differently
Write down the security questions first
I should have asked these questions before the first request was implemented:
- Which process owns the private token?
- Can browser code reach the local service?
- What actions should the React interface be allowed to request?
- Can a normal website trigger the same local endpoint?
If those questions had been written first, direct browser access probably would not have reached the first working version.
Add the failing test before changing the code
The cleaner order would have been:
- reproduce the failed request
- add a test that proves the unsafe or broken behavior
- make the code change
- run that test again
- run the app
I followed parts of that order, but not consistently enough during the first build.
Save a short session record
The commit, tests, and documentation show what changed, but they do not preserve every prompt and decision in order.
For future work, I want to save a short record containing the important instruction, the options the agent proposed, what I rejected, the final choice, and the commands used to verify it. That would make a walkthrough like this more exact without publishing private conversations.
Keep unrelated fixes in separate commits
The first AgentDock commit also contains other fixes found during nearby sessions, including UTF-8 stream handling, error responses, and the production service build.
Those changes are useful, but combining them makes the history harder to read. I would now commit the desktop connection fix separately so the problem, decision, code, and tests can be reviewed together.
What I learned
The first version looked reasonable inside the React code. It was wrong when we looked at the whole request path.
The useful part of the agent session was not how quickly code appeared. It was the review step that produced two options, including one that changed the design. The quick option would have made the demo work. The chosen option made the product safer and gave future code a smaller set of allowed actions.
My working pattern after this session is straightforward:
build a small working path
→ run it
→ ask a separate reviewer to challenge it
→ compare the options
→ fix the right layer
→ run the real app again
→ keep the lesson in tests and documentation
I use coding agents to do substantial implementation work. I still own the decision about what is safe to ship and what evidence is enough.
Evidence
Current note, 31 August 2026: AgentDock has continued to change after this session. Later work added protocol v2 and interactive sessions. Codex is currently handling parts of that later implementation. Those changes are outside the session described here.