Skip to content

Repository files navigation

TinyTask

TinyTask for Linux

Record what you do. Play it back.

A small macro recorder for Linux on Wayland, modelled on TinyTask for Windows.

PlatformSessionLanguageRuns as


Looking for a macro recorder for Linux that captures mouse and keyboard and replays them exactly on Wayland without running as root?, You found it!. This app reads events straight from /dev/input and replays them through the compositor on KDE Plasma, or through a virtual input device elsewhere, so applications cannot tell a macro from a person.

Table of Contents

Features

  • Records mouse movement, the buttons, the wheel and the keyboard
  • Reads your input devices through a privileged helper, so your account never gets an ACL on them
  • Records touchpads, drawing tablets and the absolute pointer a virtual machine gives you
  • Replays through your compositor where it can, and through a virtual device where it cannot
  • Undoes the pointer acceleration KDE, GNOME, sway and Hyprland apply
  • Configurable global hotkeys
  • Repeats once, a set number of times or until you stop it
  • Reads and writes .rec files in TinyTask's Windows format
  • A status overlay with the time of your macro, the counts and the stop shortcut and more

Requirements

  • An active graphical session (sounds stupid but yea you need this): the access below follows whoever is logged in at the machine, so over SSH or from a system service you get none of it (but ik you need this for roblox)
  • Read access to /dev/input, for recording. Nothing grants it by default: the nodes are owned by root:input and your user is in neither that group nor holding an ACL. install.sh offers a small privileged helper that opens the devices and hands them to TinyTask alone, which changes no permission on the machine. Playing back a macro made elsewhere needs nothing. See How recording gets read access
  • polkit, only for that helper. It is what asks you for the administrator password and starts the helper as root. Nearly every desktop distribution ships it. Without it the helper cannot be authorised and the udev rule is the only way left
  • A way to replay input. Almost every desktop can do it for you and nothing needs root. Where none can, TinyTask replays through /dev/uinput, which needs a second udev rule. See Desktop Support
  • XWayland on a Wayland session - the window is an X11 client, so without it TinyTask has no display to open
  • The X11 and text libraries every desktop already ships - libX11, Xinerama, Xcursor, Xfixes, Xext, Xrender, pango, cairo, glib and fontconfig. The prebuilt binary does not load without them
  • glibc 2.35 or newer - for the prebuilt archive. Anything as recent as Ubuntu 22.04 has it, ldd --version tells you yours. Build it yourself if it is older
  • Rust - 1.97 or newer, only if you build it yourself (rustup installs it in one command)
  • Pointer acceleration set to Flat for the mouse and for the touchpad if you record with one. Recording sums the raw movements the device sends so the adaptive profile and the default nearly everywhere scales them by a factor that changes with speed and no fixed number can undo it, so macros land off target. TinyTask reads the setting on KDE, GNOME, sway and Hyprland and tells you at startup when it cannot compensate

No desktop in particular is required. What each one gives you is in Desktop Support.

Desktop Support

Recording and playback work on every desktop. Recording goes through /dev/input and needs the read rule everywhere, because no desktop grants that access on its own. What changes is how a macro is played back, and what else you get.

DesktopPlays back without a udev ruleHowStatus overlayTray iconReads your mouse speed
KDE PlasmaKWin, granted to this binary alone
GNOMEportal, granted once and remembered⚠️
Hyprlandvirtual pointer and keyboard⚠️
Swayvirtual pointer and keyboard⚠️
Nirivirtual pointer and keyboard⚠️
Wayfirevirtual pointer and keyboard⚠️
COSMICits compositor has no virtual pointer⚠️
X11, any desktopXTEST⚠️
  • ✅ = Works.
  • ⚠️ = Works only if something else provides it.
  • ❌ = Not available

TinyTask tries each of those in turn and falls back to /dev/uinput, the only playback path that needs a udev rule of its own. tinytask --injector says which one it picked and why it skipped the others. Run it first if a macro does not replay.

They are not equally good. On Plasma the grant is per application: KWin hides the interface and offers it only to the binary your desktop entry names, so nothing else on the machine gains anything. On GNOME the portal asks you once and remembers, which is the same idea. The wlroots protocols ask nobody: any program that can reach your $WAYLAND_DISPLAY may use them. That still beats an ACL granted to your whole account, but it is not a permission.

The overlay needs the wlr-layer-shell protocol. GNOME does not implement it and X11 has no equivalent, so there the overlay never appears and Prefs greys the setting out.

The tray icon needs a StatusNotifierItem host. Plasma has one built in. GNOME needs the AppIndicator extension, and a bare compositor needs a bar that provides one, such as Waybar. Without a host the window simply never goes to the tray.

Download

Take the archive for your machine from the releases page. There is one for x86_64 and one for aarch64; uname -m tells you which you are on. Unpack it and run the installer:

tar -xzf tinytask-*-linux.tar.gz
cd tinytask-*-linux
bash install.sh

That puts TinyTask in your application menu. The launcher points at the binary in the folder you unpacked, so leave the folder where it is. bash install.sh --uninstall takes it back out.

The installer offers the input helper whenever you cannot already read /dev/input, because recording is impossible without one or the other. It offers the udev rule for /dev/input only when the helper cannot be used, and the one that opens /dev/uinput only where nothing better can replay a macro. Read How recording gets read access before you say yes to any of them.

On GNOME, run tinytask --portal-consent once, approve the dialog and tick its remember box. TinyTask never raises that dialog on its own.

Build and Run

git clone https://github.com/burlone0/TinyTask-Linux.git
cd TinyTask-Linux
cargo build --release
./target/release/tinytask

The first build takes a few minutes, FLTK compiles its own C++ library but later ones take seconds. That needs CMake, a C++ compiler and the -dev packages for the libraries under Requirements.

Debian, Ubuntu, Mint, Pop!_OS

sudo apt install cmake g++ libx11-dev libxext-dev libxft-dev libxinerama-dev \
libxcursor-dev libxrender-dev libxfixes-dev libpango1.0-dev libgl1-mesa-dev libglu1-mesa-dev

Arch, CachyOS, Manjaro, EndeavourOS

sudo pacman -S --needed cmake gcc libx11 libxext libxft libxinerama libxcursor \
libxrender libxfixes pango mesa glu

Fedora, RHEL, Nobara

sudo dnf install cmake gcc-c++ libstdc++-static libX11-devel libXext-devel libXft-devel \
libXinerama-devel libXcursor-devel libXrender-devel libXfixes-devel pango-devel \
mesa-libGL-devel mesa-libGLU-devel

openSUSE

sudo zypper install cmake gcc-c++ libX11-devel libXext-devel libXft-devel libXinerama-devel \
libXcursor-devel libXrender-devel libXfixes-devel pango-devel Mesa-libGL-devel glu-devel

Alpine

sudo apk add cmake g++ libx11-dev libxext-dev libxft-dev libxinerama-dev \
libxcursor-dev libxrender-dev libxfixes-dev pango-dev mesa-dev glu-dev

Only the Debian and Arch lines have been run. The rest name the same libraries under each distribution's own convention. Tell me with an Issue if one is wrong.

The same installer works from the checkout and --link also puts tinytask on your PATH:

bash install.sh --link

Without --link it only makes that symlink when ~/.local/bin already exists, rather than creating a directory on your PATH behind your back.

Usage

The window is a single strip of five buttons: Open, Save, Rec, Play, Prefs

Press Ctrl+Shift+R (Default Keybind) or the Rec button to start recording. The cursor jumps to the top-left corner, it establishes a known origin. Do whatever you want recorded, then press it again to stop.

Press Ctrl+Shift+P (Default Keybind) or the Play to play back your macro, again to stop a macro that is running.

You can change the keybinds in Prefs > Keys by pressing the combination you want. It needs at least one modifier because a bare key would fire while you type and the two must differ.

The play combination is the emergency stop and the only way to halt a macro set to run continuously. Bind it to something your compositor does not already use.

The record combination cannot appear inside a macro, its keys are stripped or replaying would press them and start recording again.

Closing the window sends it to the tray (you can disable that in Prefs)

The status overlay appears while a macro records or plays, put it at any edge or corner of the screen or switch it off in Prefs > Window and overlay.

Command Line

tinytask --record macro.rec # record until the hotkey, then save
tinytask --play macro.rec # replay it
tinytask --loops 5 # repetitions for --play, 0 means forever
tinytask --from-screen WxH # size of the screen a macro came from
tinytask --inspect macro.rec # decode and analyse a file
tinytask --injector # show how macros will be replayed
tinytask --list-devices # show the input devices being read
tinytask --list-screens # show the desktop geometry in use
tinytask --portal-consent # ask the desktop portal for permission, once
tinytask --portal-forget # throw that permission away

A .rec file does not record the screen it was made on so nothing is ever scaled for you. When you know a macro came from a machine of a different size, say it so the coordinates are mapped onto yours, use: tinytask --play macro.rec --from-screen 1920x1080

