LinearSDK

Hex.pmHexDocsGitHub

LinearSDK

LinearSDK is an Elixir SDK for Linear with a thin provider-facing client and a generated full-schema API reference published as module docs.

The repo is intentionally thin:

What this repo owns

Install

def deps do
  [
    {:linear_sdk, "~> 0.2.0"}
  ]
end
mix deps.get

For active local development beside sibling checkouts, linear_sdk can also be consumed from a relative path:

{:linear_sdk, path: "../linear_sdk"}

Inside this repo, the shared prismatic dependencies resolve by one stable policy:

That keeps local development, packaging, and downstream dependency behavior aligned without requiring a committed vendored deps/ tree.

Real Linear Onboarding

The current upstream linear/linear repo and Linear's live docs both point to the same operating model:

Auth Model

There are three different things to keep straight:

  1. Personal API key This is a user-created secret from Linear settings. You use it directly against the GraphQL API. No OAuth app is involved.
  2. OAuth app This is the app configuration you create in Linear. It gives you a client_id, client_secret, redirect URI list, and optional client-credentials support. It is not itself a GraphQL credential.
  3. OAuth access token This is the credential returned after the OAuth app completes an authorization-code flow or a client-credentials flow. This is what you send to Linear's GraphQL API.

For authorization-code installs, Linear also returns a refresh token. For client-credentials tokens, Linear's docs say there is no refresh token and your server is expected to fetch a new token when needed.

LinearSDK makes the actual GraphQL auth modes explicit:

# Personal API key from Linear settings
client =
  LinearSDK.Client.new!(
    api_key: System.fetch_env!("LINEAR_API_KEY")
  )

# OAuth access token that you obtained elsewhere
oauth_client =
  LinearSDK.Client.new!(
    access_token: System.fetch_env!("LINEAR_OAUTH_ACCESS_TOKEN")
  )

For provider-local OAuth helpers:

{:ok, request} =
  LinearSDK.OAuth.authorization_request(
    client_id: System.fetch_env!("LINEAR_OAUTH_CLIENT_ID"),
    redirect_uri: System.fetch_env!("LINEAR_OAUTH_REDIRECT_URI"),
    scopes: ["read", "write"],
    actor: :app,
    generate_state: true,
    pkce: true
  )

Generated GraphQL versus provider-local OAuth HTTP:

OAuth Quickstart

You do not look up an OAuth access token in Linear account preferences. Linear issues the access token only after the OAuth flow completes. In practice:

If you are trying to find the app setup page inside Linear, the current official docs point to Settings -> API -> Your Applications for OAuth apps. That is different from account preferences.

For humans, the simplest path now uses the example helper:

examples/run_all.sh --setup-oauth
examples/run_all.sh --oauth
examples/run_all.sh

For write-capable example runs:

examples/run_all.sh --setup-oauth-write
examples/run_all.sh --oauth-write
examples/run_all.sh --with-write

Those helpers are shortcuts for the full mix linear.oauth ... commands below.

The direct read-only command is:

export LINEAR_OAUTH_CLIENT_ID="..."
export LINEAR_OAUTH_CLIENT_SECRET="..."
export LINEAR_OAUTH_REDIRECT_URI="http://127.0.0.1:40071/callback"
mix linear.oauth --save --manual --no-browser

That flow:

  1. prints the authorize URL
  2. asks you to approve the Linear app
  3. exchanges the returned code
  4. saves the token JSON to ~/.config/linear_sdk/oauth/linear.json unless you override LINEAR_OAUTH_TOKEN_PATH

If you want a write-capable token for the mutation examples, request explicit write scope:

mix linear.oauth --save --manual --no-browser --scope read --scope write

When the optional loopback callback-listener dependencies are present, mix linear.oauth can capture http://127.0.0.1/... callbacks directly. Without them, it falls back to the same paste-back flow documented above.

To refresh the saved token file in place:

mix linear.oauth refresh

If your Linear app supports the client-credentials grant:

mix linear.oauth client-credentials --save --scope read --scope write

Then run either:

mix run examples/viewer.exs
mix run examples/oauth_saved_token_viewer.exs
mix run examples/oauth_application_info.exs
examples/run_all.sh
examples/run_all.sh --with-write

This repo now includes dedicated OAuth examples as well as the operator-facing task wrapper:

For the full walkthrough, including app setup, token modes, and how to find your project slug, issue reference, and target workflow states, see guides/oauth-and-token-management.md, examples/README.md, and guides/real-linear-usage.md.

First Live Query

client =
  LinearSDK.Client.new!(
    api_key: System.fetch_env!("LINEAR_API_KEY")
  )

{:ok, response} =
  LinearSDK.execute_document(
    client,
    """
    query Viewer {
      viewer {
        id
        name
        email
      }
    }
    """
  )

Live Examples

All example scripts under examples/ are real Linear connections only. They do not use mocks or fake transports.

export LINEAR_API_KEY=lin_api_...
examples/run_all.sh

That default suite is read-only and auto-discovers a project slug and issue when your workspace has accessible data. If there is no accessible project slug, the polling example falls back to a workspace-scoped issue query so the suite still runs. Mutation examples are available too. The simplest human path is:

examples/run_all.sh --oauth-write
examples/run_all.sh --with-write

The low-level equivalent is still LINEAR_CONFIRM_WRITE=1.

If you want setup instructions instead of immediately running examples:

examples/run_all.sh --setup
examples/run_all.sh --setup-oauth
examples/run_all.sh --setup-oauth-write

If you want the direct OAuth example scripts instead of the helpers:

mix run examples/oauth_authorize_url.exs
mix run examples/oauth_exchange_code.exs
mix run examples/oauth_saved_token_viewer.exs
mix run examples/oauth_refresh_and_viewer.exs
mix run examples/oauth_application_info.exs

See examples/README.md for the full list and the OAuth onboarding checklist.

Docs Map

API reference is published under the Modules tab in HexDocs:

Generation Tasks

mix linear.ir
mix linear.generate
mix linear.verify

Generation consumes the committed upstream schema files:

Quality Bar

mix ci

That runs: