feat: smart default download path + stdin/stdout support#222
Conversation
Add shared utilities for inferring file extensions from object content types when generating default download paths. This is the complement of adjustFileExtension() in runloop-fe (PR #1714), which strips extensions for mount paths — this module adds extensions for download paths. Rules: - text/binary with no suffix → .txt/.bin - gzip + .tar suffix → .tgz (not .tar.gz) - gzip/tar/tgz with mismatched suffix → append correct extension - All suffix checks are case-insensitive Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change `object download <id> <path>` to `object download <id> [path]` - When path is omitted, auto-resolve using object name/content_type via the new getDefaultDownloadPath utility - When path is `-`, write downloaded data to stdout - Warn on stderr when writing binary content types to a TTY - Structured output (-o json) goes to stderr when using stdout mode Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cc1315c to
a76fc90
Compare
- When path is `-`, read upload data from stdin - Require --name and --content-type for stdin uploads since they cannot be inferred from a filename - Update command description to document stdin support Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update both object list and detail TUI screens to use getDefaultDownloadPath, which infers file extensions from the object's content_type when pre-filling the download path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Auto-generated by docs:commands pre-push hook. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
a76fc90 to
633528d
Compare
Binary is too broad a category to infer a meaningful extension. Files with binary content type now keep their name unchanged. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When `rli object upload --name <name>` is called without any file paths, create the object via the API and print the pre-signed upload URL to stdout. This enables external upload workflows (e.g. curl) matching the frontend's "Copy URL and Close" pattern. The object stays in UPLOADING state until the user uploads and completes externally. - Change `<paths...>` to `[paths...]` (Commander optional variadic) - Skip interactive screen buffer for 0-paths mode - Default content type to "unspecified" when omitted - Add null guard for upload_url from API response Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
path - as a signifier is probably not a user friendly way to allow download to std out, maybe --stdout or something |
|
Stdin support: object upload - --name --content-type reads from stdin (cannot be mixed with other paths) this can be automatic with |
|
URL-only upload: object upload --name with no paths creates the object and prints the pre-signed upload URL to stdout, enabling external upload workflows (e.g. curl -X PUT -T file "$(rli object upload --name foo)") i dont understnad this |
the
good idea actually (will change so that it won't print the URL in this case and actually work)!
in our website, when you create an object, it doesn't ask you for the file to upload only until you press the create button. Then it gives you a pre-signed upload URL, or you can upload the object instead. rl-cli doesn't support pre-signed upload URL, so I figured that not specifying a input file to upload means one wants to do the upload URL way |
When no paths are provided and stdin is a pipe (not a terminal), upload now reads from piped stdin instead of printing the pre-signed URL. This enables `echo data | rli obj upload --name foo --content-type text` without explicitly passing `-`. Zero-byte pipes are handled correctly. Extend processUtils with Buffer support on stdout/stderr.write and AsyncIterable on stdin, so upload and download go through the mockable abstraction instead of process globals directly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🤖 I have created a release *beep* *boop* --- ## [1.17.0](v1.16.0...v1.17.0) (2026-05-12) ### Features * add --public flag to agent create, fix object upload --public ([#219](#219)) ([6e7a8b3](6e7a8b3)) * add clipboard keybinds to detail screens ([#231](#231)) ([83874ca](83874ca)) * add TUI features and fix benchmark pagination total count ([#230](#230)) ([7565d45](7565d45)) * agent object picker, multi-mount support, and TUI improvements ([#217](#217)) ([dbe2a5c](dbe2a5c)) * pty support ([#234](#234)) ([3cfd720](3cfd720)) * smart default download path + stdin/stdout support ([#222](#222)) ([419a961](419a961)) * support multi-path tar/tgz archive creation in obj upload ([#220](#220)) ([3528701](3528701)) ### Bug Fixes * menu header clipping and breadcrumb hyperlink ([#221](#221)) ([3ef6271](3ef6271)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Summary
object download <id> [path]— when path is omitted, auto-generates from object name + content_type with smart extension inference. Use-to write to stdout.object upload - --name <name> --content-type <type>reads from stdin. Also auto-detected when stdin is piped with no paths (e.g.echo data | rli obj upload --name foo --content-type text). Zero-byte pipes upload an empty object rather than printing the URL.object upload --name <name>with no paths and no piped stdin creates the object and prints the pre-signed upload URL to stdout, enabling external upload workflows (e.g.curl -X PUT -T file "$(rli object upload --name foo)")stdout.write/stderr.writeacceptstring | Buffer(wasstringonly), andstdinis nowAsyncIterable<Buffer>— upload and download go through the mockable abstraction instead ofprocessglobals directlyExtension inference rules (case-insensitive)
text.txtbinarygzip.gz.gz.tar→.tgztar.tar.tartgz.tgz.tgzThis is the complement of
adjustFileExtension()from runloop-fe PR #1714 — that strips extensions for mount paths (post-decompression), this adds extensions for download paths.Test plan
inferDownloadExtensionandgetDefaultDownloadPathpass-path and piped stdin auto-detection, including 0-byte pipes)rl object download <id>without path → verify auto-generated filename has correct extensionrl object download <id> custom.out→ verify explicit path still worksrl object download <id> -→ verify data goes to stdout; verify TTY warning for binary typesecho "hello" | rl object upload --name test --content-type text→ verify upload from stdin (no-needed)echo -n '' | rl object upload --name test --content-type text→ verify 0-byte upload (not URL mode)rl object upload - --name test --content-type text→ verify explicit stdin uploadrl object upload --name test-url --content-type text→ verify prints upload URL (no pipe)🤖 Generated with Claude Code