Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
0d66ecf
add detail view and create/finish time for task
Jan 19, 2026
0bdf404
add task note and agent support
Jan 24, 2026
619f63f
use fixed data file
Jan 24, 2026
2ed9dd3
Hide done tasks by default with toggle shortcut
Jun 26, 2026
a7533ca
Move help to popup panel and hidden done tasks by default
Jun 26, 2026
b07ec81
Add Chinese README translation
Jun 26, 2026
f2c8409
Replace install methods with fork-appropriate instructions
Jun 26, 2026
bbbb2d1
Fix clone URL to point to fork repository
Jun 26, 2026
6caa677
Fix help modal vertical centering on macOS terminals
Jun 26, 2026
45f04d0
Fix delete modal text clipping on narrow terminals
Jun 26, 2026
5d488e8
Show confirm/cancel hint on delete modal
Jun 26, 2026
d22349d
Fix delete modal hint text not visible due to height overflow
Jun 26, 2026
a7ab634
Replace delete modal text with interactive confirm/cancel list
Jun 26, 2026
30af37c
Fix delete modal navigation not responding to keyboard input
Jun 26, 2026
91eae53
Technical debt cleanup: reduce bloat and fix bugs
Jun 26, 2026
8e9410d
Clarify priority semantics and widen narrow modals
Jun 26, 2026
b6a939d
Apply cargo fmt with current stable rustfmt
Jul 24, 2026
49e9b6d
Fix out-of-bounds selection after project creation and add test suite
Jul 24, 2026
39dfc78
Add task stopwatch, global pomodoro timer, and time estimates
Jul 26, 2026
03f642a
Render timer as block digits and keep finished countdowns on screen
Jul 27, 2026
85aafff
Add kanban board view with three status lanes in the task view
Jul 29, 2026
ef3ac97
Refactor event loop and data migration check
Jul 31, 2026
534b1d4
Add global Markdown notes with full-page preview and editor
Aug 1, 2026
d861751
Add CI workflow to run format, clippy, build, and test checks
Aug 25, 2026
f65736c
Clean up clippy warnings and enforce them in CI
Aug 25, 2026
5a3427e
Add near-complete test coverage and enforce it in CI
Aug 25, 2026
65efe92
Bump GitHub Actions to Node 24 runtimes
Aug 25, 2026
fd8a572
Add semantic-versioning release pipeline with prebuilt binaries
Aug 25, 2026
efb63e4
chore: release v0.2.2
github-actions[bot] Aug 25, 2026
4724e7a
chore: release v0.2.3
github-actions[bot] Aug 25, 2026
bc36c22
fix: give release assets platform-specific names
Aug 25, 2026
8c56638
chore: release v0.2.4
github-actions[bot] Aug 25, 2026
e051ffc
Add opt-in performance benchmarks (bench feature)
Aug 25, 2026
bcce79a
chore: release v0.2.5
github-actions[bot] Aug 25, 2026
2862bb0
Release: tag-driven pipeline instead of auto-bumping bot
Aug 26, 2026
ac04695
chore: release v0.2.6
Aug 26, 2026
fb44dd6
Restore the terminal on panic via a panic hook
Aug 29, 2026
b5a57c7
Enforce a version bump with every code change
Aug 29, 2026
063360a
fix(json): write data atomically via temp file and rename
Sep 12, 2026
a58ab0f
fix(json): verify migrated data before removing the legacy file
Sep 12, 2026
bb84fb1
fix(json): never overwrite corrupt on-disk data with empty
Sep 12, 2026
3c5af7e
refactor(json): pass slices to the write paths instead of cloning
Sep 12, 2026
4387940
refactor(json): drop the global VERSION mutex
Sep 12, 2026
75eba39
fix(main): restore normal Tab/BackTab direction in modals
Sep 12, 2026
d622bea
fix(task): reject duplicate task titles on create and rename
Sep 12, 2026
566fcc1
feat(cli): print usage for --help and -h
Sep 12, 2026
7478afc
fix(view): reuse Task::estimate_progress in the details modal
Sep 12, 2026
e55d09d
fix(project): close the 1..=24 percent done-color gap
Sep 12, 2026
be420fe
fix(task): sort unknown status/priority last and normalize done prior…
Sep 12, 2026
49b8c06
fix(note): reject empty titles on rename and touch updated_at
Sep 12, 2026
ce1d4f8
refactor(task): simplify the selection lookup in load_items
Sep 12, 2026
585ac12
refactor(project): count done tasks without cloning
Sep 12, 2026
08aea10
refactor(ui): build delete-confirm items at the render site
Sep 12, 2026
6e2a4f1
fix(ui): rename create_rect_area params and guard the underflow
Sep 12, 2026
096eb82
style: fix the load_statuses_items typo and other trivial idioms
Sep 12, 2026
9cf90c6
refactor: idiomatic cleanups across call sites
Sep 12, 2026
3343227
refactor: get_current takes &App, not &mut App
Sep 12, 2026
cbb16c6
perf(view): avoid the per-frame note body clone in show_note
Sep 12, 2026
6a906a5
docs: fix stale comments and docs drift
Sep 12, 2026
7498226
refactor: split main.rs into app.rs and dedicated test modules
Sep 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .githooks/post-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
#
# After a commit that bumps the crate version, create the matching
# vX.Y.Z tag if it does not exist yet. Pushing that tag is what
# triggers the GitHub Release pipeline (.github/workflows/release.yml).
#
# Enable the repo hooks once per clone:
# git config core.hooksPath .githooks (or ./scripts/install-hooks.sh)
set -euo pipefail

