多機能Todoに疲れた人へ ─「一枚の紙」だけのタスク管理CLI

Table of Contents

はじめに

ターミナルで作業中、ふと「あれもやらなきゃ」と思いついたとき、頭の中を書き出す場所が欲しくなります。 物理的なメモ用紙ならすぐに書けますが、ターミナルから手を離すのは煩わしい。 かといって多機能なTodoアプリを開くと、プロジェクトやタグを考えているうちに書きたかったことを忘れてしまう。

そこで作ったのが Tiny Task Tool です。コマンド名はタイプしやすいように ttt としました。

「一枚の紙」のシンプルさをターミナルで再現することを目指した、ミニマルなタスク管理ツールです。

この記事では、ttt のコンセプトと使い方を紹介しつつ、Claude Codeとの協働開発でドキュメント駆動とTDDがいかに効果的だったかをお伝えします。

Tiny Task Tool とは

ttt(Tiny Task Tool) は「デジタルなメモ用紙」を目指したTUIタスク管理ツールです。

ttt demo

主な特徴

  • 一枚の紙: ファイルは常に1つ。「どのファイルに書こう」という選択を排除
  • 今に集中: タスクをすぐ書き出し、完了したらアーカイブ。シンプルな運用
  • ノード指向: 階層構造のタスクを直感的に扱える。親を完了すれば子も完了
  • Unix 哲学: フォーカス機能以外は外部エディタやGitに任せる

インストール

# go install(推奨)
go install github.com/yostos/tiny-task-tool@latest

# Homebrew
brew install yostos/tap/ttt

基本的な使い方

ターミナルで ttt と打つだけで、1ページのタスク表がTUIで開きます。

ttt                    # TUIでタスク表を開く
ttt -t "牛乳を買う"     # コマンドラインからタスクを追加
ttt sync               # git pushでリモートと同期

TUIでは e でエディタを開き、a でアーカイブ、q で終了。キーバインドはVim/Emacsユーザー向けにカスタマイズ可能です。

タスクのフォーマット

シンプルなMarkdownチェックボックス形式です。

- [ ] 未完了のタスク
- [x] 完了したタスク @done(2026-01-18)
  - [x] 子タスクも自動で完了 @done(2026-01-18)

