add-deltachat — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited add-deltachat (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
The adapter drives the @deltachat/stdio-rpc-server JSON-RPC subprocess directly — pure Node.js against the DeltaChat core library. Messages are delivered over email with Autocrypt/OpenPGP encryption.
Skip to Credentials if all of these are already in place:
src/channels/deltachat.ts existssrc/channels/deltachat-registration.test.ts existssrc/channels/index.ts contains import './deltachat.js';@deltachat/stdio-rpc-server is listed in package.json dependenciesOtherwise continue. Every step below is safe to re-run.
git fetch origin channelsgit show origin/channels:src/channels/deltachat.ts > src/channels/deltachat.ts
git show origin/channels:src/channels/deltachat-registration.test.ts > src/channels/deltachat-registration.test.tsAppend to src/channels/index.ts (skip if already present):
import './deltachat.js';pnpm install @deltachat/[email protected]pnpm run build
pnpm exec vitest run src/channels/deltachat-registration.test.tsBoth must be clean before proceeding. deltachat-registration.test.ts is the one integration test: it imports the real channel barrel and asserts the registry contains deltachat. It goes red if the import './deltachat.js'; line is deleted or drifts, if the barrel fails to evaluate (so the channel genuinely would not register), or if @deltachat/stdio-rpc-server isn't installed (the import throws) — so it also implicitly verifies the dependency from step 4. Importing is safe: deltachat instantiates the rpc client only in setup() (at host startup), never at import.
End-to-end message delivery against a real email account is verified manually once the service is running — see Wiring and Troubleshooting.
A dedicated email account is strongly recommended — it will accumulate DeltaChat-formatted messages and store encryption keys. Not all providers work well with DeltaChat; check https://providers.delta.chat/ before picking one.
Default security modes: IMAP uses SSL/TLS (port 993), SMTP uses STARTTLS (port 587). Both are configurable via .env — see Credentials below.
To find the correct hostnames for a domain:
node -e "require('dns').resolveMx('example.com', (e,r) => console.log(r))"Most providers publish their IMAP/SMTP hostnames in their help docs under "manual setup" or "IMAP access."
Add to .env:
[email protected]
DC_PASSWORD=your-app-password
DC_IMAP_HOST=imap.example.com
DC_IMAP_PORT=993
DC_IMAP_SECURITY=1 # 1=SSL/TLS (default), 2=STARTTLS, 3=plain
DC_SMTP_HOST=smtp.example.com
DC_SMTP_PORT=587
DC_SMTP_SECURITY=2 # 2=STARTTLS (default), 1=SSL/TLS, 3=plainSecurity settings are applied on every startup, so changing them in .env and restarting takes effect without wiping the account.
Sync to container: mkdir -p data/env && cp .env data/env/env
The following are read from the process environment (not .env). To override them, add Environment= lines to the systemd service unit or your launchd plist:
| Variable | Default | Description |
|---|---|---|
DC_ACCOUNT_DIR | dc-account | Directory for DeltaChat account data (IMAP state, keys, blobs) |
DC_DISPLAY_NAME | NanoClaw | Bot display name shown in DeltaChat |
DC_AVATAR_PATH | _(none)_ | Absolute path to avatar image; set at startup only |
The /set-avatar command (send an image with that caption) is the easiest way to set the avatar at runtime without modifying the service file. Only users with owner or global admin role can use it.
Run from your NanoClaw project root:
source setup/lib/install-slug.sh
# Linux
systemctl --user restart $(systemd_unit)
# macOS
launchctl kickstart -k gui/$(id -u)/$(launchd_label)On first start the adapter configures the email account (IMAP/SMTP credentials, calls configure()). Subsequent starts skip straight to startIo(). Account data is stored in dc-account/ in the project root (or your DC_ACCOUNT_DIR).
DeltaChat contacts cannot be added by email alone — to start a chat, the user must open the bot's invite link in their DeltaChat app or scan its QR code. This triggers the SecureJoin handshake.
#### Step 1 — Get the invite link
After the service starts, the adapter logs the invite URL and writes a QR SVG:
grep "invite link" logs/nanoclaw.log | tail -1
# url field contains the https://i.delta.chat/... invite link
# also written to dc-account/invite-qr.svg (or $DC_ACCOUNT_DIR/invite-qr.svg)The invite URL is stable (tied to the bot's email and encryption keys) so it stays valid across restarts.
#### Step 2 — Add the bot in DeltaChat
Two options for the user to connect:
https://i.delta.chat/... URL and open it on the device running DeltaChat. The app recognises it and shows a "Start chat" prompt.dc-account/invite-qr.svg in a browser or image viewer, display it on screen, and scan it from the DeltaChat app using the QR-scan button on the new-chat screen.After accepting, DeltaChat exchanges keys and creates the chat automatically.
#### Step 3 — Wire the chat to an agent
Once the first message arrives the router auto-creates a messaging_groups row. Look up the chat ID:
pnpm exec tsx scripts/q.ts data/v2.db \
"SELECT platform_id, name FROM messaging_groups WHERE channel_type='deltachat' AND is_group=0 ORDER BY created_at DESC LIMIT 5"Then run /init-first-agent — it creates the agent group, grants the user owner access, and wires the messaging group in one step:
pnpm exec tsx scripts/init-first-agent.ts \
--channel deltachat \
--user-id deltachat:[email protected] \
--platform-id <platform_id from above> \
--display-name "Your Name"Add the bot email to a DeltaChat group. When any member sends a message, the router creates a messaging_groups row with is_group = 1. Run /manage-channels to wire it to an agent group.
If you're in the middle of /setup, return to the setup flow now.
Otherwise, run /init-first-agent to create an agent and wire it to your DeltaChat DM (see Wiring above), or /manage-channels to wire this channel to an existing agent group.
deltachat"12") — the DeltaChat core's internal chat identifierdeltachat:{email} — the contact's email addressmessaging_groups as shown aboveisolated session modedc-account/invite-qr.svg; see Wiring for the bootstrap flow/set-avatar — send an image with this caption to change the bot's DeltaChat avatar (admin/owner only)maybeNetwork() called every 10 minutes to recover from prolonged idleNot supported: DeltaChat reactions, message editing/deletion, read receipts.
isConnected() returns true when the internal connectivity value is ≥ 3000:
| Range | Meaning |
|---|---|
| 1000–1999 | Not connected |
| 2000–2999 | Connecting |
| 3000–3999 | Working (IMAP fetching) |
| ≥ 4000 | Fully connected (IMAP IDLE) |
grep "Channel credentials missing" logs/nanoclaw.log | grep deltachatAll six required vars (DC_EMAIL, DC_PASSWORD, DC_IMAP_HOST, DC_IMAP_PORT, DC_SMTP_HOST, DC_SMTP_PORT) must be present in .env.
grep "DeltaChat" logs/nanoclaw.log | tail -20Common causes:
DC_IMAP_PORT/DC_IMAP_SECURITY or DC_SMTP_PORT/DC_SMTP_SECURITY in .envSet DC_SMTP_SECURITY=1 and DC_SMTP_PORT=465 in .env, then restart.
grep "Channel adapter started.*deltachat" logs/nanoclaw.loggrep "DeltaChat: IO started" logs/nanoclaw.log/init-first-agent to create their user record and wire the chatpnpm exec tsx scripts/q.ts data/v2.db "SELECT mg.platform_id, mga.agent_group_id FROM messaging_groups mg JOIN messaging_group_agents mga ON mg.id = mga.messaging_group_id WHERE mg.channel_type='deltachat'"rm -f dc-account/accounts.lock
systemctl --user restart "$(. setup/lib/install-slug.sh && systemd_unit)"The account is already configured — IO restarts automatically on service start. If the RPC subprocess is stuck, restart the service. Check for errors:
grep "DeltaChat" logs/nanoclaw.error.log | tail -20The messaging group exists but may not be wired to an agent group. Run:
pnpm exec tsx scripts/q.ts data/v2.db "SELECT id, platform_id, name FROM messaging_groups WHERE channel_type='deltachat'"If the group has no entry in messaging_group_agents, wire it with /manage-channels.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.