A command line interface to https://linear.app - list, take, create, develop, and update issues without leaving your terminal.
This is an Elixir/OTP port of linear-cli-rb
(the original Ruby CLI): same commands, same wrapper scripts (lcls,
lcreate, …), but shipped as a single standalone binary - no Ruby runtime
or gem install - via Burrito, and
real concurrency (Task.async_stream) for operations that touch several
issues at once. Looking up 10 issues by id, for example, runs in ~1.5s here
vs ~5s doing it one at a time.
You can run the CLI from the container image without installing anything.
$ podman run --rm -e LINEAR_CLI_DAEMON= -e LINEAR_API_KEY="$LINEAR_API_KEY" ghcr.io/rubyists/linear-cli:v0 lcls (1)
$ docker run --rm -e LINEAR_CLI_DAEMON= -e LINEAR_API_KEY="$LINEAR_API_KEY" ghcr.io/rubyists/linear-cli:v0 lcls (2)-
Podman usage
-
Docker usage -
:v0tracks the latest 0.x release; pin:v0.1.2(or whichever version) for a fixed image
|
❗
|
The image sets LINEAR_CLI_DAEMON=true by default so its own
entrypoint can also run as the long-lived Oban scheduling daemon. Override it
to an empty value (as above) for one-off interactive CLI usage - otherwise
lc/the wrapper scripts never see your command at all.
|
Grab the tarball for your platform from the
latest release - macOS
(Apple Silicon), Linux (x86_64), and Windows (x86_64) are all built as
standalone executables with no Erlang/Elixir install required. Each tarball
bundles lc with the wrapper scripts (lcreate, lcls, lclose,
lcomment, lproj).
$ curl --retry 5 --retry-all-errors -sLO https://github.com/rubyists/linear-cli/releases/latest/download/lc_macos_aarch64.tar.gz
$ curl --retry 5 --retry-all-errors -sLo SHA256SUMS https://github.com/rubyists/linear-cli/releases/latest/download/SHA256SUMS
$ grep -q lc_macos_aarch64.tar.gz SHA256SUMS && grep lc_macos_aarch64.tar.gz SHA256SUMS | shasum -a 256 -c - (1)
$ mkdir lc && tar -xzf lc_macos_aarch64.tar.gz -C lc
$ sudo mv lc/* /usr/local/bin/-
Linux:
sha256sum -c -instead ofshasum -a 256 -c -.
Every release also publishes sbom.cdx.json - a CycloneDX SBOM covering the
app, its Hex dependencies, and the Erlang/OTP and Elixir versions it was
built with. The container image has its own separate SBOM (its OS packages -
irrelevant if you’re not using the container), published as a workflow
artifact on the release’s build rather than a release asset.
On macOS, Gatekeeper blocks lc itself (the wrapper scripts are plain shell,
so they’re unaffected) since it isn’t signed/notarized yet:
$ xattr -d com.apple.quarantine /usr/local/bin/lc$ brew tap rubyists/tap
$ brew install lcSee https://github.com/rubyists/homebrew-tap for the formula itself.
$ curl --retry 5 --retry-all-errors -fsSL https://raw.githubusercontent.com/rubyists/linear-cli/main/install.sh | bashDetects your platform, downloads and checksum-verifies the matching release
tarball (the same one the "Download a release binary" section above uses),
and installs lc plus the bin/ wrapper scripts onto a directory already on
your $PATH - no Erlang/Elixir/Zig toolchain required. LC_VERSION pins a
specific release tag instead of the latest one; LC_INSTALL_DIR pins a
specific install directory.
$ curl --retry 5 --retry-all-errors -fsSL https://raw.githubusercontent.com/rubyists/linear-cli/main/uninstall.sh | bashRemoves exactly what install.sh installed, by replaying the manifest it
wrote - not a guess at where things ended up.
You must set the LINEAR_API_KEY environment variable to your Linear API key.
You can find your API key in your Linear Settings.
Short aliases are available for the top-level commands and some subcommands, so you don’t have to type the full name every time:
| Command | Aliases |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$ lc w --teams
$ lc i ls
$ lc i dev CRY-1234issue take has no alias.
You can get help/usage for any command or subcommand by using the --help flag.
$ lc --help
$ lc [COMMAND] --help
$ lc [COMMAND] [SUBCOMMAND] --helplcls is a wrapper script provided to list issues. It’s an alias for lc issue list.
$ lcls
$ lcls --full
$ lcls -f CRY-1$ lc issue take CRY-1234
$ lc issue take CRY-456 CRY-789$ lc issue create --title "My new issue" --description "This is a new issue" --labels Bug,Feature --team CRY
$ lc issue create -t "My new issue" -T CRY -l Improvement,Feature|
ℹ️
|
If you don’t provide a title, team, labels, or description, you will be prompted to enter them. |
|
💡
|
When creating an issue, you can use the --dev (or --develop) option to immediately start development on the issue.
|
Switches to the branch for the issue, creating the branch if it doesn’t exist.
$ lc issue develop CRY-1234All of the update options can work on multiple issues at a time.
$ lc issue update --comment "Here is a comment" CRY-1234 (1)
$ lc issue update --close --reason "I do not like you" CRY-14 CRY-15 (2)
$ lc issue update --cancel --trash --reason "I have no idea why you are here" CRY-16 CRY-17 (3)
$ lc issue update --comment - CRY-14 CRY-15 (4)
$ lcomment CRY-1234 CRY-3 (5)-
Comments on the issue with the provided text
-
Closes multiple issues without prompting (reason is added as a comment)
-
Cancels multiple issues without prompting and moves them to the trash (reason is added as a comment)
-
Opens your editor for the comment (use
-to prompt) -
Always prompts for a comment (
lcommentis a wrapper forlc issue update --comment -)
Not in Ruby’s linear-cli - save a named team/project bundle once, then
switch to it instead of passing --team/--project on every issue
create/issue list.
$ lc profile create manhattan --team CRY --project Manhattan
$ lc profile use manhattan
$ lc profile list
$ lc profile show
$ lc profile delete manhattanAn explicit --team/--project on the command line always overrides the
active profile.
Issue commands also accept a bare number (lc issue develop 1234) in
place of a full team-prefixed identifier - it’s resolved via the active
profile’s team, then favorited teams, then a prompt across every team you
belong to.
Not in Ruby’s linear-cli - favorite the teams/projects you actually
care about, and once any exist, team list/project list default to
showing just favorites of that kind. --all bypasses the favorites
filter only - it doesn’t change team list’s `--no-mine or project
list’s `--mine/--team scope, it just shows everything within
whatever scope you already asked for.
$ lc team favorite CRY
$ lc team list
$ lc team list --all
$ lc team unfavorite CRY
$ lc project favorite Manhattan
$ lc project listThe bin/ wrapper scripts (ported verbatim from linear-cli’s own `exe/scripts/)
make the common commands shorter to type. They just exec lc …, so they work
anywhere lc is on your $PATH.
$ lcls
$ lcreate --description "This is a new issue" --labels Bug,Feature --team CRY
$ lclose --reason "This issue sucks" CRY-1234 CRY-456
$ lcomment CRY-1234
$ lproj list --mineFirst, activate the repo’s git hooks (enforces conventional-commit subjects on every commit, and again on every commit about to be pushed):
$ mix setupRun the development checkout directly from the repository root with mix lc.
It compiles and starts the application as needed, then forwards arguments,
interactive input, output, and exit status to the same CLI entry point used by
the release binary:
$ mix lc whoami
$ mix lc issue list --output jsonThe project uses ExUnit and mix format. Run tests with:
$ cd app
$ mise exec -- mix test
$ mise exec -- mix format --check-formatted$ cd app
$ mise exec -- env MIX_ENV=prod BURRITO_TARGET=<target> mix release lc<target> is one of macos_aarch64, linux_x86_64, or windows_x86_64.
This project follows the Conventional Commits specification.
To contribute, please follow that commit message format, or your pull request may be rejected.
