Skip to content

Development environment

Run OpenQuok's agent, backend, workers and web apps locally, execute tests, database scripts, and deployment commands.

8 min read

Connect your agent today

Draft from chat, review in your calendar, and publish only what you approve.

Start for $0

Backend local development

You can work from the monorepo root (as defined in the root package.json) or backend/. Pick one.

Frontend local development

You can work from the monorepo root or change into web/ and run package scripts there.

Redis (cache)

If you use CACHE_PROVIDER=redis, run Redis locally or use a managed instance and set REDIS_HOST, REDIS_PORT, and password fields to match.

Workflow-style jobs can run in the API process (Flowcraft), but the repo also ships long-running workers under orchestrator/.

Worker Processes (BullMQ)

If you configure orchestrator flows to use BullMQ, the API enqueues jobs to Redis and separate worker processes execute them.

Run local Redis (BullMQ) — quickest path is Docker Compose:

# From repo root
docker compose -f infra/docker-compose.yml up -d redis

Start a worker locally — each worker is its own process:

# From repo root
pnpm orchestrator:dev:worker:integration-refresh-bullmq
pnpm orchestrator:dev:worker:notification-email-bullmq
pnpm orchestrator:dev:worker:scheduled-social-post-bullmq

Worker env and Redis queue details live in Configuration → Worker → Docker (local Redis).

CLI auth server (device flow)

The CLI auth server (agent/server) implements the OAuth2 device flow.

Most developers can use the hosted server by default, but you can run it locally for end-to-end testing.

Run local Postgres (auth server state) — the auth server stores device-flow state in Postgres:

# From repo root
docker compose -f infra/docker-compose.yml up -d postgres

