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
29 changes: 29 additions & 0 deletions cli/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,9 +462,38 @@ func (r *RootCmd) login() *serpent.Command {
Value: serpent.BoolOf(&useTokenForSession),
},
}
cmd.Children = []*serpent.Command{
r.loginToken(),
}
return cmd
}

func (r *RootCmd) loginToken() *serpent.Command {
return &serpent.Command{
Use: "token",
Short: "Print the current session token",
Long: "Print the session token for use in scripts and automation.",
Middleware: serpent.RequireNArgs(0),
Handler: func(inv *serpent.Invocation) error {
tok, err := r.ensureTokenBackend().Read(r.clientURL)
if err != nil {
if xerrors.Is(err, os.ErrNotExist) {
return xerrors.New("no session token found - run 'coder login' first")
}
if xerrors.Is(err, sessionstore.ErrNotImplemented) {
return errKeyringNotSupported
}
return xerrors.Errorf("read session token: %w", err)
}
if tok == "" {
return xerrors.New("no session token found - run 'coder login' first")
}
_, err = fmt.Fprintln(inv.Stdout, tok)
return err
},
}
}

// isWSL determines if coder-cli is running within Windows Subsystem for Linux
func isWSL() (bool, error) {
if runtime.GOOS == goosDarwin || runtime.GOOS == goosWindows {
Expand Down
28 changes: 28 additions & 0 deletions cli/login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,3 +537,31 @@ func TestLogin(t *testing.T) {
require.Equal(t, selected, first.OrganizationID.String())
})
}

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

t.Run("PrintsToken", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)

inv, root := clitest.New(t, "login", "token", "--url", client.URL.String())
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t).Attach(inv)
ctx := testutil.Context(t, testutil.WaitShort)
err := inv.WithContext(ctx).Run()
require.NoError(t, err)

pty.ExpectMatch(client.SessionToken())
})

t.Run("NoTokenStored", func(t *testing.T) {
t.Parallel()
inv, _ := clitest.New(t, "login", "token")
ctx := testutil.Context(t, testutil.WaitShort)
err := inv.WithContext(ctx).Run()
require.Error(t, err)
require.Contains(t, err.Error(), "no session token found")
})
}
3 changes: 3 additions & 0 deletions cli/testdata/coder_login_--help.golden
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ USAGE:
macOS and Windows and a plain text file on Linux. Use the --use-keyring flag
or CODER_USE_KEYRING environment variable to change the storage mechanism.

SUBCOMMANDS:
token Print the current session token

OPTIONS:
--first-user-email string, $CODER_FIRST_USER_EMAIL
Specifies an email address to use if creating the first user for the
Expand Down
11 changes: 11 additions & 0 deletions cli/testdata/coder_login_token_--help.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
coder v0.0.0-devel

USAGE:
coder login token

Print the current session token

Print the session token for use in scripts and automation.

———
Run `coder --help` for a list of global options.
15 changes: 15 additions & 0 deletions docs/admin/users/sessions-tokens.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ The [Coder CLI](../../install/cli.md) and
token to authenticate. To generate a short-lived session token on behalf of your
account, visit the following URL: `https://coder.example.com/cli-auth`

### Retrieve the current session token

If you're already logged in with the CLI, you can retrieve your current session
token for use in scripts and automation:

```sh
coder login token
```

This is useful for passing your session token to other tools:

```sh
export CODER_SESSION_TOKEN=$(coder login token)
```

### Session Durations

By default, sessions last 24 hours and are automatically refreshed. You can
Expand Down
10 changes: 10 additions & 0 deletions docs/ai-coder/ai-bridge/client-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ Instead of distributing provider-specific API keys (OpenAI/Anthropic keys) to us

Again, the exact environment variable or setting naming may differ from tool to tool; consult your tool's documentation.

### Retrieving your session token

If you're logged in with the Coder CLI, you can retrieve your current session
token using [`coder login token`](../../reference/cli/login_token.md):

```sh
export ANTHROPIC_API_KEY=$(coder login token)
export ANTHROPIC_BASE_URL="https://coder.example.com/api/v2/aibridge/anthropic"
```

## Configuring In-Workspace Tools

AI coding tools running inside a Coder workspace, such as IDE extensions, can be configured to use AI Bridge.
Expand Down
5 changes: 5 additions & 0 deletions docs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -1487,6 +1487,11 @@
"description": "Authenticate with Coder deployment",
"path": "reference/cli/login.md"
},
{
"title": "login token",
"description": "Print the current session token",
"path": "reference/cli/login_token.md"
},
{
"title": "logout",
"description": "Unauthenticate your local session",
Expand Down
6 changes: 6 additions & 0 deletions docs/reference/cli/login.md

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

16 changes: 16 additions & 0 deletions docs/reference/cli/login_token.md

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

Loading