Skip to main content

A task manager in your terminal.

Project description

tasky

A task manager in your terminal.

CI Python 3.12+ Built with Textual License: MIT Written by AI

  Projects       │  Todo                      Notes │  buy milk
 ────────────────┤ ─────────────────────────────────┤ ─────────────────────────────
  Add a project  │  What needs doing?               │  Add a note
                 │
  All         3  │  ✓  buy milk  #groceries     ✎ 2 │   oat, not soya
  groceries   1  │  ○  walk dog                     │   14 Jul 09:14
  health      1  │  ○  book dentist  #health    ✎ 1 │
                 │                                  │   the corner shop stocks it
                 │                                  │   14 Jul 09:15 · edited 17:02
  2 projects     │  2 active · 1 completed          │  2 notes

Status: early days. You can add todos, edit them, complete them, delete them, archive the completed ones, keep notes against any of them, and file them under projects. Tasky records when each one was added and completed, and shows you both.

📝 This is a personal project, and it was written entirely by AI.

Tasky was built for one person's use and shared in case it's useful to you. It is not a product: there's no warranty, no support, and no promise that it will be maintained.

Every part of it was written by AI (Claude), not by hand — the code, the tests, and this documentation included. See About this project.

Install

pip install tasky-tui

The distribution is named tasky-tui because tasky was already taken on PyPI. The command you run is still tasky.

Usage

tasky

Type a todo and press enter to add it. Tab down to the list and press enter on a todo to mark it done. Your todos are saved as you go, and are still there next time.

Key Action
enter Add the typed todo, complete the selected one, or show the selected project
alt+e Edit the selected todo — or the selected note or project, in its pane
alt+d Delete the selected todo — or the selected note or project, in its pane
alt+z Undo the last delete, of whichever you just deleted
alt+m Move the selected todo to a project
alt+n Step into the notes drawer
alt+p Step into the projects pane
escape Cancel an edit in progress, or leave the pane you're in
alt+a Archive completed todos
alt+v Show the archive (alt+v again to go back)
alt+u Restore the selected todo from the archive
alt+q Quit

Shortcuts work while you're typing, so you never have to leave the input to use them. The footer only offers the ones that would actually do something where you are.

The pane you're standing in is the one that's lit — its edge and its heading — so the keys, which mean the thing in front of you, always have somewhere obvious to point.

Each todo shows when you added it and when you completed it (in a wider terminal than the one sketched above — see below). The dates are stored as UTC and shown in your own timezone. Reopening a todo clears its completion date, since it is no longer done.

Projects

A todo can be filed under a project, and most of them never are. Filing is something you do when it helps, not a toll you pay on the way in — so a tasky with no projects in it is the tasky that was here before, one pane fewer, every key meaning what it always did.

The way in is the bar you're already typing in. If the last word of a todo starts with a #, that word is the project it goes in:

buy milk #groceries

The project is made the first time you name it, so there's no step between deciding to file something and having somewhere to file it. #Groceries and #groceries are one project, not two.

Only the last word counts, and that's the whole rule. pay invoice #123 to acme is a todo about an invoice and nothing else, because the hash isn't at the end — so a todo that has to carry a hash word has somewhere to put it. pay invoice #123 does file itself under a project called 123, which is the price of a rule you can hold in your head. It isn't a trap: the project is written on the row, alt+e hands you back the very line you typed, and deleting the tag takes the todo back out again.

That round trip is what makes the tag the whole truth. What's in the bar is what the todo is: no tag means no project, whether you never typed one or you've just rubbed it out. Nothing is remembered behind your back.

alt+m is the other door, for when the todo is already there and the project is an afterthought — which is most of the time. It opens the same bar on the same todo with the tag started for you, so naming a project is a word and an enter rather than a trip to the end of a line you didn't want to edit. It starts the tag fresh rather than filling in the one that's there, so enter on the bare # takes the todo out of its project: the "nowhere" answer is a keystroke, not nine backspaces.

alt+p steps into the pane, and lands you on the projects rather than in its bar — you're rarely here to make one, since there's a project on the end of every todo you type. You're here to stand in one. enter shows a project's todos and hands the focus back to the list, because choosing a project is something you do on the way to working in it. The first row is All, which is not a project but the way back out of one.

