Projects
A project is the unit of attribution. Every session, conversation, and meeting attaches to exactly one project (or to none, until it’s classified). Projects roll up to categories — seven values that match how the team actually thinks about work — and, where useful, drill down to subcategories for finer breakdowns.
The taxonomy lives in codika-os-app/seeds/projects.yaml and is materialized into the projects and project_path_prefixes tables by npm run db:sync:projects. There is one source of truth; no parallel hand-curated lists.
The seven categories
Section titled “The seven categories”| Category | What it covers | Subcategories |
|---|---|---|
client | Anything done for an external client. One project per client; slug = client folder name. | knowledge | product (set on the session, not the project row) |
product | External products Codika operates (Propale, Slideless, etc.). | — |
tool | Internal tools the team operates (codika-os, bot factory, env vault). | — |
platform | The core Codika platform — the flagship app, supporting services, infra, libs, templates, marketplaces. | app | cloud-run | infra | libs | template | marketplace |
growth | Sales and content work — playbooks, campaigns, carousels, outbound. | content | strategy | outreach |
knowledge | Company-OS and workspace reading/writing that isn’t a deliverable. | company-os | general |
private | Personal sandboxes. Excluded from company rollups. | — |
Each category exists because removing it would collapse a distinction the dashboard needs to surface:
clientis the leverage story for revenue-bearing work. Splitting it from internal categories is the whole point of the dashboard.productisolates Codika’s own products from client engagements — different economics, different planning cadence.toolcaptures the internal apps that keep the agency running but aren’t products. Lumped intoplatform, they’d inflate the platform leverage number.platformis the engine. Subcategories (app/cloud-run/infra/libs/template/marketplace) let us see where platform work is concentrated this month without minting six top-level categories.growthkeeps outbound and content visible as their own line item. Without it, every campaign session would land inknowledge:generaland disappear.knowledgeis the catch-all for reading, exploring, writing strategy. Splittingcompany-os(the agents-org plugin) fromgenerallets us tell “agent infrastructure” apart from “everything else workspace-rooted.”privateis opt-out: anything underprivate/projects/is captured locally but never rolls up to the team view.
Subcategory placement
Section titled “Subcategory placement”Subcategories live on different rows depending on whether the project is single-scope or multi-scope:
- Single-scope projects (like
codika-app→platform:app) carry the subcategory on the project row itself. Every session attributed tocodika-appis implicitlysubcategory = 'app'. - Multi-scope projects (every
clientproject) carrysubcategory = NULLon the project row. The subcategory is decided per session, stored insessions.attribution_subcategory. The path classifier reads it from the matchedproject_path_prefixesrow: editing a file underagency/crm/codika-clients/clients/creafid/emitssubcategory = 'knowledge'; editing underagency/projects/creafid/emitssubcategory = 'product'.
This is what lets a client like Creafid show “20h knowledge, 50h product” on a single donut without splitting it into two projects.
prompt_only projects
Section titled “prompt_only projects”Most projects are reached by path matching — the classifier scans paths_touched, finds the longest matching prefix in project_path_prefixes, and picks the owning project. But some work doesn’t touch the workspace at all. Outbound campaign prep happens in Lemlist, Apollo, LinkedIn — no files. Workspace-rooted reading sessions might touch a dozen places without landing decisively on any.
For those cases the taxonomy ships two prompt_only: true projects:
growth:outreach— Lemlist/Apollo/LinkedIn pipeline work. No path prefixes. The agent classifier picks it when prompt evidence describes outbound, lead enrichment, or content scheduling.knowledge:general— workspace-rooted exploration that doesn’t fit anywhere more specific. Path-matched againstworkspace/withpriority: low, plus picked by the agent classifier when nothing more specific applies.
prompt_only projects are invisible to the path classifier; they exist only so the agent-inline classifier (see Classification) has a slug to land on.
Discovery rules
Section titled “Discovery rules”seeds/projects.yaml declares one or more discovery rules per category. The seeder walks them and mints projects + path prefixes accordingly.
| Rule shape | What it does |
|---|---|
root + leaf: direct-child | Lists the named workspace folder; mints one project per direct subdirectory. Slug = bare folder name. legacy_paths are also rewritten with the same leaf and attached as legacy path prefixes (so historical sessions still attribute). |
flat_path | Mints exactly one project at the given path. Used for marketplace, knowledge:company-os, etc. |
path_prefixes | Mints one project rooted at multiple explicit paths. Used for growth:strategy (playbooks + campaigns). |
prompt_only | Mints a project with no path prefixes. Reached only by the agent classifier. |
The seeder also lints before writing. Two prefixes can’t belong to two different projects. Every client:knowledge slug must exist as client:product (and vice versa) — the parity rule. Slugs must be kebab-case.
Anatomy of a project row
Section titled “Anatomy of a project row”| Column | Purpose |
|---|---|
slug | Stable, machine identifier. Kebab-case. Unique per (category, slug). Never change it — URL routes (/tracking/projects/<slug>) and the CLI classifier depend on it. |
display_name | Long-form label, e.g. “Creafid”. |
alias | Short chip label shown in the UI. Defaults to display_name if not set. |
color | Palette key (indigo, teal, rose …). Resolved to HSL at render. |
category | One of the 7. Required. |
subcategory | Set on single-scope projects (e.g. app for codika-app). NULL for multi-scope (client) projects. |
client_slug | References clients(slug). Non-null iff category = 'client'. |
prompt_only | true for projects with no path prefixes (only reached by the agent classifier). |
org_scope | 'company' or 'private'. Private projects are excluded from company-level rollups. |
is_active | Soft-delete flag. Inactive projects still resolve for historical sessions but don’t appear in pickers. |
Path prefixes live in project_path_prefixes. Each row carries its own subcategory (which the classifier uses for sessions.attribution_subcategory) and an is_legacy flag for prefixes kept around to attribute pre-reorg history.
Taxonomy at a glance
Section titled “Taxonomy at a glance”Sourced from seeds/projects.yaml. One row per discovery rule; the slug column shows either a fixed project slug or <leaf> for direct-child rules that mint one project per subdirectory.
| Category | Subcategory | Discovery | Slug |
|---|---|---|---|
client | knowledge | agency/crm/codika-clients/clients/* | <leaf> |
client | knowledge | agency/crm/codika-clients/prospects/* | <leaf> |
client | product | agency/projects/* | <leaf> |
product | — | products/* | <leaf> |
tool | — | agency/tools/* | <leaf> |
platform | app | core/app/* | <leaf> |
platform | cloud-run | core/cloud-run/* | <leaf> |
platform | infra | core/infra/* | <leaf> |
platform | libs | core/libs/* | <leaf> |
platform | template | templates/* | <leaf> |
platform | marketplace | agency/plugins/codika-product-marketplace | marketplace |
growth | content | workspace/content | content |
growth | strategy | workspace/openclaw/docs/playbooks + workspace/openclaw/docs/campaigns | strategy |
growth | outreach | prompt_only | outreach |
knowledge | company-os | agency/plugins/codika-agents-org | company-os |
knowledge | general | workspace (priority: low) | general |
private | — | private/projects/* | <leaf> |
Linear projects (planned)
Section titled “Linear projects (planned)”Each codika-os project is a 1:1 candidate for a Linear project. The schema doesn’t yet store the link (no linear_project_id column), but the slug/category model was chosen to match Linear’s nomenclature so the join is straightforward when the sync ships. See Known follow-ups below.
See also
Section titled “See also”- Project taxonomy operations — adding a project, handling agent suggestions, fixing slug-parity violations.
- Classification — the two-phase classifier (path-based at sync, agent-inline on demand).
- Schema changes — Drizzle workflow when the project model evolves.
Known follow-ups
Section titled “Known follow-ups”- Linear sync —
projects.linear_project_idcolumn to associate each project with its Linear project. Sessions → Linear issues falls out once it’s wired. - Per-session subcategory KPIs — the dashboard currently surfaces category-level rollups; per-subcategory tiles (e.g. “client knowledge vs product time”) are a follow-up.
- In-app project edits — alias/color editing is still seeds-side. An admin form is planned.