██████╗██╗ ████████╗
██╔════╝██║ ╚══██╔══╝
██║ ██║ ██║
██║ ██║ ██║
╚██████╗███████╗██║
╚═════╝╚══════╝╚═╝
▸ command line tasks
▸ file-backed · rust · tui · agents
A file-system-backed task manager written in Rust. clt stores work in Markdown files or task folders, gives humans a fast CLI and TUI Kanban board, and can coordinate Codex agent runs across multiple registered projects.
- File-based Persistence: Tasks are stored in
tasks/backlog.md,tasks/todo.md,tasks/doing.md, andtasks/done.md, or in status folders such astasks/todo/. - Long Task Files: In a status folder, each direct file is a task.
cltdisplays the first sentence and preserves the full file content. - Nested Boards: A task subfolder can contain its own
backlog,todo,doing, anddonefiles or folders. The TUI can open those as subtask boards. - Kanban TUI: A visual board view powered by
ratatui, with nested board navigation and a full-screen registered-projects pane. - Simple CLI: Easy commands to add, move, and list tasks.
- Smart Root Detection: Automatically finds the git repository root to keep tasks centralized, or uses the current directory.
- Agent Registry: Register many projects, toggle them on or off, inspect
todo/doingcounts, choose per-project Git automation, and open any registered task board from the TUI. - Model Catalog: Configure provider presets or custom Responses endpoints, keep a clean enabled/favorite model list, and select CLT-wide or per-project provider/model targets.
- Codex Automation: Run one Codex task at a time per enabled project, either in the foreground or through a background service.
- Agent Skills: Includes installable
clt-task-managementandgit-commitskill folders for task-board and safe commit workflows.
Ensure you have Rust and Cargo installed.
cargo install clt-rsAfter upgrading clt, restart the background agent so the running service uses the newly installed binary:
clt agent startA command cannot directly change the directory of the shell that launched it, so clt provides a small shell wrapper for project switching. Add the appropriate line to your shell configuration:
# ~/.zshrc
eval "$(command clt shell-init zsh)"
# ~/.bashrc
eval "$(command clt shell-init bash)"Restart the shell or reload its configuration. After opening another registered project from the agent projects pane, pressing q now exits clt and leaves the shell in that project's directory. Other clt commands continue to work through the wrapper.
The installed clt binary embeds both agent skills. Before an automated Codex run, clt looks for each required skill by its frontmatter name in the standard repository, user, and admin skill directories. If a skill is unavailable, clt adds its bundled instructions to that run's prompt automatically, so cargo install clt-rs is sufficient for agent automation.
To make the skills discoverable to Codex outside clt agent runs, clone this repository and copy the skill folders into the skills directory inside your home .agents directory. From the repository root, run:
mkdir -p ~/.agents/skills
cp -R skills/clt-task-management skills/git-commit ~/.agents/skills/Each copied folder contains the skill's SKILL.md file. Restart your agent after copying the folders so it can discover the new skills.
Initialize the task directory structure:
clt initCreate folder-backed statuses from the start:
clt init --foldersNote: By default, clt looks for the root of your git repository to store the tasks/ folder. To force use of the current directory instead, use the --local flag:
clt --local initOpen the interactive TUI Kanban board:
cltPress Enter to open a folder task with subtasks, e to edit the selected task, Space to create a task, Backspace to return to the parent board, and q to quit.
Tap r, then press one arrow key to reorganize the selected task: Up/Down changes its position and Left/Right moves it between columns. The operation is one-shot, and Esc cancels it.
You can also use Shift+Up and Shift+Down to reorder the selected task, and Shift+Left and Shift+Right to move it between columns. Ctrl-P reorders the selected task up and Ctrl-N reorders it down; these portable alternatives work in stock macOS Terminal and through SSH or tmux.
Stock macOS Terminal does not encode Shift in its default Up/Down sequences, so the modifier is lost before clt receives it. To keep using Shift+Up/Down there, add these two mappings on the Mac under Terminal > Settings > Profiles > Keyboard:
- Shift+Up: send
\033[1;2A - Shift+Down: send
\033[1;2B
Press a to move the selected task into the archive. Press A to open the archive's single-panel scrolling view, and press A again to return to the Kanban board.
Backlog is a fourth column for captured work that is not ready to be acted on. It is hidden by default; the task-board console title shows its current task count. Press b to move the selected task to Backlog, B to show or hide the Backlog column, or 0 to show and focus it. When visible, Backlog appears to the left of To Do and works with the normal Left/Right focus and task-movement controls. Keys 1, 2, and 3 continue to focus To Do, Doing, and Done.
Press Tab to toggle between the task board and the full-screen Agent Projects pane. In Agent Projects, Up/Down selects a registered project, Enter opens that project's task board, Space toggles the project ON or OFF, Delete removes it from the agent list after a y/n confirmation, and g cycles the GIT column through OFF, COM, and PUSH. These modes disable Git automation, ask Codex to commit after a completed task, or ask Codex to commit and push. Removing a project only unregisters it from the agent list; it does not delete the project or its task files. The currently open project is marked with *, the pane's top border shows the current local time before the daemon status, and the terminal title updates to the active project.
On the task board, select a Done task or a currently blocked Todo/Doing task and press c to continue its automated run in an interactive Codex session. CLT temporarily hands the terminal to Codex, then restores the same board and selection when the interactive session exits. This is available for tasks handled after CLT began recording task-specific Codex session IDs; older tasks report that no session is recorded.
The agent projects pane also monitors the installed background service. If the operating system still reports the service as running but its daemon check-in becomes stale, the pane restarts the service automatically and shows service restarting while it recovers. A service explicitly stopped with clt agent stop remains stopped.
Press l from the Kanban board to open the active project's live agent output, or its latest recorded output when no run is active. The same key opens the selected project's output from the agent projects pane. The console expands and follows new output until l or Esc closes the log.
Press uppercase M from either the task board or Agent Projects to open the Models page; uppercase M, Tab, or Esc returns to the pane you came from. The Models page keeps a catalog of providers and model targets with aligned, labeled columns. USE shows live availability, FAV marks favorites, and the separate CLT and CODEX columns identify the effective CLT-wide default and the user's Codex config default; YES is shown when a row has that role. THINK shows each model's default reasoning level: press t to cycle through system, low, medium, high, extra-high, max, and ultra. A model setting is used for agent runs unless the selected project has its own reasoning override. Changing THINK on the CODEX=YES model also updates Codex's top-level reasoning default immediately; choosing system removes that override. Pressing c to choose a new Codex default writes both its model and reasoning setting. When no explicit CLT override exists, CLT follows the Codex default and both columns mark the same model. The provider pane always shows the available presets: press 1 through 4 to add or enable OpenAI, OpenRouter, Ollama, or LM Studio. Ollama and LM Studio query their standard local URLs for models immediately. To remove a provider, select it in the left pane and press x or Delete; its models and affected CLT/project selections are removed, along with its custom Codex provider configuration. Built-in OpenAI cannot be removed, but Space can disable it.
Press n to add another local or custom OpenAI-compatible endpoint. CLT asks for a friendly name, the API base URL, and an optional API-key environment-variable name; it creates the internal provider ID automatically. Enter the API root, for example http://127.0.0.1:9090/v1. Include /v1 when that is where the server exposes its compatible API, or omit it when the server exposes endpoints directly at the host root. Do not paste a complete operation URL ending in /chat, /chat/completions, /models, or /responses. After saving, CLT requests <base URL>/models and shows every returned model in the Models pane. Newly discovered models start OFF, so use Right, Up/Down, and Space to choose exactly which models appear in project selection. Press r to discover again later, or a to enter a model ID manually when an endpoint does not expose /models. Space also enables or hides the selected provider, and f toggles model favorite status. Favorites sort first.
Press d on a model to make its provider/model pair the CLT-wide default for new agent runs. Press c only when you also want to update the top-level model_provider and model values in the user's Codex config.toml; CLT preserves other TOML content and creates config.toml.clt.bak before its first edit. Custom provider definitions use Codex's model_providers table with wire_api = "responses", so the selected endpoint must support the Responses API at <base URL>/responses.
Provider API keys remain ordinary environment variables. The Models page shows whether the configured variable, such as OPENROUTER_API_KEY, is visible to the current CLT process, but it never accepts, stores, or writes secret values or .env files. OpenAI can also use the normal Codex login. A foreground daemon inherits its launch environment; a background user service must have the same variables in its service-manager environment.
Each registered project has persisted Codex launch settings in the CODEX column. Overrides are shown compactly as provider:model/thinking/fast; default means the project follows the CLT-wide default, which in turn falls back to the user's Codex config when unset. Press lowercase m to cycle through the CLT default and currently enabled provider/model targets, f to toggle Fast mode, and t to cycle through the default, low, medium, high, extra-high, max, and ultra reasoning levels. Settings are resolved when a new run launches; an already running process is unchanged.
clt agent can run Codex against enabled registered projects that have unblocked todo tasks. It can also recover a task left in doing when a previous agent lease belongs to a crashed process or has expired. When every task across Todo and Doing is currently blocked, the scheduler starts a blocked-task monitor run even if Todo is not empty. Backlog tasks are deliberately ignored until they are promoted to Todo. Each project keeps its own repo-local tasks/ board, while the agent stores cross-project runtime state in one central state directory.
Before registering a project, initialize its task board and make sure the codex CLI is installed and authenticated. With no path, register uses the same project root that normal clt commands use:
clt init --folders
clt agent registerCodex uses Bubblewrap (bwrap) to sandbox commands on Linux. Install the distribution package before starting the agent:
# Ubuntu or Debian
sudo apt install bubblewrap
# Fedora
sudo dnf install bubblewrapUbuntu 24.04 may also restrict the unprivileged user namespace that Bubblewrap needs. If Codex reports bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted, install and load the Bubblewrap-specific AppArmor profile:
sudo apt install apparmor-profiles apparmor-utils
sudo install -m 0644 \
/usr/share/apparmor/extra-profiles/bwrap-userns-restrict \
/etc/apparmor.d/bwrap-userns-restrict
sudo apparmor_parser -r /etc/apparmor.d/bwrap-userns-restrictVerify the sandbox before starting the background agent:
codex sandbox -- /bin/true
echo $?The sandbox command should produce no output and exit with status 0. Prefer the AppArmor profile over disabling kernel.apparmor_restrict_unprivileged_userns globally. See the Codex sandbox documentation for platform prerequisites and container-specific guidance.
Register more projects by passing their paths:
clt agent register ~/code/project-a
clt agent register ~/code/project-b
clt agent projectsTurn projects off and on without removing them from the registry:
clt agent pause ~/code/project-a
clt agent resume ~/code/project-aIn the TUI agent pane, the same state appears as OFF or ON.
Configure the optional git-commit skill instruction per project:
clt agent git-commit enable ~/code/project-a
clt agent git-commit push ~/code/project-a
clt agent git-commit disable ~/code/project-aenable selects commit-only mode, push selects commit-and-push mode, and disable turns Git automation off. The scheduler adds matching instructions to the Codex prompt after task completion and verification. Existing enabled registrations migrate to commit-only mode. In the TUI, the modes appear as COM, PUSH, and OFF in the GIT column.
Agent-facing workflow skills are included in the repository's skills/ directory:
skills/clt-task-management/: task-board workflow guidance for usingclt.skills/git-commit/: git commit and optional push workflow guidance.
Automated clt agent runs use embedded copies when these skills are not installed. Copy the folders into ~/.agents/skills/ using the commands in Installation only when you also want to invoke them directly in other Codex sessions.
Run one foreground scheduler pass:
clt agent run --onceThe scheduler scans enabled projects, picks projects with pending unblocked todo tasks, takes an agent lease, and starts one Codex run at a time. Each normal Codex run is prompted to inspect the board, move one available task to doing, complete it, run relevant checks, update the task through clt, and stop after that single task. If a crashed run left a stale lease and a task in doing, the scheduler reclaims the lease and prompts the replacement run to resume that task before starting new work.
Unblocked Todo work takes priority over blocked-task recovery, while blocked Todo entries are skipped during normal selection. When all tasks across Todo and Doing are blocked, a monitor run reviews the blocker notes and works on exactly one existing task from either status. It can complete that task, add a newer UNBLOCKED YYYY-MM-DD: note and return it to Todo after resolving its blocker, or update its blocked note with the latest attempt. The latest dated BLOCKED, UNBLOCKED, or COMPLETED state note determines whether a task is currently blocked. Successful recovery lets the ordinary scheduler carry on; if the board is unchanged, the run is recorded as blocked and another monitor attempt waits for CLT_AGENT_FAILURE_BACKOFF_SECONDS instead of creating a tight retry loop. Unmarked Doing tasks are left alone because they may belong to a human or another workflow.
Automated runs start Codex with --sandbox danger-full-access --ask-for-approval never so tasks can update Git metadata without pausing for interactive approval. This removes the Codex command sandbox for the entire run. Register only trusted repositories, or run the agent inside an externally isolated container or VM.
Run the scheduler continuously in the foreground:
clt agent daemonStart or stop the background service:
clt agent start
clt agent stopOn macOS, start installs a user launchd service named com.alpinevibrations.clt.agent. On Linux, it installs a user systemd service named clt-agent.service. Other platforms can still use clt agent run --once or clt agent daemon, but start and stop are unsupported.
Run clt agent start and clt agent stop as your normal user, not with sudo; these commands manage per-user services.
On Linux, clt recovers the standard /run/user/<uid> systemd runtime directory when an SSH or non-interactive shell does not export XDG_RUNTIME_DIR. If the user bus is not running at all, log in through a systemd/PAM-managed session or ask an administrator to enable the always-on user manager with sudo loginctl enable-linger "$USER", then start the service again.
Inspect agent state and recent output:
clt agent status
clt agent logs
clt agent clean
clt agent pause .
clt agent resume .
clt agent unregister .clt agent clean resets stored failure and blocked-recovery state, deletes recorded run history, removes agent run logs, and truncates background service logs. It keeps registered projects and task boards intact, and refuses to run while active Codex leases exist.
By default, agent state is stored at ~/Library/Application Support/clt on macOS, $XDG_STATE_HOME/clt on Linux when XDG_STATE_HOME is set, or ~/.local/state/clt otherwise. The state directory contains agent.db, scheduler run logs, and background service logs such as agent-service.out and agent-service.err. Override it with:
CLT_AGENT_STATE_DIR=/path/to/state clt agent daemonUseful runtime tuning variables are:
CLT_AGENT_MAX_GLOBAL_JOBS: maximum Codex runs active globally, default12.CLT_AGENT_POLL_INTERVAL_SECONDS: daemon delay between scheduler passes, default15.CLT_AGENT_RUN_TIMEOUT_SECONDS: Codex process timeout, default2700.CLT_AGENT_LEASE_TIMEOUT_SECONDS: active lease expiry, default3600.CLT_AGENT_FAILURE_BACKOFF_SECONDS: delay after a failed project run or an unchanged blocked-task recovery, default300.CLT_AGENT_SUCCESS_COOLDOWN_SECONDS: delay after a successful project run, default5.CLT_AGENT_CODEX_PATH: optional Codex executable override. By default,clt agent startverifies thatcodexworks and the background service resolvescodexfrom the storedPATHinstead of pinning the executable's absolute location.CLT_AGENT_HEARTBEAT_TAIL: print a short stderr tail on still-running heartbeats when set to1,true,yes, oron; defaultfalse.
If Codex is installed through a version manager such as NVM, make sure the PATH used for clt agent start contains a stable bin directory. For example, NVM can maintain ~/.nvm/current; putting ~/.nvm/current/bin before version-specific directories lets the service continue finding codex after switching Node versions. Run clt agent start again after changing the service PATH; on Linux this reloads and restarts the existing user service.
Add a new task to the To Do list:
clt add My first taskMetadata: You can optionally add metadata (tags, priority, or IDs) which will be stored in parentheses:
clt add "Fix login bug" "BUG, HIGH"Backlog is for captured work that is not ready to enter the To Do queue. clt add creates To Do tasks; move a task to Backlog when it needs to be deferred, list the Backlog for review, and promote it to To Do when it is ready:
clt status todo 1 backlog
clt list backlog
clt status backlog 1 todoAutomated agent runs ignore Backlog tasks until they are promoted to To Do.
Change the status of a task:
clt status todo 1 doing
clt status doing 1 doneAlternatively, mark a task as done quickly:
clt done doing 1Remove a task from a specific list:
clt delete todo 1Get an overview of all tasks, or filter by status:
clt list
clt list backlog
clt list todoStatus number 0 is an alias for backlog; the existing 1, 2, and 3 aliases remain Todo, Doing, and Done.
You can create folder-backed statuses during init or expand an existing markdown list:
clt init --folders
clt expand todo
clt expandclt expand todo migrates only todo.md. clt expand migrates backlog.md, todo.md, doing.md, and done.md. The original Markdown files are preserved as .bak files.
A folder-backed status looks like this:
tasks/
backlog.md
todo/
0001-write-release-plan.md
doing.md
done.md
Each file in tasks/todo/ is one task. The CLI and TUI show the first sentence, while the file can hold longer notes, checklists, and links. If a folder-backed task moves into a Markdown-backed status, clt expands that destination status to a folder and preserves the old Markdown file as status.md.bak.
Task folders become navigable subtask boards when they contain status stores:
tasks/
doing/
0001-ship-dashboard/
task.md
backlog.md
todo.md
doing.md
done.md
The folder's task.md provides the parent task text. Inside the TUI, selecting that task and pressing Enter opens its nested board.
If you want to contribute or build from source:
git clone <repository-url>
cd cli-task
cargo build --releaseRelease notes are tracked in CHANGELOG.md. New user-facing features, behavior changes, and bug fixes should be added under Unreleased first, then moved into a versioned section when publishing a release.