Standing in a project, the list is that project: a todo you add joins it without being told to, alt+a archives the completed todos of that project and leaves the ones you can't see alone, and the #tag comes off the rows — it would only repeat the same word down the screen, and the pane and the title say it once already. Edit a todo out of the project you're standing in and it leaves the list, because a project you're standing in is a place, not a suggestion.

In the pane, the keys you know mean the project in front of you: alt+e renames it — once, everywhere, since the todos point at it rather than spell it — alt+d deletes it, and alt+z puts it back with the todos it held. Deleting a project isn't deleting its todos; they go on existing, simply filed nowhere. That's what makes it safe, and alt+d on the todos themselves is right there if throwing them away is what you meant.

A project name is one word, so that you can always type it as a tag. A project outlives the todos in it: archive the last one and the project is still there to add to. That's the whole reason a project is a thing in its own right rather than a word written on a todo — and the reason a rename is one edit instead of one per todo.

The archive can be read a project at a time, which is much of what an archive is for. Your projects themselves are read-only in there: rearranging them from inside a record of what happened is not a thing to want.

Notes

A todo is one line, and sometimes one line isn't enough. The drawer on the right holds as many notes as you like against the todo you're on, and it follows the highlight — so you can run down your list and read what you wrote about each one, without opening anything.

alt+n steps across into it. Type a note and press enter to add it. alt+e (or enter on the note itself) opens it for editing, alt+d deletes it, and alt+z puts a deleted one back where it was. escape backs out of an edit; press it again to go back to the list. tab moves between the two panes.

Those are the keys you already know from the list, and in the drawer they mean the note in front of you rather than the todo it belongs to. Which pane you're standing in is what decides — the footer changes as you move, so it always shows what the keys will do where you are. The Notes column on the todo list shows which todos have something written against them.

Each note records when it was written, and when it was last rewritten. The edited half of that line only appears once you've actually changed it, so "written and never touched since" is something you can see at a glance.

Notes belong to their todo. Archive the todo and the notes go with it; delete it and they go too, with nothing orphaned behind. Notes on an archived todo can be read but not changed — like the archived todo itself, they're a record of what happened. alt+u the todo back to your list if you want to write more.

Four things want the width, and they give way in that order. The todo itself always gets it. Then the notes drawer, which is about the todo you're standing on, and so the pane worth having open while you read down the list. Then the projects pane. The dates are the first to step aside and the last to come back: they're a record and the todo is the point — and they're the only one of the four you can't ask for, since alt+n and alt+p fetch a pane wherever you're standing, and a todo wears its project on its own row.

A terminal of about 130 columns holds all four. Narrower than that, the dates step aside for the panes; they're still in the file, and still there when you widen the window. Narrower than 100, the projects pane stops standing beside the list, and narrower than 60 the notes drawer does too. A pane that can't stand beside the list isn't gone: alt+n and alt+p put it in front of the list instead, and escape gives the list back. So the notes and the projects are reachable in any terminal; they just can't always be read at the same time as the todos they belong to.

alt+e opens the selected todo for editing in the same bar you add todos with, with its text already there and the cursor at the end. enter saves it, escape leaves it as it was. Editing the wording doesn't make it a new todo, so it keeps the day you added it — and a completed todo stays completed.

alt+d deletes the selected todo, and alt+z puts it back exactly where it was. One level of undo: it's for the delete you just regretted, not a history to walk back through. Deleting isn't archiving — a deleted todo is gone, not filed away.

Completing a todo leaves it in the list, struck through, so you can see what you got done and undo a mis-click. alt+a sweeps those into the archive once you're finished with them. alt+v shows the archive, newest first; tasky only reads it when you ask for it, so opening the app stays instant no matter how much you archive.

alt+u puts an archived todo back on your list, exactly as it was — still completed, so it is a true undo of archiving. Press enter on it to reopen it. alt+d works in the archive too, and there it means gone for good — otherwise the archive would be a one-way door that only ever grows. alt+z undoes that as well.

The archive itself is read-only: it's the record of what you finished, so alt+e doesn't apply there. Restore a todo with alt+u if you want to change it.

Where your data lives

Tasky stores everything in the standard user data directory for your OS:

OS Location
Linux ~/.local/share/tasky/ (or $XDG_DATA_HOME/tasky/)
macOS ~/Library/Application Support/tasky/
Windows %LOCALAPPDATA%\tasky\

Set TASKY_DATA_DIR to override it.

