Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
0875d6c
feat: binary-only parameters become CLI flags that take filenames only
stainless-app[bot] Apr 2, 2026
5edec04
feat: better error message if scheme forgotten in CLI `*_BASE_URL`/`-…
stainless-app[bot] Apr 2, 2026
7da15e2
feat: allow `-` as value representing stdin to binary-only file param…
stainless-app[bot] Apr 2, 2026
ba52bbe
chore: switch some CLI Go tests from `os.Chdir` to `t.Chdir`
stainless-app[bot] Apr 2, 2026
7d1a565
chore: mark all CLI-related tests in Go with `t.Parallel()`
stainless-app[bot] Apr 3, 2026
6073189
chore: modify CLI tests to inject stdout so mutating `os.Stdout` isn'…
stainless-app[bot] Apr 3, 2026
87613ec
fix: fall back to main branch if linking fails in CI
stainless-app[bot] Apr 6, 2026
575418c
fix: fix quoting typo
stainless-app[bot] Apr 6, 2026
c913d27
chore(cli): let `--format raw` be used in conjunction with `--transform`
stainless-app[bot] Apr 8, 2026
c64d07c
chore(cli): additional test cases for `ShowJSONIterator`
stainless-app[bot] Apr 9, 2026
547c3e1
fix: fix for failing to drop invalid module replace in link script
stainless-app[bot] Apr 9, 2026
6d33e1a
chore: add documentation for ./scripts/link
stainless-app[bot] Apr 13, 2026
3b62e8d
chore(cli): fall back to JSON when using default "explore" with non-TTY
stainless-app[bot] Apr 14, 2026
2a1a9d8
chore(ci): remove release-doctor workflow
stainless-app[bot] Apr 14, 2026
5a62637
feat(cli): alias parameters in data with `x-stainless-cli-data-alias`
stainless-app[bot] Apr 14, 2026
86bdc85
chore(cli): switch long lists of positional args over to param structs
stainless-app[bot] Apr 15, 2026
cf0bd76
chore(ci): support manually triggering release workflow
stainless-app[bot] Apr 16, 2026
21ec6dd
feat(cli): send filename and content type when reading input from files
stainless-app[bot] Apr 16, 2026
d7201c6
feat(cli): add `--raw-output`/`-r` option to print raw (non-JSON) str…
stainless-app[bot] Apr 16, 2026
158e705
chore(ci): add github env support for goreleaser
stainless-app[bot] Apr 17, 2026
a19782c
chore(cli): use `ShowJSONOpts` as argument to `formatJSON` instead of…
stainless-app[bot] Apr 17, 2026
544f575
chore(tests): bump steady to v0.22.1
stainless-app[bot] Apr 17, 2026
bcc4657
chore: add install.ps1 for Windows (#14)
AgentWings Apr 21, 2026
6fbf8f5
chore(internal): more robust bootstrap script
stainless-app[bot] Apr 22, 2026
4a34328
chore(cli): default to jsonl format
stainless-app[bot] Apr 22, 2026
7385da5
release: 0.2.0
stainless-app[bot] Apr 22, 2026
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
2 changes: 2 additions & 0 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ on:
push:
tags:
- "v*"
workflow_dispatch: {}
jobs:
goreleaser:
runs-on: ubuntu-latest
environment: production
steps:
- name: Checkout
uses: actions/checkout@v6
Expand Down
20 changes: 0 additions & 20 deletions .github/workflows/release-doctor.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.1.0"
".": "0.2.0"
}
2 changes: 1 addition & 1 deletion .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 29
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/dedalus-labs%2Fdedalus-018f649c40452f64a7454d2841a410297ef931793d4f6dbfebab541b060a2b21.yml
openapi_spec_hash: 7fd462f39c9dcf835904c06fea51ef46
config_hash: 89f7a7d317d1c89fd73ebaf74c5918cf
config_hash: 816359ffd81767484efabdc39744bf77
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,45 @@
# Changelog

## 0.2.0 (2026-04-22)

Full Changelog: [v0.1.0...v0.2.0](https://github.com/dedalus-labs/dedalus-cli/compare/v0.1.0...v0.2.0)

### Features

* allow `-` as value representing stdin to binary-only file parameters in CLIs ([7da15e2](https://github.com/dedalus-labs/dedalus-cli/commit/7da15e2f6c1d715fc55e26fa2bd7be95eba5ff0e))
* better error message if scheme forgotten in CLI `*_BASE_URL`/`--base-url` ([5edec04](https://github.com/dedalus-labs/dedalus-cli/commit/5edec044b3dda53824fa2981ffe94b557fc3ce65))
* binary-only parameters become CLI flags that take filenames only ([0875d6c](https://github.com/dedalus-labs/dedalus-cli/commit/0875d6c6e2426509185f56022f763b2927b07af2))
* **cli:** add `--raw-output`/`-r` option to print raw (non-JSON) strings ([d7201c6](https://github.com/dedalus-labs/dedalus-cli/commit/d7201c60f8794ec1c0fe6fcfdd85ece68996c7f9))
* **cli:** alias parameters in data with `x-stainless-cli-data-alias` ([5a62637](https://github.com/dedalus-labs/dedalus-cli/commit/5a6263723604bb1a35fbc53c5f99e7fd7fd0463a))
* **cli:** send filename and content type when reading input from files ([21ec6dd](https://github.com/dedalus-labs/dedalus-cli/commit/21ec6dd8f92d9feafd9e43abd08f9f9fddddf64a))


### Bug Fixes

* fall back to main branch if linking fails in CI ([87613ec](https://github.com/dedalus-labs/dedalus-cli/commit/87613ecfe5030a1a76be6dcfdb29161ff58a2550))
* fix for failing to drop invalid module replace in link script ([547c3e1](https://github.com/dedalus-labs/dedalus-cli/commit/547c3e146cf035cee1b466a85a06529c0117edf2))
* fix quoting typo ([575418c](https://github.com/dedalus-labs/dedalus-cli/commit/575418c4b4a58aa2496fef880d038c59da9e7fb8))


### Chores

* add documentation for ./scripts/link ([6d33e1a](https://github.com/dedalus-labs/dedalus-cli/commit/6d33e1af76dc27b3c70c252b1d28894050b0a7dc))
* add install.ps1 for Windows ([#14](https://github.com/dedalus-labs/dedalus-cli/issues/14)) ([bcc4657](https://github.com/dedalus-labs/dedalus-cli/commit/bcc46570a2f7da106880f864936e0e95bf0cb52b))
* **ci:** add github env support for goreleaser ([158e705](https://github.com/dedalus-labs/dedalus-cli/commit/158e705d900c2cda1e52b8984e821044a7ac38fe))
* **ci:** remove release-doctor workflow ([2a1a9d8](https://github.com/dedalus-labs/dedalus-cli/commit/2a1a9d8c0b94a6c06c2ab828c1c8a6fbf1382f39))
* **ci:** support manually triggering release workflow ([cf0bd76](https://github.com/dedalus-labs/dedalus-cli/commit/cf0bd764b2563d4ab838a99c6ebbf1c45b7ae3e3))
* **cli:** additional test cases for `ShowJSONIterator` ([c64d07c](https://github.com/dedalus-labs/dedalus-cli/commit/c64d07ce2e2819b489ee60e500379bb3d3b4fc67))
* **cli:** default to jsonl format ([4a34328](https://github.com/dedalus-labs/dedalus-cli/commit/4a3432861ff1ba54f4d1b13d7481d9bef18ceb49))
* **cli:** fall back to JSON when using default "explore" with non-TTY ([3b62e8d](https://github.com/dedalus-labs/dedalus-cli/commit/3b62e8d1b6b6305b4cb36aec45abf4f88d3b6a2c))
* **cli:** let `--format raw` be used in conjunction with `--transform` ([c913d27](https://github.com/dedalus-labs/dedalus-cli/commit/c913d2739ca2f58b5498e7aea3b644b4068a1fe8))
* **cli:** switch long lists of positional args over to param structs ([86bdc85](https://github.com/dedalus-labs/dedalus-cli/commit/86bdc85c82d6f81d2d0614cb7e705b55ece80fe7))
* **cli:** use `ShowJSONOpts` as argument to `formatJSON` instead of many positionals ([a19782c](https://github.com/dedalus-labs/dedalus-cli/commit/a19782cd7fed5d41883ed7800b6d2c4c0bde7ced))
* **internal:** more robust bootstrap script ([6fbf8f5](https://github.com/dedalus-labs/dedalus-cli/commit/6fbf8f509d44d42ad50ccc7cb59b62d443ff6a7e))
* mark all CLI-related tests in Go with `t.Parallel()` ([7d1a565](https://github.com/dedalus-labs/dedalus-cli/commit/7d1a565862ae3190b48e40ff892073eca20a5480))
* modify CLI tests to inject stdout so mutating `os.Stdout` isn't necessary ([6073189](https://github.com/dedalus-labs/dedalus-cli/commit/6073189d85a64ac3d53c0f8b08899a2b617740b8))
* switch some CLI Go tests from `os.Chdir` to `t.Chdir` ([ba52bbe](https://github.com/dedalus-labs/dedalus-cli/commit/ba52bbea1667ea208f169c8b1b768e714ad3eeb7))
* **tests:** bump steady to v0.22.1 ([544f575](https://github.com/dedalus-labs/dedalus-cli/commit/544f575622b41ceb09a9491a1c28898e09142757))

## 0.1.0 (2026-04-02)

Full Changelog: [v0.0.4...v0.1.0](https://github.com/dedalus-labs/dedalus-cli/compare/v0.0.4...v0.1.0)
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,23 @@ base64-encoding). Note that absolute paths will begin with `@file://` or
```bash
dedalus <command> --arg @data://file.txt
```

