Quickstart
Ce contenu n’est pas encore disponible dans votre langue.
This tutorial walks you through the core Contextia workflow: initializing a project, creating a spec, annotating your code, and validating that everything links together. By the end, you will have a working .contextia/ directory with a real spec, annotated code, and passing checks.
We will use a small Python project as the example, but Contextia works with any language.
Step 1: Initialize the project
Section titled “Step 1: Initialize the project”Navigate to your project root and run:
contextia initContextia detects your project’s language and structure, then creates the .contextia/ directory:
Detected languages: pythonCreated .contextia/config.yamlCreated .contextia/system/identity.mdCreated .contextia/system/specs/Created .contextia/system/rationale/Created .contextia/system/norms/Created .contextia/work/tasks/Initialized Contextia project in /home/user/my-projectThe init command auto-detects your project’s languages by looking for telltale files (pyproject.toml, package.json, Cargo.toml, go.mod, etc.) and configures annotation parsing accordingly.
Let’s look at what was generated:
version: "1.0"project: name: my-project languages: - python paths: source: - src/ test: - tests/annotations: prefix: "@" comment_syntax: python: "#"output: color: true default_format: humanThe identity file is a Markdown document that describes your project for both humans and AI agents:
---type: identityversion: 1---
# my-project
<!-- Describe your project: what it does, who it serves, key constraints -->Step 2: Create your first spec
Section titled “Step 2: Create your first spec”Specs are behavioral contracts — they define what your system should do. Let’s create one for a user authentication module:
contextia new spec --title "User Authentication"This creates a new spec from the built-in template:
Created .contextia/system/specs/SPEC-001-user-authentication.mdOpen the file and fill in the spec:
---type: specid: SPEC-001title: User Authenticationstatus: draftdecisions: - DEC-001paths: - src/auth/login.py - src/auth/tokens.pytags: - auth - security---
# User Authentication
## Overview
The authentication module handles user login, token issuance, and sessionvalidation. All endpoints require HTTPS. Passwords are never stored inplaintext.
## Behavior
### Login
- Accept email and password via POST `/api/auth/login`- Validate credentials against the user store- On success, return a JWT access token (15 min expiry) and a refresh token (7 day expiry)- On failure, return 401 with a generic error message (do not reveal whether the email exists)
### Token refresh
- Accept a valid refresh token via POST `/api/auth/refresh`- Return a new access token- If the refresh token is expired or revoked, return 401
### Logout
- Accept an access token via POST `/api/auth/logout`- Add the token to the revocation list- Return 204
## Constraints
- Passwords hashed with bcrypt, minimum cost factor 12- JWT signed with RS256, keys rotated quarterly- Rate limit: 5 failed login attempts per email per 15-minute windowNotice the frontmatter fields:
id: SPEC-001— unique identifier, referenced by tasks and code annotationsstatus: draft— lifecycle state (draft, active, deprecated, superseded)decisions— links to architectural decisions that constrain this specpaths— source files that implement this spec (top-down traceability)tags— for search and filtering
Step 3: Annotate your code
Section titled “Step 3: Annotate your code”Now let’s connect the spec to your source code. Open a source file and add annotations using comments:
from datetime import datetime, timedelta
from auth.tokens import create_access_token, create_refresh_tokenfrom auth.users import verify_credentialsfrom auth.rate_limit import check_rate_limit, record_failure
# @spec SPEC-001# @spec SPEC-001.loginasync def login(email: str, password: str) -> dict: """Authenticate a user and return token pair.""" if not check_rate_limit(email): raise RateLimitError("Too many login attempts")
user = await verify_credentials(email, password) if user is None: record_failure(email) # @decision DEC-001 -- generic error, do not reveal email existence raise AuthenticationError("Invalid credentials")
access_token = create_access_token(user.id, expires=timedelta(minutes=15)) refresh_token = create_refresh_token(user.id, expires=timedelta(days=7))
return { "access_token": access_token, "refresh_token": refresh_token, }
# @spec SPEC-001.logoutasync def logout(token: str) -> None: """Revoke an access token.""" await revoke_token(token)The annotations create bottom-up links from code to specs:
@spec SPEC-001— this function implements the User Authentication spec@spec SPEC-001.login— specifically the login sub-behavior@decision DEC-001— this line is constrained by a specific architectural decision
These annotations complement the top-down links in the spec’s frontmatter (paths: [src/auth/login.py]). Together, they form bidirectional traceability between specs and code.
Step 4: Run check
Section titled “Step 4: Run check”The check command validates the integrity of your context architecture. It verifies that links between artifacts are consistent, required fields are present, and annotations in code match their specs:
contextia checkIf everything is correctly linked, you will see:
Checking .contextia/ integrity...
Specs: 1 found, 1 activeDecisions: 0 found (1 referenced but missing: DEC-001)Norms: 0 foundTasks: 0 foundAnnotations: 3 found in 1 file
Warnings: SPEC-001 references DEC-001 but no decision file exists → Create it with: contextia new decision --id DEC-001
Annotations validated: ✓ src/auth/login.py:9 @spec SPEC-001 (spec exists) ✓ src/auth/login.py:10 @spec SPEC-001.login (spec exists) ✓ src/auth/login.py:19 @decision DEC-001 (decision missing)
Result: 1 warning, 0 errorsThe check found that our spec references DEC-001, but we have not created that decision file yet. Let’s fix that:
contextia new decision --id DEC-001 --title "Generic authentication errors"---type: decisionid: DEC-001title: Generic authentication errorsstatus: accepteddate: 2026-03-02specs: - SPEC-001---
# Generic authentication errors
## Context
The login endpoint needs to communicate authentication failures to the client.
## Decision
Return a generic "Invalid credentials" message for all authentication failures,regardless of whether the email exists in the system.
## Rationale
Revealing whether an email is registered enables account enumeration attacks.A generic error message prevents attackers from distinguishing between"email not found" and "wrong password" scenarios.
## Alternatives considered
- **Specific error messages**: Better UX but enables enumeration. Rejected for security reasons.- **Timing-equalized responses**: Add artificial delay to mask lookup timing. Considered complementary, not a replacement for generic messages.Run check again:
contextia checkChecking .contextia/ integrity...
Specs: 1 found, 1 activeDecisions: 1 found, 1 acceptedNorms: 0 foundTasks: 0 foundAnnotations: 3 found in 1 file
All annotations validated ✓All links resolved ✓
Result: 0 warnings, 0 errorsStep 5: Explore with trace
Section titled “Step 5: Explore with trace”The trace command shows full traceability for a file or directory — which specs govern it, which decisions constrain it, and which tasks have touched it:
contextia trace src/auth/Tracing: src/auth/
src/auth/login.py ├── @spec SPEC-001 User Authentication │ ├── @spec SPEC-001.login (sub-behavior: login) │ └── @decision DEC-001 Generic authentication errors └── @spec SPEC-001.logout (sub-behavior: logout)
src/auth/tokens.py └── @spec SPEC-001 User Authentication (via paths in spec)
Coverage: Files with annotations: 1 / 2 (50%) Spec path coverage: 2 / 2 (100%)Trace gives you a complete picture of how code, specs, and decisions relate. It works at file, directory, or individual spec level:
# Trace a single spec to see all its linked artifactscontextia trace SPEC-001
# Trace with full depth to include norms and task historycontextia trace src/auth/ --depth fullWhat happens when an AI agent connects
Section titled “What happens when an AI agent connects”With the MCP server configured (see Installation), here is what an AI agent experiences when it connects to your project:
- The MCP server starts and discovers your
.contextia/directory - The agent receives the
contextia://identityresource automatically — your project’s identity file - The agent receives the
contextia://indexresource — a navigation map of all specs, decisions, norms, and tasks
When the agent is assigned a task, it calls load_context to get everything it needs:
Agent calls: load_context(task_id="TASK-042")
Response includes: - Task TASK-042 full content - SPEC-001 (referenced by task) - DEC-001 (referenced by SPEC-001) - Applicable norms (matched by tag) - Previous session logs (if any)The agent works with full knowledge of the relevant specs and constraints. It does not need to search, guess, or ask you to paste context into the chat.
Next steps
Section titled “Next steps”You now have a working Contextia project with:
- A configured
.contextia/directory - A behavioral spec with frontmatter links
- Code annotations creating bidirectional traceability
- Passing integrity checks
From here, you can:
- Create a task with
contextia new taskto assign work that references your specs - Add norms with
contextia new normto codify your team’s coding conventions - Set up the MCP server to let AI agents access your context architecture directly
- Add
contextia checkto your CI pipeline to prevent broken links from being merged
For a deeper understanding of each artifact type and its schema, see the reference documentation.