cd "$(git rev-parse --show-toplevel)"

# Only act on commits that changed the `version` line of Cargo.toml.
if ! git diff -U0 HEAD~1 HEAD -- Cargo.toml 2>/dev/null | grep -qE '^\+version = "[0-9]+\.[0-9]+\.[0-9]+"'; then
exit 0
fi

VERSION="$(grep -m1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/')"
TAG="v$VERSION"

# Nothing to do if the tag already exists (e.g. created manually).
[ -z "$(git tag -l "$TAG")" ] || exit 0

git tag "$TAG"
echo "post-commit: created tag $TAG"
echo "publish the release with: git push origin master --tags"
51 changes: 51 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env bash
#
# Require every code change to bump the crate version in the SAME commit.
# "Code" means anything that ships in the release binary: src/, tests/,
# Cargo.toml and Cargo.lock. Docs, scripts and CI changes are exempt.
#
# Rationale: releases are tag-driven and the version lives in Cargo.toml,
# so a code commit without a version bump can never become a release.
#
# Enable the repo hooks once per clone:
# git config core.hooksPath .githooks (or ./scripts/install-hooks.sh)
set -euo pipefail

cd "$(git rev-parse --show-toplevel)"

CODE_RE='^(src/|tests/|Cargo\.toml$|Cargo\.lock$)'

# No code changes in this commit: nothing to check.
git diff --cached --name-only | grep -qE "$CODE_RE" || exit 0

# The commit must change the `version` line of Cargo.toml (staged).
if ! git diff --cached -U0 -- Cargo.toml | grep -qE '^\+version = "[0-9]+\.[0-9]+\.[0-9]+"'; then
cat >&2 <<'EOF'
error: this commit changes code but does not bump the version.

Every code change must ship as a new release: bump the version and
stage it together with your changes, e.g.:

./scripts/bump-version.sh patch # or: minor / major
git add Cargo.toml Cargo.lock

(bypass with: git commit --no-verify)
EOF
exit 1
fi

NEW_VER="$(git show :Cargo.toml | grep -m1 '^version = ' | sed 's/version = "\(.*\)"/\1/')"

# The tag must be fresh — reusing a released version would clash.
if [ -n "$(git tag -l "v$NEW_VER")" ]; then
echo "error: tag v$NEW_VER already exists; bump to a fresh version" >&2
exit 1
fi

# Cargo.lock must be staged in sync with the new version.
LOCK_VER="$(git show :Cargo.lock | awk '/^name = "basilk"$/{getline; print; exit}' | sed 's/version = "\(.*\)"/\1/')"
if [ "$NEW_VER" != "$LOCK_VER" ]; then
echo "error: Cargo.toml bumps to $NEW_VER but the staged Cargo.lock still says $LOCK_VER" >&2
echo "run ./scripts/bump-version.sh (it updates both) and stage Cargo.lock" >&2
exit 1
fi
79 changes: 79 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: CI

on:
push:
branches: [master]
pull_request:

env:
CARGO_TERM_COLOR: always

jobs:
version-bump:
name: Version bumped with code changes
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0

# Backstop for the local pre-commit hook: any change to the code
# that ships in the release binary (src/, tests/, Cargo manifests)
# must come with a version bump in Cargo.toml, otherwise the
# change can never become a GitHub Release.
- name: Code changes must bump the version
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
BASE="${{ github.event.pull_request.base.sha }}"
else
BASE="${{ github.event.before }}"
fi
if [ -z "$BASE" ] || [ "$BASE" = "0000000000000000000000000000000000000000" ]; then
echo "no base revision to compare against; skipping"
exit 0
fi
if ! git diff --name-only "$BASE" HEAD | grep -qE '^(src/|tests/|Cargo\.toml$|Cargo\.lock$)'; then
echo "no code changes; nothing to check"
exit 0
fi
OLD="$(git show "$BASE":Cargo.toml | grep -m1 '^version = ')"
NEW="$(grep -m1 '^version = ' Cargo.toml)"
if [ "$OLD" = "$NEW" ]; then
echo "::error::code changed but the Cargo.toml version was not bumped (still ${NEW#version = })"
echo "::error::bump it with ./scripts/bump-version.sh [patch|minor|major] and include it in the change"
exit 1
fi
echo "version bumped: $OLD -> $NEW"

