Platform Guide

InnoDay is the hub every project reports to.

Tickets, boards, repositories, scope, and releases usually live in five different tools. InnoDay pulls them into one project-shaped record — and makes that record follow you into the directory where you actually write code.

What is InnoDay?

InnoDay is an AI-powered team-orchestration platform. Every significant event — ticket work, board syncs, repo additions, scope changes, releases — is recorded in one place, against one project, so a project's full history is always queryable instead of rebuilt from git logs.

A single, queryable record of truth

Development state scatters by default. The board knows what is planned, GitHub knows what shipped, the release tool knows the version, and the decisions from the last meeting live in someone's notes. Reconstructing “where is this project?” means stitching those together by hand, every time.

InnoDay's premise is that every significant event is recorded in one place, against one project. Skills, agents, and CLI tools all write back to it, so the history is always there to query. The rule of thumb: if you need to remember it across sessions or share it with the team, it belongs in InnoDay.

You don't self-host to use it. The common path is uv tool install innoday, then point the CLI at the shared, Railway-hosted environment. You only clone the repository to develop InnoDay itself.

Six problems it solves

The “record of truth” idea earns its keep by clearing six specific frustrations that show up on any multi-repo, multi-project software team.

P01

Deploy internal resources into projects with Claude Code — efficiently

Old way — context rebuilt by hand every session

A new model for software development: skills, agents, and project context are packaged and dropped into a project so an AI teammate can start productive work immediately, instead of being re-briefed from scratch each time.

P02

Manage many projects and their board activity in one place

Old way — one browser tab per board, per project

Every project's tickets and board movement roll up to a single hub, so a lead can see the whole portfolio without hopping between Linear, Jira, and Trello workspaces.

P03

Collect timelines across every process

Old way — history scattered across tools & git logs

Ticket work, board syncs, scope changes, repo additions, and releases all land on one curated project timeline — a chronological record that stitches together events which normally live in separate systems.

P04

Generate active, human-readable summaries

Old way — "what happened this week?" is a research task

Because the events are all in one place, InnoDay can synthesize them with Claude into plain-language updates — scrum reports, work summaries, assignment breakdowns — so anyone can understand what's going on without reading raw ticket data.

P05

Organize releases across repositories

Old way — repos tagged one at a time, notes written later

A single release tags every repo in a project together — discovered by GitHub topic — and ships with an auto-generated, feature-level summary, so a version means the same thing across the whole codebase.

P06

Greater transparency into the team deployed to an org

Old way — opaque — who's doing what, where?

The hub makes the shape of the work visible — which projects are active, who (human or agent) is on what, and how effort is distributed across an organization.

The project sits at the center of everything

InnoDay's data model is a strict hierarchy. An organization is the tenant and security boundary. Inside it, a project is the unit you actually work inside — and it is the join point that every other concept attaches to.

Fig. 1 — one project ties five concerns together

Why “project-centric” is more than a diagram: the database enforces it. A board can't exist without a project, a ticket can't exist without a project, and a release version is unique per project. There is no such thing as an org-only ticket floating outside a project.

The concepts, and the rule that binds each to a project

ConceptWhat it isThe binding rule
OrganizationThe tenant and security boundary; holds members, license, and everything below.alias is globally unique — used in config keys and API paths.
ProjectThe working unit. Carries goals, scope limits, spec, status, priority, tags.alias (≤10 chars, e.g. PF) is the ticket prefix, unique per-org.
Board RegistrationLinks a project to one external board (Linear / Jira / Trello / Notion).project_id is NOT NULL & unique — one board per project, enforced in the schema.
TicketA work item; gets a display ref like PF-42. Synced from a board or created directly.project_id is required; denormalized onto the ticket at create/sync time.
RepositoryA GitHub repo record, carrying an architectural layer (UI / API / DATA / AI).Attached to a project only by topic-label discovery — no manual link command.
Scope DocumentVersioned requirements: deliverables, success criteria, assumptions, exclusions.Versioned per project; one row flagged is_current.
ReleaseA version record with status planned → released.Version unique per project; created by the release mechanism, not by board sync.

How planning reaches your working directory

The centerpiece

This is the part that makes InnoDay more than a tracker. Planning artifacts — tickets, boards, scope — live server-side. But the developer works in a folder full of repositories on their own machine. InnoDay closes that gap with one small file and one resolution rule.

The file: when you onboard a workspace, InnoDay writes a .innoday/project.yml into it. It records exactly which org and project this directory represents — by stable UUID, not just a name — plus the repos that belong to the project and the release state that blastoff owns.

~/workspaces/hs/pf/.innoday/project.yml
# written by the workspace onboarder — schema v2
schema_version: 2
org:
  alias: hs
  name: Haviland Software
  innoday_id: 2e2ffce7-…      # org UUID — the source of truth
  github_org: havilandsoftware
project:
  alias: pf
  name: PixelFuel
  innoday_id: e52b7372-…      # project UUID
  github_topic: pixelfuel     # repos are discovered by this label
repos:
  - name: pixelfuel-blastoff
  - name: pixelfuel-website
release_configs:              # blastoff version state, preserved on refresh
  pf: { next_version: … , last_released_version: … }

