Skip to content

Commit d2063cf

Browse files
roboalchemistclaude
andcommitted
LINE-23: Schema introspection - ProjectUpdate type audit
Added new fields from Linear GraphQL schema: - slugId: URL-friendly identifier - isDiffHidden: Whether project diff is hidden - isStale: Whether update is stale - diff: JSON object of changed fields - diffMarkdown: Markdown-formatted diff text - infoSnapshot: Snapshot of project state when update was created - commentCount: Number of comments on the update Added CLI flags: - --hide-diff for create command - --hide-diff for update command Updated display output (plaintext and rich) to show new fields. Tested with live API - all new fields returned correctly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent e8899bd commit d2063cf

2 files changed

Lines changed: 95 additions & 11 deletions

File tree

cmd/project_update.go

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ var statusGetCmd = &cobra.Command{
159159
if plaintext {
160160
fmt.Printf("# Project Status Update\n\n")
161161
fmt.Printf("- **ID**: %s\n", update.ID)
162+
fmt.Printf("- **Slug ID**: %s\n", update.SlugId)
162163
fmt.Printf("- **Health**: %s\n", update.Health)
163164
if update.User != nil {
164165
fmt.Printf("- **Author**: %s (%s)\n", update.User.Name, update.User.Email)
@@ -177,7 +178,19 @@ var statusGetCmd = &cobra.Command{
177178
if update.URL != "" {
178179
fmt.Printf("- **URL**: %s\n", update.URL)
179180
}
181+
if update.IsStale {
182+
fmt.Printf("- **Stale**: yes\n")
183+
}
184+
if update.IsDiffHidden {
185+
fmt.Printf("- **Diff Hidden**: yes\n")
186+
}
187+
if update.CommentCount > 0 {
188+
fmt.Printf("- **Comments**: %d\n", update.CommentCount)
189+
}
180190
fmt.Printf("\n## Body\n%s\n", update.Body)
191+
if update.DiffMarkdown != nil && *update.DiffMarkdown != "" {
192+
fmt.Printf("\n## Changes Since Last Update\n%s\n", *update.DiffMarkdown)
193+
}
181194
return
182195
}
183196

@@ -209,10 +222,30 @@ var statusGetCmd = &cobra.Command{
209222
color.New(color.Bold).Sprint("URL:"),
210223
color.New(color.FgBlue, color.Underline).Sprint(update.URL))
211224
}
225+
if update.IsStale {
226+
fmt.Printf("%s %s\n",
227+
color.New(color.Bold).Sprint("Stale:"),
228+
color.New(color.FgYellow).Sprint("Yes"))
229+
}
230+
if update.IsDiffHidden {
231+
fmt.Printf("%s %s\n",
232+
color.New(color.Bold).Sprint("Diff Hidden:"),
233+
"Yes")
234+
}
235+
if update.CommentCount > 0 {
236+
fmt.Printf("%s %d\n",
237+
color.New(color.Bold).Sprint("Comments:"),
238+
update.CommentCount)
239+
}
212240
fmt.Printf("%s %s\n",
213241
color.New(color.Bold).Sprint("ID:"),
214242
color.New(color.FgWhite, color.Faint).Sprint(update.ID))
215243
fmt.Printf("\n%s\n", update.Body)
244+
if update.DiffMarkdown != nil && *update.DiffMarkdown != "" {
245+
fmt.Printf("\n%s\n%s\n",
246+
color.New(color.Bold).Sprint("Changes Since Last Update:"),
247+
*update.DiffMarkdown)
248+
}
216249
fmt.Println()
217250
},
218251
}
@@ -231,6 +264,7 @@ Health values: onTrack, atRisk, offTrack
231264
Examples:
232265
linear-cli project status create PROJECT-ID --body "Sprint going well" --health onTrack
233266
linear-cli project status create PROJECT-ID --body-file status-update.md --health atRisk
267+
linear-cli project status create PROJECT-ID --body "Private update" --hide-diff
234268
cat report.md | linear-cli project status create PROJECT-ID --body-file - --health onTrack`,
235269
Args: cobra.ExactArgs(1),
236270
Run: func(cmd *cobra.Command, args []string) {
@@ -274,6 +308,10 @@ Examples:
274308
if health != "" {
275309
input["health"] = health
276310
}
311+
if cmd.Flags().Changed("hide-diff") {
312+
hideDiff, _ := cmd.Flags().GetBool("hide-diff")
313+
input["isDiffHidden"] = hideDiff
314+
}
277315

278316
update, err := client.CreateProjectUpdate(context.Background(), input)
279317
if err != nil {
@@ -320,7 +358,8 @@ Examples:
320358
linear-cli project status update UPDATE-ID --body "Updated status text"
321359
linear-cli project status update UPDATE-ID --body-file updated-status.md
322360
linear-cli project status update UPDATE-ID --health offTrack
323-
linear-cli project status update UPDATE-ID --body "New text" --health onTrack`,
361+
linear-cli project status update UPDATE-ID --body "New text" --health onTrack
362+
linear-cli project status update UPDATE-ID --hide-diff`,
324363
Args: cobra.ExactArgs(1),
325364
Run: func(cmd *cobra.Command, args []string) {
326365
plaintext := viper.GetBool("plaintext")
@@ -357,6 +396,11 @@ Examples:
357396
input["health"] = health
358397
}
359398

399+
if cmd.Flags().Changed("hide-diff") {
400+
hideDiff, _ := cmd.Flags().GetBool("hide-diff")
401+
input["isDiffHidden"] = hideDiff
402+
}
403+
360404
if len(input) == 0 {
361405
output.Error("No updates specified. Use --body and/or --health.", plaintext, jsonOut)
362406
os.Exit(1)
@@ -461,11 +505,13 @@ func init() {
461505
statusCreateCmd.Flags().StringP("body", "b", "", "Status update body text (required unless --body-file is used)")
462506
statusCreateCmd.Flags().String("body-file", "", "Read body from a markdown file (use - for stdin)")
463507
statusCreateCmd.Flags().String("health", "", "Project health: onTrack, atRisk, offTrack")
508+
statusCreateCmd.Flags().Bool("hide-diff", false, "Hide the project diff in this update")
464509

465510
// update flags
466511
statusUpdateCmd.Flags().StringP("body", "b", "", "New body text")
467512
statusUpdateCmd.Flags().String("body-file", "", "Read body from a markdown file (use - for stdin)")
468513
statusUpdateCmd.Flags().String("health", "", "New health: onTrack, atRisk, offTrack")
514+
statusUpdateCmd.Flags().Bool("hide-diff", false, "Hide the project diff in this update")
469515

470516
// Aliases so "linear-cli project update-status" also works — handled via Aliases on projectStatusCmd
471517
}

pkg/api/queries.go

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -525,16 +525,23 @@ type ProjectUpdates struct {
525525
}
526526

527527
type ProjectUpdate struct {
528-
ID string `json:"id"`
529-
Body string `json:"body"`
530-
User *User `json:"user"`
531-
CreatedAt time.Time `json:"createdAt"`
532-
UpdatedAt time.Time `json:"updatedAt"`
533-
EditedAt *time.Time `json:"editedAt"`
534-
ArchivedAt *time.Time `json:"archivedAt"`
535-
Health string `json:"health"`
536-
URL string `json:"url"`
537-
Project *Project `json:"project"`
528+
ID string `json:"id"`
529+
SlugId string `json:"slugId"`
530+
Body string `json:"body"`
531+
User *User `json:"user"`
532+
CreatedAt time.Time `json:"createdAt"`
533+
UpdatedAt time.Time `json:"updatedAt"`
534+
EditedAt *time.Time `json:"editedAt"`
535+
ArchivedAt *time.Time `json:"archivedAt"`
536+
Health string `json:"health"`
537+
URL string `json:"url"`
538+
Project *Project `json:"project"`
539+
IsDiffHidden bool `json:"isDiffHidden"`
540+
IsStale bool `json:"isStale"`
541+
Diff map[string]interface{} `json:"diff"`
542+
DiffMarkdown *string `json:"diffMarkdown"`
543+
InfoSnapshot map[string]interface{} `json:"infoSnapshot"`
544+
CommentCount int `json:"commentCount"`
538545
}
539546

540547
type Documents struct {
@@ -2998,13 +3005,20 @@ func (c *Client) GetProjectUpdates(ctx context.Context, projectID string, first
29983005
projectUpdates(first: $first, after: $after) {
29993006
nodes {
30003007
id
3008+
slugId
30013009
body
30023010
health
30033011
url
30043012
createdAt
30053013
updatedAt
30063014
editedAt
30073015
archivedAt
3016+
isDiffHidden
3017+
isStale
3018+
diff
3019+
diffMarkdown
3020+
infoSnapshot
3021+
commentCount
30083022
user {
30093023
id
30103024
name
@@ -3054,13 +3068,20 @@ func (c *Client) GetProjectUpdate(ctx context.Context, id string) (*ProjectUpdat
30543068
query ProjectUpdate($id: String!) {
30553069
projectUpdate(id: $id) {
30563070
id
3071+
slugId
30573072
body
30583073
health
30593074
url
30603075
createdAt
30613076
updatedAt
30623077
editedAt
30633078
archivedAt
3079+
isDiffHidden
3080+
isStale
3081+
diff
3082+
diffMarkdown
3083+
infoSnapshot
3084+
commentCount
30643085
user {
30653086
id
30663087
name
@@ -3100,11 +3121,20 @@ func (c *Client) CreateProjectUpdate(ctx context.Context, input map[string]inter
31003121
projectUpdateCreate(input: $input) {
31013122
projectUpdate {
31023123
id
3124+
slugId
31033125
body
31043126
health
31053127
url
31063128
createdAt
31073129
updatedAt
3130+
editedAt
3131+
archivedAt
3132+
isDiffHidden
3133+
isStale
3134+
diff
3135+
diffMarkdown
3136+
infoSnapshot
3137+
commentCount
31083138
user {
31093139
id
31103140
name
@@ -3150,12 +3180,20 @@ func (c *Client) UpdateProjectUpdate(ctx context.Context, id string, input map[s
31503180
projectUpdateUpdate(id: $id, input: $input) {
31513181
projectUpdate {
31523182
id
3183+
slugId
31533184
body
31543185
health
31553186
url
31563187
createdAt
31573188
updatedAt
31583189
editedAt
3190+
archivedAt
3191+
isDiffHidden
3192+
isStale
3193+
diff
3194+
diffMarkdown
3195+
infoSnapshot
3196+
commentCount
31593197
user {
31603198
id
31613199
name

0 commit comments

Comments
 (0)