Then set DATABASE_URL in agent/server/.env.development.local to match (defaults to postgresql://openquok:openquok@localhost:5432/openquok_cli_auth).

Run the CLI auth server locally:

# From repo root
pnpm agent-server:dev

Once running, point the CLI at it via OPENQUOK_AUTH_SERVER or —authServer — see CLI authentication.

Running the CLI from the monorepo (unpublished)

Run from source (recommended for daily dev) — uses the cli script (tsx src/index.ts); no build needed, picks up source changes on every invocation:

pnpm --filter ./agent cli -- --help
pnpm --filter ./agent cli -- integrations:trigger --help
pnpm --filter ./agent cli -- auth:login --authServer http://localhost:3111

Per-command —help shows the Examples: section with copy-pasteable invocations for non-obvious payloads (JSON -d, ISO timestamps, etc.).

Run the compiled binary — useful when you want to confirm the published bundle behaves the same:

pnpm --filter ./agent build
node agent/dist/index.js auth:login --authServer http://localhost:3111

Run the compiled binary via the start script — same end result, slightly tidier:

pnpm --filter ./agent build
pnpm --filter ./agent start -- auth:login --authServer http://localhost:3111

Smoke-test the CLI surface — after adding or renaming commands under agent/src/commands/, verify every group is wired into registerAllCommands and responds to —help:

# 1. Top-level --help: should list auth, integrations, posts, analytics, upload, upload-from-url
pnpm --filter ./agent cli -- --help

# 2. Each command must respond to --help with its yargs Examples: block
pnpm --filter ./agent cli -- analytics:platform --help
pnpm --filter ./agent cli -- analytics:post --help
pnpm --filter ./agent cli -- posts:status --help
pnpm --filter ./agent cli -- posts:delete --help
pnpm --filter ./agent cli -- posts:missing --help
pnpm --filter ./agent cli -- posts:connect --help
pnpm --filter ./agent cli -- upload-from-url --help

Connectivity smoke — requires a valid opo_ programmatic token or stored credentials. Confirms auth + workspace plumbing end-to-end against a running backend:

pnpm -s --filter ./agent cli -- auth:status
pnpm -s --filter ./agent cli -- integrations:list | jq '.[] | {id, identifier}'
pnpm -s --filter ./agent cli -- posts:list | jq '.success, (.data.posts | type)'

Every command emits machine-readable JSON on stdout, so piping into jq is the recommended way to test the CI.

pnpm -s --filter ./agent cli -- integrations:list

Smoke-test post kanban review (CLI + web)

Use this flow to seed agent-edited drafts with the CLI and exercise the kanban review board on the account page . The CLI always sends isAgent: true on posts:create; human actions in the dashboard clear is_agent_edited when you mark a post reviewed or schedule it from the UI.

Start the API and web app

In separate terminals from the repository root:

pnpm backend:dev
pnpm web:dev

Sign in at https://localhost:5173 with the same workspace you will use for CLI credentials.

Point the CLI at your local API

The CLI defaults to the hosted API unless overridden. For local smoke runs:

export OPENQUOK_API_URL=http://localhost:3000

Use the same origin your web app uses for API calls if you proxy through another host (see HTTPS local development and the API base URL). Set this before auth:login --apiKey so the CLI does not call the hosted API with a local-only key.

Authenticate the CLI

Programmatic token (fastest) — rotate a token from AccountSettingsDevelopersAccess, then store it:

pnpm -s --filter ./agent cli -- auth:login --apiKey "opo_your_programmatic_token"

Or export OPENQUOK_API_KEY for the session (run auth:logout first if ~/.openquok/credentials.json already exists — stored credentials take priority over env).

OAuth device flow — requires the local auth server (pnpm agent-server:dev) and the same --authServer pattern as above:

pnpm --filter ./agent cli -- auth:login --authServer http://localhost:3111

Confirm connectivity:

pnpm --filter ./agent cli -- auth:status

List channels and create an agent draft

Resolve an integration UUID, then create a draft (lands in the kanban Drafted column with the agent flag set):

pnpm -s --filter ./agent cli -- integrations:list | jq '.[] | {id, identifier}'

Alternatively, print it via terminal:

pnpm -s --filter ./agent cli -- integrations:list

If you see “success”: false and 401, re-run auth:login --apiKey after OPENQUOK_API_URL is set, or run auth:logout when stale ~/.openquok/credentials.json points at the wrong API.

Set variables from the list output (replace the placeholder, or capture the first channel id):

export INTEGRATION_ID="<integration-id>"
export SCHEDULED_AT="$(node -e "const d=new Date(Date.now()+864e5); d.setUTCHours(12,0,0,0); process.stdout.write(d.toISOString())")"
echo "INTEGRATION_ID=$INTEGRATION_ID"
echo "SCHEDULED_AT=$SCHEDULED_AT"

Create the draft (one line — safe to copy; use --scheduledAt so the schedule time is unambiguous):

pnpm -s --filter ./agent cli -- posts:create -c "Kanban review smoke test" --scheduledAt "$SCHEDULED_AT" -i "$INTEGRATION_ID" -t draft --note "Confirm CTA link before scheduling"

Inspect the response:

pnpm -s --filter ./agent cli -- posts:create -c "Kanban review smoke test" --scheduledAt "$SCHEDULED_AT" -i "$INTEGRATION_ID" -t draft --note "Confirm CTA link before scheduling" | jq '{postGroup: .data.postGroup, postId: .data.posts[0].id, isAgentEdited: .data.posts[0].isAgentEdited, note: .data.posts[0].note, state: .data.posts[0].state}'

Expect isAgentEdited: true and state: DRAFT in the response.

See CLI — Managing posts and Update Review Todo for flag and API details.

Exercise the kanban in the browser

  1. Open Account (kanban below your profile).
  2. Set the filter to Agent (not Human).
  3. Find the card under Drafted.
  4. As a human: edit the review note, check reviewed, then schedule or publish from the dashboard — the card should move columns and no longer show as agent-edited after review.

Backend e2e

The repository includes an automated flow that creates via the real CLI bundle and asserts review + schedule over HTTP:

pnpm --filter ./backend test:e2e:post-review

Requires Supabase E2E env (same as other backend e2e suites). See backend/tests/e2e/post.review.e2e.test.ts.

Deployment

For a full production sequence, use Production deployment. The commands below are quick references from the repository root .

Backend JS bundle — runs tsup in backend/ to produce the bundled API output used for deploys.

pnpm --filter ./backend build:js

Deploy backend to Vercel — invokes the Vercel CLI with backend/ as the working directory.

pnpm vercel:deploy:backend

Deploy web to Vercel — invokes the Vercel CLI with web/ as the working directory.

pnpm vercel:deploy:web

Next Steps

Search documentation
Find a docs page
Discord Support