id = "toot" name = "toot" homepage = "https://toot.bezdomni.net/" description = "A CLI and TUI tool for interacting with Mastodon instances from the command line." executables = ["toot"] [dotfiles] # Sources: https://raw.githubusercontent.com/ihabunek/toot/master/toot/__init__.py # and https://toot.bezdomni.net/settings.html — toot uses ~/.config/toot on Unix (respecting # XDG_CONFIG_HOME) and %APPDATA%/toot on Windows. Both files are documented # by the project's settings and usage pages. paths = [ "~/.config/toot/config.json", "%APPDATA%/toot/config.json", "~/.config/toot/settings.toml", "%APPDATA%/toot/settings.toml", ] secret = [] # Source: https://raw.githubusercontent.com/ihabunek/toot/master/toot/config.py — # config.py defines App.client_secret and User.access_token; these are the # application and user credentials saved by `toot login`. [[dotfiles.secret_paths]] file = ["~/.config/toot/config.json", "%APPDATA%/toot/config.json"] format = "json" match = { key_path = ["apps.*.client_secret", "users.*.access_token"] } [commands] format = 1 label = "Mastodon from the terminal" description = "Post a status or read a timeline with toot. Login, account switching, polls, scheduling, thumbnails and the TUI are left to the command line." quality = "ai-draft" parser = { end_of_options = "--", interleave = "permute", long_equals = true, short_attached = true, short_bundles = true } [[commands.subcommand]] path = ["post"] label = "Post a status" description = "Post text, optionally with media. Leave the text empty to compose interactively or with an editor." [[commands.subcommand.source]] id = "src" kind = "manual" url = "https://raw.githubusercontent.com/ihabunek/toot/master/toot/cli/post.py" revision = "2026-10-27" evidence = """ @click.argument("text", required=False) "--media", "-m", "--description", "-d", "descriptions", "--visibility", "-v", type=click.Choice(VISIBILITY_CHOICES), VISIBILITY_CHOICES = ["public", "unlisted", "private", "direct"] "--sensitive", "-s", "--spoiler-text", "-p", "--reply-to", "-r", "--language", "-l", "--editor", "-e", toot post "hello media" --media path/to/image.png --description "Cool image" """ [[commands.subcommand.field]] id = "text" label = "Text" description = "The status text. Leave empty to compose interactively." type = "string" position = 0 sources = ["src"] [[commands.subcommand.field]] id = "visibility" label = "Visibility" type = "enum" option = ["--visibility", "-v"] choices = [{ value = "public", label = "Public" }, { value = "unlisted", label = "Unlisted" }, { value = "private", label = "Followers only" }, { value = "direct", label = "Direct" }] sources = ["src"] [[commands.subcommand.field]] id = "media" label = "Media files" description = "Up to 4 attachments; give one description per file." type = "path" option = ["--media", "-m"] multiple = true path = { kind = "file", role = "input" } sources = ["src"] [[commands.subcommand.field]] id = "description" label = "Media descriptions" description = "Accessibility description, one per attached media." type = "string" option = ["--description", "-d"] multiple = true sources = ["src"] [[commands.subcommand.field]] id = "sensitive" label = "Mark sensitive" type = "boolean" option = ["--sensitive", "-s"] sources = ["src"] [[commands.subcommand.field]] id = "spoiler_text" label = "Content warning" type = "string" option = ["--spoiler-text", "-p"] sources = ["src"] [[commands.subcommand.field]] id = "reply_to" label = "Reply to status ID" type = "string" option = ["--reply-to", "-r"] sources = ["src"] [[commands.subcommand.field]] id = "language" label = "Language code" description = "ISO 639-1 code, to skip automatic detection." type = "string" option = ["--language", "-l"] sources = ["src"] [[commands.subcommand.field]] id = "editor" label = "Compose in editor" description = "Editor command; leave empty to use the EDITOR variable." type = "string" option = ["--editor", "-e"] sources = ["src"] [[commands.subcommand.task]] id = "simple" label = "Post text" fields = ["text", "visibility", "spoiler_text", "language"] required = ["text"] [[commands.subcommand.task]] id = "media_post" label = "Post with media" fields = ["text", "media", "description", "sensitive", "visibility"] required = ["text", "media"] [[commands.subcommand.group]] id = "basic" label = "Basic" fields = ["text", "visibility", "media", "description", "sensitive"] [[commands.subcommand.group]] id = "advanced" label = "Advanced" fields = ["spoiler_text", "reply_to", "language", "editor"] [[commands.subcommand]] path = ["timeline"] label = "Read a timeline" description = "Show the home, public, hashtag, account or list timeline." [[commands.subcommand.source]] id = "src" kind = "manual" url = "https://raw.githubusercontent.com/ihabunek/toot/master/toot/cli/timelines.py" revision = "2026-10-27" evidence = """ @click.option("--account", "-a", help="Show account timeline") @click.option("--list", help="Show list timeline") @click.option("--tag", "-t", help="Show hashtag timeline") @click.option("--public", "-p", is_flag=True, help="Show public timeline") "--local", "-l", is_flag=True, help="Show only statuses from the local instance (public and tag timelines only)" "--reverse", "-r", is_flag=True, "--once", "-1", is_flag=True, "--count", "-c", type=int, default=10, help="Number of posts per page (max 20)" """ [[commands.subcommand.field]] id = "public" label = "Public timeline" type = "boolean" option = ["--public", "-p"] sources = ["src"] [[commands.subcommand.field]] id = "local" label = "Local instance only" description = "Only valid with the public timeline or a tag." type = "boolean" option = ["--local", "-l"] sources = ["src"] [[commands.subcommand.field]] id = "tag" label = "Hashtag" type = "string" option = ["--tag", "-t"] sources = ["src"] [[commands.subcommand.field]] id = "account" label = "Account" type = "string" option = ["--account", "-a"] sources = ["src"] [[commands.subcommand.field]] id = "list" label = "List" type = "string" option = ["--list"] sources = ["src"] [[commands.subcommand.field]] id = "count" label = "Posts per page" description = "Maximum 20." type = "integer" option = ["--count", "-c"] sources = ["src"] [[commands.subcommand.field]] id = "reverse" label = "Newest at bottom" type = "boolean" option = ["--reverse", "-r"] sources = ["src"] [[commands.subcommand.field]] id = "once" label = "Do not prompt for more" type = "boolean" option = ["--once"] sources = ["src"] [[commands.subcommand.task]] id = "home" label = "Home timeline" fields = ["count", "once", "reverse"] [[commands.subcommand.task]] id = "public" label = "Public timeline" fields = ["public", "local", "count", "once"] set = { public = [true] } [[commands.subcommand.task]] id = "tagged" label = "Hashtag timeline" fields = ["tag", "local", "count", "once"] required = ["tag"] [[commands.subcommand.group]] id = "basic" label = "Basic" fields = ["public", "local", "tag", "account", "list"] [[commands.subcommand.group]] id = "advanced" label = "Advanced" fields = ["count", "reverse", "once"]