Skip to main content
Glama
README.md
<picture>
  <source media="(prefers-color-scheme: dark)" srcset="assets/banner-dark.svg">
  <img alt="itaca — every project is an Ithaca; come home in seconds" src="assets/banner-light.svg" width="720">
</picture>

[![npm](https://img.shields.io/npm/v/@itacajs/cli?color=b0722e&label=%40itacajs%2Fcli)](https://www.npmjs.com/package/@itacajs/cli)
[![CI](https://github.com/Lukapetro/itaca/actions/workflows/ci.yml/badge.svg)](https://github.com/Lukapetro/itaca/actions/workflows/ci.yml)
[![license: MIT](https://img.shields.io/badge/license-MIT-8a7a5c)](./LICENSE)

**A local-first registry of every project on your machine, exposed to your coding agents via MCP.**

Switching projects costs you 10–15 minutes of agent context rebuilding, every
time: what is this repo, what stack, which dashboards, where was I? The
information already exists — scattered across package.json, config files and
your own head. itaca derives it, keeps it fresh by construction, and serves it
to any MCP client in a briefing capped at ~600 tokens.

No cloud. No accounts. No telemetry. Your `.env` files are read for pattern
matching only — **values never leave your machine**, and a CI-enforced test
suite keeps it that way.

## Quickstart

```sh
bun add -g @itacajs/cli     # or: bunx @itacajs/cli <command>

itaca scan ~/dev            # one command: every project, stack and service detected
itaca list                  # what's on this machine
itaca brief                 # "where was I?" — run inside any project
itaca open stockroom        # its dashboards, ready to open in your browser
itaca agent install         # wire up Claude Code: skill + hook + MCP, once
```

After `agent install`, every new Claude Code session starts with the project
briefing preloaded — and your agents can answer *"where was I on tomodachi?"*
without exploring a single file.

## What your agent sees

```
# tomodachi — card exchange platform
Path: /home/you/dev/tomodachi (branch feat/dashi-291, dirty)
Stack: bun · next · typescript
Status: beta — onboarding pilots (updated 2026-08-04)
Next: ship supplier import; fix onboarding drop-off
Services:
  GitHub (code) — https://github.com/you/tomodachi
  Convex (backend) — https://dashboard.convex.dev
  Stripe (payments) — https://dashboard.stripe.com
  ...
Commands: bun run dev · bun run test · bun run typecheck
Other projects: stockroom (beta), everdeep (gate G2), itaca
```

Three MCP tools, nothing more: `projects_list`, `project_get`,
`project_status_update`. The last one closes the loop — agents write a 1–2
line note at the end of a work session into the repo's `itaca.yml`, so the
narrative stays fresh without you maintaining anything.

## How it works

- **The repo is the database.** Stack, services, commands and links are
  re-derived on every scan from what's already in your code — never stale,
  nothing to maintain.
- **`itaca.yml`** holds the only durable state: narrative status, manual
  links, overrides. Committed to git, schema-validated in your editor.
- **Detection is declarative.** Every service is a small YAML rule in
  [rules/](./rules) — Neon, Convex, Cloudflare, Stripe, Polar, Vercel,
  Supabase, Clerk, Resend, Upstash, Turso, Drizzle, Better Auth, Expo,
  PostHog, Sentry, GitHub. Monorepo-aware, workspace-resolving.

```yaml
# rules/neon.yml — a detector is ~10 lines; adding one is a beginner PR
id: neon
service: Neon
category: database
match:
  any:
    - env_value: "\\.neon\\.tech"
    - dep: "@neondatabase/serverless"
links:
  - title: Neon Console
    url: "https://console.neon.tech"
```

Missing your service? [Contributing a rule](./CONTRIBUTING.md) takes ten
minutes.

## itaca v2 — hot state, journal, decisions

A second, independent format for `itaca.yml` — the *state convention* from the
[playbook](https://github.com/Lukapetro/playbook) (`itaca/SPEC-V2.md`). v1
mixed hot state with an append-only narrative log until the file stopped being
readable at a glance. v2 splits the three concerns:

| | Where | Cap |
| --- | --- | --- |
| Hot state | `itaca.yml` (`version: 2`) | ~60 lines, no history |
| Narrative | `journal/YYYY-MM-DD-slug.md` | one file per session |
| Decisions | `docs/decisions/NNNN-slug.md` | append-only ADRs |

```sh
itaca init-protocol         # scaffold the protocol into a repo (CI check, templates, dirs)
itaca context               # hot state, compact — for a SessionStart hook
itaca journal add <slug>    # new journal/YYYY-MM-DD-<slug>.md, frontmatter prefilled
itaca handoff               # the ## Handoff skeleton, ready to paste in a PR body
itaca decay                 # compress old journal entries (dry run; --apply to delete)
```

Schema: [schema/itaca-v2.schema.json](./schema/itaca-v2.schema.json), published
here so editors can resolve it — the playbook stays canonical.

```yaml
# yaml-language-server: $schema=https://raw.githubusercontent.com/Lukapetro/itaca/main/schema/itaca-v2.schema.json
version: 2
state:
  goal: Ship the v2 importer behind a flag
  doing:
    - "Importer CSV parser — PR #142"   # quote it: an unquoted " #" is a YAML comment
  blockers:
    - Staging S3 credentials not provisioned
  next_safe_action: Run the parser against fixtures/large.csv and record timings
decisions: docs/decisions/
links:
  journal: journal/
updated: 2026-08-13
```

### v1 and v2 side by side

Both formats use the filename `itaca.yml` and are told apart by `version`. A
repo is one or the other; nothing needs migrating on a schedule.

- **v1 commands are unchanged**: `scan`, `list`, `show`, `open`, `status`,
  `init`, `rules`, `mcp`, `agent` behave exactly as before, and `itaca.yml` v1
  keeps validating against [the v1 schema](./schema/itaca.schema.json).
- **The v2 commands above require a `version: 2` file.** On a v1 or missing
  file they exit non-zero and point at the migration (SPEC-V2 §4).
- **`itaca context` is v2-only** and the derived briefing moved to
  **`itaca brief`** — the one breaking change. `itaca brief` works everywhere,
  v1 and v2 alike. Re-run `itaca agent install` to update the SessionStart
  hook: it becomes `itaca context || itaca brief`, so each repo gets whichever
  applies.

## For humans too

`itaca open <project>` replaces the bookmark folders you never maintain.
`itaca list` is the machine-wide overview. And the session log your agents
write becomes, a month in, the story of every project — committed in git,
readable by you.

## Status

**Alpha, used daily by its author.** CLI + MCP surface are stable; a local
dashboard (`itaca serve`) is planned. Design doc: [SPEC.md](./SPEC.md).

## License

[MIT](./LICENSE)