Skip to main content

Tuturuuu SDK

Official TypeScript/JavaScript SDK for interacting with the Tuturuuu platform. Provides type-safe access to workspace storage, files, documents, and agent-friendly task workflows.

Installation

Quick Start

Features

Bun CLI

Use ttr for browser login, workspace discovery, and task workflows

Headless Login

Copy a short-lived CLI token from the browser when a local callback is not available

Storage Operations

Upload, download, list, and delete files and folders

Document Management

Create, read, update, and delete workspace documents

Signed URLs

Generate temporary shareable links for files

Image Resizing

Apply Supabase image transformations during share and download

Analytics

Track storage usage, file counts, and limits

CLI

The SDK package includes a native Bun-powered CLI. ttr is the primary command, and tuturuuu plus tutur3u are aliases for the same binary.
ttr login opens the browser and creates a Tuturuuu-managed CLI app-session JWT pair through apps/web. The terminal and browser confirmation page show the signed-in account email when the web session exposes it. The CLI stores that session and selected workspace, board, list, task, label, and project in the OS app config directory. personal is the default workspace after login and when no workspace has been selected: Use ttr host use to switch between Tuturuuu origins. production and prod resolve to https://tuturuuu.com; local and localhost prefer safe local environment URLs from TUTURUUU_LOCAL_BASE_URL, PORTLESS_URL, WEB_APP_URL, NEXT_PUBLIC_WEB_APP_URL, or NEXT_PUBLIC_APP_URL, then fall back to https://tuturuuu.localhost. Pass --port <port> for http://localhost:<port>, or --portless --port <port> for https://tuturuuu.localhost:<port>. Changing origins clears the saved session and selected workspace context because both are origin-specific. ttr config set-base-url <url> remains available for compatibility and uses the same host normalization and context-clearing behavior. The CLI normalizes 0.0.0.0 and unspecified IPv6 origins to localhost so the browser login flow does not open a blocked address. On Dockerized production deployments, the web auth start route also rewrites wildcard bind origins such as 0.0.0.0:7803 to the forwarded public host or the configured app URL (WEB_APP_URL, NEXT_PUBLIC_WEB_APP_URL, NEXT_PUBLIC_APP_URL, COOLIFY_URL, or COOLIFY_FQDN) before sending users to /login. If those environment values are unset and no public forwarded host is available, https://tuturuuu.com is the default fallback.
  • macOS: ~/Library/Application Support/Tuturuuu/config.json
  • Linux: $XDG_CONFIG_HOME/tuturuuu/config.json or ~/.config/tuturuuu/config.json
  • Windows: %APPDATA%\Tuturuuu\config.json
