Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.59.0] - 2026-09-30

### Added

- **`aid --model` and `aid --effort`** (#662). Each agent is told them in its own spelling:
`claude --model/--effort`, `codex --model` and `-c model_reasoning_effort=`, and
`gemini --model`. The values are passed on as typed, since the agents add models
faster than `aid` is released. `--effort` beside `--gemini` is refused, as gemini has
no such setting. Both work with `aid resume` too.
- **`aid` asks for the agent, the model and the effort before the prompt** (#662). Each is a
picker that lists the recent choices first, so one Enter repeats the last launch. The
agent picker has one row per Claude login that `dl --claude-profiles` lists, then
`codex` and `gemini`. A name that is not listed can be typed. A flag on the line
skips its picker, and Esc stops the background boot.
- **A bare `aid` picks a workspace** (#662), as a bare `dl` does. So does a line of flags with
no workspace, such as `aid --codex`.

### Fixed

- **A pasted prompt arrives whole** (#662). The prompt editor read the terminal in line mode,
which cut a paste off at 4096 bytes, submitted at its first line break, and left
lines that arrived late for the agent to read as keystrokes. It is now a raw-mode
editor with bracketed paste: a paste keeps its line breaks, Alt-Enter or Ctrl-J adds
a line, and Enter submits.
- **The agent, model and effort pickers no longer panic** (#662) on a terminal with a size of
zero, and take the workspace picker's `TERM` fallback. With no terminal they can draw
on, they are skipped, and the prompt editor still opens.

## [0.58.0] - 2026-09-30

### Added
Expand Down
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ one argument instead of a clone, a config file and a build command.
[![GitHub pull-requests merged](https://badgen.net/github/merged-prs/blooop/devlaunch)](https://github.com/blooop/devlaunch/pulls?q=is%3Amerged)
[![GitHub release](https://img.shields.io/github/release/blooop/devlaunch.svg)](https://GitHub.com/blooop/devlaunch/releases/)
[![PyPI](https://img.shields.io/pypi/v/devlaunch)](https://pypi.org/project/devlaunch/)
[![Conda](https://img.shields.io/badge/conda-v0.58.0-brightgreen?logo=anaconda)](https://prefix.dev/channels/blooop/packages/devlaunch)
[![Conda](https://img.shields.io/badge/conda-v0.59.0-brightgreen?logo=anaconda)](https://prefix.dev/channels/blooop/packages/devlaunch)
[![License](https://img.shields.io/github/license/blooop/devlaunch)](https://opensource.org/license/mit/)
[![Platform](https://img.shields.io/badge/platform-linux--64-blue)](https://github.com/blooop/devlaunch/releases)
[![Pixi Badge](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/prefix-dev/pixi/main/assets/badge/v0.json)](https://pixi.sh)
Expand Down Expand Up @@ -341,7 +341,7 @@ clone, and [docs/cleanup.md](docs/cleanup.md) says what it carries one past and

```bash
$ dl --version
dl 0.58.0
dl 0.59.0
```

`--devcontainer <variant|path>` picks a non-default `devcontainer.json`. A bare name means
Expand Down Expand Up @@ -407,15 +407,23 @@ once for the whole run:
aid https://github.com/blooop/devlaunch/pull/579 address the review comments
```

With no prompt on the line, `aid` starts the container booting and asks for the prompt while it
does. Type it free of shell quoting, with no escaping and no history expansion eating a `!`. An
empty Enter starts the agent's plain session. Piping stdin or setting `DEVLAUNCH_NO_TTY=1` skips
the question and launches one-shot, so scripts behave as they always have.
With no workspace on the line, `aid` on a terminal lets you pick one of your workspaces, as `dl`
does. With no prompt on the line, `aid` starts the container booting and asks for the prompt while it
does. Type it free of shell quoting, with no escaping and no history expansion eating a `!`. A
paste keeps its line breaks and can be any length, Alt-Enter or Ctrl-J adds a line, and an empty
Enter starts the agent's plain session. Before the prompt it asks for the agent (one row per Claude
login, then `codex` and `gemini`), the model and the effort, each in a picker that lists your
recent choices first, so one Enter repeats the last launch. A flag on the line skips its picker,
and Esc stops the boot. See [docs/cli.md](docs/cli.md#the-pickers-ahead-of-the-prompt). Piping
stdin or setting `DEVLAUNCH_NO_TTY=1` skips the question and launches one-shot, so scripts behave
as they always have.

| Option | What it does |
|---|---|
| `--claude`, `--codex`, `--gemini` | Pick the agent. Default `claude` |
| `--rm` | Delete the workspace when the agent is done. Appendable to a recalled line |
| `--model <model>` | The model the agent runs, in that agent's own spelling. Passed on as typed and not checked. See [docs/cli.md](docs/cli.md#model-and-effort-in-each-agents-spelling) |
| `--effort <level>` | How hard the agent thinks: claude's `--effort`, codex's `model_reasoning_effort`. gemini has none, so beside `--gemini` it stops |
| `--no-remote-control`, `--no-remote` | Start a plain local session. Remote Control is on by default for `claude`: the session is named after the workspace and can be read and steered from claude.ai/code or the Claude app. It needs a claude.ai login in the container |
| `--remote-control`, `--remote` | Ask for Remote Control by name. `claude` has it already; beside `--codex` or `--gemini` this says they have not got it and stops |
| `--devcontainer <variant\|path>` | Passed through to `dl` |
Expand Down
107 changes: 107 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,113 @@ claude all take it offline immediately. The entry can sit in the claude.ai list
roughly 4 hours after that before it clears, which is the web side timing out rather
than anything still running on your machine.

## Model and effort, in each agent's spelling

`--model` and `--effort` are `aid`'s own words. Each agent is told them in the
spelling its own CLI takes:

```bash
aid --model opus --effort max blooop/devlaunch # claude --model opus --effort max
aid --codex --model gpt-5.5 --effort high blooop/devlaunch
# codex --model gpt-5.5 -c model_reasoning_effort=high
aid --gemini --model gemini-3-pro blooop/devlaunch # gemini --model gemini-3-pro
```

Both take their value as the next word or joined with `=`, and both go ahead of the
workspace like the agent flags do. After the workspace they are prompt text.

**`aid` does not check the values.** Each agent adds models and effort levels on its
own release schedule, and codex already takes effort values it does not know by
name. A list in `aid` would be wrong a few weeks after each release. So `aid` holds
only the spelling of each flag, in its agent table, and passes the value on as you
typed it. A value the agent does not know is the agent's to answer for, in its own words: `claude` warns about an unknown effort and uses its default.
Leave a flag off and no flag is passed, so the agent starts on its own default.

**gemini has no effort setting.** `--effort` beside `--gemini` is refused before
anything boots, the same way `--remote-control` is refused beside an agent without
Remote Control. A value that is missing, empty or starts with `-` is refused too:
`aid --model --codex <ws>` is a typo, not a model called `--codex`.

## The pickers ahead of the prompt

`aid <workspace>` with no prompt on a terminal asks for up to three settings before
it opens the prompt editor. The workspace boots in the background the whole time.

1. **The agent**, with one row per Claude login and one row for each other agent:

```
AGENT NAME STATE ACCOUNT
claude default authed me@example.com
claude work authed me@acme.example · team
codex
gemini
```

The Claude rows are the ones `dl --claude-profiles` lists, less the named
profiles with no credential, since a launch naming one of those refuses. A
named row becomes `--claude --claude-profile <name>`, and `default` passes no
profile. codex and gemini have one row each, because `dl` forwards one login
for each of them.

Choosing a row puts its flags in front of your line and parses the line again,
so every rule of the line still holds. A row the line would refuse is not
shown: `--remote-control` on the line leaves only claude, and `--effort` leaves
out gemini. A typed `--codex` or `--claude` shows only that agent's rows, and a
typed `--claude-profile` skips this picker. So does a list of one row.
2. **The model.**
3. **The effort**, for the agents that have one.

Each picker lists your recent choices first, newest at the top. For the model and
the effort that is per agent, followed by `default`, then a few suggestions for a
first run. The cursor starts on the
first row, so one Enter repeats the last launch. Type to filter the rows. Type a
name that no row holds and Enter uses it as typed, which is how a model that came
out yesterday is chosen. It is listed from then on. Matching is exact rather than
fuzzy for that reason: a fuzzy match finds a listed row for almost any query.
Where the name is part of a listed row, such as `gpt-5.5` beside `gpt-5.5-codex`,
Alt-Enter uses the text as typed instead of the row.

A setting that a flag on the line already gave is not asked for, so
`aid --model opus --effort max <ws>` goes straight to the prompt. A line with a
prompt on it asks for nothing, as before.

**Esc cancels the launch.** In a picker Esc and Ctrl-C are keys, not signals, so
`aid` stops the background boot itself, the same way a Ctrl-C at the prompt editor
does: its `devpod up` is killed and its staged token file is removed. The exit
status is 130.

The recent choices live in `aid-recent.tsv` in the devlaunch cache, so
`XDG_CACHE_HOME` scopes them with everything else. A file that is missing or
broken reads as no history, and never stops a launch.

With no `TERM`, with `TERM=dumb`, or on a terminal whose size reads as zero,
there are no pickers. The prompt editor still opens and every setting stays at
its default.

## The prompt editor

After the pickers, `aid` draws a `> ` prompt under one line that says what is
booting. It is a small editor of its own, not the terminal's line mode, because
the line mode could not take a paste: it holds 4096 bytes of a line, it
submitted at the first line break of a paste, and the lines of a paste that came
a moment late went on to the agent as keystrokes.

- **A paste is text, line breaks included.** The editor turns on the terminal's
bracketed paste, so it knows where a paste starts and ends, and a line break
inside one never submits. A terminal without bracketed paste still sends a
paste faster than anybody types, so an Enter with more input right behind it
is read as a line break too. Windows line ends are one break.
- **Enter submits. Alt-Enter or Ctrl-J adds a line.**
- **Backspace, Ctrl-U and Ctrl-W** delete a character, the line and a word.
There is no cursor to move: the arrow keys do nothing, rather than printing
`^[[D`.
- **An empty Enter, or Ctrl-D on nothing,** starts the agent's plain session.
- **Ctrl-C stops the boot** and exits with 130, as Esc does in a picker.

A prompt taller than the screen shows its last lines under a line that counts the
ones not shown. All of it is sent. Keys typed after the Enter are not read, so
they reach the agent.

## `aid resume`: back into a session after a restart

```bash
Expand Down
11 changes: 6 additions & 5 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ members = [
# The single source of the version (docs/rust-rewrite-plan.md: cutover ships
# 0.1.0, version read from Cargo.toml).
[workspace.package]
version = "0.58.0"
version = "0.59.0"
edition = "2024"
license = "MIT"
repository = "https://github.com/blooop/devlaunch"
Expand All @@ -36,6 +36,8 @@ toml = "0.9"
toml_edit = "0.23"
clap = { version = "4", features = ["derive"] }
skim = "0.20"
# The prompt editor's column widths. skim already brings this version in.
unicode-width = "0.2"
# The terminfo lookup skim's terminal setup makes and unwraps, made first so a
# `TERM` it would panic on, or draw nothing with, can be replaced (dl's
# `select.rs`). The version skim resolves, so the answer is the one skim would
Expand Down
Loading
Loading