Skip to content

feat: multi-profile auth via ~/.config/lineark/config.toml#115

Closed
lightstrike wants to merge 3 commits intoflipbit03:mainfrom
lightstrikelabs:feat/multi-profile-support
Closed

feat: multi-profile auth via ~/.config/lineark/config.toml#115
lightstrike wants to merge 3 commits intoflipbit03:mainfrom
lightstrikelabs:feat/multi-profile-support

Conversation

@lightstrike
Copy link
Copy Markdown
Contributor

Why

The single ~/.linear_api_token file only supports one workspace at a time. Users working across multiple Linear workspaces (e.g. personal and work) have to manually swap tokens. This adds TOML-based profile support — similar to AWS CLI profiles or SSH config — so users can store multiple tokens and switch between them with a flag or env var.

Config file

~/.config/lineark/config.toml:

[profiles.default]
api_token = "lin_api_abc123"

[profiles.work]
api_token = "lin_api_def456"

Usage

lineark --profile work teams list     # use the "work" profile
LINEAR_PROFILE=work lineark whoami    # same, via env var
lineark teams list                    # uses "default" profile (or env/legacy fallback)

Auth precedence (updated)

  1. --api-token flag (unchanged)
  2. $LINEAR_API_TOKEN env var (unchanged)
  3. --profile flag / $LINEAR_PROFILE env var → named profile in config
  4. [profiles.default] in ~/.config/lineark/config.toml
  5. ~/.linear_api_token legacy fallback (backward compatible)

Changes

SDK (lineark-sdk)

  • auth.rs: New token_from_config() / token_from_config_at() for TOML config parsing, updated auto_token() to accept Option<&str> profile, $LINEAR_PROFILE env var support
  • client.rs: New Client::from_profile(), updated Client::auto(profile: Option<&str>)
  • blocking_client.rs: Mirrored from_profile() and updated auto() signature
  • Cargo.toml: Added toml dependency
  • helpers.rs: Updated doc examples for new auto() signature

CLI (lineark)

  • main.rs: Added --profile global flag, wired into client resolution
  • commands/usage.rs: Updated auth docs with config file format, --profile flag, LINEAR_PROFILE hint
  • tests/offline.rs: 8 new integration tests

Test plan

  • 10 new SDK unit tests for config file parsing (default/named profiles, missing profiles, empty tokens, malformed TOML, missing files, multiple profiles)
  • 5 new SDK unit tests for auto_token precedence (env vs config, explicit profile skips env, LINEAR_PROFILE env var, empty/whitespace ignored)
  • 8 new CLI offline integration tests (help output, valid config with temp files + HOME override, error messages for missing config/profile, --api-token overrides --profile)
  • All 66 SDK unit tests pass
  • All 85 CLI offline tests pass
  • cargo clippy --workspace -- -D warnings clean
  • cargo fmt --check clean

The single ~/.linear_api_token file only supports one workspace at a
time. This adds TOML-based profile support (similar to AWS CLI profiles)
so users can store multiple tokens and switch between them.

Config file format:

  [profiles.default]
  api_token = "lin_api_..."

  [profiles.work]
  api_token = "lin_api_..."

New auth precedence:
  1. --api-token flag
  2. $LINEAR_API_TOKEN env var
  3. --profile flag / $LINEAR_PROFILE env var → named profile
  4. [profiles.default] in config file
  5. ~/.linear_api_token legacy fallback

SDK: adds Client::from_profile(), updates Client::auto() to accept
optional profile name, adds toml dependency.

CLI: adds --profile global flag, updates usage output with config
file documentation.
SDK unit tests (10 new):
- token_from_config_at: default profile, named profile, missing
  profile, empty token, whitespace trimming, missing file, malformed
  TOML, no profiles section, empty file, multiple profiles
- auto_token precedence: env beats config, explicit profile skips env,
  LINEAR_PROFILE env var, empty/whitespace LINEAR_PROFILE ignored

CLI offline tests (8 new):
- --profile flag appears in --help and usage output
- usage shows config file example with [profiles.default]
- --profile with missing config file gives clear error
- --profile with valid temp config resolves token correctly
- default profile used when no flags set
- LINEAR_PROFILE env var selects named profile
- --profile with nonexistent profile name shows "not found" error
- --api-token overrides --profile

Refactored auth.rs to extract token_from_config_at(path, profile)
so config parsing is testable against temp files without relying on
the real ~/.config/lineark/config.toml.
@flipbit03
Copy link
Copy Markdown
Owner

flipbit03 commented Mar 6, 2026

@lightstrike I think it would be best if we first opened issues for discussions for potentially breaking changes like this one. I'd like to keep lineark deliberately config free, and I don't feel like deprecating or flagging ~/.linear_api_token as 'legacy', or moving into an arrangement where the keys/configs live 'deeper' than the root level - I want the utmost simplicity and have a clear vision for this.

For the sake of this proposal and of course your effort in ideating this, I'd like to put forward an approach similar to the current approach, but with the following multi-profile (multi-token) mechanics"

"profiles" are simply different ~/.linear_api_token files.

With that, we have:

  • lineark <command>
    • default profile, uses ~/.linear_api_token)
  • lineark --profile work <command>
    • uses work profile,
    • token should exist at ~/.linear_api_token_work,
    • warns if it doesn't exist and instructs to create the file
  • lineark --profile banana <command>
    • uses banana profile,
    • ditto..
  • incidentally, online tests' token usage become just another profile 😁
    • ~/.linear_api_token_test, unchanged from what we have now as the online test harness' token filename.

LINEAR_PROFILE=work lineark whoami

I don't think we should do this at all. The only reason to use a token as a env var is for token file-less programmatic usage that doesn't leaks the token secret in something like ps aux. Profile is not a secret to need such treatment, so the --profile flag suffices.

Also, we'd need the following tweaks:

  • Updated docs to explain this capability
  • lineark usage currently tells "it has found a token in the right file", I propose we change the string to show something along the lines of:
found profiles: "default", "work", "banana". switch with --profile <chosen_profile>

I will use this comment + your initial PR as a base for creating an issue in the repo, and then I'll pick it up and drive it to completion.

Thanks a lot @lightstrike for your efforts and comprehension!

@flipbit03
Copy link
Copy Markdown
Owner

Closing in favor of #127, which has been merged.

@lightstrike — thank you for your effort on this! Your PR was the catalyst for this feature. As discussed in the review thread, we went with a simpler, config-free approach: profiles are just separate token files (~/.linear_api_token_{name}) rather than a TOML config, and switching happens via --profile without a LINEAR_PROFILE env var. This keeps lineark deliberately config-free and the auth story as simple as possible.

Your original PR and the discussion around it directly shaped the design of #127 — much appreciated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants