@anhvupt/tito
v0.3.4
Published
Chat-first engineering coordinator for solo builders. The plan is the spec: decisions, test cases, and docs.
Readme
Tito
Quiet orchestration. Trusted continuity.
Tito is a chat-first engineering coordinator for solo builders. You talk to one coordinator. Tito confirms what you want, writes the plan as the spec, and sends only the approved slice to a sub-agent.
The spec records the decisions and the conventions behind them, the test cases you review before they are written, and the docs that must change. Tito is local-first and Git-friendly. It coordinates your documentation, rules, and specialists, and it updates the docs named in the plan before a pull request.
What Tito helps with
- One place to ask: use ordinary Cursor chat or
/titoinstead of manually coordinating several agents. - The right amount of process: Tito recommends Ask for discovery, Plan for uncertain or critical work, and Agent only for an approved implementation slice.
- Plans that make decisions: Tito confirms the goal and what is out of
scope, then asks only the questions that are large; zero is fine.
client-carefulstill asks for medium decisions.solo-balancedandsolo-fastdecide small and medium choices and report them on aDecided:line. One obvious reading continues after a one-line confirmation. Tito asks before locking a large decision or a product-vision change. The plan records that decision and includes signatures, schemas, pseudocode, or guidance code when that makes implementation clearer. Decisions name the convention they follow. Test cases carry a layer tag:[unit],[integration], or[e2e]. The plan also lists its docs impact. - A light joke, sometimes: after
Hola, Tito here!, Tito may add one short joke. It does not replace the answer, and it stays out of the CLI. - Smaller reviews: work is split into bounded slices with acceptance criteria, tests, forbidden changes, risks, and a stop condition.
- Safer changes: Tito preserves uncommitted work, refuses silent overwrites, and requires approval before commits, pushes, deployments, publication, or irreversible external actions.
- Project-aware adoption: Tito is intended to discover and preserve existing rules, skills, BMad workflows, and project-owned specialists rather than replacing them.
- Controlled model use: Tito recommends the least expensive capable tier, and each launch names the selected model. Explore, docs, and ordinary work use the cheap host family (Grok on Cursor, Sonnet on Claude). Core work uses the stronger coding family. Architecture, security, and ERP work stay on the reasoning family. If a requested model is unavailable, Tito asks instead of substituting one silently.
Specialists
You call Tito. Tito selects only the specialists the task needs. A specialist's mode decides whether it may change anything:
| Specialist | Read-only mode | Mutating mode | | --- | --- | --- | | Explorer | Scout the repository | — | | Product analyst | Clarify requirements | — | | Architect | Decide the technical approach | — | | ERP specialist | Advise or review domain rules | — | | QA reviewer | Review correctness | — | | Security reviewer | Review security-sensitive changes | — | | Frontend engineer | Design | Implement files | | Backend engineer | — | Implement files | | DevOps engineer | Plan | Change infrastructure, with approval | | Tech docs writer | — | Update technical documentation | | User docs writer | — | Update user documentation |
Several read-only specialists may work together. Coding sub-agents follow the
profile cap: client-careful 3, solo-balanced 6, and solo-fast 12. Each
has its own plan and branch. Tito does not code in the chat. Every change,
including a small one, goes to a sub-agent, and Tito returns to the user.
Before writing an approved slice, Tito lists installed skills, reads only each name and description, and names in the handoff the ones the writer must read.
When two or more slices are independent, Tito sends those sub-agents together,
each on its own branch, up to that cap, and does not line them up one after
another. Check out each branch only after you accept that branch.
Documentation writers stay one at a time. Backend and frontend work can run
together inside that cap. Docs named in
the plan are updated, or you waive them, before Tito offers a pull request.
After a module is finished, Tito still schedules the tech docs writer and then
the user docs writer, one at a time, before calling that module done. Skip
that handoff only when you explicitly waive it for that module. Each specialist carries triggers,
knowledge references, handoffs, and a stop condition. The detailed prompt stays
lean and loads knowledge only when that mode needs it.
Stack knowledge points to the stack owner's official resource for the project's version and is never copied in.
tito init writes Cursor agent files such as .cursor/agents/tito-frontend.md from the roster above, and tito upgrade refreshes them.
Chat first, CLI when useful
Chat is the primary mental model. Every operation is implemented once in the core and exposed through both chat and the CLI:
/titois the open-ended coordinator./tito-inspectandtito inspectproduce the same repository report./tito-applyandtito apply --dry-runproduce the same adoption plan.
Tito-coordinated chat responses begin with Hola, Tito here! so you can see
that the coordinator is active. The greeting is not added to CLI or
machine-readable output.
Install in a project
npm install -D @anhvupt/tito
npx tito init --profile client-careful
npx tito init --profile client-careful --confirmThe first init prints the plan and writes nothing. In a terminal, omitting
--profile asks you to choose client-careful, solo-balanced, or
solo-fast. A script or piped command must still pass --profile.
--confirm creates the missing tito.yaml, specialist agents, and /tito
skills. It also installs Tito's scoped rules under .cursor/rules/
(pull-request, screen-language, init-upgrade-admin, and commit-branch). If
AGENTS.md already exists, Tito appends its bootstrap and leaves
the existing guidance in place. It refuses to overwrite a Tito file that is
already there. In a terminal, tito init --confirm then asks for the git base
(dev, develop, main, or master), screen language (vi or en),
tenancy (single or multi), optional comma-separated surface ids, and
whether to auto-create a pull request after implementation. That question is
Auto-create a pull request after implementation? [Y/n]. Enter, y, or yes
stores yes. n or no stores no. Empty surface ids omit product.surfaces.
A non-interactive init with --profile does not ask; it stores
git.autoPullRequest: true and does not invent the other product fields.
Preview without --confirm does not ask and does not write. An existing
tito.yaml is left unchanged. Storing the answer does not open a pull request.
Errors on a terminal are red, and NO_COLOR turns that off.
Open a new Cursor chat, then start with /tito.
Upgrade an existing project after installing a newer Tito:
npx tito upgrade
npx tito upgrade --confirm--confirm installs the latest @anhvupt/tito and replaces Tito-owned
agents, skills, those Tito-owned scoped rules, and the Tito section of
AGENTS.md, which includes the stop that shows the test cases before any source edit. Consumer rules, consumer
agents, and other project skills stay untouched. In a terminal, tito upgrade --confirm asks only for settings missing from tito.yaml: git base, screen language, tenancy, surfaces, and auto-create pull request. Enter on that last question still stores yes. It does not change a value that is already present, and it does not change the profile. A non-interactive upgrade does not ask. If tito.yaml is missing, it skips those questions.
Tito is installed in each project. It is not a required global command.
An opt-in local admin index (tito admin add|list|remove|refresh) can register
repos under ~/.config/tito/admin/ and store recent commit subjects, dates, and
touched paths — never diffs. A project tito.yaml still overrides any personal
default. The safety floor cannot be weakened.
What works today
Tito 0.1 is under active development. The current implementation includes:
- strict
tito.yamlparsing withclient-careful,solo-balanced, andsolo-fastrisk profiles; - mandatory escalation for authentication, payments, secrets, production data, destructive database work, privacy, public infrastructure, irreversible actions, and financial invariants;
- deterministic Ask, Plan, and Agent routing from explicit task facts;
- an enforced lifecycle from discovery through review and completion;
- validated dependency-aware work plans with concurrent read-only readiness and one active implementation writer;
- specialist manifests whose selected mode, not the role name, owns mutation authority;
- read-only repository inspection for
tito.yamlandAGENTS.md; - deterministic dry-run adoption planning that shows create, keep, and conflict decisions without writing files;
- matching Cursor chat skills for the implemented CLI operations.
tito init --confirm can write a new tito.yaml, a missing AGENTS.md, and
the specialist agent files. It does not overwrite existing files. A lock file,
upgrade command, BMad adoption, project-agent discovery, and model/cost
reporting remain on the roadmap.
Current commands
node dist/cli.js --help
node dist/cli.js --version
node dist/cli.js inspect
node dist/cli.js inspect --root .
node dist/cli.js apply --dry-run --profile solo-balanced
node dist/cli.js init --profile solo-balanced
node dist/cli.js admin add
node dist/cli.js admin list
node dist/cli.js admin refresh
node dist/cli.js admin remove --root /path/to/repo
node dist/cli.js admin retro --week 2026-W40
node dist/cli.js guard test-first --base main --test test/example.test.mjs
node dist/cli.js worktree tidy
node dist/cli.js worktree tidy --confirminspect reads tito.yaml when it exists and checks whether AGENTS.md is
present. It does not write to the directory.
apply --dry-run prints the proposed tito.yaml and AGENTS.md actions. It
does not write. apply without --dry-run is refused.
init prints the same kind of plan for tito.yaml, AGENTS.md, and the
specialist agent files. It writes those files only with --confirm, and it
refuses when an existing file would be overwritten. In chat, /tito-init runs
this same command.
admin is opt-in. add registers the current repo (or --root), list prints
registered paths, remove drops one path, and refresh writes local branch plus
the last 50 commit subjects, dates, and file paths (secrets like .env skipped;
no diffs) for chat and CLI to share.
worktree tidy (chat: /tito-worktree-tidy) reports each linked worktree as protected, merged-clean, dirty, unmerged, behind, fresh, or missing. It removes a merged clean worktree and its local branch only with --confirm. It does not delete remote branches or rebase.
retro builds that week's report from local git and saves retros/<week>.json
and retros/<week>.md under the admin root. Review-fix counts, docs-blank, and
merge duration say unavailable until GitHub data is added.
guard test-first checks a slice branch against --base. Commit 1 may change
only the repeated --test files. Later commits may not change test/**,
*.test.*, or *.spec.* files. A failure names the file and the commit.
How work moves
The normal careful path is:
DISCOVERY → PLANNED → APPROVED → IMPLEMENTING → READY_FOR_REVIEW → APPROVED_FOR_COMMIT → DONE
Work follows clarify, then domain, then the spec doc, then failing tests, then code. Discover clarifies. The plan opens with Domain. In Code, the agent writes the spec doc named in Docs impact first, then the approved tests, confirms they fail, then implements until they pass.
Six working principles guide that path: research, then judge; fixed floor, flexible tools; adopt before building; business before tech; clarify, domain, document, test, then code; and it depends, so show it.
A small, obvious change can move from discovery directly to an explicitly approved slice. Review feedback can return an in-scope slice to implementation. Other lifecycle skips are rejected.
Git flow
Tito suggests the branch before checkout, for example Suggested branch: feat/short-slug from develop. You accept it or name another base or type. The base is dev, develop, main, or master. dev and develop are interchangeable. main and master are interchangeable. The type is feat, fix, hot-fix, chores, refactor, or debug.
tito.yaml may set the default base:
schemaVersion: 1
profile: client-careful
git:
defaultBase: develop
autoPullRequest: truegit.autoPullRequest is an optional boolean. Missing it is valid. A non-boolean value is rejected. Storing it does not open a pull request.
product.screenLanguage is optional and accepts only vi or en. A missing product block is valid. A missing screenLanguage is valid. Unknown product fields are rejected. product.tenancy is optional (single or multi). product.surfaces is an optional list of { id } entries. Missing tenancy and missing surfaces stay valid.
product:
screenLanguage: vi
tenancy: single
surfaces:
- id: adminOptional models maps pipeline roles to Cursor model slugs. Each Tito specialist card compiles to one role: explorer, planner, implementer, reviewer, or finisher. Missing keys fall back to the defaults below. Empty or unknown keys are rejected. tito init writes the full block; tito upgrade adds missing roles without changing values you already set, and rewrites Tito-owned specialist cards so pinned slugs stay current.
models:
explorer: cursor-grok-4.6-medium-fast
planner: claude-opus-5-5-medium
implementer: grok-4.7-high
reviewer: grok-4.7-high
finisher: composer-2.5- Code stays English.
- In a Vietnamese app (
screenLanguage: vi), routes and slugs are Vietnamese first. The public path is native Vietnamese, for example/tien-ich/ca-phe. Do not invent that Vietnamese by translating an English slug word for word. If the product is bilingual, the English route comes second. - An English app (
screenLanguage: en) keeps English routes and slugs. - In a Vietnamese app (
screenLanguage: vi), every string a person reads is Vietnamese: tables, labels, buttons, headings, and messages. Write native Vietnamese first. Do not invent it by translating English word for word. English may exist as a second field only when the product is bilingual, and it comes after the Vietnamese. - An English app (
screenLanguage: en) stays English on screen. - When
screenLanguageis missing and the screen language is unclear, Tito asks once. One obvious reading continues without a question. - Globalized apps store timestamps in UTC and show them in the user's timezone. There is no switch to turn that off.
A commit subject is <type>: <sentence>. The type is the same token as the branch type: feat, fix, hot-fix, chores, refactor, or debug. Examples: feat: add commit message rule, fix: reject a duplicate surface id, chores: record the commit prefix rule, and hot-fix: stop a bad release build. The words after the colon are one finished sentence of at most 70 words. The type is not counted in those 70 words. The body is a separate description. When you review a plan, Tito saves that plan and your edit as separate files under .tito/feedback/<slug>/. review.md starts with front matter outcome: accepted | edited | expanded. Tito indexes only the plan name. The plan body stays in Cursor's plan file. After an approved slice is coded, every review fix goes into one plan named review/<slug> on the same branch. Tito asks before opening a pull request only after that plan is coded, or when you accept the code with no changes. The pull request description has four parts within 2 to 50 lines: a one-line problem, what changed, review fixes, and checks for lint, code quality, conventions, tests, build, and docs. When the user comments on an open pull request, Tito updates that pull request's description in the same turn. Review fixes lists every comment, including the earlier ones. A thread reply does not replace that update. Init creates .github/pull_request_template.md from Tito's template when it is missing. Upgrade replaces that file with Tito's template. Tito does not approve a pull request. Tito merges only when you call for the merge and the pull request already has an approval. Do not merge a slice branch into main, master, dev, or develop, on the machine or on the remote, unless the user calls for that merge and the pull request already has an approval. Finishing a slice leaves the branch as it is. After a pull request is merged, Tito asks before the next slice. Tito switches back to the base branch only when you say so clearly. Tito pushes directly to the base branch only when you clearly instruct that push.
Development
Requirements:
- Node.js 20 or newer
- npm
npm install
npm run build
npm testAcknowledgement
Tito is respectfully inspired by Francesc “Tito” Vilanova: quiet leadership, continuity, trust, and understanding of the complete system. Tito is not affiliated with FC Barcelona.
License
Apache-2.0
