fedtail features

53 minutes read

As of version 0.17.0 (in progress). This is the full list of fedtail’s features: what each one does, what turns it on and off, since which version it’s there, which API or protocol it stands on and how other clients do the same. The plans are here too, and what was turned down, with the reasons.

The full settings reference is config.md, in tables by chapter. The same as one “fedtail and other clients” matrix — comparison.md. How the code is built — ARCHITECTURE.md; the spec and the queue — DESIGN.md (in Russian).

How to read it

Each chapter is a table: the feature, its status, since which version, the config key, the API or protocol, how others do it. Under the table, in “In detail”, is what each one does, in words.

  • Statuses: has · partly · no · planned; at the end — won’t do and not decided.
  • Since — the fedtail version it first came in. For the very first features it’s 0.1.0–0.3.0 roughly: not everything was written down then.
  • Config — the key as section.key. “—” means there’s no key of its own: the feature is simply in a menu or a window and does nothing until you call it. For planned features the key’s name is tentative and may change once it’s made.
  • Others — the same things in other clients: Mastodon web, Tusky, Ivory, Phanpy, Elk, Tokodon, Ice Cubes, Fedilab, Sengi, Megalodon, tut, Tuba, Whalebird. From their READMEs and release notes (as of autumn 2026) and general knowledge about them, without trying each one live. Only in fedtail means none of those listed has it so.
  • What a particular server supports (GoToSocial above all), check on yours. fedtail itself hides what the server can’t do: it explains an empty lane and draws no needless buttons.

The main principles everything else grows from:

  1. Nothing jumps. Open a lane and you stand at the first unread. New posts come and your place doesn’t move, only the counter grows. You read in order, like RSS.
  2. Every reply knows what it answers. Over a reply, a strip with the start of the original post; a click opens the whole thread as a tree.
  3. Lanes are apart. People apart, bots apart, replies to me apart from other mentions.
  4. Private by default. A new post goes to followers only. A reply is never more public than the original.
  5. Every behaviour is a config key. There’s no settings window and there won’t be. The defaults are as the author likes them; “like everyone else” is a flag away. New features come switchable.
  6. Other servers get no token of yours. Whatever fedtail takes straight from the author’s server over ActivityPub goes anonymously: they see only your IP.
  7. The core knows nothing of a GUI. Interfaces are plugins: a Qt window, a terminal, a browser; GTK next.
  8. One profile, one account. A second account is a second profile (--profile); if you like, all accounts come together in one window (ui.merge).
  9. Grown-ups sort things out themselves. Arts mode (after @arts, the founder of Point.im): everything as the author posted it, no nannying. Anyone can be told where to go, an admin too — and the admin can say the same back.

This is the list of what there is now, not a history: what changed in each version is in the CHANGELOG.

Contents: Lanes · Threads · Read marks and place · The post card · Pictures and video · Profiles · Writing · People and order · Notifications and activity · Several accounts · The application · Interfaces · Builds and installing · ActivityPub directly · Plans · Won’t do · Not there and not decided


Lanes

On the left, the lanes in groups: “Timelines” (from the widest down to your own), “Personal”, “Lists”. Which lanes to show and in what order — lanes.enabled. Group headings go with ui.sidebar_groups = false. The column’s width — ui.sidebar_width; its edge drags with the mouse, and the dragged width is kept until the number in the config changes.

WhatStatusSinceConfigAPI / protocolOthers
Federated, Home, Localhas0.2.0lanes.enabled ("federated", "home", "local")timelines/home, timelines/publiceveryone
Lane names in the config match their titleshas0.15.0home, replies, federated, my_posts, my_likes; the old people, comments, global, mine, favourites are understood too; a lane’s word is in its tooltip on the left——
Bots in a lane of their ownhas0.1.0lanes.enabled ("bots"), lanes.extra_botsthe account.bot fieldonly in fedtail
Personal laneshas0.1.0lanes.enabled, lanes.mentions_all, lanes.direct_apartnotifications, visibility=directeveryone, but laid out differently
Lists as laneshas0.2.0[lists]: enabled, refresh_minuteslists, timelines/list/:idMastodon web, Tusky, Ivory, Phanpy, Elk, Tokodon, Ice Cubes, Megalodon
Who is in a list leaves the general laneshas0.3.0lists.hide_members, lists.hide_inownonly in fedtail
Who is in a list; your own order of listshas0.13.0—lists/:id/accountsMastodon web, Ivory (who is in a list); the order — only in fedtail
Into a list — the author or the booster; only people you followhas0.13.0—lists/:id/accountsonly in fedtail
Into a list right after a followhas0.11.0lists.refresh_minuteslists/:id/accountsonly in fedtail
Hashtag lane, following tagshas0.2.0—timelines/tag/:name, tags/:name/follow, followed_tagseveryone
My likeshas0.8.0"my_likes" in lanes.enabled/api/v1/favouritesMastodon web, Tusky, Ivory, Megalodon, tut
Bookmarkshas0.3.0"bookmarks" in lanes.enabled, ui.bookmark_button/api/v1/bookmarkseveryone
Trendshas0.11.0—/api/v1/trends (tags, links, statuses)Mastodon web, Tusky, Ivory, Phanpy, Elk, Ice Cubes
An empty live lane says why it’s emptyhas0.11.0—timelines/publiconly in fedtail
Filtering a lane by media and boostshas0.11.0— (kept until restart)ownonly in fedtail
Repeated boosts don’t bring an old post up againhas0.15.0feed.repeat_boostsownonly in fedtail (a Mastodon server drops a repeat only among the freshest posts)
All / Posts only / New; Feed / Conversationshas0.3.0lanes.posts_only, feed.remember_choicesownPhanpy — similar to “Conversations”
Find in a lanehas0.2.0—own, in the local databaseonly in fedtail
Sending to a slow server without doubleshas0.16.0post.send_timeoutIdempotency-Key, accounts/:id/statusesonly in fedtail
Find in every lane at oncehas0.16.0a tick in the Ctrl+F barown, in the local databaseonly in fedtail
Finding people, tags and postshas0.2.0—/api/v2/searcheveryone
A lane of several tagshas0.14.0[[lanes.tag_groups]]; from the search — “+ to lanes”timelines/tag/:name for each tag, put together herePhanpy, Ice Cubes (“tag groups”), tut (:tag a b)
Columns side by sidehas0.14.0ui.layout, ui.columns, ui.column_width; the ❯ button at the top leftownSengi, Phanpy, tut, Whalebird, Mastodon web (advanced mode)
Collections (Mastodon 4.6)planned——/api/v1/collectionsMastodon 4.6, Fedilab
In detail

Federated, Home, Local. “Home” (home) — the people you follow, without bots; it opens by default. “Local” — your whole server. “Federated” — everything your server knows from all servers. Federated and Local are fetched only while open and have no unread counts: they are for browsing, not for reading to the end. A gap between a fresh page and what was there before is allowed in them — unlike Home, which catches up with no holes (see Catching up with no holes).

Bots in a lane of their own. Posts of accounts with the “bot” tick leave Home for a lane of their own, “Bots”. A bot without the tick goes into lanes.extra_bots: on your server — "nick", on another — "nick@server".

Personal lanes.

  • “My posts” (my_posts) — my posts and comments.
  • “Direct” (direct) — messages visible to the mentioned only. With lanes.direct_apart = true (the default) they live only here and don’t double up in “Replies to me” and “Mentions”.
  • “Replies to me” (replies) — replies to my posts and comments, even if they @ me.
  • “Mentions” (mentions) — where I was tagged in someone else’s conversation. lanes.mentions_all = true — show everything that mentions me here, replies too (they’ll be in both lanes).
  • “Subscriptions” (subs) — what’s new in threads I’m subscribed to (see Thread subscriptions).
  • “Bookmarks” (bookmarks), “My likes” (my_likes, off by default), “Activity” (activity), “Follow requests” (requests) — below, each in its own section.