## Linking different Go SDK versions

You can link the CLI against a different version of the Dedalus Go SDK
for development purposes using the `./scripts/link` script.

To link to a specific version from a repository (version can be a branch,
git tag, or commit hash):

```bash
./scripts/link github.com/org/repo@version
```

To link to a local copy of the SDK:

```bash
./scripts/link ../path/to/dedalus-go
```

If you run the link script without any arguments, it will default to `../dedalus-go`.
17 changes: 0 additions & 17 deletions bin/check-release-environment

This file was deleted.

14 changes: 13 additions & 1 deletion cmd/dedalus/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ func main() {
prepareForAutocomplete(app)
}

if baseURL, ok := os.LookupEnv("DEDALUS_BASE_URL"); ok {
if err := cmd.ValidateBaseURL(baseURL, "DEDALUS_BASE_URL"); err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)
}
}

if err := app.Run(context.Background(), os.Args); err != nil {
exitCode := 1

Expand All @@ -36,7 +43,12 @@ func main() {
fmt.Fprintf(os.Stderr, "%s %q: %d %s\n", apierr.Request.Method, apierr.Request.URL, apierr.Response.StatusCode, http.StatusText(apierr.Response.StatusCode))
format := app.String("format-error")
json := gjson.Parse(apierr.RawJSON())
show_err := cmd.ShowJSON(os.Stdout, "Error", json, format, app.String("transform-error"))
show_err := cmd.ShowJSON(json, cmd.ShowJSONOpts{
ExplicitFormat: app.IsSet("format-error"),
Format: format,
Title: "Error",
Transform: app.String("transform-error"),
})
if show_err != nil {
// Just print the original error:
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
Expand Down
4 changes: 4 additions & 0 deletions internal/apiform/form_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,12 @@ var tests = map[string]struct {
}

func TestEncode(t *testing.T) {
t.Parallel()

for name, test := range tests {
t.Run(name, func(t *testing.T) {
t.Parallel()

buf := bytes.NewBuffer(nil)
writer := multipart.NewWriter(buf)
writer.SetBoundary("xxx")
Expand Down
4 changes: 4 additions & 0 deletions internal/apiquery/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
)

func TestEncode(t *testing.T) {
t.Parallel()

tests := map[string]struct {
val any
settings QuerySettings
Expand Down Expand Up @@ -114,6 +116,8 @@ func TestEncode(t *testing.T) {

for name, test := range tests {
t.Run(name, func(t *testing.T) {
t.Parallel()

query := map[string]any{"query": test.val}
values, err := MarshalWithSettings(query, test.settings)
if err != nil {
Expand Down
40 changes: 40 additions & 0 deletions internal/autocomplete/autocomplete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
)

func TestGetCompletions_EmptyArgs(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{Name: "generate", Usage: "Generate SDK"},
Expand All @@ -26,6 +28,8 @@ func TestGetCompletions_EmptyArgs(t *testing.T) {
}

func TestGetCompletions_SubcommandPrefix(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{Name: "generate", Usage: "Generate SDK"},
Expand All @@ -43,6 +47,8 @@ func TestGetCompletions_SubcommandPrefix(t *testing.T) {
}

func TestGetCompletions_HiddenCommand(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{Name: "visible", Usage: "Visible command"},
Expand All @@ -57,6 +63,8 @@ func TestGetCompletions_HiddenCommand(t *testing.T) {
}

func TestGetCompletions_NestedSubcommand(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{
Expand All @@ -79,6 +87,8 @@ func TestGetCompletions_NestedSubcommand(t *testing.T) {
}

func TestGetCompletions_FlagCompletion(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{
Expand All @@ -102,6 +112,8 @@ func TestGetCompletions_FlagCompletion(t *testing.T) {
}

func TestGetCompletions_ShortFlagCompletion(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{
Expand All @@ -123,6 +135,8 @@ func TestGetCompletions_ShortFlagCompletion(t *testing.T) {
}

func TestGetCompletions_FileFlagBehavior(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{
Expand All @@ -142,6 +156,8 @@ func TestGetCompletions_FileFlagBehavior(t *testing.T) {
}

func TestGetCompletions_NonBoolFlagValue(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{
Expand All @@ -161,6 +177,8 @@ func TestGetCompletions_NonBoolFlagValue(t *testing.T) {
}

func TestGetCompletions_BoolFlagDoesNotBlockCompletion(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{
Expand All @@ -185,6 +203,8 @@ func TestGetCompletions_BoolFlagDoesNotBlockCompletion(t *testing.T) {
}

func TestGetCompletions_ColonCommands_NoColonTyped(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{Name: "config:get", Usage: "Get config value"},
Expand All @@ -202,6 +222,8 @@ func TestGetCompletions_ColonCommands_NoColonTyped(t *testing.T) {
}

func TestGetCompletions_ColonCommands_ColonTyped_Bash(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{Name: "config:get", Usage: "Get config value"},
Expand All @@ -221,6 +243,8 @@ func TestGetCompletions_ColonCommands_ColonTyped_Bash(t *testing.T) {
}

func TestGetCompletions_ColonCommands_ColonTyped_Zsh(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{Name: "config:get", Usage: "Get config value"},
Expand All @@ -240,6 +264,8 @@ func TestGetCompletions_ColonCommands_ColonTyped_Zsh(t *testing.T) {
}

func TestGetCompletions_BashStyleColonCompletion(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{Name: "config:get", Usage: "Get config value"},
Expand All @@ -257,6 +283,8 @@ func TestGetCompletions_BashStyleColonCompletion(t *testing.T) {
}

func TestGetCompletions_BashStyleColonCompletion_NoMatch(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{Name: "config:get", Usage: "Get config value"},
Expand All @@ -271,6 +299,8 @@ func TestGetCompletions_BashStyleColonCompletion_NoMatch(t *testing.T) {
}

func TestGetCompletions_ZshStyleColonCompletion(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{Name: "config:get", Usage: "Get config value"},
Expand All @@ -287,6 +317,8 @@ func TestGetCompletions_ZshStyleColonCompletion(t *testing.T) {
}

func TestGetCompletions_MixedColonAndRegularCommands(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{Name: "generate", Usage: "Generate SDK"},
Expand All @@ -305,6 +337,8 @@ func TestGetCompletions_MixedColonAndRegularCommands(t *testing.T) {
}

func TestGetCompletions_FlagWithBoolFlagSkipsValue(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{
Expand All @@ -329,6 +363,8 @@ func TestGetCompletions_FlagWithBoolFlagSkipsValue(t *testing.T) {
}

func TestGetCompletions_MultipleFlagsBeforeSubcommand(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{
Expand All @@ -353,6 +389,8 @@ func TestGetCompletions_MultipleFlagsBeforeSubcommand(t *testing.T) {
}

func TestGetCompletions_CommandAliases(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{Name: "generate", Aliases: []string{"gen", "g"}, Usage: "Generate SDK"},
Expand All @@ -372,6 +410,8 @@ func TestGetCompletions_CommandAliases(t *testing.T) {
}

func TestGetCompletions_AllFlagsWhenNoPrefix(t *testing.T) {
t.Parallel()

root := &cli.Command{
Commands: []*cli.Command{
{
Expand Down
6 changes: 6 additions & 0 deletions internal/jsonview/explorer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
)

func TestNavigateForward_EmptyRowData(t *testing.T) {
t.Parallel()

// An empty JSON array produces a TableView with no rows.
emptyArray := gjson.Parse("[]")
view, err := newTableView("", emptyArray, false)
Expand Down Expand Up @@ -38,6 +40,8 @@ type rawJSONItem struct {
func (r rawJSONItem) RawJSON() string { return r.raw }

func TestMarshalItemsToJSONArray_WithHasRawJSON(t *testing.T) {
t.Parallel()

items := []any{
rawJSONItem{raw: `{"id":1,"name":"alice"}`},
rawJSONItem{raw: `{"id":2,"name":"bob"}`},
Expand All @@ -49,6 +53,8 @@ func TestMarshalItemsToJSONArray_WithHasRawJSON(t *testing.T) {
}

func TestMarshalItemsToJSONArray_WithoutHasRawJSON(t *testing.T) {
t.Parallel()

items := []any{
map[string]any{"id": 1, "name": "alice"},
map[string]any{"id": 2, "name": "bob"},
Expand Down
Loading
Loading