check:
name: Build & Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy

- name: Cache cargo registry
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: cargo-${{ runner.os }}-

- name: Check formatting
run: cargo fmt --all -- --check

- name: Clippy
run: cargo clippy --all-targets --all-features -- -D warnings

- name: Build
run: cargo build --verbose

- name: Test
run: cargo test --verbose
15 changes: 13 additions & 2 deletions .github/workflows/lint_rust.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,21 @@ jobs:
lint_rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v5
- uses: hecrj/setup-rust-action@v2
with:
rust-version: "stable"
- name: "Lint Rust"
run: "cargo fmt --all -- --check"
...
- name: "Install cargo-llvm-cov"
uses: taiki-e/install-action@cargo-llvm-cov
- name: "Add llvm-tools-preview"
run: "rustup component add llvm-tools-preview"
# The whole test suite runs under coverage instrumentation. Local runs
# measure ~99.5% line coverage; the only uncovered lines are the
# real-terminal glue in main.rs (main/init_terminal/restore_terminal
# and CrosstermSource::next_key) which cannot run inside a unit test.
# The 95% gate catches regressions without being flaky across
# platforms. Measure locally with: cargo llvm-cov --workspace
- name: "Test with coverage"
run: "cargo llvm-cov --workspace --fail-under-lines 95"
126 changes: 126 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
name: Release

# Tag-driven release pipeline:
# - Pushing a `vX.Y.Z` tag builds release binaries for Linux, macOS
# (Intel + Apple Silicon) and Windows and publishes them to a GitHub
# Release with auto-generated notes.
# - The version number is bumped manually with each code change
# (./scripts/bump-version.sh or by editing Cargo.toml) and committed
# alongside the code; the post-commit hook creates the vX.Y.Z tag.
# The workflow never bumps versions or commits on its own.
# - The tag must match the version declared in Cargo.toml.
# - workflow_dispatch: re-publish an existing tag (e.g. after a build fix).
on:
push:
tags: ['v*']
workflow_dispatch:
inputs:
tag:
description: 'Existing tag to build & publish, e.g. v0.2.6 (must match Cargo.toml)'
required: true

permissions:
contents: write

# One release at a time; concurrent runs queue up instead of racing.
concurrency:
group: release
cancel-in-progress: false

jobs:
release:
name: Resolve & verify version
runs-on: ubuntu-latest
outputs:
version: ${{ steps.meta.outputs.version }}
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0

- name: Resolve version from tag
id: meta
run: |
if [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then
TAG="${{ github.event.inputs.tag }}"
else
TAG="${GITHUB_REF_NAME}"
fi
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"

# Build from the exact release commit, not the latest master
- uses: actions/checkout@v5
with:
ref: v${{ steps.meta.outputs.version }}

- name: Verify tag matches Cargo.toml
run: |
CARGO_VERSION="$(grep -m1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/')"
if [ "$CARGO_VERSION" != "${{ steps.meta.outputs.version }}" ]; then
echo "::error::tag v${{ steps.meta.outputs.version }} but Cargo.toml declares $CARGO_VERSION"
exit 1
fi

build:
name: Build ${{ matrix.target }}
needs: release
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
bin: basilk
asset: basilk-x86_64-unknown-linux-gnu
- os: macos-14
target: aarch64-apple-darwin
bin: basilk
asset: basilk-aarch64-apple-darwin
# Cross-compiled from the ARM runner; the project has no C deps
- os: macos-14
target: x86_64-apple-darwin
bin: basilk
asset: basilk-x86_64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
bin: basilk.exe
asset: basilk-x86_64-pc-windows-msvc.exe
steps:
- uses: actions/checkout@v5
with:
ref: v${{ needs.release.outputs.version }}
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Build release binary
run: cargo build --release --target ${{ matrix.target }}
- name: Stage binary with platform name
run: cp target/${{ matrix.target }}/release/${{ matrix.bin }} ${{ matrix.asset }}
shell: bash
- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: ${{ matrix.asset }}
path: ${{ matrix.asset }}
if-no-files-found: error

publish:
name: Publish GitHub Release
needs: [release, build]
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v8
with:
path: artifacts
merge-multiple: true
- name: List artifacts
run: ls -lh artifacts
- name: Create GitHub Release
uses: softprops/action-gh-release@v3
with:
tag_name: v${{ needs.release.outputs.version }}
name: v${{ needs.release.outputs.version }}
files: artifacts/*
generate_release_notes: true
Loading