The rule: every tool — the CLI, the MCP server, the release tool — walks up from wherever you are until it finds a .innoday/project.yml. It reads the org and project UUIDs out of that file and uses them for every API call. That's the whole trick: launching Claude Code or running innoday from inside a project folder “just works” with zero flags.

Fig. 2 — cwd resolution feeds all three surfaces from one file

Resolution precedence

  1. Explicit override for a single call — a --project flag or a project_id argument.
  2. The project.yml found by walking up from the current directory. (This is the normal path.)
  3. A last-used org cached on the machine — a fallback only.

There is deliberately no persistent “switch project” command. The current org/project is never written to shared machine config — it's resolved per-invocation from your directory. Two shells in two different projects never clobber each other.

What a developer actually does

Because context is ambient, the daily loop is short. Everything below resolves the project automatically from the folder you're standing in:

picking up work
# you are in ~/workspaces/hs/pf — org & project auto-resolve
$ innoday tickets list --status TODO
$ innoday tickets update --ticket-id <id> --status IN_PROGRESS
# …work in the repos project.yml lists, in a git worktree…
$ innoday sync            # pull board tickets + repo discovery + release state

The planning side (a ticket on a Linear board) and the doing side (a repo on your disk) are now two ends of the same thread — and the project.yml is the knot in the middle.

Agents and the MCP server

InnoDay ships as a Claude Code plugin as well as a CLI. The plugin bundles an MCP server and a set of agents that operate the platform on your behalf — all of them talking to the same REST API through the same cwd-resolved context.

Claude Code spawns the InnoDay MCP server locally (via uvx --from innoday mcp-server-innoday). It exposes the platform as 43 toolscreate_ticket, sync_board, create_release, get_scrum_summary, and so on. Crucially, it holds no business logic: each tool is a thin HTTP call to the same REST API the CLI uses. Change a ticket by CLI or by agent — it's the same endpoint, the same record.

Project Manager

Keeps the board honest

Grooms and triages tickets, reconciles status against activity, and runs on a schedule to sweep stale, duplicate, and orphaned work items so the backlog stays trustworthy.

client-manager

Org & project lifecycle

Sets up organizations and projects, connects boards and repositories, and runs the onboarding flow end to end.

setup-innoday

Environment bring-up

Bootstraps a working InnoDay environment — configuration, identity, and the connections a new project needs.

db-manager

Data & migrations

Handles database concerns behind the API — schema state, migrations, and integrity checks.

design-guardian

Architecture alignment

Reviews changes against the project's established patterns so new work fits the system it lands in.

test-analyst

Verification

Exercises the platform's lifecycle flows and surfaces regressions before they reach a human reviewer.

The Project Manager agent is the piece that makes “the board is the truth” sustainable: unattended, on a cadence, it does the tidying a human PM would otherwise do by hand — closing what's done, flagging what's drifted, and clearing what's orphaned.

How it’s all deployed

InnoDay itself is a FastAPI service running on Railway, backed by Supabase Postgres. Everything a developer runs locally — the CLI, the MCP server, blastoff — is a client of that one deployed API.

Fig. 3 — platform topology: local machine · GitHub · AWS · Railway · integrations

Two deploy paths coexist right now — the platform is mid-migration from source builds to signed images.

Current

Railway builds from source

Railway's GitHub App is connected to the repo and builds the Dockerfile server-side on every push to main. No CI image step involved.

Target

Signed image, pulled by Railway

GitHub Actions builds the image once, pushes it to both AWS ECR (private, scanned) and GHCR (public), signs it with Cosign, verifies the signature as a deploy gate, then triggers Railway to pull the public GHCR image.

The switch to the target path is a one-time manual step: repointing Railway's service source from the connected repo to the GHCR image. Railway pulls the public GHCR copy (not ECR) because that avoids the paid private-registry requirement; ECR remains the private, scan-on-push canonical copy, and Cosign signature verification — not secrecy — guarantees integrity.

Getting a developer connected

For most people this is a five-minute install against the shared dev environment. You are configuring a client — you are not standing up a server.

install & configure
# 1 · install the CLI (the MCP server ships in the same package)
$ uv tool install innoday

# 2 · initialize identity against the shared dev API
$ innoday init --default          # defaults to https://innoday-dev.up.railway.app
$ innoday orgs list               # verify the connection

# 3 · seed the team secret (the gotcha) — the dev API is gated; without a
#     matching X-Team-Secret header every non-public route returns 401
$ innoday config set team-secret "<the dev team secret>"

# 4 · onboard a workspace, then context resolves from the folder — no flags
$ cd ~/workspaces/hs/pf
$ innoday tickets list

If the CLI works but the MCP tools return 401, the MCP server cached the pre-seed config at startup — reconnect it (/mcp reconnect) so it re-reads the seeded config. A purely local API has no team secret.

The two config files — don’t confuse them

FileScopeHolds
~/.innoday/config.jsonYour machine, all projectsIdentity: default profile, API URL, your user id, the team secret, a cached org map. Never stores integration secrets — only pointers. The current org/project is never persisted here.
<workspace>/.innoday/project.ymlOne workspace folderWhich project this is: org & project UUIDs, the GitHub topic, the repo list, and blastoff's release state.

That's the whole model: one project-shaped record in the cloud, a small file that binds a folder to it, and a handful of clients — CLI, MCP, blastoff — that all resolve the same context from wherever you happen to be working.