cli

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 25, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package cli wires the kong grammar, the runtime, and the exit-code mapping. main() does nothing but os.Exit(cli.Run(...)) so every path is testable in-process.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Run

func Run(args []string, stdin io.Reader, stdout, stderr io.Writer) int

Run parses args and dispatches, returning the process exit code.

Types

type AgentCmd

type AgentCmd struct{}

func (*AgentCmd) Run

func (c *AgentCmd) Run(rt *Runtime) error

type AuthCmd

type AuthCmd struct {
	Status  AuthStatusCmd  `cmd:"" help:"Test the token; report account, expiry, and source."`
	Login   AuthLoginCmd   `cmd:"" help:"Authenticate (paste-the-callback-URL, or --token-stdin)."`
	Logout  AuthLogoutCmd  `cmd:"" help:"Remove stored credentials from the keyring/file (local only)."`
	Refresh AuthRefreshCmd `cmd:"" help:"Extend the long-lived (60-day) token; safe on a schedule."`
}

AuthCmd wires the Threads OAuth model (spec.md §Auth): --token-stdin (headless) + paste-the-callback-URL (human onboarding), long-lived 60d token with refresh. Secrets come via stdin/env (never argv) and persist in the OS keyring + 0600 fallback (contract §7).

type AuthLoginCmd

type AuthLoginCmd struct {
	TokenStdin bool `name:"token-stdin" help:"Read a pre-obtained token from stdin (headless; no browser)."`
}

func (*AuthLoginCmd) Run

func (c *AuthLoginCmd) Run(rt *Runtime) error

type AuthLogoutCmd

type AuthLogoutCmd struct{}

func (*AuthLogoutCmd) Run

func (c *AuthLogoutCmd) Run(rt *Runtime) error

type AuthRefreshCmd

type AuthRefreshCmd struct{}

func (*AuthRefreshCmd) Run

func (c *AuthRefreshCmd) Run(rt *Runtime) error

type AuthStatusCmd

type AuthStatusCmd struct{}

func (*AuthStatusCmd) Run

func (c *AuthStatusCmd) Run(rt *Runtime) error

type CLI

type CLI struct {
	// Output (contract §1, §6)
	Format  string `enum:"json,plain,tsv" default:"plain" help:"Output format: json, plain, or tsv."`
	JSON    bool   `help:"Shorthand for --format=json."`
	NoColor bool   `help:"Disable colored output."`
	Limit   int    `default:"50" help:"Maximum items to return for list operations."`
	Select  string `help:"Comma-separated dot-path field projection, e.g. id,text."`
	Concise bool   `help:"Drop null/empty fields from output (fewer tokens)."`

	// Safety (contract §2)
	AllowMutations bool `help:"Permit state-changing operations (off by default)."`
	DryRun         bool `help:"Print intended mutations without performing them."`
	NoInput        bool `help:"Never prompt; fail with exit 13 instead."`

	// Prompt-injection hardening (contract §8). Default-ON when an agent is consuming output
	// (JSON or non-TTY); force either way with these flags.
	WrapUntrusted   bool `help:"Fence free text from Threads as untrusted (force on)."`
	NoWrapUntrusted bool `help:"Do not fence untrusted text (force off)."`

	// Commands (noun-verb, service-namespaced)
	Profile  ProfileCmd  `cmd:"" help:"Read Threads profiles."`
	Post     PostCmd     `cmd:"" help:"List, read, and publish posts."`
	Reply    ReplyCmd    `cmd:"" help:"Read replies and manage replies on your posts."`
	Search   SearchCmd   `cmd:"" help:"Search public posts by keyword or topic."`
	Mentions MentionsCmd `cmd:"" help:"List public posts mentioning you."`
	Insights InsightsCmd `cmd:"" help:"Read post- and account-level metrics."`
	Auth     AuthCmd     `cmd:"" help:"Manage authentication."`
	Doctor   DoctorCmd   `cmd:"" help:"Diagnose setup and report fixes."`
	Schema   SchemaCmd   `cmd:"" help:"Print the machine-readable command schema (JSON)."`
	Agent    AgentCmd    `cmd:"" help:"Print the bundled agent SKILL.md."`
	Version  VersionCmd  `cmd:"" help:"Print the version."`
}

CLI is the kong grammar. Global flags are the universal agent-CLI contract surface; subcommands follow noun-verb grammar.

type DoctorCmd