For headless agent environments, use copy-token mode:
Open the printed URL in an authenticated browser, copy the returned CLI token, and paste it into the terminal. Set TUTURUUU_CONFIG to use a custom config file, or use ttr host use <target> to target a local, production, or explicit URL origin. The CLI checks the npm registry at most once per hour and writes a notice to stderr when a newer tuturuuu version is available. This keeps --json output machine-readable for agents. Use ttr upgrade to run bun i -g tuturuuu. Use --no-update-check on a single command, or set TUTURUUU_DISABLE_UPDATE_CHECK=1, to disable the check. CLI sessions are dedicated Tuturuuu gateway JWTs, separate from normal browser and Supabase Auth sessions. The CLI stores a short-lived app-session access JWT plus a longer-lived refresh JWT, refreshes shortly before access-token expiry, updates the saved config with the rotated refresh token, and retries once after a 401 response. Refresh JWTs only carry the CLI refresh scope, so they cannot be used directly as API bearer tokens. If refresh fails because the user no longer exists or the refresh JWT has expired, run ttr login again. The SDK fetch wrapper must attach CLI bearer tokens, refresh sessions, and retry 401 responses only for relative Tuturuuu API paths or absolute URLs whose origin exactly matches the configured CLI base URL. Cross-origin absolute URLs must be delegated without Authorization headers. API routes used by ttr must accept the CLI app-session access JWT from the Authorization: Bearer ... header. For apps/web routes, prefer withSessionAuth with targetApp: 'platform' and requiredScope: 'cli:access' when the route is CLI-only; shared user profile routes can include the platform target alongside satellite app targets. Shared API routes should verify the CLI app-session token before falling back to Supabase session auth and then keep workspace membership checks explicit. When a handler lives in packages/apis and is reused by multiple apps, keep @tuturuuu/auth imports in the app-owned route wrapper and pass a pre-authenticated context into the shared handler so package builds do not form an auth/UI/API cycle. SDK version and changelog PRs are generated by .github/workflows/release-please.yaml from Conventional Commits on production. Release Please tracks the SDK in release-please-config.json as the sdk component, records the current version in .release-please-manifest.json, and updates packages/sdk/package.json in the combined monorepo release PR. SDK releases are then published automatically from .github/workflows/release-sdk-package.yaml when that version bump lands on production or when the release workflow itself changes. The same publish workflow can be dispatched manually to catch up a version that already landed on production. Manual dispatches from any other ref are rejected before dependency installation, packaging, or npm trusted publishing can run. The workflow runs the SDK tests, skips publication if the exact package version already exists on npm, waits for publishable Tuturuuu workspace dependencies to be visible on npm, prepares a tarball with npm pack outside the trusted-publish job, and then publishes that tarball through npm trusted publishing. Only the final publish-npm job requests id-token: write, so GitHub Actions mints the short-lived OIDC token after dependency installation, package builds, and version checks have already finished. That job downloads the prepared artifact, verifies its package name and version, confirms the bundled npm CLI supports trusted publishing, runs npm publish ./<tarball> --ignore-scripts, and polls npm view until the exact SDK version is visible without using an NPM_TOKEN. npm treats the downloaded artifact as a local file path. The job targets the GitHub environment sdk-release-production; keep that environment restricted to the production branch in repository settings, and keep the npm trusted publisher bound to the same environment name so a branch-selected workflow cannot mint a matching npm publish identity. Do not add bun install, npm install -g, package builds, package lifecycle scripts, or repository secrets to the SDK release workflow. Because the tuturuuu package is public and tutur3u/platform is a public repository, npm also generates and attaches build provenance attestations automatically. The package manifest inside the tarball must keep repository metadata aligned with the provenance repository: repository.url is https://github.com/tutur3u/platform, and repository.directory points at the package directory. .github/workflows/sdk-version-bump.yaml is retired and no longer generates patch-version PRs. Do not restore checksum or package-only bump automation for the SDK; release-please must remain the version/changelog source of truth. The SDK imports @tuturuuu/devbox, @tuturuuu/types, and @tuturuuu/internal-api through package exports that point at their git-ignored dist/ directories. The release workflow must build those workspace packages in the non-OIDC build and prepare jobs before running SDK tests or creating the npm pack tarball; otherwise a clean Actions checkout cannot resolve the SDK imports. The workflow then runs node scripts/ci/prepare-npm-package-manifest.js packages/sdk before npm pack so the published manifest contains concrete npm versions instead of local workspace: protocol ranges. Keep matching npm release workflows for the SDK runtime workspace dependencies so consumers can install the published SDK. When release-please bumps the SDK and one of those dependencies in the same production push, the SDK workflow waits for the dependency versions before it packs and publishes. If a dependency release workflow for the same SHA fails, the SDK wait fails immediately instead of waiting for npm visibility until timeout. The matching npm-side trusted publisher must stay configured at https://www.npmjs.com/package/tuturuuu/access with these exact values:
  • Provider: GitHub Actions
  • Organization or user: tutur3u
  • Repository: platform
  • Workflow filename: release-sdk-package.yaml
  • Environment name: sdk-release-production
If the npm-side configuration drifts (for example after a repo rename, missing first-publish setup, package access drift, or after moving the publish step into another workflow file), npm publish can fail with ENEEDAUTH, E404, or permission text. Update the npm package access or trusted publisher entry first; do not paper over the failure by reintroducing a long-lived NPM_TOKEN. After confirming a trusted-publisher release works end to end, the npm package settings should keep Require two-factor authentication and disallow tokens enabled so the package cannot be published with classic tokens.

Devbox Setup

Use ttr box setup on self-hosted runner machines before offloading expensive checks, Supabase workflows, or E2E suites. The command clones or reuses https://github.com/tutur3u/platform.git at ~/Documents/tuturuuu, runs bun install --frozen-lockfile, starts the local Supabase stack with bun sb:start, reads supabase status -o json, and upserts local Supabase connection values into ignored apps/*/.env.local files with secret values redacted from CLI output.
ttr box doctor stays read-only. Use ttr box setup --yes only when the host should install detected missing prerequisites through its package manager. Use ttr box repair --dir . after a CLI upgrade to repair an existing runner service without registering a new runner token.

Scoped Help

Use scoped help when you know the area but not the exact flags. Help commands do not require login, do not read the saved config, and do not run the update check.
Global help shows the command map. Group help explains defaults and shared flags. Action help focuses on a single operation, including required ids, payload flags, and practical examples.

Agent-Friendly Discovery

For autonomous engineering workflows, start by discovering the current account and selected context:
ttr whoami shows login state, account email, current workspace, selected board/list/task/label/project ids, base URL, config path, and the Tuturuuu CLI session label. Use --json --no-update-check when another agent is going to parse stdout. The v1 task surface covers workspaces, boards, lists, tasks, labels, projects, relationships, moves, and bulk task updates. Read-oriented groups list by default, so ttr tasks and ttr workspaces are equivalent to their explicit list forms. ttr boards shows active, unarchived boards by default; use ttr boards --archived, ttr boards --deleted, or ttr boards --all when an agent needs archived or deleted board inventory. Unscoped ttr tasks starts from the personal workspace and lists personal tasks plus open tasks assigned to the user in other accessible workspaces; selecting a board/list or passing --workspace scopes the result back to that context. ttr tasks shows open tasks by default by excluding rows with completed_at or closed_at and by limiting task-list statuses to not_started and active. That default hides tasks in documents, review, done, and closed lists, and tasks from archived boards; use --all, --include-archived, --documents, --review, --done, --closed, --include-documents, --include-review, --include-done, or --include-closed to adjust that filter. Results are paginated at 50 tasks by default; use --page/--page-size or --limit/--offset to page through larger task sets. Human-readable task lists show a footer with the total task count and current page/max page. Add --compact to task lists when an agent only needs the task title, task list name, and per-task workspace name. Task lists are ordered by priority and due date, with prettier due dates and configured task-list colors in table output. Human-readable tables use smooth box borders, respect the terminal width, and wrap long cell content so task titles stay readable instead of overflowing narrow panes. Add --json when another agent or script needs machine-readable output. Use ttr tasks search <query> for ranked task search. Search defaults to --mode hybrid, accepts --mode text for PostgreSQL full-text search only and --mode semantic for embedding similarity only, and supports --query/--q, --limit/--match-count, --threshold/--match-threshold, --workspace/--ws, --compact, and --json. Search output preserves API relevance order and shows the score when available. Existing list filtering with ttr tasks --q <query> is unchanged and remains the lightweight list text filter. tasks create, boards create, and lists create accept a quoted positional name as a shorthand for --name. Task CRUD accepts either the task UUID or the board identifier shown in the UI, such as VHP-12; prefixed identifiers resolve within the selected workspace even when another list is selected, and matching human-readable output keeps that prefixed identifier visible. Marking a task completed stamps completed_at so Tuturuuu moves it to the first done list; pass --list <done-list-id> or include list_id in --json-payload to choose another done destination. Use ttr tasks done [task-id] as the quick shortcut. Use ttr tasks close [task-id] to stamp closed_at; pass --list <closed-list-id> to choose a specific closed destination. Task templates are single-task starters, separate from board templates. Workspace templates are managed with ttr task-templates list/show/create/update/delete/use and can be imported from or exported to local markdown files. Local templates live under .tuturuuu/task-templates/*.md, use YAML frontmatter for fields such as key, name, task_name, priority, label_ids, assignee_ids, and project_ids, and use the markdown body as the task description. Markdown descriptions from --description-format markdown and local template bodies support GFM pipe tables and are stored as TipTap/Yjs table content for the web editor. ttr tasks create --template <key-or-path> resolves workspace keys or local markdown paths; explicit flags such as --name, --list, --priority, --labels, and --projects override template defaults.

Finance CLI

Finance commands use the selected workspace and the same authenticated internal APIs as the web app. Use --workspace or --ws to target a different workspace, and use --json-payload when a script needs to send fields that do not have dedicated flags yet. Finance list output is paginated by default; use --page/--page-size or --limit/--offset to move through larger result sets. Finance API routes that back ttr finance should resolve access through getFinanceRouteContext from @tuturuuu/apis/finance/request-access, with app-owned routes passing resolveFinanceRouteAuthContext(request) from apps/web/src/lib/finance-route-auth.ts when they need CLI app-session bearer token support. Keep CLI token verification in the app layer so @tuturuuu/apis does not depend on @tuturuuu/auth; getFinanceRouteContext still keeps the pre-authenticated actor, browser Supabase sessions, personal workspace resolution, and finance permission checks on the same path.

Calendar CLI

Calendar commands use the selected workspace and the same authenticated calendar APIs as the web app. Use --workspace or --ws to target a different workspace, and use --json when scripts need the raw structured response. Human output renders resource-specific tables for events, calendars, categories, accounts, provider calendars, connections, sources, and schedulable tasks. Event time input is exact ISO datetime only. events create requires --start and exactly one of --end or --duration-minutes; events update --duration-minutes also requires --start. Source flags map to provider payloads: use --source-provider tuturuuu --calendar <workspace-calendar-id> for workspace calendars, or --source-provider google|microsoft --connection <connection-id> for connected provider calendars. calendar calendars reset is destructive and requires --yes.
Common task workflows:
For terminal workflows, omit an id from use, get, update, delete, or move commands to pick a workspace, board, list, task, label, or project with the keyboard. The interactive picker shows one-based indexes, colored badges such as [FREE] Tuturuuu and [PRO] Personal, task-list color swatches, the selected row, and muted metadata. Use up/down or j/k to move, space/enter to select, and escape/q to cancel. Interactive selection is disabled for --json output. Picker labels, descriptions, badges, and color names derived from platform data must visibly escape terminal control characters before rendering. Use ttr -v or ttr --version to print the installed CLI version.

Client Initialization

Basic Usage

With Custom Configuration

Storage API

List Files

Lists files and folders in the workspace drive.

Upload File

Uploads a file to the workspace drive.

Download File

Downloads a file as a Blob.
Apply an image transform during download:

Delete Files

Deletes one or more files or folders.

Create Folder

Creates a new folder in the workspace drive.

Share File

Generates a signed URL for temporary file sharing.
Apply an image transform before generating the signed URL:

Get Analytics

Retrieves storage usage statistics for the workspace.

Documents API

List Documents

Lists documents in the workspace with optional filters.

Create Document

Creates a new document in the workspace.

Get Document

Retrieves a document by its ID.

Update Document

Updates an existing document.

Delete Document

Deletes a document permanently.

Search Documents

Searches documents by name (alias for list() with search).

CMS Delivery

The SDK also exposes the external-project delivery client that powers Tuturuuu CMS preview surfaces and branded external apps.
For the Yoola adapter, artworkCategories comes from the configured gallery taxonomy on singleton-sections/gallery (profile_data.categoryOptions) rather than being inferred from every artwork entry. External app admin dashboards can auto-create and bind the workspace studio before their first diff/apply when the workspace ID is configured and the app token has external-projects:* or manage scope:
Operators can use the authenticated CLI instead of app-local token scripts:

Public Folder Asset Sync

External apps can keep seed media in their local public/ folder and still publish it through Tuturuuu Drive. Mark each manifest asset with metadata.publicPath, metadata.localAssetPath, metadata.sourcePublicPath, or a relative sourceUrl.
The linker writes deterministic storage paths under external-projects/{adapter}/{collectionSlug}/{entrySlug}/{filename}. External apps can upload those assets through signed upload URLs, or through the external-project asset multipart route when they need the app server to stream the file with a server-owned bearer token. Production Supabase keys are not needed in external apps.

TanStack Query

For React apps, keep the SDK as the delivery boundary and TanStack Query as the cache owner:
In external Next.js apps, prefer hydrating the delivery query once near the root layout and deriving page-level view models from that shared cache instead of letting each route perform its own SDK fetch.

Error Handling

The SDK provides specific error classes for different scenarios:

Error Properties

All error classes include:
  • message - Human-readable error description
  • code - Machine-readable error code
  • statusCode - HTTP status code
  • name - Error class name

TypeScript Support

The SDK is fully typed with TypeScript:

API Key Management

Creating an API Key

  1. Log in to your Tuturuuu workspace
  2. Navigate to SettingsAPI Keys
  3. Click “Create API Key”
  4. Set a descriptive name
  5. Assign a Workspace Role (determines permissions)
  6. Optionally set an expiration date
  7. Copy the generated key (starts with ttr_)
  8. Store securely (you won’t see it again)

Best Practices

Never commit API keys to version control! Use environment variables or secret management services.

Permissions

API keys inherit permissions from their assigned Workspace Role. The role determines what operations the key can perform. Required Permissions: Note: Permissions are managed through workspace roles, not individual API keys. To modify what an API key can do, update its assigned role’s permissions in SettingsRoles.

Security Best Practices

CRITICAL: Never expose API keys in client-side code! API keys must remain server-side only.

❌ Insecure (NEVER do this)

Create server-side API routes that proxy SDK calls:
Then call from your client component:

Node.js/Express Backend

Serverless Functions (Netlify, Vercel, AWS Lambda)

Security Checklist

Always use the SDK in server-side contexts:
  • Next.js API Routes (App Router or Pages Router)
  • Node.js backend servers
  • Serverless functions
  • Server Components (React Server Components)
Store API keys in environment variables:
Never use NEXT_PUBLIC_ prefix for API keys!
Ensure secrets never get committed: gitignore # .gitignore .env.local .env*.local
This exposes the variable to the browser: bash # BAD - Exposed to client! NEXT_PUBLIC_TUTURUUU_API_KEY=ttr_key
Never import the SDK in files with 'use client' directive.
Never commit keys to version control:

Complete Example

See the external app example for a complete implementation showcasing:
  • ✅ Secure server-side API routes
  • ✅ File upload with progress
  • ✅ Storage analytics dashboard
  • ✅ Proper error handling
  • ✅ Environment variable configuration

Rate Limiting

The API enforces rate limits per API key to ensure fair usage and system stability:

Rate Limits by Operation

Rate Limit Headers

Every API response includes rate limit information in the headers:
  • X-RateLimit-Limit - Maximum requests allowed in the time window
  • X-RateLimit-Remaining - Number of requests remaining in current window
  • X-RateLimit-Reset - Unix timestamp when the rate limit resets

Handling Rate Limits

When you exceed the rate limit, the API returns a 429 Too Many Requests response:

Workspace-Specific Rate Limits

Workspace administrators can configure custom rate limits for their workspace through Workspace Secrets. These override the default limits for all API keys in that workspace. To set custom rate limits:
  1. Navigate to SettingsWorkspace SettingsSecrets
  2. Add one or more of these secrets:
Example Configuration:
This configuration allows 500 requests per minute for all API keys in the workspace, instead of the default 100.
Workspace-specific rate limits only apply to operations that don’t have explicit per-operation limits. For operations like uploads and downloads, the operation-specific limits still apply.

Best Practices

Implement exponential backoff when handling rate limits to avoid hammering the API with retries.
Monitor rate limit headers to track your usage and avoid hitting limits:

Examples

Basic Usage

Complete example of all SDK operations

Error Handling

Comprehensive error handling patterns

Support

GitHub

Source code and issues

Discord

Community support

Docs

Full documentation

Changelog

The package version is managed by Release Please, and the full, authoritative changelog is generated per release. For the complete history (currently shipping the 0.10.x line), see the maintained changelog rather than this page:

CHANGELOG.md

Full per-release changelog (source of truth)

npm

Published versions and release tags
Highlights since the initial release:
  • Storage operations (list, upload, download, delete, folders, share, analytics)
  • Document operations (CRUD, search)
  • ttr CLI with workspace, host switching, and session-based auth
  • Finance commands (wallets, transactions, transfers, tags, wallet checkpoints)
  • Calendar commands
  • External projects support and remote devbox tooling
  • Comprehensive error handling, full TypeScript types, and Zod validation
Do not treat any version number quoted in this page as exact — the SDK is on a fast release cadence. Always check the linked changelog or npm for the current version.

License

MIT