Skip to content

Conversation

@ralfschimmel
Copy link

@ralfschimmel ralfschimmel commented Dec 4, 2025

Summary

Add comprehensive document management for Linear:

  • documents create: Create new documents with optional project/team association
  • documents read: Read document content by ID
  • documents list: List documents, filterable by project or issue
  • documents update: Update document title, content, project, icon, color
  • documents delete: Soft delete (trash) documents

Key Features

Issue Integration

  • --issue filter on documents list shows documents attached to an issue
  • --attach-to option on documents create links a new document to an issue

These features use Linear's Attachments API internally to link documents to issues.

Design Decision

The attachments CLI commands have been removed from this PR. The attachments service is kept as internal plumbing for documents-to-issues linking only.

Linear has a confusing distinction between:

  • Embeds: Files uploaded into issue descriptions (parsed from markdown)
  • Attachments: External links explicitly attached to issues

Since the primary use case is Documents (for workflow systems), keeping attachments as internal-only avoids user confusion.

Test plan

  • Build passes
  • documents create --title "Test" creates a document
  • documents list returns documents
  • documents list --issue ABC-123 returns documents attached to issue
  • documents read <id> returns document content

🤖 Generated with Claude Code

@czottmann
Copy link
Owner

czottmann commented Dec 6, 2025

Thanks for the PR, @ralfschimmel! I seem to be unable to get it to work, though.

I have a Linear issue (ZCO-1569) which contains a PNG and a GIF (both embeds), and a MD document (as attachment). All three are listed when I read the issue:

> tsx src/main.ts issues read ZCO-1569