type DoctorCmd struct {
	ForAgent bool `name:"for-agent" help:"Terser, machine-skimmable diagnostics for an agent."`
}

DoctorCmd runs real environment/auth/connectivity diagnostics.

func (*DoctorCmd) Run

func (c *DoctorCmd) Run(rt *Runtime) error

type InsightsAccountCmd

type InsightsAccountCmd struct {
	Metrics []string `help:"Subset of metrics to return (default: all)."`
	Since   string   `help:"ISO-8601 start of the window."`
	Until   string   `help:"ISO-8601 end of the window."`
}

func (*InsightsAccountCmd) Run

func (c *InsightsAccountCmd) Run(rt *Runtime) error

type InsightsCmd

type InsightsCmd struct {
	Post    InsightsPostCmd    `cmd:"" help:"Per-post metrics by media id."`
	Account InsightsAccountCmd `cmd:"" help:"Account-level metrics + demographics."`
}

InsightsCmd reads post- and account-level metrics. Numeric → no injection fencing needed.

type InsightsPostCmd

type InsightsPostCmd struct {
	ID string `arg:"" help:"Media id of the post."`
}

func (*InsightsPostCmd) Run

func (c *InsightsPostCmd) Run(rt *Runtime) error

type MentionsCmd

type MentionsCmd struct {
	List MentionsListCmd `cmd:"" help:"List public posts that mention you."`
}

MentionsCmd lists public posts mentioning the authenticated user. Free text from other users → fenced in agent mode (contract §8).

type MentionsListCmd

type MentionsListCmd struct {
	Cursor string `help:"Opaque pagination cursor."`
}

func (*MentionsListCmd) Run

func (c *MentionsListCmd) Run(rt *Runtime) error

type PostCmd

type PostCmd struct {
	List   PostListCmd   `cmd:"" help:"List the authenticated user's posts."`
	Get    PostGetCmd    `cmd:"" help:"Get one post by media id."`
	Create PostCreateCmd `cmd:"" help:"Publish a post (mutation; reviewed-artifact via --dry-run/--apply)."`
	Repost PostRepostCmd `cmd:"" help:"Repost a post by media id (mutation)."`
	Delete PostDeleteCmd `cmd:"" help:"Delete a post by media id (mutation, idempotent)."`
}

PostCmd groups the post noun-verb subcommands (the primary noun).

type PostCreateCmd

type PostCreateCmd struct {
	Text          string   `help:"Post text."`
	Image         []string `help:"Image URL (repeatable for a carousel)."`
	Video         []string `help:"Video URL (repeatable for a carousel)."`
	Link          string   `help:"Link attachment URL."`
	ReplyTo       string   `help:"Reply to this media id."`
	Quote         string   `help:"Quote this media id."`
	Topic         string   `help:"Topic tag."`
	ReplyAudience string   `enum:",everyone,accounts_you_follow,mentioned_only" default:"" help:"Who can reply."`
	Apply         string   `help:"Publish only the plan whose --dry-run hash equals this value."`
}

PostCreateCmd publishes a post. High-stakes + irreversible + public, so it uses the reviewed-artifact = approval pattern (contract §2): `--dry-run` emits the exact plan plus a content hash; `--apply <hash>` publishes only if the recomputed hash matches.

func (*PostCreateCmd) Run

func (c *PostCreateCmd) Run(rt *Runtime) error

type PostDeleteCmd

type PostDeleteCmd struct {
	ID string `arg:"" help:"Media id to delete."`
}

func (*PostDeleteCmd) Run

func (c *PostDeleteCmd) Run(rt *Runtime) error

type PostGetCmd

type PostGetCmd struct {
	ID string `arg:"" help:"Media id of the post."`
}

func (*PostGetCmd) Run

func (c *PostGetCmd) Run(rt *Runtime) error

type PostListCmd

type PostListCmd struct {
	Since  string `help:"Only posts on/after this ISO-8601 date."`
	Until  string `help:"Only posts on/before this ISO-8601 date."`
	Cursor string `help:"Opaque pagination cursor from a previous nextCursor."`
}

func (*PostListCmd) Run

func (c *PostListCmd) Run(rt *Runtime) error

type PostRepostCmd

type PostRepostCmd struct {
	ID string `arg:"" help:"Media id to repost."`
}

func (*PostRepostCmd) Run

func (c *PostRepostCmd) Run(rt *Runtime) error

type ProfileCmd

