feat!: complete architecture redesign with GraphQL codegen, auth system, and developer tooling#45
Merged
iamfj merged 177 commits intoczottmann:nextfrom Feb 13, 2026
Merged
feat!: complete architecture redesign with GraphQL codegen, auth system, and developer tooling#45iamfj merged 177 commits intoczottmann:nextfrom
iamfj merged 177 commits intoczottmann:nextfrom
Conversation
Add GitHub Actions workflow for automated PR assistance using Claude. This workflow provides intelligent PR reviews and suggestions. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add GitHub Actions workflow for automated code reviews using Claude. This workflow analyzes code changes and provides detailed feedback. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add concurrency configuration to the Claude code review workflow to manage simultaneous runs and cancel in-progress jobs for pull requests.
Changes GetIssueById and GetIssueByIdentifier to use CompleteIssueWithCommentsFields fragment instead of CompleteIssueFields, restoring comment data that was inadvertently removed during the GraphQL file migration. This fixes a data regression where reading issues by ID or identifier would no longer return comment data as expected. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Creates query loader modules in src/queries/ that read GraphQL operations from .graphql files and export them as string constants. This bridges the gap between the new .graphql file structure and existing service imports. The loaders: - Read .graphql files at runtime using Node.js fs module - Extract individual operations with fragment dependencies - Export query/mutation strings with the same names services expect - Enable existing code to work without modification Fixes TypeScript compilation errors where services imported from deleted src/queries/*.ts files. Services now successfully import from the new loader modules which dynamically load from graphql/queries/ and graphql/mutations/ directories. Files added: - src/queries/issues.ts - src/queries/documents.ts - src/queries/attachments.ts - src/queries/project-milestones.ts Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Updates AGENTS.md (CLAUDE.md) to reflect the new GraphQL architecture: - Documents the dual structure of graphql/ directory (source .graphql files) and src/queries/ (runtime query loaders) - Updates "Query Definitions" section to explain both components - Rewrites "Adding GraphQL Queries" workflow to document the new process: 1. Define operations in .graphql files 2. Run npm run generate for codegen 3. Query loaders automatically extract operations - Changes references from src/queries/common.ts to graphql/queries/issues.graphql - Explains the separation between human-written .graphql files and generated TypeScript types in src/gql/ Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add type aliases for GraphQL query/mutation return types to improve readability in method signatures. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Return raw codegen types directly instead of transforming to manual types. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Return union type of raw codegen types instead of transforming. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Return raw codegen type directly. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Return raw codegen type directly. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Use QuerySearchIssuesArgs instead of full query type. Remove transformation. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Delete transformIssueData and doTransformIssueData - no longer needed since services return raw codegen types. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Line 166 referenced undefined variable 'id' instead of 'input.id'. This caused a ReferenceError when resolving non-UUID issue identifiers. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Line 572 referenced non-existent 'input.milestoneId' instead of 'input.projectMilestoneId'. This would show 'undefined' in error messages when milestone resolution fails. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Lines 670-677 spread entire searchArgs object into GraphQL variables, but SearchIssues query only accepts 'term' and 'first' parameters. This caused GraphQL validation errors when extra properties like 'limit' were passed through. Now destructures only 'term' from searchArgs and passes it explicitly along with 'first' parameter. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Pass QuerySearchIssuesArgs fields directly instead of wrong type. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Ensure parameters match IssueUpdateInput type from codegen. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add type aliases, remove transformations, return raw GraphQL types. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add type aliases, remove transformations, return raw GraphQL types. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Define CycleListOptions and CycleReadOptions locally. Replace LinearCycle with codegen type alias. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add missing option interfaces (MilestoneListOptions, MilestoneReadOptions, MilestoneCreateOptions, MilestoneUpdateOptions) and replace LinearProjectMilestone with ProjectMilestoneUpdateInput from codegen. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Delete linear-types.d.ts - all types now generated from GraphQL schema via codegen. - Add type aliases in linear-service.ts for LinearLabel, LinearComment, and CreateCommentArgs - Replace LinearProject with inline type definition - Fix bug in graphql-issues-service.ts: use input.projectMilestoneId instead of input.milestoneId - Remove dead code for milestone fallback lookup Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cess Biome's --unsafe flag incorrectly converted command.parent!.parent! to optional chaining, causing TypeScript errors. Non-null assertions are correct here since Commander.js always sets parent references. Also disables noNonNullAssertion biome rule as it conflicts with the established Commander.js patterns in this codebase. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
build(tooling): add biome, lefthook, and commitlint
…nd maintainability
…s with relations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tring Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Moves resolveIssueId calls for relation targets to before the createIssue call so invalid target identifiers fail fast without leaving a partially created issue. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Covers the defensive null check branch on the issue query result. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deduplicate relation flag logic between issues create and update by extracting resolveRelationTarget() and applyRelation() helpers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Consolidate duplicated relation flag validation from create and update handlers into a shared function using the RelationFlags interface. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat(issues): add issue relations support (blocking/blocked by/related/duplicate)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Consolidates duplicate regex loops in embed-parser, simplifies URL parsing, and removes redundant documentation comments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extracts shared SOURCE_LABELS constant in auth, inlines arrow functions, uses ternary for optional ID resolution, and removes unused ErrorResponse interface. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
refactor: remove verbose JSDoc and simplify codebase
This was referenced Feb 13, 2026
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.
Overview
Hey Carlo! 👋
This is a comprehensive contribution from my fork that redesigns the Linearis architecture from the ground up. The goal was to make the codebase more maintainable, type-safe, and extensible — while also adding several new features that the community has been requesting.
This PR represents ~18 merged PRs in my fork, covering architecture, features, tooling, and documentation. I've organized everything below so you can review it incrementally.
Stats: 189 files changed, ~21k insertions, ~38k deletions (net reduction of ~17k lines)
What Changed and Why
1. GraphQL Codegen Migration
PRs: #2, #3, #4, #5, #6, #7, #8
Why: The original codebase used manually maintained TypeScript type definitions and runtime GraphQL string loading. This was error-prone, hard to keep in sync with the Linear API schema, and lacked compile-time type safety.
What:
graphql-codegeninfrastructure with acodegen.config.ts.graphqlfiles undergraphql/queries/andgraphql/mutations/linear-types.d.ts) with auto-generated typesclient.request<T>()call is now fully typed with codegen outputsrc/queries/runtime loader and manual types2. Five-Layer Architecture Redesign
PR: #10
Why: The original
utils/directory mixed concerns — ID resolution, GraphQL operations, business logic, and CLI orchestration were all tangled together. This made it hard to test individual layers, reuse logic, or reason about data flow.What: Introduced a strict five-layer architecture:
src/client/src/resolvers/LinearSdkClientsrc/services/GraphQLClientsrc/commands/createContext()src/common/Key design decisions:
GraphQLClientandLinearSdkClientwrappersnotFoundError,multipleMatchesError)3. CLI Naming Redesign & Two-Tier Usage System
PRs: #12, #14
Why: Since Linearis is designed for LLM agents, the usage/help system needs to be token-efficient. Traditional
--helpoutput is verbose and wastes tokens. Also, some command names were inconsistent (e.g.,project-milestonesvsmilestones,embedsvsfiles).What:
project-milestones→milestones,embeds→fileslinearis usage): ~200 token overview of all domainslinearis <domain> usage): ~300-500 token detailed reference per domainDomainMetawith structured metadataUSAGE.mdis auto-generated on every build and shipped with the package4. Authentication System
PR: #26
Why: The original auth only supported env vars and a plaintext token file. There was no interactive setup, no token validation, and no secure storage — making it hard for new users to get started.
What: Full
linearis authcommand group:linearis auth login— interactive token setup with browser-based token page, encrypted local storagelinearis auth status— shows current auth method and token sourcelinearis auth logout— removes stored credentials~/.linearis/tokenGetViewerGraphQL query5. Issue Relations Support
PR: #30 — addresses czottmann/linearis#27
Why: Community-requested feature for managing issue dependencies and relationships.
What:
issue-relation-servicewith create, find, and delete operationsissues createandissues update:linearis issues create "Task" --team ENG --blocks ENG-124 linearis issues update ENG-123 --related ENG-200 linearis issues update ENG-123 --duplicate ENG-50--blocks,--blocked-by,--related,--duplicate6. Developer Tooling
PRs: #29, #23, #9
What:
7. Codebase Simplification
PR: #31
What: Final cleanup pass removing verbose JSDoc comments that restated what the code expressed, simplifying expressions, and removing unused interfaces. Net result: -634 lines with no behavioral changes.
8. Agent Instructions & Skills
PRs: #27, #28
What:
AGENTS.md(also serves asCLAUDE.md) documenting all architectural rules, patterns, and anti-patterns for AI-assisted developmentBreaking Changes
project-milestones→milestones,embeds→files--issues-first→--limit)searchsubcommands merged intolistwith filter flagsUpstream Issues Addressed
How to Review
I'd suggest reviewing in this order:
AGENTS.mdfor the full picturegraphql/directory andcodegen.config.tssrc/client/src/common/src/resolvers/andsrc/services/src/commands/tests/unit/src/commands/auth.ts,src/common/encryption.ts,src/common/token-storage.tsAll Fork PRs (chronological)
Happy to discuss any of this, break things into smaller pieces if preferred, or adjust the approach. Looking forward to your feedback! 🙏