Skip to content

Commit 49d3592

Browse files
feat: implement nested task hierarchy with parent-child support, add Steel theme, and improve task editing UI
1 parent a2504ed commit 49d3592

21 files changed

Lines changed: 400 additions & 173 deletions

File tree

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.4.2]
9+
### Added
10+
- **Nested Tasks & Hierarchy**: Support for parent/child task relationships, including collapsible parent tasks and task nesting UI.
11+
- **API Support**: Added `parent_id` and `collapsed` fields to the API and data model.
12+
- **New Theme**: Added "Steel" theme, featuring a professional deep-blue industrial aesthetic.
13+
14+
### Fixed
15+
- **Animation Bug**: Tab animation now correctly respects the animation toggle setting when cancelling a quit operation.
16+
817
## [1.4.1]
918

1019
### Added

README.md

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,19 @@ Fast. Local. Yours.
1111
<br/>
1212

1313
[![Release](https://img.shields.io/github/v/release/programmersd21/kairo?style=for-the-badge&logo=github&color=7c3aed)](https://github.com/programmersd21/kairo/releases)
14-
[![CI](https://img.shields.io/github/actions/workflow/status/programmersd21/kairo/ci.yml?branch=main&style=for-the-badge&logo=githubactions&color=2563eb)](https://github.com/programmersd21/kairo/actions)
14+
[![CI](https://img.shields.io/github/actions/workflow/status/programmersd21/kairo/ci.yml?branch=main&style=for-the-badge&logo=github&color=2563eb)](https://github.com/programmersd21/kairo/actions)
1515
[![Go Report Card](https://img.shields.io/badge/go%20report-A%2B-brightgreen?style=for-the-badge&logo=go&logoColor=white)](https://goreportcard.com/report/github.com/programmersd21/kairo)
1616
[![License: MIT](https://img.shields.io/badge/License-MIT-f59e0b?style=for-the-badge)](https://opensource.org/licenses/MIT)
1717

1818
</div>
1919

20+
![Home Screen](screenshots/home_screen.png)
21+
2022
---
2123

2224
You know that feeling when your task manager gets in the way of your actual work?
2325

26+
2427
Kairo was built because of that feeling.
2528

2629
No browser tabs. No subscriptions. No mouse. Just you, your terminal, and your tasks — right where your brain already lives.
@@ -83,12 +86,24 @@ Most tools ask you to adapt to them. Kairo adapts to you.
8386
| Plain-text tools lack structure | Full tagging, filtering, and fuzzy search |
8487
| Legacy TUIs feel clunky | Modern, animated, keyboard-first UX |
8588

89+
![Filter Tags](screenshots/filter_tags.png)
90+
8691
Your tasks are yours. They don't belong in someone else's cloud.
8792

8893
---
8994

9095
## ✨ What it can do
9196

97+
### Nested Tasks & Hierarchy
98+
Organize your workspace into hierarchies.
99+
100+
- **Creating Nested Tasks**: When creating or editing a task, use the **Parent** field to specify the ID of the parent task. This instantly nests the task under the parent in your list view.
101+
- **Collapsing/Expanding**:
102+
- Parents with children are marked with an indicator (`` for expanded, `` for collapsed).
103+
- Use **`Space`** on a parent task to toggle its expanded/collapsed state.
104+
- When a parent is collapsed, all its children are hidden, keeping your view focused.
105+
- **Hierarchy Visibility**: Tasks are automatically indented based on their nesting level, making it easy to visualize your project structure at a glance.
106+
92107
### It's fast — genuinely fast
93108
Sub-millisecond fuzzy search. Full keyboard control. Vim bindings (`j/k/gg/G`). Natural language deadlines like `tomorrow 10am` or `next friday`. You never have to leave the keyboard.
94109

@@ -99,13 +114,17 @@ Tasks can automatically reappear based on a schedule. Weekly (e.g. `mon,wed,fri`
99114
SQLite storage with WAL mode. Fully offline. Optional Git-backed sync — no backend, no account, no lock-in. Export to JSON, CSV, Markdown, or plain text whenever you want.
100115

101116
### It grows with you
102-
A Lua plugin system lets you hook into task events. A headless CLI API means you can automate anything. And an MCP server opens Kairo up to AI agents that can read and manage your tasks directly — now with full support for recurring schedules.
117+
A Lua plugin system lets you hook into task events. A headless CLI API means you can automate anything. And an MCP server opens Kairo up to AI agents that can read and manage your tasks directly — now with full support for recurring schedules and nested hierarchies.
103118

104119
### AI — when you want it, invisible when you don't
105120
Optional Gemini integration (`gemini-3.1-flash-lite-preview` / `gemini-2.0-flash-lite` / `gemini-2.5-flash-lite`). Toggle it with `ctrl+a`. It never runs unless you invoke it. Now you can create and manage complex recurring tasks using simple natural language prompts. Your workflow, your call.
106121

107122
### Beautiful by default
108-
32 built-in themes. Live switching with `t`. Bento-style layout. Real-time Markdown preview (`ctrl+p`). Cinematic animations for create, complete, and delete (with a global toggle in `ctrl+s` to disable them for maximum speed). It's a terminal app that you'll actually enjoy looking at.
123+
32 built-in themes. Live switching with `t`. Bento-style layout. Real-time Markdown preview (`ctrl+p`). Cinematic animations for create, complete, and delete.
124+
125+
Each theme features a complete color palette that fills your entire terminal window with a seamless, edge-to-edge background — no gaps, no terminal defaults bleeding through. Whether you're in fullscreen mode or a resized window, the themed background covers the entire viewport consistently. All colors are fully reset to your terminal's default when Kairo exits.
126+
127+
**Note:** Animations can be fully disabled in `config.toml` (`animations = false`) or the Settings TUI.
109128

110129
---
111130

@@ -114,6 +133,7 @@ Optional Gemini integration (`gemini-3.1-flash-lite-preview` / `gemini-2.0-flash
114133
| Key | What it does |
115134
|---|---|
116135
| `n` | New task |
136+
| `Space` | Toggle collapse/expand |
117137
| `e` | Edit |
118138
| `z` | Complete |
119139
| `d` | Delete |
@@ -126,11 +146,17 @@ Optional Gemini integration (`gemini-3.1-flash-lite-preview` / `gemini-2.0-flash
126146
| `x` | Import/Export | |
127147
| `ctrl+d` | Welcome tour | |
128148

149+
<div style="display: flex; gap: 10px;">
150+
<img src="screenshots/help_menu.png" width="30%" />
151+
<img src="screenshots/settings_menu.png" width="30%" />
152+
<img src="screenshots/theme_menu.png" width="30%" />
153+
</div>
154+
129155
---
130156

131157
## 🚀 Automate everything
132158

133-
Kairo has a full CLI API for scripting and pipelines:
159+
Kairo has a full CLI API for scripting and pipelines. It fully supports `parent_id` and `collapsed` state for automation:
134160

135161
```bash
136162
# Create a task from anywhere
@@ -144,18 +170,6 @@ kairo api update --id <id> --status done
144170

145171
# Export your whole list
146172
kairo export --format markdown
147-
148-
# Sync via Git
149-
kairo sync
150-
151-
# Start the MCP server (for AI agents)
152-
kairo mcp # stdio mode
153-
kairo mcp 8080 # SSE mode
154-
```
155-
156-
JSON mode for maximum scriptability:
157-
```bash
158-
kairo api --json '{"action":"create","payload":{"title":"API task"}}'
159173
```
160174

161175
---
@@ -176,10 +190,6 @@ end)
176190
return plugin
177191
```
178192

179-
Available hooks: `task_create` · `task_update` · `task_delete` · `app_start` · `app_stop`
180-
181-
Available API: `create_task`, `update_task`, `delete_task`, `list_tasks`, `on`, `notify`
182-
183193
**Find sample plugins [here](https://github.com/programmersd21/kairo/tree/main/plugins).**
184194

185195
---
@@ -205,6 +215,7 @@ Your input (CLI / TUI / Lua / AI)
205215
| Feature | Status |
206216
|---|---|
207217
| Local-first SQLite storage ||
218+
| Folders & Nested Tasks ||
208219
| Full TUI with 32 themes ||
209220
| Keyboard-only workflow ||
210221
| Git sync (no backend) ||

VERSION.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.4.1
1+
1.4.2

internal/api/api.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ type TaskDTO struct {
107107
Recurrence string `json:"recurrence,omitempty"`
108108
RecurrenceWeekly []string `json:"recurrence_weekly,omitempty"`
109109
RecurrenceMonthly int `json:"recurrence_monthly,omitempty"`
110+
ParentID string `json:"parent_id,omitempty"`
111+
Collapsed bool `json:"collapsed,omitempty"`
110112
CreatedAt string `json:"created_at"`
111113
UpdatedAt string `json:"updated_at"`
112114
}
@@ -123,6 +125,8 @@ func toDTO(t core.Task) TaskDTO {
123125
Recurrence: string(t.Recurrence),
124126
RecurrenceWeekly: t.RecurrenceWeekly,
125127
RecurrenceMonthly: t.RecurrenceMonthly,
128+
ParentID: t.ParentID,
129+
Collapsed: t.Collapsed,
126130
CreatedAt: t.CreatedAt.Format("2006-01-02T15:04:05Z"),
127131
UpdatedAt: t.UpdatedAt.Format("2006-01-02T15:04:05Z"),
128132
}
@@ -145,6 +149,8 @@ func (api *TaskAPI) handleCreate(ctx context.Context, payload json.RawMessage) R
145149
Recurrence string `json:"recurrence,omitempty"`
146150
RecurrenceWeekly []string `json:"recurrence_weekly,omitempty"`
147151
RecurrenceMonthly *int `json:"recurrence_monthly,omitempty"`
152+
ParentID string `json:"parent_id,omitempty"`
153+
Collapsed bool `json:"collapsed,omitempty"`
148154
}
149155

150156
var p CreatePayload
@@ -170,6 +176,8 @@ func (api *TaskAPI) handleCreate(ctx context.Context, payload json.RawMessage) R
170176
Recurrence: core.RecurrenceType(p.Recurrence),
171177
RecurrenceWeekly: p.RecurrenceWeekly,
172178
RecurrenceMonthly: 0,
179+
ParentID: p.ParentID,
180+
Collapsed: p.Collapsed,
173181
}
174182

175183
if p.RecurrenceMonthly != nil {
@@ -251,6 +259,8 @@ func (api *TaskAPI) handleUpdate(ctx context.Context, payload json.RawMessage) R
251259
Recurrence *string `json:"recurrence,omitempty"`
252260
RecurrenceWeekly []string `json:"recurrence_weekly,omitempty"`
253261
RecurrenceMonthly *int `json:"recurrence_monthly,omitempty"`
262+
ParentID *string `json:"parent_id,omitempty"`
263+
Collapsed *bool `json:"collapsed,omitempty"`
254264
}
255265

256266
var p UpdatePayload
@@ -271,6 +281,8 @@ func (api *TaskAPI) handleUpdate(ctx context.Context, payload json.RawMessage) R
271281
patch := core.TaskPatch{
272282
Title: p.Title,
273283
Description: p.Description,
284+
ParentID: p.ParentID,
285+
Collapsed: p.Collapsed,
274286
}
275287

276288
if p.Recurrence != nil {

0 commit comments

Comments
 (0)