diff --git a/CHANGELOG.md b/CHANGELOG.md index a2fbbee..024fb15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ All notable changes to APIMux CLI are documented here. +## [1.1.4] - 2026-05-12 + +### Fixed + +- Changed the fresh-install default APIMux service URL from local development + (`http://127.0.0.1:8081`) to production (`https://apimux.io/api/core`). +- Kept local/private service usage available through `APIMUX_BASE_URL`, + `--base-url`, or `apimux config set --base-url ...`. + +### Documentation + +- Clarified that localhost is a development override, not the default product + endpoint. + ## [1.1.3] - 2026-05-12 ### Added diff --git a/README.md b/README.md index b783767..ee005fc 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ Authorize the CLI: apimux auth login ``` +The CLI defaults to the production APIMux service at `https://apimux.io/api/core`. + On SSH/headless servers, print the authorization URL instead of opening a browser: ```bash @@ -49,7 +51,13 @@ apimux auth login --no-browser `auth login` also auto-detects common headless environments such as SSH, CI, `NO_BROWSER=1`, and Linux without `$DISPLAY`. -For CI or manual API key setup, use `apimux config set --api-key ... --base-url ...`. +For CI or manual API key setup, use `apimux config set --api-key ...`. Override the service URL only for local development or private deployments: + +```bash +APIMUX_BASE_URL=http://127.0.0.1:8081 apimux schema capabilities +apimux --base-url http://127.0.0.1:8081 schema capabilities +apimux config set --base-url http://127.0.0.1:8081 +``` Run a capability: diff --git a/docs/development.md b/docs/development.md index 306cac9..c239d3d 100644 --- a/docs/development.md +++ b/docs/development.md @@ -19,6 +19,6 @@ make test make release-build ``` -Local config is stored under `APIMUX_CONFIG_DIR` when set, otherwise `~/.apimux/config.json`. Older configs under the platform user config directory are still read as a fallback and are migrated on the next write. +Local config is stored under `APIMUX_CONFIG_DIR` when set, otherwise `~/.apimux/config.json`. Older configs under the platform user config directory are still read as a fallback and are migrated on the next write. Fresh installs default to the production APIMux service at `https://apimux.io/api/core`. -Use `apimux auth login --web-url http://localhost:` to exercise browser-assisted CLI auth against a local web app without persisting the web URL. For CI or manual API key setup, use `apimux config set --base-url ... --api-key ...`. +Use `apimux auth login --web-url http://localhost:` to exercise browser-assisted CLI auth against a local web app without persisting the web URL. Use `APIMUX_BASE_URL`, `--base-url`, or `apimux config set --base-url ...` to point CLI capability calls at a local service such as `http://127.0.0.1:8081`. For CI or manual API key setup against production, `apimux config set --api-key ...` is enough unless you intentionally need a non-production service. diff --git a/docs/install.md b/docs/install.md index 5bf6f36..ca7a93b 100644 --- a/docs/install.md +++ b/docs/install.md @@ -6,6 +6,8 @@ Default install path: curl -fsSL https://github.com/reorc/apimux-cli/releases/latest/download/install.sh | sh ``` +After installation, `apimux` defaults to the production APIMux service at `https://apimux.io/api/core`. Use `APIMUX_BASE_URL`, `--base-url`, or `apimux config set --base-url ...` only when you need to point the CLI at a local or private service. + Environment variables: - `APIMUX_VERSION`: install a pinned version such as `v1.0.0` diff --git a/internal/command/root.go b/internal/command/root.go index 45972bb..6b7e6f1 100644 --- a/internal/command/root.go +++ b/internal/command/root.go @@ -122,7 +122,7 @@ func (r *Root) newCommand(runCtx *runContext) *cobra.Command { cfg := runCtx.cfg cfg.BaseURL = strings.TrimSpace(baseURL) if cfg.BaseURL == "" { - cfg.BaseURL = "http://127.0.0.1:8081" + cfg.BaseURL = config.DefaultBaseURL } bodyOutput, ok := output.ParseBodyOutput(outputMode) diff --git a/internal/command/root_support.go b/internal/command/root_support.go index 7623394..9f19fdb 100644 --- a/internal/command/root_support.go +++ b/internal/command/root_support.go @@ -12,6 +12,7 @@ import ( "github.com/reorc/apimux-cli/internal/buildinfo" "github.com/reorc/apimux-cli/internal/client" + "github.com/reorc/apimux-cli/internal/config" "github.com/reorc/apimux-cli/internal/output" ) @@ -214,7 +215,7 @@ func applyPersistentArgs(runCtx *runContext, args []string) error { } if strings.TrimSpace(baseURL) == "" { - baseURL = "http://127.0.0.1:8081" + baseURL = config.DefaultBaseURL } parsedOutput, ok := output.ParseBodyOutput(bodyOutput) if !ok { diff --git a/internal/command/root_test.go b/internal/command/root_test.go index 6169d38..ffd0b49 100644 --- a/internal/command/root_test.go +++ b/internal/command/root_test.go @@ -7,6 +7,8 @@ import ( "net/http/httptest" "strings" "testing" + + "github.com/reorc/apimux-cli/internal/config" ) func TestInvalidOutputReturnsNonZero(t *testing.T) { @@ -141,6 +143,59 @@ func TestSchemaCapabilitiesJSONFlag(t *testing.T) { } } +func TestHelpShowsProductionBaseURLDefault(t *testing.T) { + tempDir := t.TempDir() + t.Setenv("APIMUX_CONFIG_DIR", tempDir) + + var stdout bytes.Buffer + var stderr bytes.Buffer + + root := NewRoot(&stdout, &stderr) + exitCode, err := root.Execute(context.Background(), []string{"--help"}) + if err != nil { + t.Fatalf("execute root: %v", err) + } + if exitCode != 0 { + t.Fatalf("expected exit code 0, got %d, stderr=%s", exitCode, stderr.String()) + } + if !strings.Contains(stdout.String(), `default "`+config.DefaultBaseURL+`"`) { + t.Fatalf("expected production base URL default in help, got %s", stdout.String()) + } +} + +func TestConfigShowsProductionBaseURLDefault(t *testing.T) { + tempDir := t.TempDir() + t.Setenv("APIMUX_CONFIG_DIR", tempDir) + + var stdout bytes.Buffer + var stderr bytes.Buffer + + root := NewRoot(&stdout, &stderr) + exitCode, err := root.Execute(context.Background(), []string{"config"}) + if err != nil { + t.Fatalf("execute root: %v", err) + } + if exitCode != 0 { + t.Fatalf("expected exit code 0, got %d, stderr=%s", exitCode, stderr.String()) + } + if !strings.Contains(stdout.String(), `"base_url": "`+config.DefaultBaseURL+`"`) { + t.Fatalf("expected production base URL in config output, got %s", stdout.String()) + } + if !strings.Contains(stdout.String(), `"base_url": "default"`) { + t.Fatalf("expected default source in config output, got %s", stdout.String()) + } +} + +func TestPersistentArgFallbackUsesProductionBaseURL(t *testing.T) { + runCtx := &runContext{} + if err := applyPersistentArgs(runCtx, nil); err != nil { + t.Fatalf("apply persistent args: %v", err) + } + if runCtx.cfg.BaseURL != config.DefaultBaseURL { + t.Fatalf("expected production base URL fallback, got %s", runCtx.cfg.BaseURL) + } +} + func TestCompletionZshGeneratesScript(t *testing.T) { var stdout bytes.Buffer var stderr bytes.Buffer diff --git a/internal/config/config.go b/internal/config/config.go index 7b432f7..f172a38 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -10,6 +10,8 @@ import ( const envConfigDir = "APIMUX_CONFIG_DIR" +const DefaultBaseURL = "https://apimux.io/api/core" + type Config struct { BaseURL string `json:"base_url,omitempty"` APIKey string `json:"api_key,omitempty"` @@ -32,7 +34,7 @@ func Load() (Config, error) { func LoadDetailed() (Loaded, error) { cfg := Config{ - BaseURL: "http://127.0.0.1:8081", + BaseURL: DefaultBaseURL, } sources := map[string]string{ "base_url": "default", diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 515862c..34e5896 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -26,6 +26,19 @@ func TestLoadPrefersEnvOverFile(t *testing.T) { } } +func TestLoadDefaultsToProductionBaseURL(t *testing.T) { + tempDir := t.TempDir() + t.Setenv(envConfigDir, tempDir) + + cfg, err := Load() + if err != nil { + t.Fatalf("load config: %v", err) + } + if cfg.BaseURL != DefaultBaseURL { + t.Fatalf("expected default base URL %s, got %s", DefaultBaseURL, cfg.BaseURL) + } +} + func TestSaveWritesConfigFile(t *testing.T) { tempDir := t.TempDir() t.Setenv(envConfigDir, tempDir)