Architecture
Joy's internal architecture - crate structure, data model, status workflow, and configuration.
Crate Structure
Joy is implemented in Rust as a set of crates within the joyint/joy repository. The joy-core library crate contains the shared logic, while joy-cli and joy-ai are binary and library crates that depend on it.
What joy-core Provides
| Module | Purpose |
|---|---|
| Item model | Types, priorities, effort, tags, dependencies, parent-child relationships |
| YAML I/O | Read and write .joy/ files with validation |
| Status logic | State machine for item lifecycle |
| Event log | Append-only log of all actions for audit |
| Config system | Layered configuration with defaults, project, and personal overrides |
| Git integration | Commit detection, branch awareness, VCS abstraction |
Data Model
The data model centers on workspaces, projects, items, and milestones.
Item Types
Every item has a type that describes what kind of work it represents:
| Type | Purpose |
|---|---|
| epic | Large body of work, contains child items |
| story | User-facing feature or change |
| task | Technical work, implementation step |
| bug | Defect to fix |
| rework | Improvement to existing code (refactor, cleanup) |
| decision | Architectural or process decision to document |
| idea | Captured thought, not yet committed to |
Priority and Effort
Priority levels: critical, high, medium, low.
Effort uses a 1-7 scale: 1 = trivial, 2 = small, 3 = medium, 4 = large, 5 = major, 6 = heavy, 7 = massive.
Status Workflow
Items follow a defined lifecycle. The status workflow ensures items move through predictable states.
Status Descriptions
| Status | Meaning |
|---|---|
| new | Just created, not yet triaged |
| open | Accepted and ready to work on |
| in-progress | Actively being worked on |
| review | Work done, waiting for review |
| closed | Completed and verified |
| deferred | Postponed, can be reopened later |
Config Layering
Joy uses a layered configuration system. Each layer overrides the previous one, so project settings can override defaults, and personal preferences can override project settings.
How Layering Works
- Code defaults - Hard-coded values in
joy-core. Always present, always reasonable. - config.defaults.yaml - Shipped with Joy, defines the default configuration schema and values.
- Global config - User-level settings in
~/.config/joy/config.yaml. Apply to all workspaces. - Personal config - Project-level personal overrides in
.joy/config.personal.yaml. Gitignored, per-user.
Each layer only needs to specify the values it wants to override. Everything else falls through to the layer below.