6.6 KiB
AGENTS.md — OpenCode Tool Usage Guide
This file tells AI coding agents which tools are available and when to use them. It is read by agents working on the Memex / Passepartout project.
Development Workflow (Must Follow)
All development MUST follow this cycle, beginning to end:
- Start in REPL — Everything begins and ends in the Passepartout REPL (port 9105)
- TDD in REPL:
- Write a test (use
passepartout: deftestor equivalent) - Run the test → it should FAIL
- Develop code in REPL to make the test pass
- Use lisp-structural-check to validate code while developing
- Evaluate forms with
eval-defunor equivalent - Run tests again → they should PASS
- Repeat until feature is complete
- Write a test (use
- Reflect in Org — Once code works in REPL, reflect it in the .org literate source file
- Tangle with Emacs — Use
org-babel-tangleto generate .lisp from .org - Validate tangled lisp — Run
lisp-structural-checkon the result - Commit — Only after validation passes
When tools fail:
- If any recommended tool fails, you MUST explain:
- Why it failed (specific error, missing dependency, etc.)
- How we can make it work (fix, configuration, alternative approach)
- Then PAUSE and ask for permission before trying a different method
Rule: Do not leave the REPL to develop. If something can't be done in REPL, explain why and ask before proceeding otherwise.
Available Tools — Use These First
1. Passepartout REPL (port 9105)
The daemon runs with ALL skills loaded. Use it instead of the deploy-crash-cycle.
Send forms via Python bridge:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 9105))
msg = '(:type :event :payload (:sensor :repl-eval :code "(+ 1 2)"))'
s.sendall(f"{len(msg):06x}".encode() + msg.encode())
Or via SBCL directly (attached to daemon):
(sb-bsd-sockets:socket-send sock payload len)
Key functions available:
(passepartout:lisp-structural-check "code-string")— returns (values t nil) or (values nil "error")(passepartout:lisp-validate "code-string" :semantic t)— full validation(passepartout:log-message "format ~a" arg)— write to daemon log- Any exported symbol from
passepartoutpackage
2. Lisp Structural Tools (pre-deploy validation)
ALWAYS run these before tangling/deploying Lisp changes.
lisp-structural-check works on ANY Lisp string, not just Org blocks:
;; Via REPL — send to port 9105:
(passepartout:lisp-structural-check "<lisp-code-string>")
;; Returns: (values t nil) on success, (values nil "error details") on failure
For Org files:
(passepartout:literate-block-balance-check "/path/to/file.org")
These catch paren mismatches in <1 second vs. the 60-second deploy-crash cycle.
3. Emacs Interactive
Use Emacs for interactive Lisp development:
forward-sexp/backward-sexp— navigate balanced expressionsshow-paren-mode— visual paren matchingeval-defun(C-M-x) — evaluate the current top-level formeval-region— evaluate selected regionorg-babel-tangle— tangle a single file:M-x org-babel-tangle- Batch tangle:
emacs --batch --eval "(progn (require 'org) (find-file \"file.org\") (org-babel-tangle) (kill-buffer))"
4. Tmux (for TUI testing)
# Start TUI in detached session
tmux new-session -d -s test "passepartout tui 2>&1 | tee /tmp/tui.log"
# Send keys
tmux send-keys -t test "hello world" Enter
# Capture output
tmux capture-pane -t test -p -S -200
# Clean up
tmux kill-session -t test
5. Pre-Commit Hook
Validates staged org files by tangling + compiling in daemon:
ln -sf ../../scripts/pre-commit-repl-check .git/hooks/pre-commit
Run manually: passepartout setup or git commit (hook auto-runs).
6. TUI REPL (via /eval + Swank)
The TUI process has its own REPL for live development:
Built-in /eval command — type in the TUI input:
/eval (+ 1 2)→=> 3displayed in chat/eval *state*→ inspect full TUI state plist/eval (view-status sw)→ force status bar re-render/eval (add-msg :system "test")→ inject a test message
Emacs + Swank REPL — connect Emacs to the TUI process:
- Start TUI:
passepartout tui - In Emacs:
M-x slime-connect RET 127.0.0.1 RET 4006 C-M-xany form fromorg/gateway-tui.org→ evaluates in live TUI process- Configure port:
export TUI_SWANK_PORT=4009(default: 4006)
Croatoan note: Rendering functions (view-status, view-chat, view-input) write to the terminal and can't be fully tested from Emacs. Inspect return values instead, and test rendering with /eval commands in the TUI itself.
Commands
- Validate code: Send to REPL at port 9105 using socket bridge (see Development Workflow)
- Run tests:
(passepartout:run-tests)in REPL - Tangle org:
emacs --batch --eval "(progn (require 'org) (find-file \"file.org\") (org-babel-tangle) (kill-buffer))"
Project Structure
- Source (literate):
org/ - Source (tangled):
lisp/ - Tests:
tests/ - Scripts:
scripts/ - Deployment:
~/.local/share/passepartout/ - TODO tracking:
docs/ROADMAP.org
When Done Means
- Tests pass:
(passepartout:run-tests)returns success - Code validated:
lisp-structural-checkreturns(values t nil) - Org reflected: Code exists in .org source file
- Org tangled: .lisp generated from .org
- Committed: Only after all above pass
Boundaries
- Always do: Use REPL first for all development, use TDD, validate with lisp-structural-check
- Ask first: Before editing .lisp directly (skip org), before deploying, before git commit
- Never do: Edit .lisp files manually (they're autogenerated), skip validation before commit
Iteration
When the agent makes the same mistake twice, add a rule to this file to prevent recurrence.
Project Architecture
- Thin harness, fat skills — core provides hooks (
defskill,register-actuator,*probabilistic-backends*), skills provide handlers - Org is source of truth —
.orgfiles tangle to.lisp. Never edit.lispdirectly - Package:
passepartoutexports all symbols inlisp/core-defpackage.lisp - XDG data dir:
~/.local/share/passepartout/(deployed lisp/org files) - Config:
~/.config/passepartout/.env
Key Libraries
- Croatoan — 0-based coordinates,
(setf (cursor-position win) '(y x))for cursor,add-stringwith:y/:xkeyword args. Source:~/quicklisp/dists/quicklisp/software/croatoan-20241012-git/src/ - Babel — string encoding/decoding
- usocket — TCP sockets
- bordeaux-threads — threading primitives