TUI Mastodon Client
- Home, local, federated, list, hashtag, bookmark, favourite, and notification timelines, plus search
- Live updates over the streaming API with automatic reconnection and backfill
- Threads with reply indentation, profiles with custom fields and follow state
- Images and avatars through the kitty graphics protocol or sixel, with block-character fallback and alt text
- Content warnings and sensitive media hidden until you ask
- Favourite, boost, bookmark, follow, vote in polls
- Compose and reply in your own editor
- Links view with numbered shortcuts, copy to clipboard, open in browser
- Keyboard driven with a built-in help screen, mouse supported
This project uses just as a command runner and requires Go for building.
justorjust installbuilds and installs the binary toPREFIX/bin/(default:/usr/local/bin)just buildbuilds the binary in the current directoryjust testruns the unit testsjust lintchecks formatting and runsgo vetjust racebuilds a race-detector binary for manual testingjust uninstallremoves the installed binaryjust cleanremoves built binaries
tuitPress ? at any time for the list of keybindings.
On first run, the app guides you through Mastodon authentication and then starts:
$ tuit
Enter the URL of your Mastodon server: mastodon.social
Open this URL in your browser and authorize the app:
https://mastodon.social/oauth/authorize?...
Paste the authorization code here: [paste-code-from-browser]
Credentials saved to /Users/you/.config/tuit/config.json
| OS | Location |
|---|---|
| Linux | $XDG_CONFIG_HOME/tuit/config.json or ~/.config/tuit/config.json |
| macOS | $XDG_CONFIG_HOME/tuit/config.json or ~/.config/tuit/config.json |
| Windows | %APPDATA%\tuit\config.json |
The preferences block in config.json is optional; missing fields use the defaults shown here.
{
"auth": { "...": "..." },
"preferences": {
"split_ratio": "2:3",
"show_images": true,
"expand_cw": false,
"show_sensitive_media": false,
"timestamp": "absolute",
"default_visibility": "public",
"editor": "",
"desktop_notifications": false,
"confirm_boost": true,
"keys": {
"down": "j,Down",
"up": "k,Up"
}
}
}split_ratiosets the width of the timeline versus the detail paneshow_imagesturns image rendering off when falsetimestampisabsolute(2006-01-02 15:04, the default) orrelative(5m,2h,3d)default_visibilityapplies to new posts:public,unlisted,private, ordirect; replies inherit the visibility of the post they answereditoroverrides$VISUALand$EDITORfor composingdesktop_notificationsraises a terminal notification when you are mentionedconfirm_boostasks before boosting or removing a boostkeysrebinds actions; the action names are the ones listed in?and below, and several keys can be given separated by commas (Ctrl+d,Enter,Esc,Tab,Space,Up,Down,PgUp,PgDown,Home,Endare understood)
- Credentials are stored in plain text in the config file
- The config directory is created with mode
0700and the file with0600(owner only); existing files are tightened on load - The access token has
read writescope, which favourites, boosts, follows, votes, and posts need
If authentication fails, the error is printed to the terminal on exit. To start over, delete the config file and run tuit again.
Set TUIT_DEBUG=1 to write a debug log to debug.log in the user cache directory (~/Library/Caches/tuit/ on macOS, ~/.cache/tuit/ on Linux).
Action names in parentheses are what the keys preference accepts.
| Key | Action |
|---|---|
? |
Show or hide the help (help) |
q |
Close the current thread or profile; at a root timeline, ask to quit (quit) |
Esc |
Close the current thread, profile, or links view (back) |
Ctrl+c |
Quit immediately (force_quit) |
Tab |
Switch focus between the timeline and the detail pane (focus_next) |
h |
Focus the timeline (focus_timeline) |
l |
Focus the detail pane (focus_detail) |
r |
Fetch newer items for the current timeline (reload) |
t |
Open the thread of the selected status (thread) |
u |
Open the profile of the selected status's author (profile) |
U |
Open your own profile (own_profile) |
i |
List the links and media of the selected status (links) |
x |
Show or hide content behind a content warning or sensitive media (toggle_cw) |
y |
Copy the selected status or link URL to the clipboard (yank) |
O |
Open the status on its original server in the browser (open_original) |
o |
Open the status on your server in the browser (open_local) |
v |
Open the link card, or the first link in the status (open_link) |
| Key | Action |
|---|---|
1 |
Home (home) |
2 |
Notifications; opening them marks them read (notifications) |
3 |
Local timeline (local) |
4 |
Federated timeline (federated) |
5 |
Your bookmarks (bookmarks) |
6 |
Your favourites (favourites) |
L |
Choose one of your lists (lists) |
# |
Open a hashtag timeline (hashtag) |
/ |
Search statuses and accounts (search) |
| Key | Action |
|---|---|
f |
Favourite or unfavourite the selected status (favourite) |
b |
Boost or unboost the selected status (boost) |
s |
Bookmark or unbookmark the selected status (bookmark) |
F |
Follow or unfollow the selected account or author (follow) |
p |
Vote in the selected status's poll (vote) |
c |
Write a new post in your editor (compose) |
R |
Reply to the selected status in your editor (reply) |
| Key | Action |
|---|---|
j |
Next status; loads more at the end (down) |
k |
Previous status (up) |
Ctrl+d |
Down half a page (page_down) |
Ctrl+u |
Up half a page (page_up) |
g |
First status (top) |
G |
Last status (bottom) |
The same keys scroll the detail pane when it has focus.
| Key | Action |
|---|---|
j/k |
Select next or previous link |
Enter |
Open the selected link (select) |
1..9 |
Open a link by number |
y |
Copy the selected link |
q/Esc |
Close the links view |
Click a row to select it or a pane to focus it. The wheel moves through the timeline or scrolls the detail pane.
c opens your editor (preferences.editor, then $VISUAL, then $EDITOR, then vi) on an empty file; R prefills the mentions of the selected status and inherits its visibility and content warning. Save and quit to continue, or quit with an empty file to discard the post. Tuit then asks for an optional content warning and shows the character count and visibility; press v to cycle the visibility and y to post.


