# fix(trail): review feedback — stderr auth errors, trim type/priority, partial-update clarity

`d4732b1`→[main](/content/gh/entireio/cli/commits/main/index.html)·
  
computermode·1w ago·6 files·+58 added/-27 removed

- Route auth/not-logged-in messages to stderr (not stdout) for approve,  
  request-changes, approvals, comment, attachment, and watchers, so  
  '--json' output stays machine-parseable.  
- Trim --type/--priority before sending on the wire (they were validated  
  trimmed but sent raw).  
- When the split metadata/body update partially applies, report that the  
  metadata change already landed so only --body needs a retry.  
- Correct the splitTrailUpdate comment to match the code's label handling.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

## Sessions

01KX6THZDP2XW3WDGFFAZ4WRXW View transcript

### CLI Trail Commands and UI Parity

Claude Code·Opus 4.8·1 step

## Changes

6

- cmd/entire/cli  
  
  - Mtrail_approval_cmd.go +9/-7
  
  - Mtrail_attachment_cmd.go +3/-3
  
  - Mtrail_cmd.go +18/-7
  
  - Mtrail_cmd_test.go +16
  
  - Mtrail_comment_cmd.go +10/-9
  
  - Mtrail_watchers_cmd.go +2/-1

```go
return ""
}

goc func submitTrailApproval(ctx context.Context, w io.Writer, insecureHTTP bool, repoOverride, selector, branch, event, message, successVerb string) error {
func submitTrailApproval(ctx context.Context, w, errW io.Writer, insecureHTTP bool, repoOverride, selector, branch, event, message, successVerb string) error {
if selector != "" && strings.TrimSpace(branch) != "" {
return errors.New("pass a trail selector or --branch, not both")
}
1 unmodified line

if err != nil {
return err
}
return runAuthenticatedTrailAPI(ctx, w, insecureHTTP, repoOverride, func(ctx context.Context, client *api.Client) error {
// Auth/not-logged-in messages go to stderr; w carries command output only.
return runAuthenticatedTrailAPI(ctx, errW, insecureHTTP, repoOverride, func(ctx context.Context, client *api.Client) error {
found, forge, owner, repoName, err := resolveNumberedTrail(ctx, client, repoOverride, selector, branch)
if err != nil {
return err
}
26 unmodified lines

// The trail must be open and have a linked branch.`,
Args: cobra.MaximumNArgs(1),  
RunE: func(cmd *cobra.Command, args []string) error {  
return submitTrailApproval(cmd.Context(), cmd.OutOrStdout(), trailInsecureHTTP(cmd),
return submitTrailApproval(cmd.Context(), cmd.OutOrStdout(), cmd.ErrOrStderr(), trailInsecureHTTP(cmd),
trailRepoFlag(cmd), selectorFromArgs(args), branch, "APPROVE", message, "Approved")
},
}

func runTrailApprovals(ctx context.Context, w io.Writer, insecureHTTP bool, repoOverride, selector, branch string, jsonOut bool) error {  
func runTrailApprovals(ctx context.Context, w, errW io.Writer, insecureHTTP bool, repoOverride, selector, branch string, jsonOut bool) error {  
if selector != "" && strings.TrimSpace(branch) != "" {
return errors.New("pass a trail selector or --branch, not both")
}
return runAuthenticatedTrailAPI(ctx, w, insecureHTTP, repoOverride, func(ctx context.Context, client *api.Client) error {
// Auth/not-logged-in messages go to stderr; w carries command output only.
return runAuthenticatedTrailAPI(ctx, errW, insecureHTTP, repoOverride, func(ctx context.Context, client *api.Client) error {
found, forge, owner, repoName, err := resolveNumberedTrail(ctx, client, repoOverride, selector, branch)
if err != nil {
return err
}
//Additional contents omitted for brevity.
```
