Repository navigation
Conversation
1 of 3 tasks
`load-string`ing a buffer that opens with `(ns foo)` -- which every real .lg file does -- switches the current namespace permanently, and it escapes the call: it happens even when `load-string` runs from inside an already-compiled function, and it never switches back. legmacs evaluates in its own live namespace, so that namespace *is* the editor. One `C-c C-e` on an ordinary file therefore cost you every alias main.lg set up -- `buf/`, `km/`, `dispatch/`, `render/` -- for the rest of the session, and the next `C-x C-e` failed with "Can't resolve ... in this context". `preserving-ns` grabs `(ns-name *ns*)`, runs the thunk, and `in-ns`es back. It reifies the outcome rather than using `finally`, since a let-go `try` whose only trailing clause is `finally` swallows the in-flight exception, and a `catch` that rethrows skips the `finally` -- neither shape both propagates and restores. Only eval-buffer is wrapped. `C-x C-e`, `C-j` and the *repl* buffer are deliberately left alone: an `(in-ns 'foo)` you typed and evaluated on purpose should still move you. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Type a call where you want the code, put point in it, press C-c C-v, and
the form is replaced by whatever the model writes -- as one undo step.
The context is the point of it. vibe-replace sends the whole buffer with
the call site swapped for a <<<VIBE:HERE>>> marker, plus the column that
marker starts at, so the answer is written to fit that exact spot --
surrounding defns, aliases and indentation included -- rather than being
a generic answer to the prompt in isolation.
`vibe` stays an ordinary function: C-x C-e on a (vibe "...") form echoes
the generated code instead of splicing it, and it composes, e.g.
(str (vibe "a") (vibe "b")). vibe-replace parks the call site in an atom
for the duration of the eval rather than passing it as an argument, which
is what makes both work.
This is the only command here that blocks on something slow, and it
stays out of the pure pipeline: vibe-replace does no I/O at all, it sets
:message "vibing..." and :pending-vibe and returns. main.lg's loop paints
that frame first, then resolve-effects runs the request. Doing it inline
would have frozen the screen on a stale frame for the whole round trip.
Config is ~/.config/legmacs/vibe.edn ({:key "sk-..."}, optional :model,
default gpt-5.6-luna), merged wholesale so :provider/:url/:max-tokens/
:system work from there too. Four layers, each beating the last:
defaults, vibe.edn, the config atom (legmacs-init.lg), per-call opts.
:openai and :anthropic ship; a provider is four keys and two functions.
Two guards are load-bearing. resolve-pending re-checks that a (vibe form
still opens at :start before touching the buffer, and it refuses to
splice a non-string result -- let-go's `eval` returns compile errors as
an #error value instead of raising them, so a typo'd prompt would
otherwise be pasted into your code.
Tested without a network: the call-site search, prompt building, fence
stripping, config parsing and splicing are all pure, and resolve-pending
is exercised on the paths that fail before any HTTP happens. Verified
end to end against a mock OpenAI server driving the real chord pipeline.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft / experiment — not for mainline as-is.
Type a call where you want the code, put point in it, press
C-c C-v:One undo puts the call back.
What makes the answers usable
The model gets the whole buffer with the call site swapped for a
<<<VIBE:HERE>>>marker, plus the column that marker starts at — so it writescode shaped to fit that spot (surrounding defns, aliases, indentation) rather
than a generic answer to the prompt in isolation.
vibestays an ordinary function:C-x C-eon the form echoes the generatedcode instead of splicing it, and
(str (vibe "a") (vibe "b"))works.vibe-replaceparks the call site in an atom for the duration of the evalrather than passing it as an argument, which is what makes both true at once.
Blocking without freezing
This is the only command in legmacs that waits on something slow, and it stays
out of the pure pipeline.
vibe-replacedoes no I/O — it sets:message "vibing..."plus:pending-vibeand returns, exactly like any othercommand.
main.lg's loop paints that frame, thenresolve-effectsruns therequest. Inline I/O would have left the screen frozen on a stale frame for the
whole round trip with no way to say what it was waiting for.
Setup
~/.config/legmacs/vibe.edn:{:key "sk-..."}Optional
:model(defaultgpt-5.6-luna). The file is merged wholesale, so:provider/:url/:max-tokens/:systemwork from there too. Fourlayers, each beating the previous:
defaults, vibe.edn, theconfigatom(legmacs-init.lg), per-call opts.
:openaiand:anthropicship; a provideris four keys and two functions.
Testing
40 tests, no network: call-site search, prompt building, fence stripping,
config parsing and splicing are pure, and
resolve-pendingis exercised on thepaths that fail before any HTTP. Verified end to end against a mock OpenAI
server driving the real chord pipeline. Full suite 1029/1029 on let-go 1.12.2.
The first commit is independent and probably should land
1aade41 fixes a pre-existing bug that has nothing to do with vibe:
load-stringing a buffer that opens with(ns foo)— every real.lgfile —relocates the running namespace permanently, even from inside a compiled
function. Since legmacs evaluates in its own live namespace, one
C-c C-eonan ordinary file cost you
buf/,km/,dispatch/andrender/for the restof the session, and the next
C-x C-efailed with "Can't resolve ... in thiscontext". vibe just made it visible. Cherry-pick it out if this branch never
merges.
🤖 Generated with Claude Code