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:
tsk takes inspiration from git and FORTH and is expected to be used alongside the former.
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 stores its data in git refs (refs/tsk/*) inside a
host git repository, so any filesystem git itself runs on will work. Use
the tsk git-pull and tsk git-push commands to
update/push these refs.
When tsk git-pull finds incompatible edits to the same
task body, it opens an editor on a temporary file with conflict markers,
then commits the edited result as a normal two-parent merge commit.
Saving an empty resolution aborts that task merge and leaves the local
task ref unchanged. Incompatible property edits are resolved
last-one-wins by the task commit timestamps, and the merge commit
message records each property conflict and the side that won.
cargo install --locked tsk-cliWith Nix Home Manager, add this flake’s module and enable
programs.tsk:
{
imports = [
inputs.tsk.homeManagerModules.default
];
programs.tsk = {
enable = true;
installSkill = true;
};
}installSkill writes the output of tsk skill
to ~/.agents/skills/tsk/SKILL.md.
cargo install --path .Build the optional MCP server with:
cargo install --path . --features mcpMake sure ~/.cargo/bin is in your PATH.
Run tsk mcp to host an MCP server over standard input
and output. Configure the client to start tsk mcp inside
the target repository, or pass -C DIR. The server exposes
each CLI command as a tool, except mcp and
serv.
A summary of commands and their functionality can be seen with:
tsk help
tsk uses virtual text files tracked by special refs in a git repo for its functionality. Any git repo can be made into a tsk workspace.
New tasks are created with the tsk push command. A title
is always required, but can be modified later. A unique, human-readable
identifer is selected scoped to the namespace and may be used to as a
stable reference within that namespace.
The contents of the stack may be printed using the
tsk list command. Open tasks across the active namespace
may be printed using tsk open; it shows each task id, the
queue index or indexes containing it (comma-separated), or
none when the open task is not currently queued.
Tasks are marked as “completed” and removed from the active queue
with the tsk drop command. To remove a task from the active
queue while leaving its status unchanged, use tsk abandon.
Completed tasks can be marked open again with tsk reopen;
by default this places them at the top of the active queue, or
tsk reopen --no-queue can leave them unqueued.
Queues are independent ordered stacks; task lifecycle comes from the
protected status property, not from queue membership.
Create one with tsk queue create NAME; new queues default
to can-pull=false, which prevents other queues from pulling
tasks out of them. Use tsk queue create -p NAME to create a
pullable queue, or tsk queue can-pull NAME true|false to
change that flag later. Inbox items are ordered top-first like queue
tasks; tsk accept with no key accepts the top inbox item.
Use tsk accept -T tsk-N to place an open task that is not
currently assigned to any queue onto the active queue.
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.
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:
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:
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>.
New dependent tasks can be created while saving a task by writing a
title between [> and <]. For example,
blocked by [> provision database <] creates a new
task titled provision database, replaces that text with an
internal link such as [[tsk-12]], and records protected
depends-on / blocks properties between the two
tasks.
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