Splitting “replies to me” from “mentions” is what other clients don’t do: usually it all lands in one notifications lane.

Lists as lanes. The server’s lists are lanes of their own in the “Lists” group. Create, rename, delete, make exclusive — from the menu; add a person — with a right click on their post. fedtail rereads the lists and who is in them every lists.refresh_minutes minutes.

Who is in a list leaves the general lanes. Put a person or a bot in a list — their posts, their boosts and others’ boosts of their posts are read in the list’s lane and disappear from the general lanes, so they don’t clutter them. hide_members: "all" — so with any list; "exclusive" — only with exclusive ones (the server itself takes such people out of Home, fedtail carries that to the other lanes); "off" — don’t take out. Which lanes — lists.hide_in (by default Home, Bots, Federated, Local).

Who is in a list; your own order of lists. Right click on a list on the left: “Who is in it…” — a tab with its people (and those waiting for a follow to be confirmed), each with “Take out of the list”; “Move up” and “Move down” — your own order of lists. Servers keep no order of lists; fedtail remembers it, new ones go to the end.

Into a list — the author or the booster; only people you follow. A boost’s ⋯ menu has two items: “Author to a list (@…)” and “Booster to a list (@…)” — a relay bot is a person too, as far as a list goes. The server takes into lists only people you follow: for the rest the lists in the submenu are dead (they don’t click at all), signed “follow first”, with a “Follow” item. Right click on the “♻ boosted by …” line — the booster’s profile or “To a list”; the name on that line links to the profile.

Into a list right after a follow. The server won’t take into a list someone you don’t follow yet (the request waits with a locked account). fedtail remembers which list you wanted them in and adds them itself as soon as the follow is confirmed.

Hashtag lane, following tags. A click on a #tag opens its lane inside (with ui.links_in_app). Follow a tag — with the button in its lane’s header; the server mixes followed tags into Home, and fedtail offers them first when you type #.

My likes. The posts you liked. The lane is off by default.

Bookmarks. “Bookmark” — with the button under a post (ui.bookmark_button = false moves it into the ⋯ menu), the m key or the command ~ #a3f. The server keeps bookmarks, so they are shared with other clients.

Trends. Popular tags, links and posts, as your server counts them. GoToSocial doesn’t count trends.

An empty live lane says why it’s empty. If the server turned the public timelines off (or gives them to its own users only), Federated and Local don’t hang empty in silence: fedtail says the server turned them off.

Filtering a lane by media and boosts. Over a lane you can leave only text, only pictures, gifs, video or only boosts. It’s a quick look, not a setting: after a restart everything is as it was.

Repeated boosts don’t bring an old post up again. A post comes into a lane once — as itself or with its first boost. A boost of a post this lane has had already, or one already read (in a thread, in another lane), is not shown and not counted as unread; the post stays where it first came. repeat_boosts = true — every boost again, as everyone does. The server (Mastodon) drops a repeat only if the original was among the last ~40 posts of the feed — that’s why old posts kept surfacing again and again.

All / Posts only / New; Feed / Conversations. Over a lane, two switches. “All / Posts only / New”: with all the comments, only top-level posts, or only what’s unread. “Feed / Conversations”: “Conversations” gathers a thread into one card, like conversations on Point. In which lanes “posts only” is on from the start — lanes.posts_only. Remember the choice between runs — feed.remember_choices = true; by default every run starts afresh.

Find in a lane. Ctrl+F finds in the open lane by text, nick, #id and picture captions. It searches its own database and doesn’t ask the server, so it works offline too. Enter, ↓, F3 or Ctrl+F again — to the next match, Shift+Enter — to the previous one.

Find in every lane at once. The “In every lane” tick in the Ctrl+F bar: you remember a phrase but not where you saw it. It searches everything stored in every lane at once (in the sidebar’s order, newest to oldest in each, a post once), the counter says which lane the match is in; the next match opens its lane by itself and loads it down to the post. The tick is remembered.

Finding people, tags and posts. Search on the server: people, tags, posts (as far as the server indexes them), and a link to a post or a profile — the server finds it and fetches it.

A lane of several tags. Type #грузия #georgia -#politics in the search: one lane of all these tags opens — any of them, +#tag must be there, -#tag — without. The “+ to lanes” button keeps it on the left, in the “Tags” group; it is fetched while open, like Federated. The same lanes can be described in the config, [[lanes.tag_groups]] (name, any, all, none). The server needs a request per tag (GoToSocial reads only one tag at a time), fedtail puts them together itself, without repeats.

Columns side by side. Several lanes on screen at once, in columns. By default — one lane at a time; the ❯ button at the top left (next to ≡ and ↔) turns columns on for now, and the window starts as ui.layout says. A click on a lane on the left adds a column (or scrolls to it), ✕ takes it away, ‹ › move it; the set is remembered. These are the same lanes as in the single view: place, filters and read marks are each their own, and Federated and the other browse lanes keep updating while they stand in a column.

Collections (Mastodon 4.6). Shared sets of accounts. Coming once GoToSocial has them.


Threads

WhatStatusSinceConfigAPI / protocolOthers
A thread as a tree, comments numberedhas0.1.0—statuses/:id/contextPhanpy — indented; numbers only in fedtail
Over a reply — what it answershas0.1.0feed.show_reply_contextin_reply_to_idSengi and Megalodon — similar
A whole thread: replies from the author’s serverhas0.3.0feed.complete_threadsthe replies collection over ActivityPub, search?resolve=trueonly in fedtail (Mastodon 4.5+ does it on the server)
A thread grows when Mastodon has gathered the replieshas0.8.0feed.complete_threadsthe Mastodon-Async-Refresh headerMastodon web
Thread subscriptions, as on Pointhas0.2.0[subs]: auto, interval_minutes, active_days, max_threads, replies_to_me, leave_mutesownonly in fedtail
Mute a threadhas0.11.0—statuses/:id/mute and ownMastodon web, Tusky, Ivory
Long texts and eventshas0.14.0feed.long_form⋯ → “📄 Read it whole”: Article, Page, Event from the author’s server—
In detail

A thread as a tree, comments numbered. A thread opens as a tree: every reply under what it answers, every comment numbered /1, /2, /2/1, as on Point and Juick. The command line can address a comment by its number.

Over a reply — what it answers. Over a reply in a lane, a strip “↪ in reply to…” with the start of the original post; a click opens the whole thread. No reply in a lane hangs as a scrap.

A whole thread: replies from the author’s server. Your server knows only the replies that reached it, so other people’s threads have holes. Open a thread — fedtail reads the list of replies straight from the author’s server and asks your server to fetch what’s missing; the thread grows by itself a couple of seconds later. Requests to other servers go without your token. false — make do with what your own server knows.

A thread grows when Mastodon has gathered the replies. Mastodon 4.5+ gathers missing replies itself and says when it’s done; fedtail waits for that signal and rereads the thread.

Thread subscriptions, as on Point. The server tells you only of replies that mention you: if two people answer each other under your post, you won’t know. fedtail itself rereads the threads you’re subscribed to every subs.interval_minutes minutes and puts what’s new into the “Subscriptions” lane. Subscribe — in a post’s ⋯ menu, with the button in the thread’s header or the command S #a3f (U #a3f — unsubscribe). subs.auto — what to subscribe to by itself: "posts" — your own posts, "comments" — threads you comment in. A thread quiet for subs.active_days days is not checked any more; one round checks at most subs.max_threads threads. Replies to you come to “Replies to me” anyway; subs.replies_to_me = true — show them in “Subscriptions” too. Unsubscribing mutes the thread’s mentions as well (replies there tag everyone in it by themselves); subs.leave_mutes = false — leave “Subscriptions” only.

Mute a thread. Notifications from the thread stop coming and its subscription goes. A server that can do it remembers it for all clients; where it can’t (GoToSocial), fedtail mutes the thread itself: its mentions are dropped as they come — even replies to posts of the thread it never saw. The item in a post’s ⋯ menu is always there.

Long texts and events. Articles from WriteFreely, Ghost, Plume, Lemmy posts, Mobilizon events. The Mastodon API flattens them into an ordinary post with the text cut. The ⋯ menu of such a post has “📄 Read it whole”: fedtail takes the full text straight from the author’s server over ActivityPub, for an event — also the time and the place.


Read marks and place

WhatStatusSinceConfigAPI / protocolOthers
Oldest on top, nothing jumpshas0.1.0feed.order, feed.start_at, feed.on_newownonly in fedtail
Catching up with no holeshas0.1.0feed.page_size, feed.catch_up_limitmin_idonly in fedtail
When a post counts as readhas0.1.0read.mark_read, read.read_buttonownonly in fedtail (the manual mode)
Your own posts are always readhas0.13.0—own—
The first run doesn’t start with a pilehas0.1.0feed.first_run_mark_readown—
The reading place is shared with other clientshas0.8.0read.sync_markers/api/v1/markersMastodon web, Tusky, Ivory, Phanpy, Ice Cubes
Cards are built around the reading placehas0.11.0feed.build_at_once, feed.render_limitownonly in fedtail
Esc draws a curtain instead of closing the windowhas0.3.0ui.esc, ui.start_laneownonly in fedtail
In detail

Oldest on top, nothing jumps. feed.order = "oldest_first" — oldest on top, you read downwards, like RSS or Point ("newest_first" — as everyone does). feed.start_at = "first_unread" — open a lane and you stand at the first unread ("newest" — at the freshest). feed.on_new = "keep_position" — new posts come and the place doesn’t move, only the counter grows ("jump_to_newest" — jump to the new).

Catching up with no holes. Lanes meant to be read to the end catch up forward from the last known post, page by page (page_size posts a request, up to catch_up_limit a poll — the rest on the next one). So the local copy has no holes and you can read strictly in order. The “load what’s missing” button other clients keep fixing (Fedilab in 2026 — half a dozen fixes about holes and jumps, some on GoToSocial) isn’t needed here.

When a post counts as read. "on_scroll" — when you’ve scrolled past the whole post; "on_open" — the whole lane as soon as you open it; "manual" — by hand only: “All read” over the lane, “Mark read” and “Read up to here” (this one and everything older) in the ⋯ menu. In the manual mode a lane always waits exactly where you stopped, even reading one post at a time. read.read_button = true — a ✓ button under each unread post. The menu items work in any mode.

Your own posts are always read. A post you wrote is read, wherever it came from: from Tusky at night, through a thread, fetched after a restart.

The first run doesn’t start with a pile. At the very first run, everything fetched counts as read.

The reading place is shared with other clients. Read Home or mentions to the end on the phone — here it’s read too, and the other way round. Works with Mastodon, GoToSocial, Akkoma — if that client tells the server its place: Mastodon’s web, Ivory, Phanpy do; Tusky keeps its place in Home to itself and shares only notifications. false — read marks live in fedtail only.

Cards are built around the reading place. When a lane opens, build_at_once cards are built around where you read; the rest — as you scroll near an edge, and far behind they are let go (more than three build_at_once — back to one behind and two ahead). What you read doesn’t move; a filter and “unread only” also build only around the reading place. At most render_limit latest posts are kept on screen, older ones with the “older” button. 0 in build_at_once — build everything at once (on hundreds of posts that takes seconds).

Esc draws a curtain instead of closing the window. Esc closes what’s on top (a picture, the search), and the last Esc with ui.esc = "curtain" draws a curtain over all lanes: the window stays, the counts on the left, nothing on the right, and nothing is marked read — open it in the morning and the new has piled up. "tray" — off to the tray, "off" — nothing. What to start with — ui.start_lane: "none" (the curtain, Enter opens the last one), "last" or a lane’s name.


The post card

WhatStatusSinceConfigAPI / protocolOthers
Arts modehas0.11.0ui.arts_mode (on by default, recommended)—nobody has it as one switch
Content warnings (CW)has0.1.0ui.expand_cwspoiler_texteveryone can set it
Open every CW in a thread at onceno——ownSengi, Megalodon (the same CW across a thread)
Sensitive pictureshas0.8.0feed.sensitive_mediastatus.sensitiveeveryone
Link cardshas0.8.0feed.link_cardsstatus.cardeveryone
Servers’ emoji as pictureshas0.8.0feed.custom_emojiemojis of the post and the accounteveryone
No emoji at allhas0.15.0feed.emoji = false — no server pictures, no Unicode ones, no reactions; a name made only of emoji shows the login—Tusky (animation only), Fedilab (only servers’ own emoji)
Quotes: showing themhas0.8.0feed.quotesstatus.quoteMastodon 4.5+, Ivory, Phanpy, Elk, Ice Cubes, Fedilab
Polls: seeing and votinghas0.3.0—polls/:id, polls/:id/voteseveryone
Poll results without votinghas0.3.0— (the “Results” button of a poll)—Fedilab
Edit historyhas0.3.0—statuses/:id/historyMastodon web, Ivory, Phanpy, Elk, tut
Translation by the serverhas0.8.0feed.translatestatuses/:id/translateMastodon web, Ivory, Phanpy, Elk, Ice Cubes, Fedilab
Emoji reactionspartly — shown only0.11.0—pleroma.emoji_reactionsPhanpy, Elk, Fedilab
Who liked and boostedhas0.11.0—favourited_by, reblogged_by (and from the author’s server)Mastodon web, Tusky, Ivory, Phanpy, Elk, tut
Honest countershas0.2.0feed.honest_counters (off), feed.counters_via_accountsthe author’s server’s API without a tokenonly in fedtail
Who quoted my posthas0.11.0—statuses/:id/quotes, …/quotes/:id/revokeMastodon 4.5+
Folding hashtag paddinghas0.14.0feed.collapse_tagsownPhanpy
~~text~~ struck out when the server knows no Markdownhas0.14.0feed.text_markupown—
Labels on the cardhas0.14.0feed.old_days; “bot” — alwaysownSengi
In detail

Arts mode. Everything as the author posted it, no nannying. Turns on at once: content warnings (CW) open, “sensitive” pictures without a cover, server filters neither hide nor fold posts, no “Report” item. Your own mutes and blocks work as usual; what the server itself cuts off (domain blocks) never reaches a client — that can’t be got round. false — everything as everyone has it, and then each of these is set on its own (ui.expand_cw, feed.sensitive_media). Named after @arts — the founder of Point.im and the author of its rules. The principle comes from there too: on a grown-up site grown-ups sort things out themselves. Anyone can be told where to go, an admin too — and the admin can say the same back.

Content warnings (CW). true — text and pictures under a CW open at once; false — folded, opened with the “show” button.

Open every CW in a thread at once. Not needed with arts mode on. If people who turned it off ask — a button in the thread’s header.

Sensitive pictures. Pictures the author marked sensitive (without a CW): "hide" — under a cover, a click shows them; "show" — seen at once. Under a CW they are hidden together with the text anyway.

Link cards. The title, description and picture of the page a post links to (the server collects them): "full" — with the picture, "text" — a line or two, "off" — not shown. A post with its own pictures has no card.

Servers’ emoji as pictures. :blobcat: and the rest — as pictures in posts and names. false — leave them as text and don’t fetch the pictures.

Quotes: showing them. A post inside a post (Mastodon 4.5+, Akkoma, Misskey and others): "card" — framed inside, "link" — a line with a link, "off" — as the server sent it (usually “RE: link”).

Polls: seeing and voting. Options, percentages, the deadline; voting for one or several options, as the author set.

Poll results without voting. The “Results” button next to “Vote” — look without voting.

Edit history. An edited post is marked so and has all its earlier versions.

Translation by the server. “Translate” in the ⋯ menu of a post in another language — if your server can (Mastodon with DeepL or LibreTranslate). The translation is right in the card, with an “original” button.

Emoji reactions. Reactions from Akkoma, Pleroma, Misskey and their forks show under the post. Adding your own isn’t possible yet; GoToSocial doesn’t support them.

Who liked and boosted. Lists of people at the counters. If your server doesn’t know everyone, the rest is read from the author’s server.

Honest counters. Your server knows only the likes and boosts that reached it, so the numbers on other people’s posts are low. With honest_counters = true, when a thread opens fedtail asks the author’s server for the real numbers — without a token, but with your IP. If that server won’t give numbers without a login and you have other accounts (profiles), counters_via_accounts lets it ask as them: the author’s server, if you have an account there, or a server that already has the post. Each account’s token goes only to its own server.

Who quoted my post. The list of quotes of my post and “take my post out of this quote”.

Folding hashtag padding. A paragraph of nothing but hashtags (more than three) in a lane folds into the first three and “… +N” in small type; in an open thread it’s whole, but small too. Hashtags inside the text aren’t touched.

Boost carousel. Boosts in a row — as one strip scrolled sideways (as in Phanpy). Won’t do: sideways is awkward to read, and it fits badly with “nothing jumps” and read marks. The same job is done by the “Boosts” tick in the filter, “without their boosts” on a profile and relays in a list of their own.

Labels on the card. Next to the date: “old, N days” — a post older than feed.old_days (30) days; such posts come from someone’s outbox or an old thread; “[bot]” — on bots. There is no “from another server” label yet.


Pictures and video

WhatStatusSinceConfigAPI / protocolOthers
Picture viewerhas0.1.0ui.image_viewer, ui.image_upscale, ui.image_height—everyone
Picture gridhas0.9.0ui.media_gridmeta.focusMastodon web, Tusky, Phanpy, Elk
Picture descriptions (alt)has0.9.0ui.alt_textdescriptioneveryone
Video, audio, gifs inside the windowhas0.11.0ui.video_player, ui.gifvmedia_attachmentseveryone
Video without a hardware decoder (the default)has0.16.0ui.video_decode—only in fedtail
Save a picture, video, gifhas0.2.0ui.save_dir—Tusky, Ivory
Pictures and video ahead of time, a disk cachehas0.13.0feed.prefetch, ui.image_disk_mb, ui.video_disk_mbownonly in fedtail
Memory for pictureshas0.2.0ui.image_cache_mb, ui.image_decodeown—
In detail

Picture viewer. A click on a picture — its own viewer ("internal": ← → to flip, Esc to close) or the browser ("browser"). Small pictures are enlarged to the window at most image_upscale times. The height of a single picture in a lane — image_height.

Picture grid. Several pictures in a post: "natural" — each whole, its own shape; "square" — an even grid of squares cut around the author’s focus point. A single picture is never cut.

Picture descriptions (alt). "tooltip" — on hover; "caption" — also as a caption under the pictures. Descriptions are found by Ctrl+F.

Video, audio, gifs inside the window. A video plays over the window (Space — pause, ← → — seek, M — sound, O — to the browser, Esc — close), audio — with a player in the card. Needs QtMultimedia (Debian: python3-pyside6.qtmultimedia python3-pyside6.qtmultimediawidgets); without it — a still frame with ▶ and the browser. Mastodon’s gifs (short silent videos): "play" — loop in the card while it’s on screen (at most three at once), "click" — a still frame, a click plays it over the window.

Save a picture, video, gif. The ⤓ button, the S key in the viewer, a right click on a picture in a lane. "" — into the desktop’s Downloads.

Pictures and video ahead of time, a disk cache. As soon as a poll brings new posts, their pictures are fetched to disk by background workers of their own — open a lane and everything is there. "previews" (the default) — previews (of videos too), avatars and link pictures; "all" — also originals, the videos themselves and gifs (videos one at a time, up to 300 MB each); "off" — only when a post is on screen. The picture cache keeps within image_disk_mb (1 GB), videos — in their own folder, video_disk_mb (10 GB); over the limit go the ones not opened the longest. A video opened once plays from disk the next time.

Memory for pictures. Decoded pictures are held in memory up to image_cache_mb MB, the oldest thrown out first (reread from disk at once). image_decode = "box" — decode to the size of the frame, minding the screen’s density: several times less memory; "full" — up to 1200 pixels on the longer side, sharper when the window is stretched.


Profiles

WhatStatusSinceConfigAPI / protocolOthers
Your own and other people’s profileshas0.2.0—accounts/:id, accounts/:id/statuseseveryone
Pinned postshas0.8.0feed.profile_pinnedstatuses?pinned=trueeveryone
Featured tags and recommended peoplehas0.9.0feed.profile_featuredfeatured_tags, endorsementsMastodon web
A little-known person’s profile — from their serverhas0.8.0feed.remote_profiles, feed.remote_postsActivityPub outboxMegalodon — partly (the lists)
Posts older than my server knowshas0.11.0feed.remote_profilesActivityPub outboxonly in fedtail
Followers and follows from the person’s serverhas0.8.0feed.remote_peopleActivityPub followers, followingMegalodon
“Following since …”has0.11.0feed.follow_date_noteaccounts/:id/noteonly in fedtail
The person has movedhas0.14.0feed.show_movedaccount.moved, ActivityPub MoveMastodon web
The author’s server softwarehas0.14.0feed.server_infonodeinfo, in the profile “🖥 GoToSocial 0.17”—
What my server can dohas0.17.0≡ → account → “Server info” → “What it can do” → “Check”one harmless GET with limit=1 per feature—
In detail

Your own and other people’s profiles. The header, bio, fields, counts, posts; “followed by people you follow” (familiar_followers); follows and followers.

Pinned posts. At the top of a profile, marked 📌. false — the profile simply in time order.

Featured tags and recommended people. “Often writes about: #tags” and whom the person recommends (Mastodon 4.4+).

A little-known person’s profile — from their server. If your server knows almost nothing about a person from another server, fedtail reads their latest public posts straight from there (remote_posts of them, at most 40) and asks your server to fetch them. Without a token; servers that require signed requests simply give nothing.

Posts older than my server knows. Your server knows a person’s posts only from the moment someone on it followed them. fedtail pages through older ones straight from the author’s server.

Followers and follows from the person’s server. At the bottom of such lists — a “more from their server” button: fedtail reads them there and finds these people through your server.

“Following since …”. Servers don’t keep the day you followed someone. When you follow through fedtail, the date is written as the last line of your private note on the person ([fedtail followed 2026-10-18]): it’s seen from any device and in other clients. In fedtail the line is hidden and kept when the note is edited. false — remember it locally only.

The person has moved. A moved person’s profile has a “📦 Moved to @new” banner with “Open” and “Follow there” buttons.

The author’s server software. fedtail asks the person’s server for its nodeinfo (Mastodon, GoToSocial, Akkoma, Misskey, Lemmy…) and writes “🖥 GoToSocial 0.17.3” in the profile. The answer is kept a week per server.