タスク以外の箇条書きもノードとして挿入できます。タスクをグルーピングするためにセクション(# Task## Project A)なども扱えます。

完了したタスクには自動で @done(日付) タグが付き、設定した日数が経過するとarchive.mdに移動します。

なぜ作ったのか

きっかけはZennで見かけた「Markdown Paper という選択肢」という記事でした。ephe.app の「一枚の紙」コンセプトをCLIに持ち込んだ aeph の紹介記事です。

コンセプトには共感しましたが、aephは複数ファイルに対応しており、「一枚の紙」とは少し違うと感じました。そこでaephのソースコードを参考にするのではなく、ゼロから自分のコンセプトで作ることにしました。

既存のツールにも同様の問題がありました。

  1. Todo アプリ: 多機能すぎる。プロジェクト、優先度、タグ…考えているうちに書きたいことを忘れる
  2. Markdown エディタ: ファイル名やフォルダを考える必要がある
  3. GUI アプリ: ターミナルから離れるコンテキストスイッチが発生する

単一ファイル、選択肢なし、気を散らすものなし。机の上のメモ用紙のように、「開いて、書いて、終わったら消す」だけの体験が欲しかったのです。

Claude Code との開発体験

このプロジェクトはClaude Codeを活用し、以下のプロセスで開発しました。

  1. コンセプト文書化(concept.md)
  2. 詳細仕様策定(specification.md)
  3. アーキテクチャ選定(architecture.md)
  4. テストコード先行開発
  5. 実装
  6. テスト自動化

ドキュメント駆動が効いた理由

Claude Codeとの協働で最も効果的だったのは、まずドキュメントを書き、それに従って開発するアプローチでした。

1. concept.md で方向性を固める

最初に「なぜ作るのか」「何をしないか」を明確にしました。

### やらないこと

- ファイル指定(「どのファイルを開くか」という選択を排除)
- 複数ファイル管理(一枚の紙の原則に反する)
- ファイル内編集(外部エディタに任せる)

「やらないこと」を明文化したことで、開発中に機能追加の誘惑が来ても「concept.mdに反する」と判断できました。Claudeにも「この機能はconcept.mdの方針に反しますね」とフィードバックを受けられます。

2. specification.md で仕様を詳細化

ユースケース、画面レイアウト、エラー処理まで事前に定義しました。これによりClaudeへの指示が明確になり、生成されるコードの品質が上がりました。

3. architecture.md で技術選定を記録

「なぜその技術を選んだか」「他の選択肢をなぜ却下したか」を記録しました。後から見返したとき、またClaudeに文脈を伝えるときに役立ちました。基本的に記載方法は Architectural Decision Record(ADR)形式 を採用して記載しています。

以下は言語選定の際の例です。

候補却下理由
Rust学習コストが高い。所有権/ライフタイムの概念が独特で、AI 駆動開発でコンパイルエラー修正時に堂々巡りするリスク
PythonPEP 668 により配布が複雑化。起動速度も遅い
TypeScript単一バイナリ配布ができず「摩擦をなくす」原則に反する

TDD が AI 駆動開発と相性が良い理由

テスト駆動開発(TDD)はClaude Codeとの開発で特に威力を発揮しました。

テストファーストのメリット

  1. 期待動作の明確化: テストコードが「仕様書」として機能し、開発前に私が確認できるためClaudeへの指示が曖昧にならない
  2. リグレッション防止: AIが生成したコードの変更が既存機能を壊していないか即座に確認
  3. リファクタリングの安心感: テストが通れば安心して改善できる

実際の開発フロー

# 1. まずテストを書く(Red)
$ go test ./...
# FAIL: TestArchiveCompletedTasks - 期待する動作のテストが失敗

# 2. Claude に実装を依頼
# 「このテストを通す実装をお願いします」

# 3. テストが通ることを確認(Green)
$ go test ./...
# PASS

# 4. リファクタリング
# 「この実装をより読みやすくリファクタリングしてください」

特に階層タスクのアーカイブ処理のような複雑なロジックでは、テストケースを先に書いておくことで、エッジケースの考慮漏れを防げました。

Claude Code との対話で心がけたこと

  1. ドキュメントを参照させる:「concept.mdの方針に従って」「specification.mdの仕様通りに」
  2. 小さな単位で依頼: 一度に多くを頼まず、テスト→実装→確認のサイクルを回す
  3. コミットを細かく: 動作確認できた時点でコミット。戻れるポイントを作る

技術スタック

分野選択理由
言語Go単一バイナリ配布、高速起動
TUIbubbletea + lipgloss成熟したエコシステム、Elm アーキテクチャ
設定pelletier/go-toml v2TOML 1.0 準拠、高速
テストtesting + testify標準+簡潔なアサーション

まとめ

ttt は「一枚の紙」という思想にこだわった結果、機能を削ることで価値を磨けたツールになったと思います。私自身も便利に使っています。もっと高機能なツールはたくさん ありますが、コンセプトに賛同いただける多くの方に使ってもらえれば幸いです。

Claude Codeとの開発では、ドキュメント駆動TDD の組み合わせが非常に効果的でした。

  • ドキュメント駆動: 要件だけでなく方針を文書化するところから、Claude Codeと協働する
  • TDD: 期待動作を定義し、品質を担保する

「Claude Codeに任せきり」ではなく「Claude Codeと協働する」開発スタイルとして、このアプローチはおすすめできます。

興味を持っていただけたら、ぜひ使ってみてください。

https://github.com/yostos/tiny-task-tool


この記事で紹介したドキュメント(concept.md, specification.md, architecture.md)は GitHub リポジトリの docs/ ディレクトリで公開しています。