main: non-interactive -p/--prompt one-shot mode (closes #4)

Adds `aish -p "<text>"` for Unix-pipeline composability:

  tail app.log | aish -p "any anomalies?"
  aish -p "summarize: $(curl -sS https://...)"

The flag bypasses repl.lua entirely. On invocation:

  1. Stdin: when not a TTY, read to EOF and prepend to the prompt as a
     fenced block. ffi.libc.isatty(0) gates the read so interactive
     `aish -p "..."` (no pipe) doesn't hang.
  2. Resolve config.models[config.default_model].
  3. Stream broker.chat_stream replies to stdout; finalize with newline.
  4. Exit 0 on success, 1 on broker error, 2 on arg / config error.

Behavior NOT in -p mode (kept simple per the issue's "no repl.lua
involvement"):
  - No MCP, no tool loop, no Norris, no routing, no memory injection.
  - "CMD:" lines in the reply are printed verbatim, NOT executed —
    callers can grep / pipe them as they wish.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-16 21:06:27 +00:00
parent 0700dce881
commit 81c3b1b44a
2 changed files with 71 additions and 2 deletions
+9
View File
@@ -38,6 +38,10 @@ int poll(struct pollfd *fds, unsigned long nfds, int timeout);
enforcement via LOCK_EX | LOCK_NB — fail-fast if another aish
process holds the lock. */
int flock(int fd, int operation);
/* TTY detection for non-interactive mode (`aish -p`). Returns 1 if the
fd refers to a terminal, 0 otherwise (sets errno on error). */
int isatty(int fd);
]]
local C = ffi.C
@@ -174,4 +178,9 @@ function M.flock(fd, op)
return false, ffi.string(C.strerror(C.__errno_location()[0]))
end
-- ---------------------------------------------------------------- isatty
function M.isatty(fd)
return C.isatty(fd) == 1
end
return M