愚直な協調ツール

タスクとアーキテクチャ決定をリポジトリの中に。どのコーディングエージェントからも呼べる、ひとつの CLI の向こうに。

npm install -g @haksolot/ank
npx skills add haksolot/ank

オープンソース、Apache-2.0。Linux、macOS、Windows に対応。

ループを一周してみる

~/auth-service
ank context src/auth/

CONSTRAINTS (1 active)
  ADR-06d2  Opaque sessions rather than stateless JWT

TASKS (1)
  TASK-820d  [open] Migrate auth to opaque sessions

> ank claim TASK-820d to start

ank claim 820d
claimed TASK-820d259af6a7 migrate-auth-to-opaque-sessions -> HEAD

ank context

TASK-820d  Migrate auth to opaque sessions

DONE_CRITERIA
  The auth tests pass and no reference to jwt.verify remains in src/auth/

CONSTRAINTS (1 active)
  ADR-06d2  Do not introduce self-contained JWTs for user auth. Every session goes through the Redis store.

ank log "jwt.verify removed from session.ts"
logged LOG-6b0f39d7a4c1 on TASK-820d259af6a7

ank done
running: auth-tests ... ok (0.0s)
running: no-jwt ... ok (0.0s)
proof recorded: auth-tests@94a1f671c577 -> local/e3b0c44298fc@9c45c50  (scope/18d14da584ab)
proof recorded: no-jwt@791cc818d0ad -> local/e3b0c44298fc@9c45c50  (scope/18d14da584ab)
TASK-820d259af6a7 -> done

本物の出力です。クイックスタートから取っています。そのテストスイートが、変更のたびにこれらのコマンドをバイナリに対して再実行しています。

いま使っているエージェントでそのまま動く

ank はコマンドラインツールです。シェルコマンドを実行できるエージェントなら、どれでもこのループを回せます。シェルを持たないクライアントは MCP 経由で同じ動詞を使えます。

  • Claude Code
  • Codex
  • Cursor
  • OpenCode
  • Gemini CLI
  • GitHub Copilot
  • Cline
  • Amp
  • pi
  • Antigravity
  • Goose
  • Kiro
  • Roo Code
  • Kilo Code
  • Windsurf
  • Qwen Code
  • Mistral Vibe
  • OpenHands
  • Junie
  • Devin

コマンド一つで、ここに並ぶエージェントのうち検出されたものと、ほか三十種ほどに skills をインストールします。

エージェントはコードを読めても、スレッドは読めない

エージェントはコードを一行残らず読めます。でも、トラッカーも、wiki も、「セッションに自己完結型の JWT は絶対に使わない」と決めたあのスレッドも読めません。次のセッションがそれを書いてしまうのを止めるものは何もありません。

ank はそうした決定と作業を .ank/ に置き、制約対象のコードに glob で結びつけます。エージェントは作業の前に ank context src/auth/ を実行し、ルールはタスクと一緒に届きます。

リポジトリの中のただの markdown ファイルで、ほかの変更と同じようにレビューされます。動かすサーバーはありません。claim は git の ref です。

6 つの動詞

エージェントに必要なループのすべて。ほかの動詞は ank help で一覧できます。

  1. ank context <path>

    この範囲を縛るものと、着手できるもの。最初に呼ぶのは必ずこれ。

  2. ank claim <id>

    タスクを取り、その完了条件を凍結する。

  3. ank show <id>

    エンティティの全体:frontmatter、本文、ログ。

  4. ank log "<message>"

    作業しながら、わかったことを書く。書くことで claim が更新される。

  5. ank done

    宣言された検証を実行し、証明を記録する。

  6. ank release --reason "<why>"

    タスクを返す。理由を添えて。

根底にある 3 つの考え方

どれもツールそのものの性質であって、守るよう求められる慣習ではありません。

階層ではなく scope

制約と作業は、glob だけでつながる 2 つの平面です。去年書かれたルールが今日作られた作業を縛り、glob はファイルシステムと突き合わせて確かめられます。ラベルではそうはいきません。epic も親タスクも、同期を保つべき集計もありません。

ank new adr --title "Opaque sessions rather than stateless JWT" \
    --scope "src/auth/**" \
    --constraint "Do not introduce self-contained JWTs for user auth. Every session goes through the Redis store."
created ADR-06d29e727d24 Opaque sessions rather than stateless JWT

完了条件は claim の時点で凍結される

タスクを claim すると、その done_criteria がハッシュで凍結され、ファイルを編集する人の手の届かない場所に記録されます。自分を通すために条件を書き換えても何も通りません。ank check がその食い違いを示します。claim は 1 つの ID につき同時に 1 つ。そして claim は git の ref なので、2 つのエージェントが同じタスクに手を伸ばしても、取れるのは 1 つだけです。

ank claim 820d
claimed TASK-820d259af6a7 migrate-auth-to-opaque-sessions -> HEAD
ank claim 51c2
error[7]: human:marie holds a live claim on TASK-820d259af6a7 (expires in 30m)
  -> ank release --reason "<why>"   (a second session on this machine sets its own ANK_AGENT)

自分で完了を宣言する者はいない

自分の結果を自分で報告するエージェントは、単に間違っていることがあります。ank done は検証を自ら実行し、実際に走ったものをハッシュ付きで記録します。実行するものがないタスクには、あなたが渡す証明が必要です。そして、どの拒否も、それを解決するコマンドを名指しします。

ank claim 51c2
claimed TASK-51c2a0f6d418 say-in-the-readme-what-a-session-is-now -> HEAD
ank done
error[5]: proof required to move TASK-51c2a0f6d418 to done
  -> ank done --proof commit:<sha>

ank ではないもの

  • トラッカーではない。 スプリントも見積もりもベロシティもロードマップもありません。

  • wiki ではない。 入れるのは、エージェントにとって実行可能か拘束力のあるものだけです。

  • セキュリティ境界ではない。 守るのはドリフトからであって、攻撃者からではありません。

ank は ank で作られている

ank 自身のリポジトリがこのループで回っています。ルートの .ank/ には、そのコードが従う ADR と、それを作ってきたタスクが入っていて、ドキュメントはそれらの決定を id で引用しています。

バージョンが 0.x なのは意図的です。ループと終了コードは仕様が決まっていますが、保存形式はまだです。

GitHub で .ank/ を見る

ank をインストール

コマンドは二つ。Linux、macOS、Windows に対応し、git 2.34 以降が必要です。

npm install -g @haksolot/ank
npx skills add haksolot/ank