What my server can do. A score of “show me one” requests (nothing changes on the server), a few seconds in the background — the window doesn’t freeze. Each feature gets an answer: yes, no, there but closed to me, unclear; limits (characters, attachments, poll options) as numbers. What can’t be asked without changing something (dismissing one notification, muting a thread) is told from what server this is. The last check is kept and shown at once; the answers also tell fedtail which buttons to show.


Writing

WhatStatusSinceConfigAPI / protocolOthers
The compose panel and draftshas0.1.0ui.compose, ui.compose_size, post.drafts_autosavestatuseseveryone
Visibility: private by default, a reply never wider than the posthas0.1.0post.default_visibility, post.reply_never_widervisibility, /api/v1/preferencesonly in fedtail (never wider)
Markdownhas0.1.0account.markdown, post.plain_postscontent_typeGoToSocial and Akkoma clients
Preview before sendinghas0.14.0post.previewownFedilab
Content warning (CW)has0.2.0post.cw_fieldspoiler_texteveryone
Pictures: drag, paste, description, focushas0.2.0post.alt_reminder, post.focus_point/api/v2/media, focuseveryone (focus — Mastodon web, Ivory)
Shrinking pictures to the server’s limithas0.14.0post.resize_imagesinstance.configuration.media_attachmentsFedilab
Completing #tags, @nicks, :emoji:has0.7.0post.complete_tags, post.complete_mentions, post.complete_emojiaccounts/search, custom_emojiseveryone
CamelCase hint for hashtagshas0.2.0post.camelcase_hintownonly in fedtail
The post’s languagehas0.3.0post.language, post.languageslanguageeveryone
A poll in a posthas0.8.0—poll[options]everyone
Call someone into a threadhas0.16.0post.invitea reply with a mentiononly in fedtail (in others — by hand)
Reply with quotes, piece by piecehas0.17.0post.quote_prefixown (the reply’s text)Thunderbird and mail clients — for mail; no fediverse client
Copy the handle @user@serverhas0.16.0—ownMastodon web (Copy handle)
Quoting a post; who may quote minehas0.8.0post.quote_action, post.quote_policyquoted_status_id, quote_approval_policyMastodon 4.5+, Ivory, Phanpy
Who may reply, boost, like (GoToSocial)has0.8.0post.who_can_reply, post.who_can_boost, post.who_can_likeinteraction_policyGoToSocial clients
A scheduled posthas0.8.0post.schedulescheduled_at, scheduled_statusesMastodon web, Ivory, Phanpy, Megalodon
Edit, delete, pin your own posthas0.3.0—PUT statuses/:id, statuses/:id/source, statuses/:id/pineveryone
Delete and redrafthas0.14.0post.redraftstatuses/:id/source + DELETE statuses/:idMastodon web, Megalodon
A thread as a chainhas0.14.0post.chainin_reply_to_idIce Cubes (up to five posts)
A command line as on Pointhas0.3.0ui.command_line, post.plain_postsownonly in fedtail (tut — vim-style commands)
In detail

The compose panel and drafts. ui.compose = "inline" — a panel inside the main window (the keyboard layout isn’t reset: KDE keeps it per window); "window" — a window of its own. The panel’s size — in percent of the window (compose_size), the ⤡ button switches normal and big. Drafts are saved as you type and survive closing.

Visibility: private by default, a reply never wider than the post. A new post goes to followers by default ("private"); "server" — as set on the server. A reply is never more public than the original post.

Markdown. "auto" — ask the server; GoToSocial and Akkoma understand Markdown, vanilla Mastodon doesn’t.

Preview before sending. The “👁 Preview” button in the panel: the Markdown already rendered (if the server understands it), the CW, visibility, language, each part of a chain, how many pictures; “Send” or “Edit” from there.

Content warning (CW). The CW field is open at once or hidden behind the “⚠ Warning” button. In a reply, the original post’s CW is filled in by itself.

Pictures: drag, paste, description, focus. Drag a file in or paste from the clipboard. A double click on a picture — the description and the focus point. A picture without a description — before sending, ask “Describe” or “Send as is”. Marking pictures sensitive — with a tick.

Shrinking pictures to the server’s limit. The server says what picture it takes (in pixels and bytes). Bigger — before the upload fedtail shrinks a copy to the pixel limit and recompresses it as JPEG (with transparency — PNG) under the byte limit, instead of being refused. Your file isn’t touched, gifs aren’t flattened. post.resize_images = false — as is.

Completing #tags, @nicks, :emoji:. #ge — first the tags you follow, then the frequent ones in the lanes. @ar — first the people seen most in the lanes, then those the server finds. :co — the server’s emoji, Tab or Enter puts it in.

