tsk
===
A fast & simple CLI task manager
--------------------------------
The motivation for tsk is simple: make managing tasks as fast and easy as
possible with a focus on small, ephemeral tasks.
Secondary goals include:
- Provide the minimum amount of features necessary to be usable by a team
- Support local and non-local workspaces
- Be adaptable to almost any environment, even employer-mandated JIRA use
- Be flexible, within reason
tsk takes inspiration from git and FORTH and is expected to be used alongside
the former.
Dependencies
------------
tsk is written in Rust. To compile from source, a recent Rust toolchain is
required. As of now, it is developed using Rust 1.81.0.
Additionally, for fuzzy-finding functionality, the fzf command must be installed
and in the shell's PATH.
https://github.com/junegunn/fzf
tsk workspaces must be created on filesystems that support symlinking.
Task-level metadata requires Linux's xattr(7) API and a filesystem that supports
it. Patches that implement this for other operating systems are welcome.
tsk expects to run on POSIX-like systems. Microsoft Windows and other
non-UNIX-ey operating systems will never be directly supported.
Installation
------------
```sh
cargo install --locked tsk-cli
```
Building
--------
```sh
cargo install --path .
```
Make sure ~/.cargo/bin is in your PATH.
Overview
--------
A summary of commands and their functionality can be seen with:
tsk help
tsk uses plain text files for all of its functionality. A workspace is a folder
that contains a .tsk/ directory created with the `tsk init` command. The
presence of a .tsk/ folder is searched recursively upwards until a filesystem
boundary or root is encountered. This means you can nest workspaces and use
folders to namespace tasks while also using tsk commands at any location within
a workspace.
New tasks are created with the `tsk push` command. A title is always required,
but can be modified later. A unique identifier is selected automatically and a
file with the title and any body contents supplied are stored in the
.tsk/archive folder. A symlink is then created in the .tsk/tasks folder marking
the task as "open." The task is then added to the top of the "stack" by having
its tsk-ID and title added to the .tsk/index file.
The contents of the stack may be printed using the `tsk list` command.
Tasks are marked as "completed" and removed from the index with the `tsk drop`
command. They will remain in the .tsk/archive folder, but are excluded from
fuzzy searches by default.
The priority of a task may be manipulated in any of several ways:
`tsk swap` swaps the top two task on the stack
┌─────────┐ ┌─────────┐
│ tsk-100 │ │ tsk-102 │
└─────────┘ └─┬─────▲─┘
│ │
┌─────────┐ ┌─▼─────┴─┐
│ tsk-102 │ ───────► │ tsk-100 │
└─────────┘ └─────────┘
┌─────────┐ ┌─────────┐
│ tsk-108 │ │ tsk-108 │
└─────────┘ └─────────┘
`tsk rot` moves the 3rd task on the stack to the top of the stack and shifts
the first and second down
┌─────────┐ ┌─────────┐
│ tsk-100 │ │ tsk-108 ◄─┐
└─────────┘ └────┬────┘ │
│ │
┌─────────┐ ┌────▼────┐ │
│ tsk-102 │ ───────► │ tsk-100 │ │
└─────────┘ └────┬────┘ │
│ │
┌─────────┐ ┌────▼────┐ │
│ tsk-108 │ │ tsk-102 ├─┘
└─────────┘ └─────────┘
`tsk tor` moves the task on the top of the stack behind the third, shifting the
second and third tasks up.
┌─────────┐ ┌─────────┐
│ tsk-100 │ │ tsk-102 ├─┐
└─────────┘ └────▲────┘ │
│ │
┌─────────┐ ┌────┴────┐ │
│ tsk-102 │ ───────► │ tsk-108 │ │
└─────────┘ └────▲────┘ │
│ │
┌─────────┐ ┌────┴────┐ │
│ tsk-108 │ │ tsk-100 ◄─┘
└─────────┘ └─────────┘
`tsk prioritize` will take a selected task and move it to the top of the stack
from any other position in the stack. It is selected either by ID or using fuzzy
finding.
`tsk deprioritize` moves a selected task to the bottom of the stack from any
position.
Roadmap
-------
- Configurable workspace-scoped prefix tags (tsk- vs example-)
- Extended Attribute-based Metadata
- Task Linking
- IMAP4/SMTP-based synchronization and sharing
- Export + sync with external task managers
- GitLab
- GitHub
- JIRA
- Obsidian
- More?
- tsk -> html export
- Editor plugins
- nvim-telescope
- nvim
- others?
- Man page
Format
------
The tsk text format can be thought of as a derivative of Markdown and scdoc, but
not quite either. Markdown is a great baseline for rich-text while scdoc
restricts itself to rich text formatting that can be displayed effectively in a
terminal. As tsk's primary goal is to be a fast, terminal-centric task manager,
this property is a *must.*
Additionally, it should be similar enough to Markdown such that it is easy to
export to other applications, as outlined above in the roadmap.
Meanwhile, both Markdown and scdoc have some limitations and make choices that,
while appropriate for their domain, are not appropriate for tsk. Some notable
differences from both:
- There is only one way to do any type of formatting
- Hard line breaks are real, not imaginary
- Inline formatting control characters must be surrounded by space, newline, or
common punctuation
A core feature of the format is *linking*. That is, references to other tasks
utilizing wiki-link style links: `[[]]`. The content within the link is mapped
to the local workspace if the `tsk-` prefix is used, or a mapped non-local
workspace if another prefix is used. These mappings are specified using a text
file within the .tsk folder.
A quick overview of the format:
- \!Bolded\! text is surrounded by exclamation marks (!)
- \*Italicized\* text is surrounded by single asterisks (*)
- \_Underlined\_ text is surrounded by underscores (_)
- \~Strikethrough\~ text is surrounded by tildes (~)
- \=Highlighted\= text is surrounded by equals signs (=)
- \`Inline code\` is surrounded by backticks (`)
Links like in Markdown, along with the wiki-style links documented above.
Raw links can also be written as \<https://example.com\>.
Misc
----
tsk is heavily inspired by git. It mimics its folder structure and some
commands. The concept of the stack is inspired by FORTH and the observation that
most of the time, only the top 3 priorities at any given moment matter and tasks
tend to be created when they are most important. This facilitates small,
frequent creation of tasks that help both document problems and manage
fast-paced work environments.
tsk is not intended to be checked into git, however there is not a reason that it
cannot be. This repository's development is managed using tsk itself.
Git does *not* track extended filesystem attributes. If you wish to avoid constantly
re-indexing, use something like metastore:
https://github.com/przemoc/metastore
Clone this repository
For self-hosted knots, clone URLs may differ based on your setup.
Download tar.gz
Properties are now stored as plain blobs in the task tree (one file per
key, lines are values), so reads/writes go through the same per-task
commit history as content. A new properties module maintains a per-key
index ref at refs/tsk/properties/<key> with a tree of <stable-id> blobs;
each key gets its own commit history so concurrent edits to different
keys cannot conflict.
CLI: tsk prop {list,add,set,unset,keys,values,find}. find accepts an
optional key/value and falls through to fzf for whichever is missing,
with a <any> sentinel to skip value-narrowing.
Validation: 4 new unit tests in properties.rs, 2 new integration tests
in multi_user.rs covering the binary CLI plus push/pull visibility of
the index across clones.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Implements tsk-3: switching with no argument lists existing namespaces
through fzf with the active one marked, plus a <new> sentinel for
creating one on the fly. namespace switch behaves the same way.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Each task is now a tree {content, title, <prop>...} with its own commit
history at refs/tsk/tasks/<sha-of-initial-content>. Namespaces are trees
mapping human ids to stable ids at refs/tsk/namespaces/<name>. Queues
hold the index, can-pull marker, and inbox at refs/tsk/queues/<name>.
New commands: share (cross-namespace task binding), queue (list/current/
create/switch), pull (pull a task from another queue when can-pull).
Adds git-tsk binary alongside tsk so the tool can be invoked as a git
subcommand. Drops the file-backed mode; tsk now requires a git repo.
Validation: 48 unit tests across object/namespace/queue/workspace plus
tests/multi_user.rs spinning bare origin + two clones for share, assign,
concurrent push, and namespace round-trip.
Out of scope (left as TODOs): prop, follow, find/fzf, bundle, migrate,
log, reopen, foreign remote, internal link translation between human
and stable ids, merge driver for refs/tsk/queues/* on concurrent push.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>