type ProfileCmd struct {
	Get ProfileGetCmd `cmd:"" help:"Get a profile (self or by user id)."`
}

ProfileCmd reads a Threads profile. The biography is user-controlled → fenced in agent mode.

type ProfileGetCmd

type ProfileGetCmd struct {
	User string `arg:"" optional:"" default:"me" help:"User id, or 'me' (default)."`
}

func (*ProfileGetCmd) Run

func (c *ProfileGetCmd) Run(rt *Runtime) error

type ReplyCmd

type ReplyCmd struct {
	List   ReplyListCmd   `cmd:"" help:"List top-level replies to a post."`
	Tree   ReplyTreeCmd   `cmd:"" help:"Show the full conversation tree for a post."`
	Create ReplyCreateCmd `cmd:"" help:"Reply to a post (mutation)."`
	Hide   ReplyHideCmd   `cmd:"" help:"Hide a reply on your post (mutation, idempotent)."`
	Unhide ReplyUnhideCmd `cmd:"" help:"Unhide a reply on your post (mutation, idempotent)."`
}

ReplyCmd groups reply reads + reply management. Reply text comes from other users → fenced in agent mode (contract §8). hide/unhide are idempotent (contract §9).

type ReplyCreateCmd

type ReplyCreateCmd struct {
	ID    string `arg:"" help:"Media id to reply to."`
	Text  string `help:"Reply text."`
	Image string `help:"Image URL."`
	Apply string `help:"Publish only the plan whose --dry-run hash equals this value."`
}

func (*ReplyCreateCmd) Run

func (c *ReplyCreateCmd) Run(rt *Runtime) error

type ReplyHideCmd

type ReplyHideCmd struct {
	ID string `arg:"" help:"Reply id to hide."`
}

func (*ReplyHideCmd) Run

func (c *ReplyHideCmd) Run(rt *Runtime) error

type ReplyListCmd

type ReplyListCmd struct {
	ID     string `arg:"" help:"Media id of the post."`
	Cursor string `help:"Opaque pagination cursor."`
}

func (*ReplyListCmd) Run

func (c *ReplyListCmd) Run(rt *Runtime) error

type ReplyTreeCmd

type ReplyTreeCmd struct {
	ID     string `arg:"" help:"Media id of the post."`
	Cursor string `help:"Opaque pagination cursor."`
}

func (*ReplyTreeCmd) Run

func (c *ReplyTreeCmd) Run(rt *Runtime) error

type ReplyUnhideCmd

type ReplyUnhideCmd struct {
	ID string `arg:"" help:"Reply id to unhide."`
}

func (*ReplyUnhideCmd) Run

func (c *ReplyUnhideCmd) Run(rt *Runtime) error

type Runtime

type Runtime struct {
	Cfg   *CLI
	Out   *output.Writer
	API   api.Threads
	Creds *auth.Credentials
	Stdin io.Reader
	Ctx   context.Context
	Wrap  bool // effective prompt-injection fencing decision
}

Runtime is the per-invocation context bound into every command's Run method.

func (*Runtime) Guard

func (rt *Runtime) Guard(op string) error

Guard enforces the read-only-by-default mutation gate (contract §2).

type SchemaCmd

type SchemaCmd struct{}

func (*SchemaCmd) Run

func (c *SchemaCmd) Run(rt *Runtime) error

type SearchCmd

type SearchCmd struct {
	Posts SearchPostsCmd `cmd:"" help:"Search posts by keyword or topic tag."`
}

SearchCmd searches public Threads posts. Results are attacker-controllable free text → fenced in agent mode (contract §8). The envelope carries scope:public|self so an agent knows whether advanced access was actually in effect (without it, the API returns only own posts).

type SearchPostsCmd

type SearchPostsCmd struct {
	Keyword   string `arg:"" help:"Keyword or topic to search."`
	MediaType string `enum:",text,image,video" default:"" help:"Filter by media type."`
	Mode      string `enum:"keyword,tag" default:"keyword" help:"Search mode: keyword or topic tag."`
	Cursor    string `help:"Opaque pagination cursor."`
}

func (*SearchPostsCmd) Run

func (c *SearchPostsCmd) Run(rt *Runtime) error

type VersionCmd

type VersionCmd struct {
	Check bool `help:"Check for a newer release (network, short timeout, fail-silent)."`
}

func (*VersionCmd) Run

func (c *VersionCmd) Run(rt *Runtime) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL