Conversation
…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>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Issue Linking ReminderThis PR doesn't appear to have a linked issue. Consider linking to:
Using If this PR doesn't need an issue, you can ignore this message. |
✔️ Bundle Size Analysis
Bundle breakdown |
🔗 Docs PreviewPreview URL: https://feat-linear-integration-wiza.ralph-starter-docs.pages.dev This preview was deployed from the latest commit on this PR. |
Greptile SummaryThis PR introduces an interactive Linear issues wizard ( Key changes:
Issues found:
Confidence Score: 4/5
Sequence DiagramsequenceDiagram
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
Last reviewed commit: 549bb51 |
src/commands/linear.ts
Outdated
| 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; | ||
| } |
There was a problem hiding this 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.
| 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!
- 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>
Summary
ralph-starter lineartop-level command for interactive Linear issue selectionsrc/integrations/wizards/shared.tsralph-starter run --from linearis used without--projectChanges
src/commands/linear.ts— Linear wizard with GraphQL team/project/issue fetchingsrc/cli.ts— Registerralph-starter linearcommandsrc/commands/run.ts— Wizard fallback for--from lineardocs/docs/sources/linear.md— Wizard section + examplesREADME.md— Commands table entryTest plan
ralph-starter linearlaunches wizard and completes flowralph-starter run --from linear(no --project) redirects to wizardralph-starter run --from linear --project ENGstill works (existing behavior)linear.app/.../issue/TEAM-123pnpm build— no new errors (pre-existing pixelmatch/sharp errors only)🤖 Generated with Claude Code