Skip to content

Windows/Git Bash: native sqlite3.exe can't open MSYS /c/ DB path (inbox/send/watch fail) + 4 related findings #197

Description

@vhsvhafmwf

Environment

  • OS: Windows 11
  • Shell: Git Bash (MINGW64)
  • agmsg: v1.1.0 (installed via npm i -g agmsgagmsg install)
  • sqlite: native Windows sqlite3.exe on PATH

Found while running several Claude Code agents coordinated through agmsg on Windows. One primary bug plus four related findings. Happy to PR the first one (or two).


① [BUG] native sqlite3.exe cannot open the MSYS /c/... DB path → inbox/send/watch fail (primary, easy fix)

agmsg_db_path() (in scripts/lib/storage.sh) returns an MSYS/Git Bash path like /c/Users/<you>/.agents/skills/agmsg/db/messages.db. The native Windows sqlite3.exe cannot open that form — it fails with unable to open database file (CANTOPEN). Because every DB call site goes through DB="$(agmsg_db_path)", this takes down inbox.sh, send.sh, watch.sh, task-*, etc. at once.

It reproduces reliably when the environment has MSYS2_ARG_CONV_EXCL=* (MSYS path conversion suppressed, so the /c/ form reaches sqlite unchanged). watch.sh keeps running even when it can't open the DB, so this presents as a silent failure that's hard to diagnose.

Fix (small, low-risk): add a cygpath -m conversion in agmsg_db_path(), mirroring the existing cygpath -w handling in agmsg_sql_readfile_path in the same file. -m yields the C:/Users/... mixed (forward-slash) form, which both Git Bash [ -f ] tests and sqlite3.exe accept. No-op off Windows:

agmsg_db_path() {
  local p
  p="$(agmsg_storage_dir)/messages.db"
  if command -v cygpath >/dev/null 2>&1; then
    p="$(cygpath -m "$p" 2>/dev/null || printf '%s' "$p")"
  fi
  printf '%s\n' "$p"
}

Since agmsg_db_path is the single chokepoint, this one change fixes every DB-backed script. I can open a PR for this.

② [BUG] watch.sh survives a DB-open failure silently

When the DB can't be opened (see ①), watch.sh keeps running and emits nothing, so the operator can't tell receiving is dead. Suggestion: a sqlite3 "$DB" 'SELECT 1;' health check at startup (and/or periodically) that prints a single ERROR: cannot open message DB <path> line to stdout on failure.

③ [FEATURE] catch-up drain of unread inbox on watcher attach

The monitor (watch.sh) streams only messages that arrive after attach. A message queued before the watcher attaches is missed — e.g. spawning a worker and immediately sending it a task: the worker reports READY but never sees/acts on the queued task, so orchestration has to wait for READY and then send live. Suggestion: on attach, drain & emit unread inbox once before entering the live stream.

④ [BUG] despawn ineffective for non-tmux (OS-terminal) spawns on Windows

spawn via an OS terminal / AGMSG_TERMINAL template does not write a placement record, so despawn --force exits with no placement record and does nothing; graceful despawn is also a no-op when no live actas lock is held. The result is that a spawned member can only be removed with leave.sh (de-register) plus manually closing the window. Suggestion: record placement (or at least launch metadata) for OS-terminal spawns so despawn can de-register consistently.

⑤ [FEATURE] length guard in send.sh

Long bodies sent over agmsg clutter the recipient inbox / terminal. Suggestion: a max-length guard in send.sh (e.g. warn + refuse over ~2KB, nudging toward a file reference) for the "short notification + payload in a file" pattern.


Thanks for agmsg — the daemonless SQLite design works well; these are all Windows/Git-Bash edges. ① in particular is a small change with a big payoff on Windows.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions