NanoClaw

NanoClaw finds attachments disappearing at two channel boundaries

NanoClaw reports inbound files silently dropped when message IDs contain path separators and Signal attachments mounted outside the agent container. A separate setup issue shows an OpenCode skill still teaching Dockerfile edits removed by the newer cli-tools registry.

← Back to homeOriginal source ↗

nanocoai/nanoclaw issue #3206 is the inspected primary source: “Inbound attachments silently dropped on channels whose message IDs contain a path separator (e.g. Google Chat).” The related records below were inspected as supporting context rather than independent confirmation.

The facts

- nanocoai/nanoclaw issue #3206 was created 2026-08-08T23:21:42Z and was open at inspection; its title is “Inbound attachments silently dropped on channels whose message IDs contain a path separator (e.g. Google Chat).” - nanocoai/nanoclaw issue #2528 was created 2026-05-18T00:23:04Z and was open at inspection; its title is “Signal channel: image/PDF attachments unreachable from agent container.” - nanocoai/nanoclaw issue #3204 was created 2026-08-08T20:33:00Z and was open at inspection; its title is “add-opencode still instructs Dockerfile ARG+RUN edits removed by the cli-tools.json refactor (and its guard test asserts the old shape).” - The repository reported 30473 stars, 869 open issues, default branch main, and last push 2026-08-06T13:28:16Z. - The latest tagged-release baseline checked was v2.1.54 published 2026-08-01T20:46:31Z.

What changed

nanocoai/nanoclaw issue #3206 reports: Inbound attachments are silently dropped on channels whose message IDs contain a path separator (e.g. Google Chat) Summary extractAttachmentFiles in src/session-manager.ts gates attachment staging on isSafeAttachmentName(messageId). That check rejects any value containing / or \. Google Chat message IDs are resource paths: so the guard rejects every one of them and returns before writing anything to disk. The result is that **no inbound attachment on Google Chat ever reaches the container.** The failure is silent from the user's side. The attachment metadata still reaches the agent, so it reports the filename it was sent and then correctly says the file is nowhere on its filesystem. In our case the agent said exactly that, which is what led us to the code. Host logs show one of these per affected message: Why it only shows up on some channels Slack, Discord and WhatsApp IDs are opaque tokens with no separators, so they pass the check and the path works. Google Chat is the outlier, which is presumably why this has gone unnoticed. Root cause The check

nanocoai/nanoclaw issue #2528 reports: Bug Images and PDFs sent over Signal arrive at the host but the agent inside the container can't open them. Reproduce 1. Install Signal via /add-signal on a v2 install. 2. From your phone, send a DM with an image attached (e.g. archetype.png). 3. Ask the agent \"can you see this image?\". Agent responds with something like *\"I see that an image came through (the path is showing) but I can't access the file from my container — the Signal attachments folder isn't mounted into my workspace\".* Same behaviour for PDFs (application/pdf), except PDFs are dropped silently — there's no handler for them at all in src/channels/signal.ts. Root cause src/channels/signal.ts (upstream/channels) builds the inbound message's structured attachments array as {path:, contentType} and also emits a [Image: ] line in the text body. The host path points into ~/.local/share/signal-cli/attachments/, which is **never mounted into the agent container** — src/container-runner.ts:buildMounts only mounts /workspace, /workspace/agent, /workspace/global, /app/CLAUDE.md, /app/src, /app/skills, /home/node/.claude, plus any additionalMounts the operator configures per-group. So the agent receives a path that doesn't resolve

nanocoai/nanoclaw issue #3204 reports: Summary.claude/skills/add-opencode/SKILL.md still instructs editing container/Dockerfile with an ARG + a dedicated RUN pnpm install -g layer. That predates the cli-tools.json refactor — container/Dockerfile on main no longer contains **any** per-CLI install blocks. The skill's own guard test then asserts the removed shape, so following the skill produces a Dockerfile inconsistent with the current build, and the validation step it tells you to run is checking for something that shouldn't exist. /add-codex already uses the correct pattern, so the two provider skills disagree with each other. Evidence on main (743e32df) The Dockerfile has no per-CLI installs; global CLIs come from the manifest: But add-opencode/SKILL.md still says: and its pre-flight checklist (line 25) lists ARG OPENCODE_VERSION / "opencode-ai@${OPENCODE_VERSION}" in container/Dockerfile as an "already installed" marker. The guard test compounds it Step 6 copies opencode-dockerfile.test.ts into src/, and step 7 runs it as the "Dockerfile install guard". It asserts precisely the shape the refactor removed: So an operator who follows the skill gets a green test for a Dockerfile edit that contradicts the manifest seam, and one

Why it matters

Channel support is not complete when text arrives but files vanish between adapter, host path and container mount. Setup instructions are part of that boundary because stale recipes can undo the intended ownership model. The operator test is whether visible output, retained state and authority still describe the same event after retries, background work or restart.

Current

The primary record was open when captured on 2026-08-09. The tagged-release baseline was v2.1.54 published 2026-08-01T20:46:31Z. Repository metadata, full source bodies, current pull requests and issues, releases, Google News, Hacker News, Lobsters, Metamesh and the rendered ClawCharts row were inspected. ClawCharts selected the subject; it did not prove the claim.

Evidence

The primary URL is https://github.com/nanocoai/nanoclaw/issues/3206. Supporting records are https://github.com/nanocoai/nanoclaw/issues/2528 and https://github.com/nanocoai/nanoclaw/issues/3204. Source bodies, timestamps and states are preserved in the daily evidence bundle. Test counts and reproductions remain attributed to their authors unless identified as independently rerun.

Source boundary

Open work is described as open, closed work as closed, and operator reports as reports. A pull request is evidence of proposed or reviewed direction, not proof of a shipped release. Search residue, package mirrors and historically published source spines were excluded.

Operator take

Normalize message identity separately from filesystem paths, stage media into an explicit shared mount, and test every setup skill against the current extension registry. Preserve a before-state receipt, make the smallest reversible change, and verify the original failure independently.

Caveat

Public project records are mutable. Status, scope and evidence can change after publication. This brief records the inspected state and does not authorize changes to a reader’s deployment.

Source inspected; source state, environment and release boundary remain explicit.