A terminal client for Tangled.
tui go tangled cli
13

Configure Feed

Select the types of activity you want to include in your feed.

cli: add issue view command

Aly Raffauf (Jul 8, 2026, 12:00 PM EDT) 352b94a6 90885a48

+78
+78
internal/cli/issue_view.go
··· 1 + package cli 2 + 3 + import ( 4 + "encoding/json" 5 + "fmt" 6 + "strings" 7 + 8 + "github.com/alyraffauf/tg/tangled" 9 + "github.com/spf13/cobra" 10 + ) 11 + 12 + var issueViewRepo string 13 + 14 + var issueViewCmd = &cobra.Command{ 15 + Use: "view <rkey>", 16 + Short: "View an issue for a Tangled repository", 17 + Long: `View an issue by its rkey (the last segment of its at:// URI). 18 + 19 + If --repo is not set, the repository is detected from the current 20 + directory's git origin remote.`, 21 + Args: cobra.ExactArgs(1), 22 + RunE: func(cmd *cobra.Command, args []string) error { 23 + ctx := cmd.Context() 24 + rkey := args[0] 25 + 26 + targetArgs := []string{} 27 + if issueViewRepo != "" { 28 + targetArgs = []string{issueViewRepo} 29 + } 30 + handle, repo, err := resolveTarget(ctx, targetArgs) 31 + if err != nil { 32 + return err 33 + } 34 + 35 + repoDid, err := findRepoDid(ctx, handle, repo) 36 + if err != nil { 37 + return err 38 + } 39 + 40 + issues, err := client.ListIssues(ctx, repoDid, tangled.IssueListOpts{ 41 + Limit: defaultListLimit, 42 + }) 43 + if err != nil { 44 + return fmt.Errorf("list issues for %s/%s: %w", handle, repo, err) 45 + } 46 + 47 + issue, authorDID, err := findIssueByRKey(issues.Items, rkey) 48 + if err != nil { 49 + return err 50 + } 51 + 52 + fmt.Printf("Title: %s\n", issue.Title) 53 + fmt.Printf("Author: %s\n", resolveAuthor(ctx, authorDID)) 54 + fmt.Printf("Created: %s\n", issue.CreatedAt) 55 + if issue.Body != "" { 56 + fmt.Printf("\n%s\n", issue.Body) 57 + } 58 + return nil 59 + }, 60 + } 61 + 62 + func init() { 63 + issueViewCmd.Flags().StringVarP(&issueViewRepo, "repo", "R", "", "Target repository as handle/repo") 64 + } 65 + 66 + func findIssueByRKey(items []tangled.IssueListItem, rkey string) (*tangled.IssueRecord, string, error) { 67 + for _, item := range items { 68 + if !strings.HasSuffix(item.URI, "/"+rkey) { 69 + continue 70 + } 71 + var issue tangled.IssueRecord 72 + if err := json.Unmarshal(item.Value, &issue); err != nil { 73 + return nil, "", fmt.Errorf("decode issue %q: %w", rkey, err) 74 + } 75 + return &issue, extractDID(item.URI), nil 76 + } 77 + return nil, "", fmt.Errorf("issue %q not found", rkey) 78 + }