L'outil de coordination stupide

Les tâches et les décisions d'architecture dans votre dépôt, derrière une seule CLI que tout agent de code peut appeler.

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

Open source, Apache-2.0. Linux, macOS et Windows.

La boucle, déroulée une fois

~/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

Une sortie réelle, tirée du quickstart. Sa suite de tests rejoue ces commandes contre le binaire à chaque modification.

Fonctionne avec l'agent que vous utilisez déjà

ank est un outil en ligne de commande. Tout agent capable de lancer une commande shell peut dérouler la boucle, et un client sans shell atteint les mêmes verbes via 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

Une seule commande installe les skills dans ceux de ces agents qu'elle détecte, et dans une trentaine d'autres.

Votre agent lit le code, pas le fil de discussion

Un agent peut lire chaque ligne de votre code, mais pas votre tracker, votre wiki, ni le fil où vous avez décidé que les sessions ne seraient jamais des JWT autoportants. Rien n'empêche la session suivante d'en écrire un.

ank garde ces décisions et le travail dans .ank/, attachés par un glob au code qu'ils contraignent. Avant de commencer, l'agent lance ank context src/auth/, et la règle arrive avec la tâche.

De simples fichiers markdown dans votre dépôt, relus comme n'importe quel autre changement. Aucun serveur à faire tourner : les claims sont des refs git.

Six verbes

Toute la boucle dont un agent a besoin. ank help liste tous les autres.

  1. ank context <path>

    Ce qui contraint ce périmètre, et ce qui est disponible. Le premier appel, toujours.

  2. ank claim <id>

    Prendre une tâche et figer son critère.

  3. ank show <id>

    L'entité entière : frontmatter, corps et log.

  4. ank log "<message>"

    Ce que vous avez appris, pendant que vous travaillez. L'écrire renouvelle le claim.

  5. ank done

    Lancer les vérificateurs déclarés et enregistrer la preuve.

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

    Rendre la tâche, en disant pourquoi.

Trois idées en dessous

Chacune est une propriété de l'outil, pas une convention qu'on vous demande de respecter.

Le scope, pas la hiérarchie

Les contraintes et le travail sont deux plans, reliés uniquement par des globs. Une règle écrite l'an dernier contraint le travail créé aujourd'hui, et un glob se vérifie contre le système de fichiers, là où une étiquette ne se vérifie pas. Pas d'epic, pas de parent, pas d'agrégat à tenir à jour.

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

Le critère est figé au claim

Prendre une tâche fige son done_criteria par un hash, hors de portée de celui qui édite le fichier. Réécrire le critère pour se débloquer ne débloque rien : ank check montre la divergence. Un seul claim à la fois par identité, et un claim est une ref git : deux agents qui visent la même tâche, un seul gagnant.

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)

Personne ne se déclare terminé

Un agent qui rapporte son propre résultat peut tout simplement se tromper. ank done lance les vérificateurs lui-même et enregistre ce qui a réellement tourné, haché. Une tâche sans rien à lancer exige une preuve que vous lui fournissez, et chaque refus nomme la commande qui le lève.

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>

Ce que ce n'est pas

  • Pas un tracker. Ni cycles, ni estimations, ni vélocité, ni roadmap.

  • Pas un wiki. N'y entre que ce qui est actionnable ou contraignant pour un agent.

  • Pas une frontière de sécurité. Il protège contre la dérive, pas contre un attaquant.

ank est construit avec ank

Son propre dépôt tourne sur cette boucle. Le .ank/ à sa racine contient les ADR auxquels son code est tenu et les tâches qui l'ont construit, et la documentation cite ces décisions par leur id.

La version est en 0.x exprès : la boucle et les codes de sortie sont spécifiés, le format de stockage ne l'est pas encore.

Lire son .ank/ sur GitHub

Installer ank

Deux commandes. Linux, macOS et Windows, avec git 2.34 ou plus récent.

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