Three files live there, shaped for different jobs:

  • todos.json — your working list. Rewritten in full on every change, which stays cheap because archiving keeps it small. Written atomically (write, then rename), so an interrupted save can't truncate it. If it ever does become unreadable, tasky moves it aside to todos.json.corrupt rather than overwriting it.
  • archive.jsonl — completed todos, one JSON object per line. Append-only, so archiving costs the same whether it holds ten todos or a hundred thousand, and it's never read at startup. A torn write damages one line, not the whole file.
  • projects.json — the projects you file todos under. A file of their own, because a project outlives the todos in it, and neither of the files above could hold one: the working list is the wrong place for something that survives the list emptying, and archive.jsonl is append-only, so nothing in it could ever be renamed. Written only when the projects themselves change, which is rarely.

All three are plain text, so you can read, grep, or back them up with anything. Each todo carries its created_at and, once completed, its completed_at — both UTC ISO 8601, so they stay unambiguous wherever you read them.

Its notes are nested inside it, each with its own created_at and, once edited, its updated_at; that's what makes archiving a todo carry its notes along for free, and deleting one take them with it. Its project is the other way about — named by id rather than nested, because it's one project and many todos, and because it goes on existing when the todos in it don't.

That does mean an archived todo can name a project you've since deleted. It shows no project, which is the truth: there's no longer one to show. Deleting a project unfiles the todos still in your list, but it doesn't reach back into the archive and rewrite what happened.

A file written by an older tasky still loads: its completed todos simply have no completion date, its todos have no notes and are in no project, and tasky won't invent any of it.

Development

This project uses uv.

uv sync          # install dependencies
uv run tasky     # run the app
uv run pytest    # run the tests

Releasing

Nobody uploads to PyPI from a laptop. Bump the version in pyproject.toml, then push a tag that agrees with it:

git tag v0.1.0
git push origin v0.1.0

That runs the tests, builds, and publishes — and the build refuses to go on if the tag and the version in pyproject.toml disagree, since a version number is a promise PyPI only lets you make once. GitHub proves who it is to PyPI with a short-lived token minted for that one run (trusted publishing), so there's no API token in the repo's secrets to leak, rotate, or forget about.

About this project

Tasky is a personal project. It was built for one person's use and put in the open in case someone else finds it useful. That's the whole of its ambition — it isn't a product, and you shouldn't plan around it. There's no warranty, no support, no roadmap, and no promise that the next version exists at all. If it breaks, you keep both pieces (though your data is plain text, so the pieces are legible ones).

It was written entirely by AI. Every line of the code, every test, and every word of this documentation was written by Claude rather than typed by a human. A human set the direction and decided what was worth building — but nothing here was hand-written, and the design decisions the prose above explains so confidently were the AI's to make.

Both of those are worth knowing before you install it. Read the code before you trust it with anything that matters; it's small enough to read in an afternoon, which is one of the better arguments for it.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tasky_tui-0.1.0.tar.gz (36.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tasky_tui-0.1.0-py3-none-any.whl (46.0 kB view details)

Uploaded Python 3

File details

Details for the file tasky_tui-0.1.0.tar.gz.

File metadata

  • Download URL: tasky_tui-0.1.0.tar.gz
  • Upload date:
  • Size: 36.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tasky_tui-0.1.0.tar.gz
Algorithm Hash digest
SHA256 37a89233a749b175f3d1ad8e6e5ae44bddb7605d7fed135e02bded594ed56002
MD5 b25d8671b75a0d5bb9e45a6b04ad51be
BLAKE2b-256 fca8003146f536aa91238c9a870bf6751cf9b3c17b050b3eaad501d75958fcd5

See more details on using hashes here.

Provenance

The following attestation bundles were made for tasky_tui-0.1.0.tar.gz:

Publisher: publish.yml on prabhuakshay/tasky

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tasky_tui-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: tasky_tui-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 46.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tasky_tui-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 83b9d1449786dd203562cdffca4b808eac440412ea28442bbae0e0cd232460ff
MD5 9042ac91bb3647b4362f62838bb16bd1
BLAKE2b-256 a2886456f74b4dec5d614902e30826cc1c763c4788c27a3f44b190a3d2c580f4

See more details on using hashes here.

Provenance

The following attestation bundles were made for tasky_tui-0.1.0-py3-none-any.whl:

Publisher: publish.yml on prabhuakshay/tasky

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page