DEV Community

Shahrukh Nisar wani
Shahrukh Nisar wani

Posted on

I Texted instinct. It Tells My Coding Agent What to Build.

Instinct as the project manager. OpenCode as the developer. An initial, open-source bridge built over a weekend.

The code is rarely the first part of a task.

Before there is a function to write, there is something to understand: a user complaint, a requirement, a page to research, a decision about what matters. That work happens outside the editor. Then someone has to turn it into a useful brief for the developer.

That is the split I wanted between Instinct and OpenCode.

Instinct is my personal assistant. It is the part I talk to from my phone, and the part I want gathering information from the outside world and turning it into work. OpenCode is the developer on my Mac. It has the repository, the tools and the coding session.

I built a bridge between them so I would not have to carry every message from one to the other. I can ask Instinct for a change, it hands the work to OpenCode, and the result comes back to me.

The interesting part is not typing a coding prompt on a phone. It is giving the two assistants different jobs.

Instinct is the PM

A project manager connects what is happening outside the codebase to what should happen inside it.

That is the role I see for Instinct: gather the relevant information, sort out the request, ask about missing decisions, and compile a brief that a coding agent can act on. The developer should get the requirement and the useful evidence, rather than a dump of every conversation that led to it.

Consider a possible workflow. I ask Instinct to research how similar products handle onboarding. It compares the findings, helps me choose an approach, and turns that choice into a task: which screens need changing, what the flow should do, and how we will check it. OpenCode then works against that brief in the repository.

That is an example of the direction, not a claim that this bridge already runs a whole product process on its own. The first version connects the handoff: Instinct can give OpenCode work and bring the response back. Better research, better briefs and better follow-through are what I want to build around it.

The human still owns the important decisions. Calling Instinct the PM does not mean it gets to invent requirements or treat every suggestion as permission to ship.

OpenCode is the developer

OpenCode handles the work that needs the codebase: reading files, making changes, running commands and reporting what happened.

It also holds the coding conversation. A follow-up can return to the same session rather than making the agent start from scratch. I can open that session on the Mac later and see the work in its original context.

OpenCode also lets me choose the model behind the developer. It supports models from different providers, as well as local models, so this workflow does not tie me to one model. I can choose among the models available through my configured providers while keeping the same repository and coding workflow.

The boundary matters. Instinct should make the task clearer before handing it over. OpenCode should use the repository to work out how to implement it. Neither needs to pretend it has done the other's job.

The handoff

Instinct and OpenCode workflow

The loop is simple:

  1. I send Instinct a request from my phone.
  2. Instinct turns it into a work order for a configured repository.
  3. The bridge on my Mac receives the task and switches to a task branch.
  4. OpenCode works in that repository.
  5. The bridge returns the output, branch and session information.
  6. Instinct uses that response to tell me what happened or what still needs attention.

This keeps me in one conversation without hiding where the coding work happens.

The source is here: https://github.com/sharkwani/instinct_openCode_bridge

The rest is the technical part. If the PM/developer split is what interests you, that is the core idea. If you want to understand what the bridge actually guarantees, the details matter.

Inside the bridge

Transport and execution are separate

The bridge is a Node daemon with a source adapter, a core task loop and an executor adapter.

The source adapter handles delivery. The Upstash Redis REST implementation puts tasks on bridge:tasks with RPUSH and receives them with BLPOP. Results use bridge:results; status events use bridge:status.

The Mac polls outward, so this queue path does not need an inbound port exposed on the laptop. There is also a local HTTP ingress bound to 127.0.0.1:8787, with task submission and result endpoints. Making that local interface reachable remotely is a separate transport choice. It is not required for the queue path.

The executor handles OpenCode. One adapter runs the CLI; another talks to a local OpenCode server. The core does not need to know which one performs the task.

The executor contract is small:

run({ task, cwd, sessionId, timeoutMs })
  -> { sessionId, summary, questions[] }
Enter fullscreen mode Exit fullscreen mode

That separation keeps delivery concerns out of the coding-agent adapter, and coding-agent details out of the queue loop.

A branch is a boundary, not a sandbox

For each task, the core switches to a sanitized bridge/<task-id> branch. Execution is serialized, including tasks arriving through the queue and the HTTP ingress, so two jobs do not race to change the checked-out branch.

After execution, it checks that HEAD is still on the expected task branch. A mismatch is reported as an error.

Those are useful checks, but they are not complete isolation. Tasks share a working directory. The dirty-tree refusal is currently disabled, and a branch check after the run cannot undo an unsafe command. The bridge itself does not push to a remote, but OpenCode's command permissions still matter.

Sessions outlive a single handoff

The server adapter accepts a session ID for follow-up work and otherwise reuses or creates a session for the repository. The result includes the session ID and an opencode --session <id> command so the developer can pick up the conversation locally.

Submitting a prompt is not the same as completing it. The adapter checks that a user message actually appeared after submission, then polls for an idle event before taking the latest assistant text. If its wait runs out, it preserves the session information instead of returning an unexplained timeout.

This distinction matters because a model can produce text while work is still underway. A progress sentence is not a receipt.

Results need interpretation

A result carries the task ID, status, branch, session ID, output, summary and diffstat.

The statuses include done, needs_input, still_running and error. In this implementation, done means the executor returned output. It does not prove that the requirement was met, tests passed, a commit was made or a change reached the remote repository. Question detection also differs by executor; it is not a dependable approval workflow.

Completed HTTP results are appended to a local results.jsonl file and loaded again when that interface starts. That gives access to recorded results after a restart. It is not full recovery for in-flight work. The queue uses a destructive BLPOP, so I would not describe the current design as guaranteed delivery or automatic crash recovery.

Why not just expose the OpenCode port directly?

You can. For solo personal use, connecting the assistant directly to an appropriately secured OpenCode server is a viable option.

If you only need to start a session and check it yourself, the extra daemon may be more than you need.

But the server endpoint does not replace task management. Someone still needs to queue the work, choose branches, preserve session references and record results. Without the bridge, Instinct would have to take on those jobs, or I would have to do them myself.

That is why I kept the daemon. I want a place on the Mac that owns the execution lifecycle, while Instinct owns the conversation and the brief. The queue lets me submit work without keeping a live session open, though the Mac still has to be awake and connected to execute it.

The bridge is useful because of that division of responsibility, not because a direct connection cannot work.

Permissions are still local

OpenCode's opencode.json controls command and file permissions. The current bridge does not provide its own permission-approval relay.

The shared bridge secret gates task submission and result access on the relevant endpoints. It is not a substitute for restricting what OpenCode can do once a task begins.

Secret handling also needs an honest description. The code includes redaction for the result's output field and scrubbing for status messages, but the general sanitization hook for summary and diffstat is still a placeholder. I would not call that a complete secret-leak prevention system.

Credentials belong outside the public repository, and permissions need to fit the actual work. A prompt asking an agent to stay on a branch is a soft rule, not a security boundary.

What this taught me

The lessons are less about models than about handing off work.

  • The brief is part of the product. An assistant should reduce ambiguity before passing a task to the developer. Sending more context is not the same as sending useful context.
  • A result needs evidence. We saw changes land while the returned message contained only a progress summary. Checking the repository directly was more reliable than treating the status as proof. Instinct's PM role has to include checking what actually landed.
  • Test the second task. A daemon can look healthy after one successful run and still stop taking work. The queue loop needs testing across repeated tasks and failures.
  • Permissions affect usability as well as safety. A rule that blocks a required file can stall remote work. Removing all rules is not the answer; making them match the task is.
  • A laptop is not an always-on worker. Sleep, a dropped tunnel and a restarted process can interrupt the handoff. Those limits should be visible instead of leaving the person waiting on a silent task.
  • Keep execution and judgment separate. The bridge carries and records work. OpenCode implements it. Instinct has to decide what the response means before telling me it is finished.

Where I want to take it

The first version gives me a conversational path from my phone to the coding agent on my Mac.

The next step is to make the PM side better: research that becomes a useful brief, a brief that becomes a scoped task, and a result that gets checked against the original request. A missing answer should come back as a question. A partial result should stay partial.

I also want this to become plug-and-play: any AI assistant on the PM side, and a choice of coding agents on the developer side, including Claude Code or Codex. The source and executor adapters give the bridge a place to make those swaps, but those integrations are not shipped here. Each one would need its own handling for sessions, permissions and results. The goal is to keep the handoff useful without making either side depend on one provider.

That is the workflow I want: Instinct connects the outside world to the work, OpenCode develops the code, and I stay involved where a human decision is needed.

The code and setup details are in the repo: https://github.com/sharkwani/instinct_openCode_bridge

Top comments (0)