{
  "id": "de732438-8ae2-4f9e-95a9-85a614b04816",
  "identifier": "ZCO-1569",
  "title": "File embed testing grounds",
  "description": "",
  "embeds": [
    {
      "label": "Confident Man and Futuristic Car.png",
      "url": "https://uploads.linear.app/7df2165d-5920-4338-950f-…/571bf0bf-3586-4f92-9427-…/1234a028-2053-452c-8da4-…?signature=…",
      "expiresAt": "2025-12-06T14:11:23.278Z"
    },
    {
      "label": "i-swear-to-god-connor.gif",
      "url": "https://uploads.linear.app/7df2165d-5920-4338-950f-…/571bf0bf-3586-4f92-9427-…/00d4a028-2053-452c-8da4-…?signature=…",
      "expiresAt": "2025-12-06T14:11:23.278Z"
    },
    {
      "label": "swift6-migration-compact.md",
      "url": "https://uploads.linear.app/7df2165d-5920-4338-950f-…/316bcc3a-baa7-4b01-a6dc-…/591f244c-5ca9-4777-bcef-…?signature=…",
      "expiresAt": "2025-12-06T14:11:23.278Z"
    }
  ],
  

I think tsx src/main.ts attachments list --issue ZCO-1569 should list the MD doc, but it doesn't, I only get an empty array back. Am I holding it wrong?

Add comprehensive document management for Linear:
- documents create: Create new documents with optional project/team association
- documents read: Read document content by ID
- documents list: List documents, filterable by project or issue
- documents update: Update document title, content, project, icon, color
- documents delete: Soft delete (trash) documents

The --issue filter on `documents list` uses the attachments API internally
to find Linear Documents that are attached to a specific issue.

The --attach-to option on `documents create` allows linking a new document
to an issue via an attachment.

Note: Attachments service is kept internal (no CLI commands) - it's used
as plumbing for the documents-to-issues linking feature.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@ralfschimmel ralfschimmel force-pushed the feature/documents-list-issue-filter branch from 9ac1a7f to 9aa04f0 Compare December 8, 2025 10:31
@ralfschimmel ralfschimmel changed the title [FEAT] Add --issue filter to documents list command [FEAT] Add documents CLI commands Dec 8, 2025
@ralfschimmel
Copy link
Author

Response to Feedback

Thanks for testing! You're right that attachments list --issue didn't show your embedded files - but that's actually expected behavior based on Linear's data model.

Linear's File Concepts

Linear has two different ways files can be associated with issues:

  1. Embeds - Files uploaded directly into issue descriptions (drag-drop/paste). These show up in the embeds array when reading an issue because they're parsed from the description markdown.

  2. Attachments - External links explicitly attached via Linear's Attachments API. These are separate entities, not inline file uploads.

Your PNG, GIF, and MD files were uploaded into the description, so they're embeds, not attachments.

Updated PR

I've removed the attachments CLI commands from this PR to avoid this confusion. The attachments service is now kept internal-only as plumbing for the documents feature:

  • documents list --issue ABC-123 - Lists Linear Documents attached to an issue (via attachments)
  • documents create --attach-to ABC-123 - Creates a document and links it to an issue

This way, the PR focuses on Documents (first-class Linear entities) without exposing the confusing attachments/embeds distinction to users.

Copy link
Owner

@czottmann czottmann left a comment

Choose a reason for hiding this comment

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

Alright, now I understand: we're talking about the (mainly) project-level documents, not issue-level files and embeds. 👍🏼

Second review: Good stuff, we're almost there! Clean architecture, good test coverage, good API design, solid error handling, and documentation. I see some issues, though.

🔴 Critical: Unrelated breaking change

src/queries/common.ts removes branchName from ISSUE_CORE_FIELDS, but:

  • src/utils/graphql-issues-service.ts:824 still references issue.branchName
  • src/utils/linear-types.d.ts:6 still defines the field

This silently breaks branch name retrieval for issues. I guess it's accidental, so please revert it.

🟡 Error message references non-existent command

src/commands/documents.ts:171 suggests:

To retry attachment: linearis attachments create --issue ...

But the PR description says attachments CLI commands were removed. People following this advice will get a "command not found" error.

🟡 Missing unit tests for URL parsing

extractDocumentIdFromUrl() (src/commands/documents.ts:53-80) handles multiple edge cases but has no unit tests. Given it's parsing URLs with assumptions about Linear's format, this deffo deserves coverage.

Minor/Optional

  • LIST_DOCUMENTS_BY_IDS_QUERY is identical to LIST_DOCUMENTS_QUERY - unless there are good arguments against it, should be consolidated

Summary

As I've said, good stuff, with some minor and easily fixable issues. Please make those changes, and I'll merge it! 🤙🏼

- Restore accidentally removed `branchName` field in ISSUE_CORE_FIELDS
- Remove misleading retry suggestion from attachment error message
- Export `extractDocumentIdFromUrl()` and add comprehensive unit tests (19 tests)
- Consolidate duplicate queries (remove LIST_DOCUMENTS_BY_IDS_QUERY)
- Improve type safety: change `_options: any` to `_options: unknown`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@ralfschimmel
Copy link
Author

Review Feedback Addressed

Thanks for the thorough review! All requested changes have been implemented:

🔴 Critical: branchName field restored

Reverted the accidental removal from ISSUE_CORE_FIELDS in src/queries/common.ts.

🟡 Error message fixed

Removed the misleading retry suggestion that referenced the non-existent attachments create command. The error now simply reports the failure without confusing advice.

🟡 Unit tests added for URL parsing

  • Exported extractDocumentIdFromUrl() for testability
  • Added 19 unit tests in tests/unit/documents-url-parsing.test.ts covering:
    • Valid Linear document URLs (various formats)
    • Non-Linear URLs (GitHub, Google Docs, etc.)
    • Linear URLs without document path (issues, projects)
    • Edge cases (malformed URLs, empty strings, no hyphens, etc.)

Minor: Query consolidation

Removed LIST_DOCUMENTS_BY_IDS_QUERY and updated the service to use LIST_DOCUMENTS_QUERY instead.

Note on _options parameters

These parameters cannot be removed because Commander.js always passes (argument, options, command) to action handlers, even when no options are defined. Removing the parameter causes command to receive the empty options object instead of the Command instance. I've:

  • Changed the type from any to unknown for better type safety
  • Added comments explaining why the parameter is required

All tests pass (except 2 pre-existing failures in cycles tests unrelated to this PR).

@czottmann
Copy link
Owner

Thanks, @ralfschimmel!

@czottmann czottmann merged commit 77b2336 into czottmann:main Dec 11, 2025
2 checks passed
czottmann added a commit that referenced this pull request Dec 11, 2025
Document new features from recent PRs:
- embeds upload command (PR #23)
- documents commands (PR #21)

Also add Ralf Schimmel to contributors.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants