devlaunch 0.0.6__tar.gz → 0.0.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -50,6 +50,7 @@ coverage.xml
50
50
  .hypothesis/
51
51
  .pytest_cache/
52
52
  cover/
53
+ test/docker/results/
53
54
 
54
55
  # Translations
55
56
  *.mo
@@ -178,16 +179,8 @@ test_suite_analysis/metadata.json
178
179
  # Claude Code local settings (personal, not shared)
179
180
  .claude/settings.local.json
180
181
 
181
- # Ralph autonomous agent state files
182
- .call_count
183
- .circuit_breaker_history
184
- .circuit_breaker_state
185
- .exit_signals
186
- .last_reset
187
- .ralph_session
188
- .ralph_session_history
189
- .response_analysis
190
182
  .claude_session_id
191
- progress.json
192
- status.json
193
183
  logs/
184
+
185
+ # uv is not this project's package manager (pixi.lock is authoritative)
186
+ uv.lock
@@ -1,3 +1,26 @@
1
+ Metadata-Version: 2.4
2
+ Name: devlaunch
3
+ Version: 0.0.8
4
+ Summary: DevLaunch - A streamlined CLI for devpod workspaces
5
+ Project-URL: Source, https://github.com/blooop/devlaunch
6
+ Project-URL: Home, https://github.com/blooop/devlaunch
7
+ Author-email: Austin Gregg-Smith <blooop@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Requires-Dist: iterfzf>=1.0.0
11
+ Requires-Dist: tomli-w>=1.0.0
12
+ Requires-Dist: tomli>=2.0.0
13
+ Provides-Extra: test
14
+ Requires-Dist: coverage<=7.14.1,>=7.5.4; extra == 'test'
15
+ Requires-Dist: hypothesis<=6.155.1,>=6.104.2; extra == 'test'
16
+ Requires-Dist: prek<0.5.0,>=0.2.28; extra == 'test'
17
+ Requires-Dist: pylint<=4.0.5,>=3.2.5; extra == 'test'
18
+ Requires-Dist: pytest-cov<=7.1.0,>=4.1; extra == 'test'
19
+ Requires-Dist: pytest<=9.0.3,>=7.4; extra == 'test'
20
+ Requires-Dist: ruff<=0.15.15,>=0.5.0; extra == 'test'
21
+ Requires-Dist: ty<=0.0.19,>=0.0.12; extra == 'test'
22
+ Description-Content-Type: text/markdown
23
+
1
24
  # devlaunch
2
25
 
3
26
  A streamlined CLI for [devpod](https://devpod.sh) with intuitive autocomplete and fzf fuzzy selection.
@@ -10,7 +33,7 @@ A streamlined CLI for [devpod](https://devpod.sh) with intuitive autocomplete an
10
33
  [![GitHub pull-requests merged](https://badgen.net/github/merged-prs/blooop/devlaunch)](https://github.com/blooop/devlaunch/pulls?q=is%3Amerged)
11
34
  [![GitHub release](https://img.shields.io/github/release/blooop/devlaunch.svg)](https://GitHub.com/blooop/devlaunch/releases/)
12
35
  [![PyPI](https://img.shields.io/pypi/v/devlaunch)](https://pypi.org/project/devlaunch/)
13
- [![Conda](https://img.shields.io/badge/conda-v0.0.5-brightgreen?logo=anaconda)](https://prefix.dev/channels/blooop/packages/devlaunch)
36
+ [![Conda](https://img.shields.io/badge/conda-v0.0.8-brightgreen?logo=anaconda)](https://prefix.dev/channels/blooop/packages/devlaunch)
14
37
  [![License](https://img.shields.io/github/license/blooop/devlaunch)](https://opensource.org/license/mit/)
15
38
  [![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)](https://www.python.org/downloads/)
16
39
  [![Pixi Badge](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/prefix-dev/pixi/main/assets/badge/v0.json)](https://pixi.sh)
@@ -32,6 +55,8 @@ pip install devlaunch
32
55
  ```
33
56
 
34
57
  Note: When using pip, you must install [devpod](https://devpod.sh/docs/getting-started/install) separately.
58
+ If `devpod` is not on `PATH`, every command that needs it prints a single install hint on stderr and exits `127`
59
+ (the shell's "command not found" code). `dl --help` and `dl --version` keep working without it.
35
60
 
36
61
  ### Shell Completions
37
62
 
@@ -72,12 +97,69 @@ dl ./path # Create from local path
72
97
  | `dl <user/repo> reset` | Clean slate (remove all, recreate) |
73
98
  | `dl <user/repo> -- <command>` | Run shell command in workspace |
74
99
 
100
+ ## Options
101
+
102
+ | Option | Description |
103
+ |--------|-------------|
104
+ | `--devcontainer <variant\|path>` | Use a non-default `devcontainer.json`. A bare name means `.devcontainer/<name>/devcontainer.json`. Stored with the workspace, so pass it once. |
105
+
106
+ Projects with demanding devcontainers — several variants, compose sidecars, or a
107
+ host-side `initializeCommand` that has to tell branch workspaces apart — are
108
+ covered in [docs/devcontainer-projects.md](docs/devcontainer-projects.md).
109
+
110
+ ## GitHub Authentication
111
+
112
+ Every workspace `dl` opens inherits the host's GitHub login, so `gh` is already
113
+ authenticated inside the container and the devcontainer.json does not have to
114
+ arrange anything for it. devpod forwards the ssh agent and git credentials on its
115
+ own, but nothing else carries `gh`.
116
+
117
+ devlaunch takes the token from `GH_TOKEN`, `GITHUB_TOKEN`, or `gh auth token`,
118
+ whichever answers first, and hands it to the container as `GH_TOKEN`. That reaches
119
+ any image and any container user, unlike a bind-mount of `~/.config/gh`, and it
120
+ works whether the host keeps its token in `hosts.yml` or in a keyring. The token
121
+ is passed to devpod through a private file and through devpod's own environment,
122
+ never on a command line, so it does not appear in `ps`. The container still needs
123
+ `gh` installed for the login to be of any use. Check a workspace with:
124
+
125
+ ```bash
126
+ dl <workspace> -- gh auth status
127
+ ```
128
+
129
+ ### Who gets the token
130
+
131
+ Everything running in the container does — including a `postCreateCommand` from a
132
+ repo you did not write. `dl someone/repo` builds and runs that project's
133
+ devcontainer with your GitHub token in its environment, and a `gh auth login` token
134
+ usually carries `repo`, `workflow`, `gist` and `read:org` scopes. devpod already
135
+ forwards the ssh agent to every workspace, so this is not a new trust boundary, but
136
+ it is a wider one. Skip it for a repo you have not read:
137
+
138
+ ```bash
139
+ DEVLAUNCH_NO_GH_TOKEN=1 dl someone/repo
140
+ ```
141
+
142
+ | Variable | Description |
143
+ |----------|-------------|
144
+ | `DEVLAUNCH_NO_GH_TOKEN=1` | Do not forward the host's GitHub login into workspaces |
145
+
146
+ ### When the token changes
147
+
148
+ `dl` refreshes the token on every start, so rotating it on the host is enough for
149
+ any workspace that gets started or restarted afterwards. Attaching to a workspace
150
+ that is *already running* skips that step, and the token it was given at startup
151
+ stays in place — including one it was given before you set
152
+ `DEVLAUNCH_NO_GH_TOKEN`. Run `dl <workspace> restart` to replace it.
153
+
75
154
  ## Global Commands
76
155
 
77
156
  | Command | Description |
78
157
  |---------|-------------|
79
158
  | `dl --ls` | List all workspaces |
80
159
  | `dl --install` | Install shell completions |
160
+ | `dl --purge [-y]` | Remove all devlaunch data |
161
+ | `dl --prune-worktrees [days]` | Remove unused worktrees (default: 30 days) |
162
+ | `dl --refresh` | Refresh completion cache |
81
163
  | `dl --help, -h` | Show this help |
82
164
  | `dl --version` | Show version |
83
165
 
@@ -102,6 +184,31 @@ dl blooop/devlaunch stop # Stop workspace
102
184
  - **Branch Support**: Specify branches with `owner/repo@branch` syntax
103
185
  - **Fast Autocomplete**: Completion cache for ~3ms response time (vs ~700ms without cache)
104
186
 
187
+ ## Worktree Backend
188
+
189
+ For git repositories, devlaunch uses an efficient worktree backend by default:
190
+
191
+ - **Efficient Storage**: Repos are cloned once to `~/.cache/devlaunch/repos/owner/repo/`, then git worktrees are created for each branch
192
+ - **Shared Git Objects**: All branches share git objects, saving disk space
193
+ - **Lazy Fetch**: Remote updates are only fetched if the configured interval has elapsed (default: 1 hour)
194
+
195
+ ### Container Sharing Mode
196
+
197
+ Use `--shared` to share a single container across multiple branches of the same repo:
198
+
199
+ ```bash
200
+ dl --shared owner/repo@branch1 # Creates container "owner-repo"
201
+ dl --shared owner/repo@branch2 # Reuses "owner-repo" container
202
+ ```
203
+
204
+ ### Pre-warming
205
+
206
+ Use `--warm` to prepare a workspace without attaching a shell:
207
+
208
+ ```bash
209
+ dl --warm owner/repo@branch # Creates container in background
210
+ ```
211
+
105
212
  ## Shell Completion
106
213
 
107
214
  After running `dl --install`, you get intelligent tab completion:
@@ -1,24 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: devlaunch
3
- Version: 0.0.6
4
- Summary: DevLaunch - A streamlined CLI for devpod workspaces
5
- Project-URL: Source, https://github.com/blooop/devlaunch
6
- Project-URL: Home, https://github.com/blooop/devlaunch
7
- Author-email: Austin Gregg-Smith <blooop@gmail.com>
8
- License-Expression: MIT
9
- License-File: LICENSE
10
- Requires-Dist: iterfzf>=1.0.0
11
- Provides-Extra: test
12
- Requires-Dist: coverage<=7.13.1,>=7.5.4; extra == 'test'
13
- Requires-Dist: hypothesis<=6.150.2,>=6.104.2; extra == 'test'
14
- Requires-Dist: prek<0.3.0,>=0.2.28; extra == 'test'
15
- Requires-Dist: pylint<=4.0.4,>=3.2.5; extra == 'test'
16
- Requires-Dist: pytest-cov<=7.0.0,>=4.1; extra == 'test'
17
- Requires-Dist: pytest<=9.0.2,>=7.4; extra == 'test'
18
- Requires-Dist: ruff<=0.14.13,>=0.5.0; extra == 'test'
19
- Requires-Dist: ty<=0.0.12,>=0.0.12; extra == 'test'
20
- Description-Content-Type: text/markdown
21
-
22
1
  # devlaunch
23
2
 
24
3
  A streamlined CLI for [devpod](https://devpod.sh) with intuitive autocomplete and fzf fuzzy selection.
@@ -31,7 +10,7 @@ A streamlined CLI for [devpod](https://devpod.sh) with intuitive autocomplete an
31
10
  [![GitHub pull-requests merged](https://badgen.net/github/merged-prs/blooop/devlaunch)](https://github.com/blooop/devlaunch/pulls?q=is%3Amerged)
32
11
  [![GitHub release](https://img.shields.io/github/release/blooop/devlaunch.svg)](https://GitHub.com/blooop/devlaunch/releases/)
33
12
  [![PyPI](https://img.shields.io/pypi/v/devlaunch)](https://pypi.org/project/devlaunch/)
34
- [![Conda](https://img.shields.io/badge/conda-v0.0.5-brightgreen?logo=anaconda)](https://prefix.dev/channels/blooop/packages/devlaunch)
13
+ [![Conda](https://img.shields.io/badge/conda-v0.0.8-brightgreen?logo=anaconda)](https://prefix.dev/channels/blooop/packages/devlaunch)
35
14
  [![License](https://img.shields.io/github/license/blooop/devlaunch)](https://opensource.org/license/mit/)
36
15
  [![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)](https://www.python.org/downloads/)
37
16
  [![Pixi Badge](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/prefix-dev/pixi/main/assets/badge/v0.json)](https://pixi.sh)
@@ -53,6 +32,8 @@ pip install devlaunch
53
32
  ```
54
33
 
55
34
  Note: When using pip, you must install [devpod](https://devpod.sh/docs/getting-started/install) separately.
35
+ If `devpod` is not on `PATH`, every command that needs it prints a single install hint on stderr and exits `127`
36
+ (the shell's "command not found" code). `dl --help` and `dl --version` keep working without it.
56
37
 
57
38
  ### Shell Completions
58
39
 
@@ -93,12 +74,69 @@ dl ./path # Create from local path
93
74
  | `dl <user/repo> reset` | Clean slate (remove all, recreate) |
94
75
  | `dl <user/repo> -- <command>` | Run shell command in workspace |
95
76
 
77
+ ## Options
78
+
79
+ | Option | Description |
80
+ |--------|-------------|
81
+ | `--devcontainer <variant\|path>` | Use a non-default `devcontainer.json`. A bare name means `.devcontainer/<name>/devcontainer.json`. Stored with the workspace, so pass it once. |
82
+
83
+ Projects with demanding devcontainers — several variants, compose sidecars, or a
84
+ host-side `initializeCommand` that has to tell branch workspaces apart — are
85
+ covered in [docs/devcontainer-projects.md](docs/devcontainer-projects.md).
86
+
87
+ ## GitHub Authentication
88
+
89
+ Every workspace `dl` opens inherits the host's GitHub login, so `gh` is already
90
+ authenticated inside the container and the devcontainer.json does not have to
91
+ arrange anything for it. devpod forwards the ssh agent and git credentials on its
92
+ own, but nothing else carries `gh`.
93
+
94
+ devlaunch takes the token from `GH_TOKEN`, `GITHUB_TOKEN`, or `gh auth token`,
95
+ whichever answers first, and hands it to the container as `GH_TOKEN`. That reaches
96
+ any image and any container user, unlike a bind-mount of `~/.config/gh`, and it
97
+ works whether the host keeps its token in `hosts.yml` or in a keyring. The token
98
+ is passed to devpod through a private file and through devpod's own environment,
99
+ never on a command line, so it does not appear in `ps`. The container still needs
100
+ `gh` installed for the login to be of any use. Check a workspace with:
101
+
102
+ ```bash
103
+ dl <workspace> -- gh auth status
104
+ ```
105
+
106
+ ### Who gets the token
107
+
108
+ Everything running in the container does — including a `postCreateCommand` from a
109
+ repo you did not write. `dl someone/repo` builds and runs that project's
110
+ devcontainer with your GitHub token in its environment, and a `gh auth login` token
111
+ usually carries `repo`, `workflow`, `gist` and `read:org` scopes. devpod already
112
+ forwards the ssh agent to every workspace, so this is not a new trust boundary, but
113
+ it is a wider one. Skip it for a repo you have not read:
114
+
115
+ ```bash
116
+ DEVLAUNCH_NO_GH_TOKEN=1 dl someone/repo
117
+ ```
118
+
119
+ | Variable | Description |
120
+ |----------|-------------|
121
+ | `DEVLAUNCH_NO_GH_TOKEN=1` | Do not forward the host's GitHub login into workspaces |
122
+
123
+ ### When the token changes
124
+
125
+ `dl` refreshes the token on every start, so rotating it on the host is enough for
126
+ any workspace that gets started or restarted afterwards. Attaching to a workspace
127
+ that is *already running* skips that step, and the token it was given at startup
128
+ stays in place — including one it was given before you set
129
+ `DEVLAUNCH_NO_GH_TOKEN`. Run `dl <workspace> restart` to replace it.
130
+
96
131
  ## Global Commands
97
132
 
98
133
  | Command | Description |
99
134
  |---------|-------------|
100
135
  | `dl --ls` | List all workspaces |
101
136
  | `dl --install` | Install shell completions |
137
+ | `dl --purge [-y]` | Remove all devlaunch data |
138
+ | `dl --prune-worktrees [days]` | Remove unused worktrees (default: 30 days) |
139
+ | `dl --refresh` | Refresh completion cache |
102
140
  | `dl --help, -h` | Show this help |
103
141
  | `dl --version` | Show version |
104
142
 
@@ -123,6 +161,31 @@ dl blooop/devlaunch stop # Stop workspace
123
161
  - **Branch Support**: Specify branches with `owner/repo@branch` syntax
124
162
  - **Fast Autocomplete**: Completion cache for ~3ms response time (vs ~700ms without cache)
125
163
 
164
+ ## Worktree Backend
165
+
166
+ For git repositories, devlaunch uses an efficient worktree backend by default:
167
+
168
+ - **Efficient Storage**: Repos are cloned once to `~/.cache/devlaunch/repos/owner/repo/`, then git worktrees are created for each branch
169
+ - **Shared Git Objects**: All branches share git objects, saving disk space
170
+ - **Lazy Fetch**: Remote updates are only fetched if the configured interval has elapsed (default: 1 hour)
171
+
172
+ ### Container Sharing Mode
173
+
174
+ Use `--shared` to share a single container across multiple branches of the same repo:
175
+
176
+ ```bash
177
+ dl --shared owner/repo@branch1 # Creates container "owner-repo"
178
+ dl --shared owner/repo@branch2 # Reuses "owner-repo" container
179
+ ```
180
+
181
+ ### Pre-warming
182
+
183
+ Use `--warm` to prepare a workspace without attaching a shell:
184
+
185
+ ```bash
186
+ dl --warm owner/repo@branch # Creates container in background
187
+ ```
188
+
126
189
  ## Shell Completion
127
190
 
128
191
  After running `dl --install`, you get intelligent tab completion:
@@ -45,13 +45,32 @@ _dl_completion() {
45
45
  fi
46
46
 
47
47
  # Global command options (only valid as first arg)
48
- local global_opts="--ls --install --help -h --version"
48
+ local global_opts="--ls --install --help -h --version --devcontainer"
49
49
 
50
50
  # Workspace subcommands
51
51
  local ws_cmds="stop rm code restart recreate reset --"
52
52
 
53
+ # Options that take a value; a variant name or a path follows them.
54
+ local value_opts="--devcontainer"
55
+
56
+ # After --devcontainer, offer the repo's variant directories (and paths).
57
+ if [[ " ${value_opts} " == *" ${prev} "* ]]; then
58
+ local variants=""
59
+ if [[ -d .devcontainer ]]; then
60
+ local d
61
+ for d in .devcontainer/*/devcontainer.json; do
62
+ [[ -f "$d" ]] || continue
63
+ d="${d#.devcontainer/}"
64
+ variants+=" ${d%/devcontainer.json}"
65
+ done
66
+ fi
67
+ COMPREPLY=( $(compgen -W "${variants}" -- ${cur}) )
68
+ compopt -o default 2>/dev/null
69
+ return 0
70
+ fi
71
+
53
72
  # Cache file location (honors XDG_CACHE_HOME)
54
- local cache_dir="${XDG_CACHE_HOME:-$HOME/.cache}/dl"
73
+ local cache_dir="${XDG_CACHE_HOME:-$HOME/.cache}/devlaunch"
55
74
  local cache_file="$cache_dir/completions.bash"
56
75
 
57
76
  # Initialize completion variables