feat(cli): add profiles - default team/project stored in local SQLite - #57
Merged
Conversation
Refs #56. Design for a new profiles feature: named, switchable team/project bundles stored in a new local SQLite file (~/.linear_cli/profiles.db, separate from Oban's own oban.db), backing lc profile create/list/use/show/delete and filling in --team/--project defaults for issue create/issue list when the flag is omitted. Implementation commits follow on this branch.
Refs #56. LinearCli.Profiles: named team/project bundles in ~/.linear_cli/profiles.db (dev/test get their own file paths in config/runtime.exs), with at most one active profile enforced by a partial unique index. Uses Exqlite directly rather than a new Ecto.Repo - interactive mode's supervisor is deliberately empty (see LinearCli.Application), and Oban's own migrations are only ever run externally via mix ecto.migrate, neither of which fits a one-shot CLI with no deploy step. New `lc profile create/list/use/show/delete` command. issue create and issue list now fall back to the active profile's team/project when --team/--project are omitted; an explicit flag still always wins. Readme documents the new commands. test_helper.exs clears the test profiles db once at suite start so a stray active profile from an earlier run can't leak into unrelated tests.
There was a problem hiding this comment.
Pull request overview
Adds a first-class “profiles” feature to the Linear CLI so users can persist and switch default team/project selections (stored locally in a dedicated SQLite DB) and have issue create / issue list automatically fall back to the active profile when flags are omitted.
Changes:
- Introduces
LinearCli.Profilesbacked by~/.linear_cli/profiles.db, including schema bootstrapping and an “exactly one active” invariant via a partial unique index. - Adds
lc profile create/list/use/show/deletewiring (Optimus spec, dispatch, commands) plus profile rendering inDisplay. - Wires profile defaults into
IssueHelpers.make_da_issue!/1andCommands.issue_list/1, with new tests and test-suite DB cleanup.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| Readme.adoc | Documents the new profiles feature and basic CLI usage. |
| documents/phase-9-plan.adoc | Adds the phase-9 design document describing decisions and intended behavior. |
| app/test/test_helper.exs | Removes the test profiles DB at suite start to prevent cross-run leakage. |
| app/test/linear_cli/profiles_test.exs | Adds unit tests for LinearCli.Profiles CRUD/activation behavior. |
| app/test/linear_cli/cli/profile_defaults_test.exs | Adds integration-ish tests for default fallback behavior in issue_list and make_da_issue!. |
| app/lib/linear_cli/profiles.ex | Implements the profiles SQLite data layer (create/list/activate/active/delete/default_*). |
| app/lib/linear_cli/cli/issue_helpers.ex | Applies profile fallback for omitted :team/:project during issue creation. |
| app/lib/linear_cli/cli/display.ex | Adds text output formatting for Profiles.Profile. |
| app/lib/linear_cli/cli/commands.ex | Adds profile_* commands and applies profile fallback in issue_list/1. |
| app/lib/linear_cli/cli.ex | Registers the new profile command, aliases, and dispatch clauses. |
| app/config/runtime.exs | Configures :profiles_db_path per env (dev/test/prod). |
| app/.gitignore | Ignores local dev/test profiles DB files. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…file on a failed switch activate/1 deactivated every profile before checking whether the target name existed, so `lc profile use <unknown>` left no profile active at all instead of leaving the previous one in place - a user-visible state change on a command that's supposed to fail. Wraps both updates in a transaction and rolls back on :not_found.
4 tasks
bougyman
added a commit
that referenced
this pull request
Aug 11, 2026
…61) ## Summary Closes #60. Full design in `documents/phase-10-plan.adoc`. - `LinearCli.Favorites`: a new `favorites` table in the same local sqlite file `LinearCli.Profiles` (#56/#57) already uses - storing resolved team keys and project ids (not raw search text, so filtering never needs re-fuzzy-matching). - New `lc team favorite/unfavorite <TEAM>` and `lc project favorite/unfavorite <PROJECT>`. - `team list`/`project list` default to favorites-only once any favorite of that kind exists; `--all` opts back out to today's full list. Invisible to anyone who's never favorited anything. This is the prerequisite for #59 (bare issue numbers resolved via favorited teams, Phase 11) - not part of this PR. ## Test plan - [x] `mix test` - full suite green apart from one pre-existing, unrelated flake in `LinearCli.GitTest` (confirmed it fails identically on `main` before this branch's changes) - [x] `mix format --check-formatted` - clean - [x] New tests: `LinearCli.FavoritesTest` (data layer) and `LinearCli.CLI.FavoritesCommandsTest` (10 tests, full `LinearCli.CLI.main/2` invocations - favorite/unfavorite for both teams and projects, favorites-only-by-default filtering, `--all` override, and the zero-favorites case explicitly asserted unchanged) - [x] `Readme.adoc` documents the new commands
bougyman
pushed a commit
that referenced
this pull request
Aug 11, 2026
🤖 I have created a release *beep* *boop* --- ## [0.8.4](v0.8.3...v0.8.4) (2026-08-11) ### Features * **cli:** add favorite teams/projects, filtering list views by them ([#61](#61)) ([6c858d9](6c858d9)) * **cli:** add profiles - default team/project stored in local SQLite ([#57](#57)) ([554e336](554e336)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
This was referenced Aug 11, 2026
bougyman
pushed a commit
that referenced
this pull request
Aug 11, 2026
🤖 I have created a release *beep* *boop* --- ## [1.0.0](v1.0.0...v1.0.0) (2026-08-11) ### ⚠ BREAKING CHANGES * graduate to 1.0.0 - disable pre-major version bumping ([#70](#70)) * **cd:** parallelize Burrito target builds and fix Trivy/Podman image scanning ([#68](#68)) * **ci:** rename release.yaml to main.yaml, workflow name to "main" ([#38](#38)) * add Readme/LICENSE, feat: wire up the issue list --project picker ([#12](#12)) ### Features * add mix githooks.install to activate the repo's git hooks ([#51](#51)) ([9b35472](9b35472)) * **api:** add LinearCli.Api GraphQL client (Phase 1) ([723f3f6](723f3f6)) * **ci:** add a full SBOM - app deps, OTP/Elixir runtime, container OS packages ([#54](#54)) ([e296fdd](e296fdd)) * **cli:** add favorite teams/projects, filtering list views by them ([#61](#61)) ([6c858d9](6c858d9)) * **cli:** add issue create/develop/pr/take/update write commands (Phase 6) ([1649618](1649618)) * **cli:** add profiles - default team/project stored in local SQLite ([#57](#57)) ([554e336](554e336)) * **cli:** add project update - post a status update to a project ([#43](#43)) ([30dc6dc](30dc6dc)) * **cli:** make version respect --output json ([#33](#33)) ([b160aad](b160aad)) * **cli:** resolve bare issue numbers via active profile, favorited teams, or a team prompt ([#65](#65)) ([8b183da](8b183da)) * **cli:** support Ruby's short subcommand aliases ([#15](#15)) ([9fca6b5](9fca6b5)) * initial commit with ash submodule ([c2ceafb](c2ceafb)) * **linear:** add Ash domain resources for Issue/Project/Team/User/Label/WorkflowState/Comment (Phase 2) ([e2a27f3](e2a27f3)) * **oban:** add scheduled monthly project rollover (Phase 7) ([11afb43](11afb43)) * phase 4 from initial plan -> complete ([012866e](012866e)) * phase 8 - packaging, releasing, and CI ([#1](#1)) ([905c238](905c238)) * scaffold Elixir port and enforce conventional commits ([a4d03a0](a4d03a0)) ### Bug Fixes * **ci:** consolidate the release pipeline into one workflow/DAG ([ba821bb](ba821bb)) * **ci:** create releases as drafts so assets survive Immutable Releases ([#19](#19)) ([8572623](8572623)) * **ci:** package release binaries with the wrapper scripts ([#24](#24)) ([5fb24a4](5fb24a4)) * **ci:** rebuild the release pipeline to stop the version-bump runaway loop ([#30](#30)) ([c311fd4](c311fd4)) * **ci:** relabel the release PR as tagged after we tag it ourselves ([ab1408e](ab1408e)) * **ci:** skip commit-subject validation in the post-merge pipeline ([#41](#41)) ([3d00a85](3d00a85)) * **cli:** reject unrecognized flags instead of treating them as issue ids ([#2](#2)) ([#4](#4)) ([e697ff6](e697ff6)) * **deps:** update ash to a non-vulnerable version ([#63](#63)) ([b838e2a](b838e2a)) ### Performance Improvements * **linear:** fan out find-by-ids and per-team project fetches (Phase 5) ([fb00153](fb00153)) ### Documentation * add Readme/LICENSE, feat: wire up the issue list --project picker ([#12](#12)) ([eb42c69](eb42c69)) ### Miscellaneous Chores * **ci:** rename release.yaml to main.yaml, workflow name to "main" ([#38](#38)) ([2581a40](2581a40)) * graduate to 1.0.0 - disable pre-major version bumping ([#70](#70)) ([87a65ae](87a65ae)) ### Continuous Integration * **cd:** parallelize Burrito target builds and fix Trivy/Podman image scanning ([#68](#68)) ([5cc829a](5cc829a)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #56.
Full design in
documents/phase-9-plan.adoc.LinearCli.Profiles: named team/project bundles in~/.linear_cli/profiles.db(separate from Oban's ownoban.db), with at most one active profile enforced by a partial unique index. UsesExqlite.Sqlite3directly rather than a newEcto.Repo- interactive mode's supervisor is deliberately empty, and Oban's own migrations are only ever run externally viamix ecto.migrate; neither fits a one-shot CLI with no deploy step.lc profile create/list/use/show/delete.issue create/issue listfall back to the active profile's team/project when--team/--projectare omitted - an explicit flag still always wins.Test plan
mix test- 197/198 passed (1 pre-existing, unrelated failure inLinearCli.GitTest- confirmed it fails identically with these changes stashed out, a local git-environment flake)mix format --check-formatted- cleanlc profile create/list/use/show/deleteend to endLinearCli.ProfilesTest(data layer) andLinearCli.CLI.ProfileDefaultsTest(the fallback wiring inmake_da_issue!/1andissue_list/1, including that an explicit flag overrides the active profile)test_helper.exsnow clears the test profiles db once at suite start, since a stray active profile left on disk by an earlier run was leaking into unrelated tests