Skip to content

feat: linear interactive wizard command#271

Open
rubenmarcus wants to merge 5 commits intomainfrom
feat/linear-integration-wizard
Open

feat: linear interactive wizard command#271
rubenmarcus wants to merge 5 commits intomainfrom
feat/linear-integration-wizard

Conversation

@rubenmarcus
Copy link
Member

Summary

  • Add ralph-starter linear top-level command for interactive Linear issue selection
  • Wizard flow: authenticate → select team → browse projects/issues or paste URL → run
  • Reuses shared wizard utilities from src/integrations/wizards/shared.ts
  • Falls back to wizard when ralph-starter run --from linear is used without --project
  • Updated Linear source docs and README commands table

Changes

  • New: src/commands/linear.ts — Linear wizard with GraphQL team/project/issue fetching
  • Modified: src/cli.ts — Register ralph-starter linear command
  • Modified: src/commands/run.ts — Wizard fallback for --from linear
  • Modified: docs/docs/sources/linear.md — Wizard section + examples
  • Modified: README.md — Commands table entry

Test plan

  • ralph-starter linear launches wizard and completes flow
  • ralph-starter run --from linear (no --project) redirects to wizard
  • ralph-starter run --from linear --project ENG still works (existing behavior)
  • URL paste mode correctly parses linear.app/.../issue/TEAM-123
  • Missing credentials prompts for API key and saves
  • pnpm build — no new errors (pre-existing pixelmatch/sharp errors only)

🤖 Generated with Claude Code

rubenmarcus and others added 4 commits March 8, 2026 11:11
…or-url)

Shared utilities for integration wizards:
- ensureCredentials(): check for existing auth, prompt for API key if missing
- askBrowseOrUrl(): common "browse or paste URL" prompt
- askForUrl(): URL input with domain validation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Interactive wizard for working with Linear issues:
- Auth check (Linear CLI or API key)
- Browse teams → projects → issues, or paste a URL
- Priority badges in issue selector
- Delegates to runCommand() for execution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add linear wizard to CLI as top-level command
- Add wizard fallback in run.ts for --from linear without project

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add interactive wizard section to Linear source docs
- Add ralph-starter linear to README commands table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 8, 2026

Issue Linking Reminder

This PR doesn't appear to have a linked issue. Consider linking to:

  • This repo: Closes #123
  • ralph-ideas: Closes multivmlabs/ralph-ideas#123

Using Closes, Fixes, or Resolves will auto-close the issue when this PR is merged.


If this PR doesn't need an issue, you can ignore this message.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 8, 2026

✔️ Bundle Size Analysis

Metric Value
Base 2425.03 KB
PR 2458.71 KB
Diff 33.68 KB (1.00%)
Bundle breakdown
156K	dist/auth
32K	dist/automation
4.0K	dist/cli.d.ts
4.0K	dist/cli.d.ts.map
20K	dist/cli.js
12K	dist/cli.js.map
604K	dist/commands
28K	dist/config
4.0K	dist/index.d.ts
4.0K	dist/index.d.ts.map
4.0K	dist/index.js
4.0K	dist/index.js.map
916K	dist/integrations
84K	dist/llm
900K	dist/loop
188K	dist/mcp
32K	dist/presets
92K	dist/setup
40K	dist/skills
392K	dist/sources
76K	dist/ui
144K	dist/utils
336K	dist/wizard

Comment on lines +91 to +94
headers: {
'Content-Type': 'application/json',
Authorization: apiKey,
},

Check warning

Code scanning / CodeQL

File data in outbound network request Medium

Outbound network request depends on
file data
.
@github-actions
Copy link
Contributor

github-actions bot commented Mar 8, 2026

🔗 Docs Preview

Preview URL: https://feat-linear-integration-wiza.ralph-starter-docs.pages.dev

This preview was deployed from the latest commit on this PR.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 8, 2026

Greptile Summary

This PR introduces an interactive Linear issues wizard (ralph-starter linear) that guides users through authenticating, selecting a team/project, and picking an issue before delegating to runCommand. It also adds shared wizard utilities (src/integrations/wizards/shared.ts) reusable across future integrations, and wires up a fallback so ralph-starter run --from linear (without --project) automatically launches the wizard.

Key changes:

  • src/commands/linear.ts — Full wizard implementation with GraphQL team/project/issue fetching, URL parsing, and priority display
  • src/integrations/wizards/shared.ts — Reusable ensureCredentials, askBrowseOrUrl, and askForUrl helpers
  • src/commands/run.ts — Wizard fallback via dynamic import when --from linear is used without --project/--issue
  • src/cli.ts — Command registration matching the figma wizard pattern

Issues found:

  • Multiple interface declarations (LinearWizardOptions, LinearTeam, LinearProject, LinearIssue, and CredentialOptions) should be type per project conventions

Confidence Score: 4/5

  • Safe to merge after fixing minor style convention issue with type vs interface declarations.
  • The PR implements a well-structured Linear wizard with proper architecture, correct fallback logic, and solid reusable utilities. The only issue is a style convention violation: several simple data structure declarations use interface instead of type as specified in the project's custom rules. This is a minor cosmetic issue that doesn't affect runtime behavior and is straightforward to fix.
  • src/commands/linear.ts and src/integrations/wizards/shared.ts need style updates to use type instead of interface for simple data structures.

Sequence Diagram

