You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit a25b7f8
Browse filesBrowse the repository at this point in the historyBrowse files
[luv-legion-44] Give sessions the environment your shell would have (#44)
tmux and ssh exec their command directly, with no shell in between, so a
session luv started — a remote dispatch, a handover, a detached start — never
sources ~/.bashrc or ~/.zshrc. It runs with whatever environment the tmux
server was started with, frozen at whenever that server first came up. The API
key an agent authenticates with and the PATH entry that makes 'codex'
resolvable both live in the rc, and both go missing — and only for the sessions
luv started for you, which is the confusing part.
So ask for them. shell_env() runs $SHELL -lic and has it print its own
environment: rc files are code, not data, and there is no reading them from
outside. The environment comes back behind a marker so an rc that greets you
doesn't corrupt the parse, and a shell that hangs, warns, or fails outright is
ignored rather than fatal.
The merge happens in main(), before anything shells out — the clone needs gh
and git on PATH as much as the agent needs its credentials — and ahead of
collect_luv_env(), so a LUV_* exported from the rc is one -e can forward.
What is already set wins: 'FOO=bar luv ...' and -e are statements about this
session, and one that quietly overrode the value you handed it would be worse
than one missing it. PATH is the exception, being a list rather than a value,
and gets the rc's entries appended after the ones that got us here.
Only for the luv that tmux or ssh started (_LUV_INNER). A luv you ran yourself
already inherited the shell it ran in, and re-deriving it there would charge
every session start for an rc that has already run. 'shell_env': false opts a
machine out entirely, read where the session runs, so a remote can decide
independently of the laptop.
Docker sessions are untouched: the container has its own environment, and -e
remains the only thing that crosses into it.
Claude-Session: https://claude.ai/code/session_012SkaBJLpVm4LP5RQL9NXf5
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+26Lines changed: 26 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -146,6 +146,32 @@ Handover flags:
146
146
|`--purge`| Delete the source folder once the copy is verified |
147
147
|`-y`| Skip the "an agent may still be running" confirmation |
148
148
149
+
## The session's environment
150
+
151
+
A session luv starts for you — a remote dispatch, a handover, a detached start
152
+
— is exec'd by tmux or ssh with no shell in between, so it never sources
153
+
`~/.bashrc` or `~/.zshrc` and would otherwise run with whatever environment the
154
+
tmux server happened to start with. luv asks your login shell (`$SHELL -lic`)
155
+
for its environment and fills in the gaps before cloning or launching anything,
156
+
so the agent gets the API keys and the `PATH` you'd have in a terminal there.
157
+
158
+
Precedence, highest first:
159
+
160
+
1. Anything already set — `FOO=bar luv …`, or `-e` — is a decision about *this*
161
+
session and is never overwritten.
162
+
2. Your rc's exports fill in the rest. `PATH` is merged instead of replaced:
163
+
entries the rc adds (nvm, pyenv, `~/.local/bin`) are appended after the ones
164
+
already there.
165
+
166
+
The probe runs on the machine the session runs on, so a remote session picks up
167
+
the *remote* user's rc. It is skipped when you run `luv` yourself — that
168
+
process already inherited your shell — and can be turned off entirely with
169
+
`luv config set shell_env false`. An rc that hangs is given 15 seconds and then
170
+
ignored.
171
+
172
+
Docker sessions are the exception: the container has its own environment, and
173
+
only `-e` crosses into it (see below).
174
+
149
175
## Docker dev environments
150
176
151
177
If a repo contains `.luv/settings.json` with a `compose_file` key, `luv` automatically starts a Docker Compose environment and runs Claude inside the `dev-environment` container.
0 commit comments