CamelCase hint for hashtags. A hashtag in one case (#georgianews) gets a hint: screen readers read #GeorgiaNews word by word.

The post’s language. The default language and a list in the post window (any ISO 639 code; “Another language…” adds to the list for good).

Call someone into a thread. A post’s ⋯ menu → “Call into the thread…”: a reply to this post with only “@” in it so far and the people list open at once — pick whom (several are fine), write a couple of words. The person gets a notification, a click — and the thread is open on their side, on their server, ready for a reply; no scary links with service ids. The thread’s other participants aren’t mentioned, the call has its own draft. If the thread isn’t public, the person called sees your reply, and the rest only as far as they could anyway. The same from the command line: #a3f @whom take a look.

Reply with quotes, piece by piece. A post’s ⋯ menu → “Reply with quote”: a reply with the post’s text already in it as a quote (> , the leading mentions left out), or only what’s selected in the post. A right click on a selection → “Quote in reply”. With a reply to this post already open, the quote goes where its cursor is, an empty line after it: select a sentence, quote, answer, select the next one — and so on through the post. The quote’s line start is post.quote_prefix; "" — no such items.

Copy the handle @user@server. The “Copy handle” button on a profile, the “Copy handle @…” item in a post’s ⋯ menu (the author and, for a boost, the booster) and in the menu of the “♻ boosted by” line. Always the full @user@server: people from your server come as just user, your server’s name is added — any client can find and mention a person by such a handle.

Quoting a post; who may quote mine. “Quote” in the ⋯ menu of a post its author lets quote. Who may quote my new posts: "public", "followers", "nobody" or "" — as on the server.

Who may reply, boost, like (GoToSocial). "everyone", "followers" (and the mentioned), "following" (and the mentioned), "mentioned", "me" or "" — as in the account’s settings. Not sent to other servers.

A scheduled post. The “⏰ Later” button: the post waits on the server, even if fedtail is closed. The list of waiting ones — ≡ → “Scheduled”.

Delete and redraft. An item in the ⋯ menu of your own post: the post is deleted, and its text (as typed), CW, visibility, language and what it answered open in the panel as a new draft; the server deletes the pictures with the post, you add them again — for servers without editing and for when an edit won’t do (changing visibility).

A thread as a chain. A line of nothing but --- splits the text into posts: they go at once, each a reply to the one before, with the same visibility, CW and language; pictures and the poll go with the first. The character counter counts each part on its own. post.chain = false — --- stays text.

A command line as on Point. At the bottom of the window (Ctrl+L): #a3f — open, #a3f text — reply, S/U #a3f — subscribe to a thread, S/U @nick — follow a person, ! — boost, ~ — bookmark, D — delete your own, @nick — profile, ? — help. Plain text without a command — a new post (post.plain_posts = false — commands only, no accidental posts).


People and order

WhatStatusSinceConfigAPI / protocolOthers
Follows and follow requestshas0.1.0"requests" in lanes.enabledfollow, follow_requestseveryone
Hide a person’s boosts; the languages of a followhas0.14.0feed.per_person_followfollow with reblogs=false, languages[]Mastodon web, Tusky, tut
Mute, block, word filtershas0.3.0—mutes, blocks, /api/v2/filterseveryone
Block a whole serverhas0.8.0—/api/v1/domain_blocksMastodon web, Ivory, Phanpy
Report to the moderatorshas0.8.0post.report_forward/api/v1/reportseveryone
A private note on a personhas0.8.0—accounts/:id/noteMastodon web, Ivory, Ice Cubes
A bell on a person’s postshas0.8.0"status" in activity.typesfollow notify=trueMastodon web, Tusky, Ivory, Megalodon
Remove from followers without a blockhas0.11.0—remove_from_followersMastodon web, Ivory
Recommend people and tags on your own profilehas0.11.0—endorse, featured_tagsMastodon web
The server’s suggestions, the profile directoryhas0.11.0—/api/v2/suggestions, /api/v1/directoryMastodon web, Tusky, Ivory
About the serverhas0.11.0—instance, instance/rules, extended_descriptionMastodon web, Ivory, Phanpy
Your profilehas0.2.0—update_credentialsMastodon web, Ivory, Phanpy, Elk, Tokodon, Ice Cubes
Post visibility as set on the serverhas0.11.0post.default_visibility = "server"/api/v1/preferencesMastodon web, Ivory
In detail

Follows and follow requests. Follow, unfollow, accept or reject a follow request (the “Follow requests” lane).

Hide a person’s boosts; the languages of a follow. On the profile of someone you follow: “♻ without their boosts” and “🌐 languages” — only their posts in these languages. The server keeps it, so it works in every client.

Mute, block, word filters. Word filters are the server’s, v2: where they apply, for how long, hide or fold. All this — in the ≡ menu → “For the tender and sensitive”: word filters, muted, blocked, blocked servers and filtered notifications; with ui.arts_mode, a line on top says the server’s filters don’t apply there.

Block a whole server. Nobody from there in any lane, follows across the border are cut.

Report to the moderators. About a person from another server — a “forward to their server too” tick (they won’t learn who reported). In arts mode the item isn’t there.

About the server. The description, rules, privacy policy.

Your profile. Name, bio, fields, avatar, header.


Notifications and activity

WhatStatusSinceConfigAPI / protocolOthers
Desktop notifications with privacy levelshas0.2.0[notify]: enabled, lanes, except, privacy, when_focused, backendownonly in fedtail (Tokodon — without privacy)
Activity: likes, boosts, followshas0.2.0activity.types/api/v1/notificationseveryone
Grouping notificationspartly0.2.0activity.typesfedtail groups them itself, it doesn’t use /api/v2/notificationsMastodon web, Ivory, Phanpy, Ice Cubes
Approve a reply, like, boost (GoToSocial)has0.13.0activity.approvals/api/v1/interaction_requestsonly in fedtail
Notifications from strangers aparthas0.9.0notify.filtered/api/v2/notifications/policy, notifications/requestsMastodon 4.3+
Severed relationships and moderators’ warningshas0.14.0activity.server_noticesnotifications severed_relationships, moderation_warningMastodon web
Dismiss a notification, clear them allhas0.11.0—notifications/:id/dismiss, notifications/cleareveryone
Server announcementshas0.9.0ui.announcements/api/v1/announcementsMastodon web, Phanpy, Elk, Megalodon
The unread number on the iconhas0.3.0ui.icon_count, ui.icon_count_except, ui.app_icon, ui.themed_iconownTokodon
Direct messages read here are read on the server toohas0.11.0"direct" in lanes.enabled/api/v1/conversations/:id/readonly in fedtail
In detail

Desktop notifications with privacy levels. Which lanes to notify about — notify.lanes (the same names as in [lanes]; "lists" — all lists, "list:Friends" — one, "all" — everything); which never — notify.except (a blacklist over lanes, say with ["all"]). privacy: "full" — who and what, "sender" — only who (fine to read with others around), "count" — only how many. About the lane in front of your eyes it keeps quiet by default (when_focused). backend: "auto" (notify-send, else the tray), "desktop", "tray".

Activity: likes, boosts, follows. The “Activity” lane: who liked, boosted, followed, a poll ended, a post you boosted was edited, a new post under a bell — with the time of each event. ["all"] — everything there is and what will be added.

Approve a reply, like, boost (GoToSocial). Interaction requests waiting for approval under your who-may-do-what settings come with “Approve” and “Reject” buttons.

Notifications from strangers apart. Mastodon holds back mentions from unknown and new accounts until you allow them. ≡ → “For the tender and sensitive” → “Filtered notifications…”: who waits, “Let in” / “Dismiss”, what to filter. "remind" — also a line at start, "menu" — in the menu only, "off" — not at all.

Severed relationships and moderators’ warnings. When your server blocks another one (or the other way round) and your follows are cut, Mastodon sends a notification with the list of what was lost; moderators may send a warning. fedtail shows them in “Activity” (activity.server_notices).

Server announcements. "banner" — a strip over the lane until you press “Got it” (the server remembers that for other clients too); reactions to announcements. "off" — not shown.

The unread number on the icon. In the tray and on the task bar button (KDE: needs the entry from --install-desktop and python3-pyside6.qtdbus). Which lanes to count — a list, as for notifications: "lists" — all lists, "list:Friends" — one, "all" — everything, plus icon_count_except — what not to count. The icon itself — an opossum holding its own tail (app_icon = "possum", also in the menu and in About), or the drawn thread bubble ("bubble"), which themed_icon paints in the theme’s colours.


Several accounts

WhatStatusSinceConfigAPI / protocolOthers
Profiles and the switcherhas0.3.0ui.switch_closes, the launch key --profile—every multi-account client
The main profile ★has0.14.0≡ → “Account and server” → “Make it the main one”; the mark ~/.config/fedtail/main-profileown—
Log in again, log outhas0.14.0≡ → “Account and server”, with a questionOAutheveryone
All accounts in one windowhas0.3.0ui.mergeownIvory, Phanpy, Elk, Tokodon, Sengi, Whalebird
An account’s colour in the shared windowhas0.14.0ui.account_colorsownFedilab
Acting as another accounthas0.14.0ui.act_asthe shared window, ⋯ → “From another account”: the post is looked up on its serverSengi, Tokodon
In detail

Profiles and the switcher. One profile — one account with its own config, theme, database and window. A right click on the avatar (or ≡ → “Account and server”) — the list, “My profile”, “About the server…” (it has the “Edit profile” button), “Add an account…”; switch_closes — whether to close the current window when switching. Which profile and account this is — on the left of the status bar: “default: @nick@server ★”.

The main profile ★. The one started without --profile and from the “fedtail” menu entry. It isn’t a folder with a special name but a mark — the main-profile file next to the profile folders; without the mark the main one is default. “Make it the main one” in the accounts menu moves it; in the list (and in --profiles) the main one is marked ★.

Log in again, log out. Both are in the accounts menu, both ask first. “Log in again…” — for a revoked token or new permissions: the old token lives until you’re in, cancelling changes nothing, and you can log in this way only to the same account (another one — “Add an account…”). “Log out…” deletes the token (read marks, drafts and the config stay); if that was the main profile, ★ goes to another one you’re logged in to and the window switches to it; if there are none — the login window. In the window of all accounts both items are unavailable.

All accounts in one window. Lanes of the same name merge, posts of other accounts are marked “→ @nick” — a reply, a like and a boost go from the account that received the post. Lists — lanes of their own. ["all"], profile names or [] — as chosen in the menu.

An account’s colour in the shared window. A coloured strip or mark on the posts that came to each account — to see in a merged window whose it is without reading “→ @nick”.

Acting as another account. Like, boost or reply not as the account that received the post: in the shared window, a post’s ⋯ menu has “From another account”: fedtail finds the post through that account’s server and does it from there; a reply opens in the editor as that account.


The application

WhatStatusSinceConfigAPI / protocolOthers
Themes as fileshas0.1.0ui.theme, ui.font_size, ui.font, ui.mono_font, ui.max_width, ui.sidebar_width, ui.actionsa TOML format of its ownothers — light and dark, Ice Cubes and Megalodon — colours of your own
Trying a theme without a restarthas0.15.0≡ → “Try a theme”; for good — ui.theme—Phanpy, Elk, Ice Cubes (they have few)
The config as a file in chaptershas0.6.1the launch keys --update-config, --rebuild-config—tut — TOML too, but not built by chapters
The settings referencehas0.13.0—tools/docs_build.pytut (a man page and a site), MediaWiki (an article per setting)
Window, tray, keyshas0.8.0ui.close_to_tray, ui.post_keys—keys — Mastodon web, Phanpy, Elk, Ivory, tut
Links to posts and profiles — insidehas0.2.0ui.links_in_appsearch?resolve=trueIvory, Phanpy, Elk, Megalodon, Fedilab
Open a link in the running fedtailhas0.14.0fedtail open URL; --install-desktop installs a web+ap:// handlerownMegalodon (share a link into the app)
Everything is stored locally, readable offlinehas0.1.0—SQLite in the profile’s data folderTusky — partly, Ice Cubes — a Home cache
Open for days without bloatinghas0.11.0ui.unload_hidden_minutes, ui.image_cache_mb, debug.trim_memoryown—
Polling the server and the live streamhas0.9.0[poll]: interval_seconds, stream, stream_gap_secondsstreaming (WebSocket)Mastodon web, Phanpy, Elk, Tokodon, Whalebird, Ice Cubes
Errors in plain words and without spamhas0.13.0—own—
A detailed log for bug reportshas0.2.0[debug], the launch keys --debug, --bug-reportown—
Federation status: how my server is doing and what failshas0.16.0≡ → “Debugging” → “Federation status”own (from what this run saw)—
Leak hunting: trends, an object census, memory snapshotshas0.14.0debug.leak_samples, debug.object_census, debug.tracemalloc; ≡ → “Debugging”own (gc, tracemalloc)—
The database doesn’t grow for ever: cleanup and a size budgethas0.17.0[storage]: max_mb, keep_per_lane, keep_activity, gc_hours, grace_hoursSQLite, incremental vacuum—
Screen readerspartly0.9.0ui.alt_text—Mastodon web, Tusky, Ivory
Interface languagehas0.1.0ui.language—everyone
Help inside, in two languageshas0.17.0≡ → “Help”own: fedtail/data/help/<lang>/—
“What’s this?”: a longer hint about any buttonhas0.17.0≡ → “What’s this?” for now; ui.whats_this — from the startown: hints.tomlKDE apps (What’s This)
In detail

Themes as files. Built in: system (as in KDE), terminal, juick, juick-classic, bnw, point, night, contrast (for weak eyes), pink, nord, solarized, paper, debug (for debugging: each state of a post — unread, the j/k cursor, found, “not seen whole yet, not read yet”, the keyboard focus — in a loud frame of its own; shape.debug = true turns the same on in any theme of your own). Your own — a file in ~/.config/fedtail/themes/. A theme sets the card’s layout too: the avatar’s shape (avatar_shape), the header in a line or the name over the date (card_header = "stacked"), where the #id stands (short_id: by the name or under the post with the reply count), which side the buttons are on (actions_align), the line between posts (rule: solid or dashed), a hatched band under the titles of the lane and the post window (header_stripes) and a dark strip over it (header_bar), the colour of the main buttons, of the lane’s title strip and of names. A theme sets the look of the whole app, not only colours; that’s why separate card templates aren’t needed (see Won’t do). The font — ui.font, over the theme’s (where the system one reads badly); a theme can bring fonts of its own ([font] files), and .ttf/.otf files in ~/.config/fedtail/fonts/ are picked up without installing them system-wide. The width of the posts column — max_width (0 — the full width; the ↔ button at the top left switches it for now and remembers the choice until the next start), labels on buttons — actions.

The config as a file in chapters. The program only reads the config. A new version brought settings — --update-config adds them to the right chapters with explanations; --rebuild-config rebuilds the file anew, keeping your values. A value written by hand stays yours when the default changes.

The settings reference. The config reference, built from the example configs: every setting with its description, choices and default, in tables by chapter, in Russian and in English. A test makes sure it keeps up with the files.

Window, tray, keys. The cross hides to the tray. j/k — through posts, r — reply, f — like, b — boost, m — bookmark, o/Enter — the thread. post_keys = false — the letters do nothing.

Links to posts and profiles — inside. @mentions, #tags and links to fediverse posts and profiles open in fedtail. Not found — the browser. Only web addresses go outside (and mailto:, xmpp:, gemini://, magnet:): fedtail won’t open a link to a file or a network share from someone’s post.

Open a link in the running fedtail. fedtail open URL from a terminal or a browser opens a post or a profile in the window already open (or starts it and opens it there). --install-desktop makes fedtail the handler of web+ap:// links — the “open in your app” buttons on servers’ pages.

Open for days without bloating. A lane not opened for unload_hidden_minutes minutes lets its cards go from memory; the one open is never unloaded. fedtail gives the freed memory back to the system (trim_memory: otherwise glibc keeps the peak after a night of lanes and pictures).

Polling the server and the live stream. A poll every interval_seconds (at least 30). The live stream ("auto", if the server offers it) wakes the poll at once, but not more often than every stream_gap_seconds. The stream only wakes, so if it drops (a laptop asleep, a proxy) nothing is lost.

Errors in plain words and without spam. A server behind a proxy is down — instead of Cloudflare’s HTML page one line “Bad Gateway — the server is down or not answering”; the same error of every poll is shown and logged once, again only when it changes or ten minutes later.

A detailed log for bug reports. In the debugging mode (mode = "auto" — on in development versions, off in releases): a log of requests, polls, actions (without the posts’ texts), errors with tracebacks, memory and thread stats every stats_minutes, a freeze watchdog (watchdog_seconds, stall_ms), slow requests, memory growth. crash.log — the stacks on a crash, kill -USR1 — the stacks on demand. The new version deletes the old version’s logs itself. --bug-report packs two days of it, without the token and the database. In detail — DEBUGGING.md.

Federation status: how my server is doing and what fails. ≡ → “Debugging” → “Federation status”: problems that don’t depend on the client. My server — what it runs, how many answers and how many with errors, how fast it answers (typical and slow ones), polling (the last good one, how many times it failed and why), the live stream (open since when, how many times it dropped). What the server can’t do (asked and got “no”). Who waits to go into a list: the name linked to the profile (opens in a tab, with “Follow”) and why they wait — a request unanswered, no follow (refused or withdrawn), or followed and going in by itself. What fails on my server and on other servers — grouped by request (ids folded: /api/v1/lists/:id/accounts), how many times, when last, and what it most likely means (“deleted on that server”, “won’t give strangers anything without a signature”, “lists take only people you follow”…). Other servers — who answered how much and with what errors. The window updates by itself while open; “Copy” — as text for an issue, “Count anew” — start from zero. For the window only your own server is asked — who those waiting in lists are; the rest is what this run saw. Addresses without parameters, no tokens.

Leak hunting: trends, an object census, memory snapshots. For days-long runs. With every stats line — a trend line: memory, Python objects, widgets, cards, pictures, threads, files — how many at start, how many now, how many an hour. Something that grew on each of the last leak_samples checks (12 — an hour) and by more than crumbs — a possible leak warning with the numbers; the first half hour doesn’t count. In the debugging mode — a census: which Python objects and Qt widgets were added since the last check and since the start (object_census). tracemalloc = true — memory tracing from the start; a snapshot — ≡ → “Debugging” → “Memory snapshot”: a file with who holds the most and what grew, by line of code. There too: “What grows: stats and census now”, “Give free memory back to the system”, tracing on/off. The session’s last line — session summary: hours, memory, peak, freezes, polls. How to leave it overnight — DEBUGGING.md.

The database doesn’t grow for ever: cleanup and a size budget. Every gc_hours (and at the first poll after start) posts nothing points at are forgotten: no lane, followed thread, “Activity” entry or reply draft. My own posts stay, and so do the boosted post, the quoted one and the parents up the whole thread of every post that stays, so visible replies aren’t fetched again. Whatever was stored recently (an open thread, a profile) lives grace_hours more. “Activity” keeps the latest keep_activity entries. The file really shrinks (incremental vacuum). If the database is still over max_mb (1 GB by default), lanes get 30 % shorter until it fits (never below 300) and grow back to keep_per_lane once there is room. Short ids (#a3f) are never forgotten. What was forgotten and how big the database is — the storage gc line in the log.

Screen readers. Picture descriptions and button names for screen readers are there, but the interface hasn’t been tried live with Orca.

Interface language. "auto" (from LANG), "ru", "en".

Help inside, in two languages. A panel in the main window, like the compose panel: the contents on the left, search through the whole help, Back and Forward. Short, by section, and at the end of each — “In detail →” into the full feature list and the settings reference: they are right here and work offline. No shortcut on purpose — F1 is next to Esc.

“What’s this?”: a longer hint about any button. Turn it on, and hovering shows a longer hint instead of the short one: what the button does, which config key changes it and which help section says more. The same menu item turns it off.


Interfaces

The core knows nothing about a GUI; interfaces are plugins. Which one to start — ui.frontend, or --ui for one run.

WhatStatusSinceConfigOthers
A Qt windowhas0.1.0ui.frontend = "qt"the main one
Commands in a terminalhas0.9.0[cli]: enabled, color, max_lines, tail_lanestut (TUI), toot (CLI)
A terminal interface (Textual)has0.10.0ui.frontend = "tui", [tui]: theme, lanes_width, show_context, pictures, picture_rowstut
Web on localhosthas0.10.0ui.frontend = "web", [web]: host, port, open_browserPhanpy, Elk — web clients
GTK4 + libadwaitaplanned——Tuba
Toga (BeeWare)planned———
In detail

Commands in a terminal. fedtail lanes, fedtail show replies -n 20, fedtail tail (the new as it comes), fedtail post "text", fedtail post --reply a3f "text", fedtail read replies. The same profile, database and read marks as the window; works without Qt.

A terminal interface (Textual). Lanes on the left, posts on the right, the command line at the bottom. The same keys, x — the lane is read, : — the command line. Lanes — [ / ], digits 1…9, h — into the lane list (j / k there), l — back to the posts, Tab — to and fro. “Activity” and “Follow requests” have rows of their own (in requests a — accept, d — reject). Pictures are drawn with half blocks: the first one small right in the lane (tui.pictures, tui.picture_rows), v — all of them full screen, ← / → between them, o — the original in the browser; needs Pillow (python3-pil) and a true colour terminal. Works over ssh. Needs python3-textual.

Web on localhost. fedtail in a browser tab: lanes, threads as trees, profiles, a “Write” button (content warning, who sees it, language, drafts), pictures in a grid with a viewer, video and audio, polls with voting, link cards, quotes, custom emoji, “More” at a lane’s end, the Point command line; on a phone the lanes slide in from the side, light and dark follow the system. At start a one-time link (15 minutes) is printed; the browser gets a key from the profile’s folder in a cookie (web.key; delete it and every browser and every old link with the key is out). host = "0.0.0.0" — from the phone on the home network too; no encryption, for your own network only. The ≡ menu (write, my profile, refresh, all read, help, keys, about) and a post’s ⋯ menu (reply with quote, subscribe / leave / mute the thread, copy the link, delete my post). A reply shows the whole post: select a piece and “❝ Quote in reply” puts it where the cursor is. The viewer goes through a post’s pictures with ← / →.

GTK4 + libadwaita. To look native in GNOME and other GTK desktops.

Toga (BeeWare). Native widgets of Windows, macOS, GTK, Android from one code. To try out.


Builds and installing

WhatStatusSinceNote
From the source: python3 -m fedtailhas0.1.0PySide6 and requests
Linux: one filehas0.5.0fedtail-X.Y.Z-linux-x86_64, built on Debian 12
A deb packagehas0.10.0built in CI on Debian 13
Windows: one .exehas0.5.0fedtail-X.Y.Z-windows.exe
A menu entry with the iconhas0.2.0--install-desktop
An apt repository of its ownplanned—from the releases’ deb packages
An installer and a signature for Windowsplanned—once there are users on Windows

ActivityPub directly

Everything here is a request to other servers without your token: they see only your IP. Servers that require signed requests (secure mode) simply give nothing, and fedtail quietly makes do with what your own server knows.

WhatStatusConfig
A whole thread: replies from the author’s serverhasfeed.complete_threads
A thread grows when Mastodon has gathered the replieshasfeed.complete_threads
Long texts and eventshasfeed.long_form
Honest countershasfeed.honest_counters (off), feed.counters_via_accounts
A little-known person’s profile — from their serverhasfeed.remote_profiles, feed.remote_posts
Posts older than my server knowshasfeed.remote_profiles
Followers and follows from the person’s serverhasfeed.remote_people
The person has movedhasfeed.show_moved
The author’s server softwarehasfeed.server_info

Plans

Each feature comes switchable, one at a time, with its entry here and a line in the CHANGELOG. The order is rough: the cheap first, the big later.

WhatChapterConfigSize
Collections (Mastodon 4.6)Lanes—once GoToSocial has them
GTK4 + libadwaitaInterfaces—large
Toga (BeeWare)Interfaces—large
An apt repository of its ownBuilds and installing——
An installer and a signature for WindowsBuilds and installing——

Won’t do

WhatWhy
Subscribing to old threads in a batchTaken off the queue.
Boost carouselSideways is awkward to read, and it fits badly with “nothing jumps” and read marks. Boosts are hidden with the filter, per person or with a list.
Card templates (like tut’s toot.tmpl)A theme already sets the look of the whole app; a second layer of templates over themes adds nothing.
AI helpers in the compose panel (as in Ice Cubes)Writing is the author’s job.
Push notifications (Web Push, UnifiedPush)A desktop has enough with the live stream and polling; push is for phones.
A node admin panel in the clientSitting in a client logged in as an admin is irresponsible. If a node ever needs setting up, there’ll be a separate tool for it.
Mastodon’s annual reportIt’s about neither reading nor conversation.
An XMPP gatewayTaken off the queue.

Not there and not decided

WhatOthersNote
Another server’s public timelineIce CubesReading another server’s Local without logging in. Many servers close it to strangers.
A link’s timeline (Mastodon 4.3+)Mastodon webEvery post about a popular link. GoToSocial can’t do it.
Sending emoji reactionsPhanpy, Elk, FedilabAkkoma, Pleroma, Misskey; GoToSocial can’t do it.
Spell checking in the compose panelTubaNot a priority. Qt has none of its own: it needs an outside library (hunspell or enchant) as an optional dependency.
The server’s grouped notifications (v2)Mastodon web, Ivory, Phanpyfedtail’s own grouping is there already.
The token from an external command (pass, gopass)tutIt’s unclear what this would add over a file readable by its owner only.