TinyTask reads your monitor layout from the display server at startup, and --list-screens prints what it found. Set TINYTASK_SCREEN=1920x1080 to state the size yourself, for a headless test or a machine where the layout cannot be read. Without the display and without that variable it refuses to run rather than guess, because a wrong size puts every coordinate somewhere else.

Known Limitations

  • The status overlay needs wlr-layer-shell. KDE, sway and Hyprland have it, GNOME and X11 do not, and there the overlay never appears at all. Prefs greys the setting out and says why, rather than pretending.
  • Hotkeys do not span two keyboards. Detection runs per device, so holding the modifiers on one and pressing the key on another do not work.
  • The adaptive acceleration profile cannot be compensated for. Its factor changes with the speed of the movement, so no fixed number undoes it. Set a flat profile, or measure the factor yourself under Prefs > Mouse.
  • Two keyboard layouts at once replay through the first. On the wlroots protocols the active layout cannot be read without keyboard focus, which TinyTask never has. It says at startup which layout it will use.
  • A tap on a touchpad is not recorded. libinput invents the click above the level TinyTask reads, so a tap leaves nothing to record. Press the physical button. Two-finger scroll is dropped rather than translated.
  • COSMIC needs the udev rule. Its compositor has the virtual keyboard but no virtual pointer, so there is nothing to replay pointer movement through.
  • The input helper has never been run from a real installation. Its protocol, both credential checks and every failure path are tested with both ends unprivileged, but no test here can install it under /usr/libexec, register the polkit action or authenticate. Report an Issue if the prompt or the handshake misbehaves on your machine.
  • The helper is not restarted if it dies. Devices already open keep working, because a descriptor stays valid once it has been handed over, so the stop hotkey stays armed and a running macro can still be stopped. What is lost is hotplug: a keyboard that sleeps and wakes comes back as a node nothing can open. TinyTask says so on standard error rather than going quiet.

How recording gets read access

Recording reads the keyboard and the mouse straight from /dev/input/event*. Those nodes are owned by root:input with mode 0660 and nothing grants you an ACL on them, on any distribution: systemd tags an input device for uaccess only when it is a joystick, so a keyboard and a mouse stay out of your reach. If you have read anywhere that your session already has this, including in an older version of this file, that was wrong.

There are two ways in and they are not the same size of step. TinyTask takes the narrower one when it can.

The input helper is the default.install.sh puts a separate program at /usr/libexec/tinytask/tinytask-input-helper and registers a polkit action for it. When TinyTask cannot read the devices itself it asks polkit to start that helper as root, and the helper opens every /dev/input/event* node read only and passes the open file descriptors back over a socket. A descriptor is checked when it is opened, not on every read, so TinyTask can read those devices while every file permission on the machine stays exactly as it was. Nothing else you run gains anything. The helper opens nothing but input devices, never writes to them, takes no path from anyone, checks that the process it is talking to is the user who asked for it, and exits when TinyTask does.

polkit asks for an administrator password and remembers the answer for a few minutes, so a restart within that window does not prompt again. That window is the cost: while it is open, another program running as you could start the helper for itself without a prompt of its own. It closes on its own and there is no prompt at all outside it.

60-tinytask-input.rules is the fallback.install.sh offers it only when the helper cannot be used, which means polkit is absent or you declined. It tags every input device for uaccess, which grants your account an ACL on all of them, read and write, until you log out. Read is the part that matters: once it is in place, any program running as you can see every key you press, passwords included. That is what a keylogger does. It cannot be narrowed to TinyTask, because Linux permissions are per user and not per application. Joining the input group grants the same read and keeps it after logout, so the rule is the narrower of those two.

60-tinytask-uinput.rules is about playback, not recording. It grants write on /dev/uinput, which lets any program running as you inject keystrokes and clicks. You only need it where nothing else can replay input, which today means COSMIC and anything not in the table above.

On a system without logind, which means Devuan, Alpine, Void with runit and anything else on eudev or OpenRC, the uaccess tag has nothing to act on and the rule does nothing at all. The helper is the only route that works there, and it does not depend on logind for anything.

Disclaimer

This replays input at the system level, it moves your real cursor and presses your real keys. A macro that goes wrong can click things you did not intend. Test one on something harmless first and remember the play combination stops it.

Automating an application may violate its terms of service. That is on you.

To Do

  1. Make a better UI (THIS IS A PRIORITY DUDE)
  2. Add smth before start the rec for choose if rec keybinds or mouse tracking or one or both yk that
  3. idk actually just these because i think that the rest is good actually

License

See LICENSE.

About

Macro recorder for KDE Plasma on Wayland, modelled on TinyTask for Windows

Resources

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages