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]
paths = [
"~/.config/toot/config.json",
"%APPDATA%/toot/config.json",
"~/.config/toot/settings.toml",
"%APPDATA%/toot/settings.toml",
]
secret = []
[[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"]