Bring your own CLI: how to monitor a Custom ACP session from your phone
A practical guide to run your own ACP-compatible CLI on your computer and still get a phone-friendly workflow for check-ins, approvals, and follow-ups.
- CLI
- 0.1.0
- Preview ref
- f36aa45
The moment you stop using the “default” providers, you hit a familiar problem:
You can run your favorite CLI on your computer.
But the phone workflow disappears.
This guide is about getting that phone workflow back:
- run your own ACP-compatible CLI locally
- still monitor sessions from your phone
- still handle approvals and follow-ups
TL;DR
- Pick an ACP-compatible CLI you want to run locally.
- Define it as a Custom ACP backend (command + detect + auth probe).
- Make it deterministic on the host computer:
- verify the binary path
- verify the working directory rules
- verify detect/auth commands
- Use a tight phone loop: check → approvals → one follow-up → leave.
The problem
Custom integrations fail for practical reasons:
- wrong binary path
- wrong working directory
- auth not materialized on the right computer
So the first goal is making the integration deterministic.
What I tried first (and where I bounced off)
- SSH/tmux: works, but becomes “do real terminal work on a phone.”
- Remote desktop: heavy and fiddly.
- Waiting: safe, but slow.
What ended up working best for me was using a dedicated phone control surface.
- Happier: your custom ACP CLI still runs on the computer, but you get a phone UI for check-ins, approvals, and follow-ups. Trade-off: it still depends on the computer running the agent being online.
If you’re new to Happier (what it is, and where to get it)
If you haven’t seen Happier before: it’s an open-source companion app (mobile/web/desktop) for coding sessions.
Get set up:
- GitHub: https://github.com/happier-dev/happier
- Install/download: https://github.com/happier-dev/happier#how-it-works
- Discord: https://discord.gg/W6Pb8KuHfg
ACP in 90 seconds (so the rest of this guide makes sense)
ACP (Agent Client Protocol) is the protocol between:
- a client (an app/IDE/dashboard) and
- an agent process (your CLI)
The default transport is stdio: newline-delimited JSON-RPC messages.
The biggest implication is practical:
- your agent’s stdout is the protocol
- your logs must go to stderr
If you mix logs into stdout, the client can’t parse the stream and everything looks “broken.”
ACP vs MCP (why both show up)
- ACP is how the client talks to your agent session.
- MCP is how the agent talks to tool servers (GitHub, browser automation, etc.).
ACP sessions can be started with an mcpServers list, so you can have:
- one custom agent CLI
- plus a consistent tool surface
The rules that make or break Custom ACP (stdio contract)
These are the most common integration killers:
- stdout must contain only ACP protocol messages
- logs must go to stderr
- messages are newline-delimited → no embedded newlines inside a single JSON message
- don’t pretty-print JSON (
indent=2will break things)
If you want one quick “is my agent compatible?” test:
- run it in ACP mode and confirm it can answer
initializewithout printing banners
Step 1: define your Custom ACP backend
This is where most people get stuck, because it’s detailed config work.
You need to define:
- name/id (how you’ll recognize it)
- command (how to start it)
- detect command (a safe “is it installed?” probe)
- auth probe (optional; only if it’s safe)
- working directory expectations (does it assume the repo root?)
A rule that saves time: start with detect only, then add auth probing later.
Capability negotiation (don’t assume methods exist)
ACP starts with initialize.
The agent responds with capabilities.
Clients should not call methods the agent doesn’t claim to support.
If “resume/load” isn’t supported, you’ll see symptoms like:
- new sessions starting when you expected resume
- missing history
So for Custom ACP, it’s normal to ship a minimal agent first (new session + prompt) and add lifecycle methods later.
Step 2: make the integration deterministic on one computer first
Before you try multi-computer workflows, make it work on one computer.
This is where “works in my terminal” diverges from “works when launched by a client.”
Checklist:
- can the command run from the expected working directory?
- does it depend on a shell init file (
.zshrc,nvm,asdf)? - does it need env vars or secrets?
- does it print banners/progress bars to stdout?
If the CLI needs credentials, don’t paste them into the backend definition. Use env vars or a saved secret system.
Auth patterns you’ll see in the wild
Most ACP agents fall into one of these auth patterns:
-
Env-var auth
- the client launches the agent with env vars
- simplest and most automation-friendly
-
Terminal login auth
- you run
<cli> loginonce in a terminal - the agent uses machine-local auth state
- you run
-
OAuth in a UI (less common for CLI-first tools)
ACP’s auth design is intentionally cautious: the agent shouldn’t be able to trick the client into running arbitrary commands for auth.
Step 3: the phone workflow
The 2-minute loop
- open session
- check approvals
- send one follow-up
- leave
Three copy/paste follow-ups
- Checkpoint
Stop after your next step and summarize:
- what you changed
- what you didn’t change
- what you want to do next
- Constraint
Don’t touch migrations/auth. If you think you need to, stop and ask.
- Proof
Before you keep going, paste the exact command you’re about to run and explain why.
Client-specific config recipes (copy/paste)
Once your agent is ACP-correct, the next source of pain is client config formats.
A few common ones people run into:
- JetBrains custom agents via an
acp.json - Zed settings JSON
- Neovim CodeCompanion ACP client (with explicit limitations)
I’m not going to pretend there’s one universal file format.
The rule is: pick one client, make it work there, then add more.
Debugging playbook (before you blame the agent)
1) Prove your agent’s stdout is clean
If you see parsing errors, 80% of the time it’s because stdout contains something that isn’t JSON-RPC.
Put all logs on stderr.
2) Avoid embedded newlines
Don’t pretty-print JSON messages. One message must be one line.
3) Prove the working directory is what you think
A lot of custom agents “work” but operate on the wrong repo because cwd is wrong.
Troubleshooting
Detect works but sessions fail to start
This usually means:
- missing env vars
- wrong working directory
- your CLI prints banners/logs to stdout
- the CLI expects a TTY (not compatible with stdio ACP)
The agent starts, but tools don’t show up
This is often MCP config mismatch:
- stdio vs http/sse fields
- missing headers/env
Auth shows “Unknown”
If your auth probe is unsafe (or not defined), Unknown is expected.
Treat it as “don’t know”, not “logged out.”
FAQ
Do I need to implement the whole ACP spec?
No.
A “minimum viable” agent supports:
- initialize
- session/new
- session/prompt
Everything else (load/resume, rich tools, attachments) can come later.
Why does it work in my terminal but not in my IDE/app?
Almost always one of:
- PATH/env mismatch
- wrong working directory
- stdout contamination
Is it safe to let an agent control auth commands?
ACP explicitly designs against this: terminal-auth flows should run the same binary, and the agent shouldn’t be able to specify arbitrary commands.
If you’re new to Happier
Happier is a companion app for running sessions on a computer you trust and monitoring them from your phone.
Get set up:
- GitHub: https://github.com/happier-dev/happier
- Install/download: https://github.com/happier-dev/happier#how-it-works
- Discord: https://discord.gg/W6Pb8KuHfg