sequenceDiagram
    actor User
    participant CLI as ralph-starter CLI
    participant LinearCmd as linearCommand
    participant Shared as shared.ts (ensureCredentials)
    participant LinearAPI as Linear GraphQL API
    participant RunCmd as runCommand

    User->>CLI: ralph-starter linear [options]
    CLI->>LinearCmd: linearCommand(options)

    LinearCmd->>Shared: ensureCredentials('linear', ...)
    alt CLI authenticated
        Shared-->>LinearCmd: '__cli_auth__'
        LinearCmd->>LinearCmd: getLinearApiKey()
    else Credentials in config/env
        Shared-->>LinearCmd: apiKey
    else No credentials
        Shared->>User: Prompt for API key
        User-->>Shared: API key input
        Shared-->>LinearCmd: saved apiKey
    end

    LinearCmd->>User: Browse or paste URL?
    alt URL mode
        User-->>LinearCmd: linear.app/…/issue/TEAM-123
        LinearCmd->>LinearCmd: parseLinearUrl(url)
        LinearCmd->>RunCmd: runCommand(identifier, {from:'linear', project:teamKey})
    else Browse mode
        LinearCmd->>LinearAPI: GetTeams query
        LinearAPI-->>LinearCmd: teams[]
        LinearCmd->>User: Select team
        User-->>LinearCmd: selectedTeam

        LinearCmd->>User: Project / All issues / Specific ID?

        alt Project mode
            LinearCmd->>LinearAPI: GetProjects(teamId)
            LinearAPI-->>LinearCmd: projects[]
            LinearCmd->>User: Select project
        end

        LinearCmd->>LinearAPI: GetIssues(filter, first:30)
        LinearAPI-->>LinearCmd: issues[]
        LinearCmd->>User: Select issue
        User-->>LinearCmd: selectedIssue

        LinearCmd->>RunCmd: runCommand(selectedIssue, {from:'linear', project:teamKey})
    end

    RunCmd-->>User: Build loop starts
Loading

Last reviewed commit: 549bb51

Comment on lines +17 to +47
export interface LinearWizardOptions {
commit?: boolean;
push?: boolean;
pr?: boolean;
validate?: boolean;
maxIterations?: number;
agent?: string;
}

const LINEAR_API_URL = 'https://api.linear.app/graphql';

interface LinearTeam {
id: string;
name: string;
key: string;
}

interface LinearProject {
id: string;
name: string;
state: string;
}

interface LinearIssue {
id: string;
identifier: string;
title: string;
url: string;
priorityLabel: string | null;
state: { name: string } | null;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use type instead of interface for data structures

All of these declarations — LinearWizardOptions, LinearTeam, LinearProject, and LinearIssue — are simple data structures with no inheritance or extension. Per the project's custom rules, type should be used instead of interface.

Suggested change
export interface LinearWizardOptions {
commit?: boolean;
push?: boolean;
pr?: boolean;
validate?: boolean;
maxIterations?: number;
agent?: string;
}
const LINEAR_API_URL = 'https://api.linear.app/graphql';
interface LinearTeam {
id: string;
name: string;
key: string;
}
interface LinearProject {
id: string;
name: string;
state: string;
}
interface LinearIssue {
id: string;
identifier: string;
title: string;
url: string;
priorityLabel: string | null;
state: { name: string } | null;
}
export type LinearWizardOptions = {
commit?: boolean;
push?: boolean;
pr?: boolean;
validate?: boolean;
maxIterations?: number;
agent?: string;
};
const LINEAR_API_URL = 'https://api.linear.app/graphql';
type LinearTeam = {
id: string;
name: string;
key: string;
};
type LinearProject = {
id: string;
name: string;
state: string;
};
type LinearIssue = {
id: string;
identifier: string;
title: string;
url: string;
priorityLabel: string | null;
state: { name: string } | null;
};

The same pattern applies to CredentialOptions in src/integrations/wizards/shared.ts at line 12.

Rule Used: Use type by default in TypeScript unless you spe... (source)

Learnt From
cytonic-network/ai-frontend#48

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/commands/linear.ts
Line: 17-47

Comment:
Use `type` instead of `interface` for data structures

All of these declarations — `LinearWizardOptions`, `LinearTeam`, `LinearProject`, and `LinearIssue` — are simple data structures with no inheritance or extension. Per the project's custom rules, `type` should be used instead of `interface`.

```suggestion
export type LinearWizardOptions = {
  commit?: boolean;
  push?: boolean;
  pr?: boolean;
  validate?: boolean;
  maxIterations?: number;
  agent?: string;
};

const LINEAR_API_URL = 'https://api.linear.app/graphql';

type LinearTeam = {
  id: string;
  name: string;
  key: string;
};

type LinearProject = {
  id: string;
  name: string;
  state: string;
};

type LinearIssue = {
  id: string;
  identifier: string;
  title: string;
  url: string;
  priorityLabel: string | null;
  state: { name: string } | null;
};
```

The same pattern applies to `CredentialOptions` in `src/integrations/wizards/shared.ts` at line 12.

**Rule Used:** Use `type` by default in TypeScript unless you spe... ([source](https://app.greptile.com/review/custom-context?memory=c862f053-5655-4b41-be69-c840e3c9f280))

**Learnt From**
[cytonic-network/ai-frontend#48](https://github.com/cytonic-network/ai-frontend/pull/48)

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@rubenmarcus rubenmarcus changed the title feat: Linear interactive wizard command feat: linear interactive wizard command Mar 8, 2026
- Anchor Linear URL regex patterns with ^https?:// (CodeQL fix)
- Change interface to type for plain data structures (Greptile)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant