On this page
- The Number One Tool:
abyss oneshot - Where Abyss Keeps Its Logs
- Managing Containers
- Common Problems, and How to Fix Them
- “Failed to connect to Docker”
- “Failed to pull Docker image”
- The Container Starts but the Agent Doesn’t
- Bind Mounts Don’t Show Up (or Show Up in the Wrong Place)
- Files You Meant to Copy In Aren’t There
- Setup Scripts Hang or Fail
- TLS / Connection Errors
- Your Editor Can’t See abyss (or Says the Agent Crashed)
- File or Terminal Requests Go to the Wrong Place
- Still Stuck? Filing a Good Bug Report
- Where to Go Next
Troubleshooting
Abyss has a lot of moving parts — it talks to Docker, starts a container, wires up an encrypted tunnel, launches your agent, and then translates everything your editor says into something the agent understands. That’s a big surface area, which means there are a lot of places something can go sideways.
This guide is here to help you find which part is misbehaving, and to give you the tools to fix the common ones yourself. Take a breath — most issues are small and easy to spot once you know where to look.
If you read through this and you’re still stuck — or you think abyss itself is doing something wrong — please don’t hesitate to leave a bug report on the issues page. I’ll take a look and either help you fix it or push a fix to abyss itself.
The Number One Tool: abyss oneshot
When something breaks, the temptation is to keep restarting your editor and hoping it works this time. Don’t. Your editor (Zed included) is great for using an agent, but it’s awkward for debugging one — it hides abyss’s logs behind a menu, and it doesn’t love agents that crash on startup.
Instead, reach for abyss oneshot. It runs a single prompt against your config and dumps every log
line straight to your terminal where you can see them. It’s the fastest way to answer “is it my
config, or is it something else?”
My go-to test prompt is:
abyss oneshot -f /path/to/your/config.yaml "What is the capital of France?"I use that exact prompt on purpose. The answer is short, so I’m not waiting around, and I’m not trying to test whether the agent is clever — I just want to know if the plumbing works end to end. If you get back “Paris,” your whole stack is healthy and the problem is somewhere else (probably your editor config).
If it errors out, the logs printed to your terminal will usually point you right at the culprit. The rest of this guide walks through the most common culprits and what to do about them.
Tip:
oneshotis also how you test changes to your config without restarting your editor. Tweak the YAML, re-run the command above, and you’ll know within seconds whether your change helped.
Where Abyss Keeps Its Logs
Abyss logs to both your terminal (stderr) and to timestamped files on disk. The terminal output is great for a quick look; the files are great for when something blew up an hour ago and you want to read back through it.
Host-Side Proxy Logs
This is where most issues live. The host-side proxy is the abyss process that runs on your
machine, outside the container. It’s the one your editor talks to, and it’s the one that does all
the Docker work — pulling images, starting containers, copying files in, tearing things down. If
something is broken, it’s almost definitely here.
It logs to both stderr and files, so you have two ways to read it:
- In your editor. Your ACP client captures the proxy’s stderr. In Zed, open the command palette
(
Ctrl+Shift+PorCmd+Shift+Pon macOS) and run “dev: open ACP logs”. You’ll see abyss’s output mixed in with ACP traffic. - On disk. Timestamped log files live at
~/.local/var/abyss/log. Each run gets its own file named with the time it started, like2025-01-30T14-22-07Z.log. Abyss automatically cleans up old files and keeps the most recent 10, so the folder won’t grow forever.
Container-Side Proxy Logs
The container-side proxy is the abyss process running inside the container. It’s the one that
actually launches your agent and translates ACP file and terminal requests into actions inside the
sandbox. It logs to both a file and stderr too, so you have two ways in:
- From the host, with
docker logs <container-id>. This is the easiest way; you don’t need to get a shell in the container. - From inside the container. If you’d rather look directly, open a shell in the container and
check
/root/.local/var/abyss/log.
Don’t know the container ID? Run
abyss docker ps(covered below) to list every abyss container that’s currently running, along with its ID.
Turning the Log Volume Up (or Down)
By default abyss logs at the debug level, which is fairly chatty and is what you want while
troubleshooting. If you ever need more detail (there usually isn’t much, but it’s there), you can
drop to trace:
abyss oneshot -l trace -f /path/to/your/config.yaml "What is the capital of France?"You can also set the level with the ABYSS_LOG_LEVEL environment variable, which is handy when
abyss is being launched by your editor and you can’t easily add flags:
export ABYSS_LOG_LEVEL=traceValid levels are trace, debug, info, warn, error, fatal, and disabled. If you’re
confident things work and just want quiet logs, info is a good everyday level.
Managing Containers
Abyss starts a fresh container for each session and stops it when the session ends. Normally you never have to think about this. But if a session crashed, or you killed abyss mid-run, you can end up with containers that are still chugging along in the background. Abyss ships a couple of commands for exactly this situation.
See What’s Running
abyss docker psThis lists every running container that abyss started (it finds them by their abyss label). You’ll
get back the container ID and its name, which is everything you need to inspect or stop it.
Clean Up Everything
abyss docker gcThis stops every running abyss container that isn’t meant to stick around. It’s the “reset button” when things have gotten into a weird state — for example, if a leftover container is holding onto a port or a bind mount and a new session won’t start because of it. Run it, then try your session again.
The one exception is containers with a persistent_name in your configuration. Those are your
agent’s long-lived home — abyss skips them so their state survives between sessions. If you really
do want one gone, abyss docker ps will show you its ID, and docker rm -f <container-id> will
take it from there.
These two are safe to run any time. They only touch containers that abyss itself created, and they stop containers rather than removing your files. If you’re ever unsure what state things are in,
abyss docker psfollowed byabyss docker gcis a fine first move.
Inspecting a Container by Hand
Sometimes you want to poke around inside a container that’s still running — to check whether a file got copied in, whether your agent is actually installed, or what a setup script left behind. Get a shell with:
docker exec -it <container-id> bashFrom there you can run ls, check /root/.local/var/abyss/log, verify your agent command exists
on the PATH, and so on. This is a great way to confirm “is the thing I’m mounting actually showing
up where I expect?”
Common Problems, and How to Fix Them
The sections below cover the issues that come up most often. They’re roughly in the order you’d hit them: Docker first, then the image, then your config, then the agent, then the connection.
“Failed to connect to Docker”
If abyss oneshot greets you with a message about failing to connect to Docker, the fix is almost
always one of two things:
- Docker isn’t running. Start the Docker daemon (or Docker Desktop, on macOS/Windows) and try
again. A quick
docker run hello-worldwill tell you whether Docker is alive and that you have permission to use it. - You need
sudoto use Docker. Abyss can’t prompt you for a password, so ifdockeronly works when you prefix it withsudo, abyss will be locked out. Add your user to thedockergroup so you can rundockerwithoutsudo. Docker’s installation guide walks through this.
“Failed to pull Docker image”
This means abyss couldn’t get the image named in your docker.image field. A few common causes:
- The image name is wrong. Double-check the spelling and the registry path. The ready-made images are listed in Docker Images.
- You don’t have access to the registry. If you’re pulling from a private registry, run
docker loginfirst so your credentials are saved. - You’re offline, or the registry is down. Try
docker pull <image>by hand — if that fails, abyss will fail the same way, and the error fromdockeris usually clearer. - You set
image_pull_policy: Neverbut don’t have the image locally. WithNever, abyss refuses to pull and will only use an image that’s already on your machine. Either build/pull the image yourself, or switch the policy toIfNotPresent(the default) orAlways.
The Container Starts but the Agent Doesn’t
If abyss brings up the container fine but your agent never responds, the trouble is usually in how the agent is being launched. Things to check:
- Is your
agent_commandcorrect? It should be the command that starts your agent in its ACP mode — for Pi that’spi-acp. If you’ve typo’d it, or pointed at a command that isn’t installed in the image, the container-side proxy will start but the agent won’t. - Does the agent actually exist on the container’s
PATH? Shell in withdocker exec -it <container-id> bashand runwhich pi-acp(or whatever your command is). If it comes back empty, the image doesn’t have it installed where abyss expects. - Are your agent’s credentials mounted in? Most agents need their config directory to talk to
an LLM. For Pi that’s
~/.pi, and because the container runs asrootyou usually mount it to/root/.pi(see Getting Started). If the mount is missing or pointed at the wrong place, the agent starts but can’t reach your LLM, which looks a lot like “it’s just hanging.” - Does the agent work on its own? Try running your
agent_commanddirectly inside the container viadocker exec. If it errors there too, the problem is the agent or its environment, not abyss.
Bind Mounts Don’t Show Up (or Show Up in the Wrong Place)
Bind mounts are the most common source of “why can’t my agent see my files?” confusion. A couple of things to keep in mind:
- A mount with no
destinationlands at the same path as on your host. That’s intentional — it keeps your editor and your agent agreeing on where files live. But it means a relativesourcegets resolved to an absolute path on your machine, and that absolute path has to exist on your machine for Docker to mount it. - Tildes (
~) only expand on the host, never in thedestination. If you writedestination: "~/foo", the~is expanded as your user on your machine, not as the container’s user. That’s almost never what you want. Use an absolute path fordestination— for the container’srootuser that usually means starting with/root/.
If a mount seems missing, shell into the container and ls the path you expected it at. If the
directory is empty or doesn’t exist, the mount didn’t take, and the host-side logs will usually tell
you why.
Files You Meant to Copy In Aren’t There
copy_files runs before your agent starts, copying files from your host (or inline strings) into
the container. If something you expected isn’t present:
- Check the
targetpath. Abyss creates missing parent directories with mode0755, but the path still has to be one you’re allowed to write to inside the container. - Check the
sourcefortype: pathentries. The path is read from your host, so it has to exist on your machine, not inside the image. - Read the host-side logs. Every copy is logged, along with any error. If a copy failed, you’ll see it there rather than having to guess.
Setup Scripts Hang or Fail
setup_scripts run in order, once each, before the agent starts. If your session seems to hang
forever at startup, a setup script is the usual suspect — abyss waits for every script to finish
before launching the agent, so a script that’s waiting on input or stuck on a network call will
pause the whole startup.
To narrow it down:
- Run the script by hand inside the container (
docker exec -it <container-id> bash) and see where it blocks. - Add
set -exto the top of bash scripts so each step is printed and the script stops at the first failure. The output shows up in the container logs. - Remember startup is serial. Each script adds to your startup time. If things feel slow but still work, consider moving static work into your image instead. See Custom Docker Images.
TLS / Connection Errors
By default abyss generates a fresh CA and certificates for every session and tears them down afterward — that’s the ephemeral mutual-TLS you don’t have to think about. The only time you’ll see TLS errors is if something interferes with that handshake, and the most common cause is a leftover container from a previous crashed session holding onto the port.
The fix is the reset button from earlier:
abyss docker gcThen try again. If you’ve deliberately set websocket.disable_tls: true in your config, you
shouldn’t see TLS errors at all — but remember that turning TLS off is only safe for local
single-user testing, so double-check that was intentional.
Your Editor Can’t See abyss (or Says the Agent Crashed)
If abyss oneshot works but your editor can’t connect, the problem is in how the editor is
configured, not in abyss itself. For Zed, check that your agent_servers block points at the real
abyss binary and the real path to your config file:
{
"agent_servers": {
"abyss": {
"type": "custom",
"command": "abyss",
"args": ["client", "-f", "/absolute/path/to/your/config.yaml"]
}
}
}A couple of things that trip people up:
- Use an absolute path to the config. Your editor may launch abyss from a different working directory than you expect, so a relative path can resolve to the wrong file.
- Make sure
abyssis on the editor’sPATH. If you can runabyss --versionin your terminal but the editor can’t find it, the editor is probably running with a different environment. Either putabysssomewhere universal like/usr/local/bin, or use the full path in"command". - Check the editor’s ACP logs. In Zed that’s
Ctrl+Shift+P→ “dev: open ACP logs”. If abyss is starting and then immediately dying, the host-side logs (on disk at~/.local/var/abyss/log) will tell you why.
File or Terminal Requests Go to the Wrong Place
By default abyss intercepts ACP file and terminal requests and runs them inside the container,
so the agent can’t reach out and touch your machine. If you’ve flipped acp.tools_on_host.filesystem
or acp.tools_on_host.terminal to true, those requests instead get forwarded to your editor and
run on your host.
If reads or writes or shell commands seem to happen in the “wrong” filesystem, check those settings. Running on the host is a deliberate escape hatch — it’s powerful, but it does mean the agent can affect your real machine, so make sure that’s actually what you meant to do. The full details are in the Configuration reference.
Still Stuck? Filing a Good Bug Report
If you’ve worked through the above and abyss still isn’t behaving, please open an issue on the issues page. A good report helps me help you quickly, so try to include:
- The abyss version (
abyss --version). - Your operating system and architecture (e.g. macOS on Apple Silicon, Linux on x86_64).
- The smallest config file that reproduces the problem. Strip out anything that isn’t needed to trigger the issue — mounts, plugins, setup scripts. The smaller it is, the faster I can reproduce it.
- The exact command you ran and the output it printed. If
abyss oneshotreproduces it, prefer that over an editor session — it’s much easier for me to run. - The relevant log file from
~/.local/var/abyss/log. Only if you are comfortable or edit them; debug logs contain the full text of ACP messages.
I’ve tried to go overboard with logging, so the issue should hopefully be clear to you, or at least to me if not. I’ll take a look and either help you fix it or push a fix to abyss itself.
Where to Go Next
- Getting Started — a clean walkthrough of a working setup, useful as a known-good baseline to compare a broken config against.
- Configuration — the full reference for every config option, in case a field isn’t doing what you expect.
- Custom Docker Images — if your troubles trace back to the image itself, this covers how to build or extend one.