JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 47
  • Score
    100M100P100Q113874F
  • License Apache-2.0

Agentic persistent planning

Package Exports

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@sqaoss/flowy) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    Flowy

    Agentic persistent planning

    npm License: Apache-2.0 CI

    Jira, Linear, Trello are built for humans clicking boards. AI agents don't click boards. When your agent needs to plan work, track progress, and close tickets, those tools add friction, load context, and get in the way.

    Flowy is where agents store plans and flow through execution. Features are master plans. Tasks are execution steps. Everything persists in a database, not as files cluttering your git history. Your agent flows through work without friction.

    You get full observability on what every agent planned, built, and shipped.

    Get Started

    Flowy runs in one of two modes. Pick the one that fits:

    • Self-hosted — a local server you run yourself (flowy serve). No account, no subscription, your data stays on your machine. Start here if you just want to try Flowy.
    • Remote (hosted) — the managed service at flowy-ai.fly.dev. Register with an email, then subscribe at checkout. The hosted server gates data operations behind an active subscription.

    Quickstart (self-hosted, no account)

    npm i -g @sqaoss/flowy
    flowy setup local          # installs the bundled server, points the CLI at localhost
    flowy serve &              # starts the local server on 127.0.0.1:4000
    
    cd my-project
    flowy init                 # auto-detects the git repo, creates + maps a project
    
    flowy feature create --title "User Auth" --description "Email + OAuth login"
    flowy feature set "User Auth"
    
    flowy task create --title "Implement OAuth" --description "Wire up the OAuth provider"
    flowy status <task-id> in_progress
    flowy status <task-id> done

    flowy serve runs in the foreground; the & backgrounds it. Stop it with kill %1 or run it in a separate terminal. Data lives in ./flowy.sqlite.

    Quickstart (remote/hosted)

    npm i -g @sqaoss/flowy
    flowy setup remote --email you@example.com   # registers; prints an apiKey + checkoutUrl
    
    cd my-project
    flowy init                                   # auto-detects the git repo, creates + maps a project
    flowy task create --title "First task" --description "Try it out"

    setup remote registers your email and stores the returned API key. It prints a checkoutUrlopen it to start a subscription. Until you do, the hosted server may reject data operations with An active subscription is required. You no longer need to choose a tier up front (--tier is optional); pick one at checkout.

    Every command outputs JSON. Your agent reads it, acts on it, moves to the next task.

    Descriptions: literal vs. file

    --description is always literal text — it is never read as a file path. To load a description from a file (or stdin), use --description-file:

    flowy task create --title "Write tests"   --description "Unit + integration tests"
    flowy feature create --title "User Auth"  --description-file auth-spec.md
    flowy task create --title "From stdin"    --description-file -      # reads stdin

    Dependencies and ready work

    Tasks can block one another. Mark a dependency, inspect it, and ask for only the tasks that are actually actionable right now:

    flowy task block <blocker-id> <blocked-id>   # blocker must finish before blocked
    flowy task deps <id>                          # what blocks this task, and what it blocks
    flowy task show <id>                          # task details, now including blockedBy/blocks
    
    flowy task list --ready                        # only unblocked, not-done tasks (active project)
    flowy task list --ready --project <project-id> # ...scoped to a specific project
    flowy task list --all                          # every task across the whole backlog

    --ready returns tasks that are not done/cancelled and have zero unfinished blockers — the work an agent can pick up next.

    Import and export

    Move a whole backlog in or out as a single JSON manifest. Import is idempotent: each node carries a stable key (a client-key), so re-importing updates the matching nodes in place instead of duplicating them. Edges (part_of, blocks) round-trip through the real edge model, so a block you created by hand is captured on export and not re-created on the next import.

    flowy export                 # print the active project's manifest to stdout
    flowy export backlog.json    # ...or write it to a file
    flowy import backlog.json    # ingest a manifest (create new, update existing by key)

    A manifest looks like:

    {
      "version": 1,
      "nodes": [
        { "key": "proj", "type": "project", "title": "My Project" },
        { "key": "auth", "type": "feature", "title": "User Auth", "parent": "proj" },
        { "key": "oauth", "type": "task", "title": "Implement OAuth", "parent": "auth", "status": "draft" }
      ],
      "edges": [
        { "source": "oauth", "target": "auth", "relation": "part_of" }
      ]
    }

    Each node's parent implies a part_of edge, so the simplest manifests need no explicit edges. blocks dependencies go in edges. The reserved __flowyKey metadata field stores the client-key; your own metadata is preserved alongside it and stripped back out on export.

    Backup and restore (local SQLite)

    In self-hosted mode your backlog lives in a single SQLite file (see Where your data lives). flowy backup takes a consistent, file-level snapshot of that database, and flowy restore reinstates one.

    flowy backup flowy-backup.sqlite             # snapshot the local DB (./flowy.sqlite by default)
    flowy backup ~/snapshots/flowy.sqlite --db ~/flowy.sqlite   # back up a DB at a custom path
    flowy restore flowy-backup.sqlite            # restore into a fresh DB (refuses to clobber)
    flowy restore flowy-backup.sqlite --force    # overwrite an existing DB

    The snapshot is taken with SQLite's VACUUM INTO, so it is transactionally consistent even while the server is running and writes a single self-contained file (no -wal/-shm sidecars). restore validates the source is a real SQLite database before touching the target, and refuses to overwrite an existing database unless you pass --force.

    Both commands resolve the database path the same way the server does: --db <path>, then $FLOWY_DB_PATH, then ./flowy.sqlite.

    backup vs. export — they're complementary, not redundant:

    flowy export (logical) flowy backup (raw)
    Format Portable JSON manifest Exact SQLite file
    Scope The active project's subtree The entire database (all projects)
    Re-importable Yes — flowy import (idempotent, cross-backend) No — restore only, local server
    Use it for Migrating between machines/backends, re-importing, diffing in git Point-in-time disaster recovery, an exact byte-faithful snapshot

    Use export/import to move a backlog around or seed another backend; use backup/restore for a true snapshot of your local server's data.

    Where your data lives

    The self-hosted server persists everything in one SQLite file. Its location depends on how you run the server:

    • flowy serve (native): ./flowy.sqlite in the current directory by default, or wherever --db/$FLOWY_DB_PATH points.
    • Docker (docker compose up): inside the named volume flowy-data, mounted at /data, with FLOWY_DB_PATH=/data/flowy.sqlite. The data outlives the container — but docker compose down -v deletes the volume and your backlog with it. Take a flowy backup first.

    To back up the Docker volume's database, point --db at the in-container path while running flowy backup from inside the container, or restore into a fresh flowy serve directory and snapshot there.

    Agent Skill

    flowy setup installs an agent skill so your AI agent automatically knows every command. If that install step fails (offline, no npx, registry hiccup), setup prints a warning telling you to install it manually:

    npx skills add sqaoss/flowy

    See skills/using-flowy/SKILL.md for the full skill reference.

    MCP Server

    flowy mcp exposes the whole backlog API as an MCP server over stdio — a second agent surface alongside the CLI. An MCP-aware client (Claude Code, Claude Desktop, etc.) spawns it and gets typed tools for the full workflow: create/update/delete/show/list for projects, features and tasks, flowy_ready_tasks, flowy_claim_task, flowy_next_task (atomically claim the next ready task — the one call an agent needs to pick up work), flowy_block/flowy_unblock, flowy_set_status, flowy_approve, flowy_search, flowy_tree, flowy_task_deps, flowy_history, flowy_import/flowy_export, and flowy_whoami.

    It is mode-aware: it reads the same ~/.config/flowy/config.json as the CLI, so it talks to whichever backend you've configured — the local flowy serve server (no account) or the hosted service. There is nothing extra to configure.

    Register it with an MCP client by pointing the client at the flowy mcp command. For Claude Code:

    claude mcp add flowy -- flowy mcp

    Or add it to a client config (e.g. Claude Desktop's claude_desktop_config.json):

    {
      "mcpServers": {
        "flowy": {
          "command": "flowy",
          "args": ["mcp"]
        }
      }
    }

    Configure the backend first (flowy setup local + flowy serve, or flowy setup remote) so the MCP server knows where to talk. Tool errors carry the same coded classes as the CLI (NOT_FOUND, VALIDATION_ERROR, …) so an agent can read and self-correct.

    Data Model

    project -> feature -> task
      1:many     1:many

    Every task belongs to a feature. Every feature belongs to a project. No orphans.

    Status Flow

    draft -> pending_review -> approved -> in_progress -> done

    Also: blocked, cancelled. Only pending_review entities can be approved.

    Self-Hosted

    Run Flowy on your own machine — no Docker, no account, no subscription. flowy setup local installs a bundled server pinned to your CLI version and points the CLI at localhost; flowy serve runs it natively over SQLite.

    flowy setup local            # install the bundled server, configure the CLI
    flowy serve                  # bind 127.0.0.1:4000, store data in ./flowy.sqlite
    flowy serve --port 5000 --host 0.0.0.0 --db ~/flowy.sqlite   # override defaults

    The self-hosted server supports the full planning workflow — init, project/feature/task CRUD, status, approve, search, tree, task deps, task list --ready/--all, import/export, and backup/restore (raw SQLite snapshots). Account-only commands (whoami, billing, key) are remote-mode features and don't apply locally.

    The canonical status flow is draft → pending_review → approved → in_progress → done, plus blocked and cancelled. By default any status change is allowed (and the status command validates the value client-side). To make the local server enforce legal transitions — rejecting illegal jumps like draft → done with a VALIDATION_ERROR — start it with FLOWY_ENFORCE_STATUS_LIFECYCLE=1. Enforcement is opt-in and off by default.

    Command Reference

    Command Description
    setup local Install the bundled local server and point the CLI at it
    setup remote --email <email> [--tier <tier>] Register with the hosted server (--tier optional)
    serve [--port] [--host] [--db] Run the bundled local server (self-hosted mode)
    mcp Run the MCP server over stdio — a second agent surface (mode-aware)
    init Auto-detect repo and create/map project
    client set name <name> Set client display name
    project create <name> Create project
    project set <name> Map current directory to a project
    project list List all projects
    project show [<id>] Show project details (defaults to active)
    project update [<id>] [--title] [--description|--description-file] [--metadata] Update a project
    project delete [<id>] Delete a project (defaults to active)
    feature create --title <t> [--description <text>|--description-file <path>] Create feature (requires active project)
    feature set <name-or-id> Set active feature
    feature unset Clear active feature
    feature list List features in active project
    feature show [<id>] Show feature details (defaults to active)
    feature update [<id>] [--title] [--description|--description-file] [--metadata] Update a feature
    feature delete [<id>] Delete a feature (defaults to active)
    task create --title <t> [--description <text>|--description-file <path>] Create task (requires active feature)
    task list [--ready] [--all] [--project <id>] List tasks: active feature, or --ready/--all (optionally scoped to a project)
    task show <id> Show task details, including blockedBy/blocks
    task update <id> [--title] [--description|--description-file] [--metadata] Update a task
    task delete <id> Delete a task
    task block <id1> <id2> Mark id1 as blocking id2
    task unblock <id1> <id2> Remove a blocking relationship
    task deps <id> Show what blocks a task and what it blocks
    status <id> <status> Update status (shorthand)
    approve <id> Approve (must be pending_review)
    search <query> [--type] [--status] [--limit] Full-text search; prints { nodes, truncated, total } and warns on stderr when results are capped at --limit
    tree <id> [--depth N] Show subtree from any entity
    import <manifest> Ingest a JSON manifest of nodes + edges (idempotent by client-key)
    export [output] Dump the active project as a manifest (stdout or file)
    backup <dest> [--db <path>] Consistent file-level snapshot of the local SQLite database
    restore <src> [--db <path>] [--force] Restore the local SQLite database from a backup (refuses to clobber without --force)
    whoami Show current user (remote mode)
    billing checkout --tier <tier> Get a checkout URL for a subscription (remote mode)
    key rotate Revoke all API keys and issue a new one (remote mode)

    All commands output JSON to stdout; errors go to stderr as { "error": "message" }.

    GraphQL API

    The CLI is a thin client over a GraphQL API. To integrate directly — or to understand what the CLI sends — see the API reference for the bundled local server:

    • docs/API.md — schema, example queries/mutations, error-code catalogue (with CLI exit codes), and limits.
    • docs/api/schema.graphql — the full SDL, regenerable with bun run sdl.

    The hosted service at flowy-ai.fly.dev exposes a superset of this schema plus account/billing operations; its API is documented separately.

    Configuration

    Config is stored at ~/.config/flowy/config.json. These environment variables override config:

    Variable Description Default
    FLOWY_API_URL GraphQL endpoint https://flowy-ai.fly.dev/graphql (remote) / http://localhost:4000/graphql (local)
    FLOWY_API_KEY API key (remote mode) --
    FLOWY_PROJECT Override active project by name --
    FLOWY_FEATURE Override active feature by ID --

    Development

    bun run test          # CLI tests
    bun run check         # Lint + format
    bun run typecheck     # TypeScript
    
    cd server && bunx --bun vitest run   # Server tests

    Open Source vs. Hosted

    This repository — the @sqaoss/flowy CLI and the bundled local server it runs via flowy serve — is open source under Apache-2.0. You can self-host the full planning workflow with no account and no subscription; your data stays in a local SQLite file on your machine.

    The hosted service at flowy-ai.fly.dev is a separate, commercial offering. It is a proprietary backend whose source is not part of this repository, and it exposes a superset of the open-source server's GraphQL schema plus account and billing operations. Using the hosted service is optional — the CLI talks to either your local server or the hosted one depending on how you configure it.

    License

    Apache-2.0. Copyright 2026 SQA & Automation SRL.