### Install Bun with curl
Source: https://guren.dev/docs/guides/getting-started
Installs Bun 1.1 or later, the only prerequisite for the quickstart. Run this in a terminal on macOS, Linux, or Windows with WSL2.
```bash
curl -fsSL https://bun.sh/install | bash
```
--------------------------------
### queue:work command example
Source: https://guren.dev/docs/guides/cli
Example of starting the queue worker with the `queue:work` command.
```bash
bunx guren queue:work
```
--------------------------------
### agent:init example
Source: https://guren.dev/docs/guides/cli
Example of the agent:init command targeting codex and cursor agents. Installs the agent harness for the selected agents into an existing app, skipping files that already exist unless --force is used.
```bash
bunx guren agent:init --target codex,cursor
```
--------------------------------
### Scaffold and run a new Guren app with bunx create-guren-app
Source: https://guren.dev/docs/guides/overview
Run these four commands in order to scaffold a new Guren app with the default prompts (SSR and SQLite), move into the project directory, install dependencies (usually a no-op because the scaffolder already installed them), and start the development server. Afterward, open http://localhost:3333 to see the running app.
```bash
bunx create-guren-app my-app # scaffold — accept the default prompts (SSR, SQLite)
```
```bash
cd my-app
```
```bash
bun install # usually a no-op: the scaffolder installs for you
```
```bash
bun run dev # start the dev server
```
--------------------------------
### Install prototype mode with bunx guren add prototype or scaffold with create-guren-app --prototype
Source: https://guren.dev/docs/guides/prototype-first
Install the prototype fixture into an existing project, or scaffold a new app with prototype mode enabled from the start. The first command writes the fixture module, adds two scripts to package.json, and wires two options; the second creates a new app with the prototype setup included.
```bash
bunx guren add prototype
```
```bash
bunx create-guren-app my-app --prototype
```
--------------------------------
### Manual auth setup with bunx guren make:auth
Source: https://guren.dev/docs/guides/authentication
Manually sets up auth without the --install flag. Then register AuthProvider in src/app.ts, add createSessionMiddleware to your middleware stack (auto-added by AuthServiceProvider unless you opt out), and register registerAuthRoutes(router) from routes/web.ts. The --install flag is safe and idempotent.
```bash
bunx guren make:auth
```
--------------------------------
### Start the dev server with bun run dev
Source: https://guren.dev/docs/guides/build-auth-app
Starts the development server. Visit http://localhost:3333/register to create an account, then http://localhost:3333/login to sign in.
```bash
bun run dev
```
--------------------------------
### Start the database with bun run db:up
Source: https://guren.dev/docs/guides/build-auth-app
Starts the Postgres database using Docker Compose.
```bash
bun run db:up
```
--------------------------------
### systemd unit for Guren application
Source: https://guren.dev/docs/guides/deployment
Example systemd unit to run the Bun server as a service. Reload systemd, enable, and start with 'sudo systemctl enable --now my-app'.
```ini
[Unit]
Description=Guren Application
After=network.target
[Service]
EnvironmentFile=/etc/guren/my-app.env
WorkingDirectory=/var/www/my-app
ExecStart=/usr/local/bin/bun run bin/serve.ts
Restart=always
[Install]
WantedBy=multi-user.target
```
--------------------------------
### Install @guren/plugin-mcp with bun
Source: https://guren.dev/docs/guides/agent-interface
Install and register the @guren/plugin-mcp package. The first command runs the plugin installer, the second adds it as a dependency.
```bash
bunx guren plugin @guren/plugin-mcp
bun add @guren/plugin-mcp
```
--------------------------------
### Install @guren/plugin-markdown with bun
Source: https://guren.dev/docs/guides/markdown
Install the plugin with bunx and add it as a dependency. Run these commands in your project root.
```bash
bunx guren plugin @guren/plugin-markdown
bun add @guren/plugin-markdown
```
--------------------------------
### queue:work options examples
Source: https://guren.dev/docs/guides/cli
Examples showing how to use the `queue:work` command with various options: `--queue`, `--max-jobs`, and `--stop-when-empty`.
```bash
# Process jobs from default queue
bunx guren queue:work
# Process specific queue
bunx guren queue:work --queue emails
# Limit number of jobs
bunx guren queue:work --max-jobs 100
# Stop when queue is empty
bunx guren queue:work --stop-when-empty
```
--------------------------------
### bunx guren --help
Source: https://guren.dev/docs/guides/cli
Shows CLI help. Run from project root; no global install required.
```bash
bunx guren --help
```
--------------------------------
### Running the Scheduler: Configure and start in app bootstrap
Source: https://guren.dev/docs/guides/scheduling
Shows how to configure the Scheduler with timezone, check interval, and logger, define a simple every-minute task, start it on app boot, and stop it on SIGTERM.
```TypeScript
// app.ts
import { Scheduler } from '@guren/core'
const scheduler = new Scheduler({
timezone: 'Asia/Tokyo',
checkInterval: 60000, // Check every 60 seconds
logger: console.log,
})
// Define schedules
scheduler.schedule((schedule) => {
schedule.call(() => console.log('Hello!')).everyMinute()
})
// Start when app boots
scheduler.start()
// Stop on shutdown
process.on('SIGTERM', () => {
scheduler.stop()
})
```
--------------------------------
### Start Bun server directly
Source: https://guren.dev/docs/guides/deployment
Starts the Bun server in production. Wrap with a process manager for reliability.
```bash
NODE_ENV=production bun run bin/serve.ts
```
--------------------------------
### Install the attachments layer
Source: https://guren.dev/docs/tutorials/10-files
Installs the attachments layer, adding storage providers, the attachments table, configuration, and the delivery route.
```bash
bunx guren add attachments
```
--------------------------------
### Scaffold authentication with bunx guren make:auth
Source: https://guren.dev/docs/guides/authentication
Scaffold the authentication stack with the CLI. The first command generates the full auth flow and installs dependencies; the second runs migrations, seeds, and starts the dev server. Use --minimal to skip registration and password reset, or --verify to add email verification.
```bash
bunx guren make:auth --install
```
```bash
bun run db:migrate
bun run db:seed
bun run dev
```
```bash
bunx guren make:auth --install --minimal
```
```bash
bunx guren make:auth --install --verify
```
--------------------------------
### Full Configuration Example
Source: https://guren.dev/docs/guides/rate-limiting
Complete example using MemoryRateLimitStore with custom keyGenerator, skip, and onRateLimited. Key is based on authenticated user ID or forwarded IP, skips admin users, and returns a custom JSON response with retryAfter.
```TypeScript
import { createRateLimitMiddleware, MemoryRateLimitStore } from '@guren/core'
const store = new MemoryRateLimitStore()
const rateLimiter = createRateLimitMiddleware({
limit: 100,
windowMs: 60 * 1000, // 1 minute
store,
keyPrefix: 'api:',
headers: true,
message: 'Rate limit exceeded. Please slow down.',
statusCode: 429,
// Key based on authenticated user or IP
keyGenerator: async (ctx) => {
const user = ctx.get('user')
if (user?.id) {
return `user:${user.id}`
}
return ctx.req.header('x-forwarded-for')?.split(',')[0] ?? 'unknown'
},
// Skip for admin users
skip: async (ctx) => {
const user = ctx.get('user')
return user?.role === 'admin'
},
// Custom response
onRateLimited: (ctx, retryAfter) => {
return ctx.json({
error: 'Too many requests',
retryAfter,
documentation: 'https://api.example.com/docs/rate-limits',
}, 429)
},
})
```
--------------------------------
### Install plugin with bunx guren plugin
Source: https://guren.dev/docs/guides/plugins
Install a plugin via the Guren CLI. The `plugin` command installs the package with `bun add` when missing (use `--no-install` to skip), verifies compatibility (`--ignore-compatibility` to bypass), adds the provider import, registers it in `createApp({ providers })`, and applies `env` and `publishes` entries from the plugin's `gurenPlugin` manifest. `--force` overwrites already-published files.
```bash
bunx guren plugin @guren/plugin-vercel
```
--------------------------------
### Install @guren/plugin-cloudflare
Source: https://guren.dev/docs/guides/cloudflare
Installs the Cloudflare plugin and registers the `cloudflare:build` command. The plugin also scaffolds `wrangler.jsonc` on the first build.
```bash
bunx guren plugin @guren/plugin-cloudflare
bun add @guren/plugin-cloudflare
```
--------------------------------
### Install and generate OpenAPI document
Source: https://guren.dev/docs/guides/routing
Installs the optional @guren/openapi package and generates an OpenAPI 3.1 JSON document to .guren/openapi.gen.json from route definitions.
```bash
bun add @guren/openapi
bunx guren openapi:generate
```
--------------------------------
### Launch the Guren interactive console
Source: https://guren.dev/docs/guides/cli
Starts the framework-aware REPL, booting the application and preloading globals like `app`, `auth`, and models. Use `:help` for shortcuts and `:editor` for multiline input.
```bash
bunx guren console
```
--------------------------------
### Dockerfile for production deployment with Bun
Source: https://guren.dev/docs/guides/deploy-production
Multi-stage Dockerfile for a Bun-based Guren application. It installs production dependencies, builds the app, and creates a minimal production image that runs the start command. The production image copies node_modules, dist, public, and package.json from the build stages.
```dockerfile
FROM oven/bun:1 AS base
WORKDIR /app
# Install dependencies
FROM base AS deps
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile --production
# Build the application
FROM base AS build
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun run build
# Production image
FROM base AS production
COPY --from=deps /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY --from=build /app/public ./public
COPY --from=build /app/package.json ./
ENV APP_ENV=production
ENV PORT=3333
EXPOSE 3333
CMD ["bun", "run", "start"]
```
--------------------------------
### Quick Start: Configure StorageManager and perform basic file operations
Source: https://guren.dev/docs/guides/storage
Sets up a StorageManager with a local disk and demonstrates storing, retrieving, checking existence, and deleting a file.
```TypeScript
import { StorageManager } from '@guren/core'
const storage = new StorageManager({
default: 'local',
disks: {
local: {
driver: 'local',
root: './storage/app',
url: '/storage',
},
},
})
// Store a file
await storage.disk().put('avatars/user-1.jpg', imageBuffer)
// Retrieve a file
const content = await storage.disk().get('avatars/user-1.jpg')
// Check if file exists
const exists = await storage.disk().exists('avatars/user-1.jpg')
// Delete a file
await storage.disk().delete('avatars/user-1.jpg')
```
--------------------------------
### Install and register guren-plugin-analytics
Source: https://guren.dev/docs/guides/plugins
Install the plugin with bun, then register it in the app's providers array. The plugin requires an API key and endpoint, which can be read from environment variables.
```bash
bun add guren-plugin-analytics
```
```typescript
// src/app.ts
import { createApp } from '@guren/core'
import { analyticsPlugin } from 'guren-plugin-analytics'
import { registerWebRoutes } from '@/routes/web'
export const app = createApp({
routes: registerWebRoutes,
providers: [
analyticsPlugin({
apiKey: process.env.ANALYTICS_API_KEY!,
endpoint: 'https://analytics.example.com',
}),
],
})
```
--------------------------------
### Install prototype mode with bunx guren add prototype
Source: https://guren.dev/docs/tutorials/15-prototype-first
Run from your project root to install prototype mode. Writes one fixture file and patches three (resources/js/app.tsx, src/app.ts, package.json). None of the prototype code reaches a production bundle.
```bash
bunx guren add prototype
```
--------------------------------
### Install AWS SDK for DynamoDB
Source: https://guren.dev/docs/guides/serverless
Install the AWS SDK for DynamoDB to use the DynamoDB session driver provided by @guren/plugin-lambda.
```bash
bun add @aws-sdk/client-dynamodb
```
--------------------------------
### Install and deploy with @guren/plugin-vercel
Source: https://guren.dev/docs/guides/deployment
Install the Vercel plugin and scaffold the required files, then build and deploy the SSR app. The plugin targets SSR apps only; API-only apps should use Docker or Lambda instead.
```bash
bunx guren plugin @guren/plugin-vercel
bun add @guren/plugin-vercel
```
```bash
bun run vercel:build
vercel deploy --prebuilt
```
--------------------------------
### agent:sync example
Source: https://guren.dev/docs/guides/cli
Example of the agent:sync command. Refreshes framework-managed files (rules, skills, subagents, hooks) for every agent detected on disk, without overwriting user-owned files.
```bash
bunx guren agent:sync
```
--------------------------------
### Generate production Dockerfile with bunx guren deploy
Source: https://guren.dev/docs/tutorials/01-zero-to-deployed
Generates a production Dockerfile for the Guren app. The generated Dockerfile is a two-stage build: the first stage installs everything and runs `bun run build`; the second copies only runtime directories (`bin/`, `src/`, `app/`, `config/`, `routes/`, `public/`, `db/`, `.guren/`) into a slim image and starts `bun bin/serve.ts` with `NODE_ENV=production`.
```bash
bunx guren deploy --target docker
```
--------------------------------
### Install production dependencies with Bun
Source: https://guren.dev/docs/guides/deployment
Install only runtime dependencies on the deployment host. Omit --production if your environment builds assets during deployment and needs dev tooling.
```bash
bun install --production
```
--------------------------------
### Manual queue manager setup
Source: https://guren.dev/docs/guides/queue
Creates a queue manager with a memory driver and accesses the default driver.
```ts
import { createQueueManager, MemoryDriver } from '@guren/core'
const queue = createQueueManager({
default: 'memory',
drivers: {
memory: () => new MemoryDriver(),
},
})
queue.driver()
```
--------------------------------
### Quick Start: Schedule a daily callback
Source: https://guren.dev/docs/guides/scheduling
Creates a Scheduler instance and schedules a callback to run daily at 3 AM. The schedule is defined using the fluent API and the scheduler is started immediately.
```TypeScript
import { Scheduler } from '@guren/core'
const scheduler = new Scheduler()
scheduler.schedule((schedule) => {
// Run a callback every day at 3 AM
schedule.call(async () => {
await cleanupOldSessions()
}).daily().at('03:00').name('cleanup-sessions')
})
scheduler.start()
```
--------------------------------
### Install Guren Lambda plugin
Source: https://guren.dev/docs/guides/deployment
Installs and registers the official AWS Lambda plugin. The CLI scaffolds src/lambda.ts (whose exports become Lambda handlers) and registers a lambda:build command.
```bash
bunx guren plugin @guren/plugin-lambda
bun add @guren/plugin-lambda
```
--------------------------------
### Create a new plugin package with bun init
Source: https://guren.dev/docs/guides/plugins
Initializes a new npm package for a Guren plugin. Run these commands in a terminal to create the directory and start a new project.
```bash
mkdir guren-plugin-analytics
cd guren-plugin-analytics
bun init
```
--------------------------------
### Run test suite commands
Source: https://guren.dev/docs/guides/testing
Commands to run the full test suite, framework packages with Bun's test runner, example apps with Vitest, a single test file, and generate a test file. Framework packages use bun:test, while example apps and React components use Vitest with jsdom.
```bash
# Full test suite
bun run test
# Framework packages (Bun test runner)
bun run test:bun
# Example apps (Vitest)
bun run test:examples
# Single file
bun test path/to/file.test.ts
# Generate a test file
bunx guren make:test posts/PostController --runner bun
```
--------------------------------
### Install Guren agent skills from catalog
Source: https://guren.dev/docs/guides/cli
Commands to install the Guren on-ramp skills from the gurenjs/agent-skills repository. Use the Claude Code plugin commands for Claude Code, and the Agent Skills CLI for other clients. Install at user scope to avoid writing into a project repository.
```bash
# Claude Code
claude plugin marketplace add gurenjs/agent-skills
claude plugin install guren@gurenjs --scope user
# Cursor, Codex, Copilot, OpenCode, Gemini CLI and others (Agent Skills CLI)
npx skills add gurenjs/agent-skills
```
--------------------------------
### Install @guren/plugin-agents and @guren/plugin-cloudflare with bun
Source: https://guren.dev/docs/guides/durable-agents
Use this command to install the agents and cloudflare plugins. The package must be in dependencies, not devDependencies, because the generated worker imports it and wrangler resolves it at deploy time. The guren cloudflare:build command refuses an app that hosts agents and only depends on it for development.
```bash
bun add @guren/plugin-agents @guren/plugin-cloudflare
```
--------------------------------
### Create Encrypter with generateKey
Source: https://guren.dev/docs/guides/encryption
Shows how to generate a 32-byte key and create an Encrypter instance. Includes an example with key rotation support using previousKeys.
```typescript
import { Encrypter, generateKey } from '@guren/core'
// Generate a new key
const key = generateKey()
console.log(key) // base64:... (32-byte key)
// Create encrypter
const encrypter = new Encrypter({ key })
// With key rotation support
const rotatedEncrypter = new Encrypter({
key: newKey,
previousKeys: [oldKey],
})
```
--------------------------------
### Deploy with docker compose -f docker-compose.production.yml up -d
Source: https://guren.dev/docs/guides/deploy-production
Starts the production stack defined in `docker-compose.production.yml` in detached mode.
```bash
docker compose -f docker-compose.production.yml up -d
```
--------------------------------
### Sliding Window Store Setup
Source: https://guren.dev/docs/guides/rate-limiting
Uses a sliding window store for smoother rate limiting.
```ts
import { SlidingWindowRateLimitStore } from '@guren/core'
const store = new SlidingWindowRateLimitStore()
const rateLimiter = createRateLimitMiddleware({
limit: 100,
windowMs: 60 * 1000,
store,
})
```
--------------------------------
### Redis Store Setup
Source: https://guren.dev/docs/guides/rate-limiting
Configures Redis-backed rate limit stores for distributed applications.
```ts
import { createRateLimitMiddleware } from '@guren/core'
import { createRedisClient, RedisRateLimitStore, RedisSlidingWindowRateLimitStore } from '@guren/core/redis'
const redis = createRedisClient({ url: process.env.REDIS_URL })
const limiter = createRateLimitMiddleware({
max: 60,
windowMs: 60_000,
store: new RedisRateLimitStore(redis),
})
// Sliding-window variant for smoother limiting
const sliding = createRateLimitMiddleware({
max: 60,
windowMs: 60_000,
store: new RedisSlidingWindowRateLimitStore(redis),
})
```
--------------------------------
### Setup NotificationManager with channels
Source: https://guren.dev/docs/guides/notifications
Imports NotificationManager, MailChannel, and DatabaseChannel from '@guren/core', creates a NotificationManager instance, and registers 'mail' and 'database' channels.
```typescript
import {
NotificationManager,
MailChannel,
DatabaseChannel,
} from '@guren/core'
const notifications = new NotificationManager()
// Register channels
notifications
.registerChannel('mail', new MailChannel(mailManager))
.registerChannel('database', new DatabaseChannel())
```
--------------------------------
### Register GitHub OAuth routes
Source: https://guren.dev/docs/guides/oauth
Registers the GitHub OAuth routes: GET /auth/github maps to the start action and GET /auth/github/callback maps to the callback action.
```ts
import { Router } from '@guren/core'
import GitHubOAuthController from '@/app/Http/Controllers/Auth/GitHubOAuthController'
export function registerWebRoutes(router: Router): void {
router.get('/auth/github', [GitHubOAuthController, 'start'])
router.get('/auth/github/callback', [GitHubOAuthController, 'callback'])
}
```
--------------------------------
### Memory Store Setup
Source: https://guren.dev/docs/guides/rate-limiting
Configures a memory-based rate limit store with cleanup on shutdown.
```ts
import { MemoryRateLimitStore } from '@guren/core'
const store = new MemoryRateLimitStore(60000) // Cleanup every 60 seconds
const rateLimiter = createRateLimitMiddleware({
limit: 100,
store,
})
// Cleanup on shutdown
process.on('SIGTERM', () => {
store.destroy()
})
```
--------------------------------
### Programmatic worker setup
Source: https://guren.dev/docs/guides/queue
Creates a worker programmatically with custom queues, settings, and event handlers, then starts and stops it.
```ts
import { Worker, MemoryDriver, createQueueManager, registerJob } from '@guren/core'
import { SendWelcomeEmailJob } from '@/app/Jobs/SendWelcomeEmailJob'
// Setup
const queue = createQueueManager({
default: 'memory',
drivers: {
memory: () => new MemoryDriver(),
},
})
const driver = queue.driver()
// Register job classes (required for worker to find them)
registerJob(SendWelcomeEmailJob)
// Create and start worker
const worker = new Worker(driver, {
queues: ['high-priority', 'default', 'emails'],
sleep: 1000,
timeout: 60000,
maxJobs: 0, // 0 = unlimited
stopWhenEmpty: false,
}, {
// Optional event handlers
jobProcessed: (job) => console.log(`Processed: ${job.name}`),
jobFailed: (job, error, willRetry) => {
console.error(`Failed: ${job.name}`, error.message, willRetry ? '(will retry)' : '')
},
workerStarted: () => console.log('Worker started'),
workerStopped: () => console.log('Worker stopped'),
})
// Start processing
await worker.start()
// Graceful shutdown (waits for current job)
await worker.stop()
```
--------------------------------
### Change into the app directory
Source: https://guren.dev/docs/tutorials/01-zero-to-deployed
Step into the newly scaffolded app directory to continue with the tutorial.
```bash
cd guren-blog
```
--------------------------------
### bunx guren add commands for standard scaffolds
Source: https://guren.dev/docs/guides/cli
High-level scaffolds for common features. The golden path starts with auth and resource, then adds more as the app grows.
```bash
bunx guren add auth
bunx guren add admin
bunx guren add resource posts --fields "title:string,body:text,published:boolean"
bunx guren add queue
bunx guren add mail
bunx guren add events
bunx guren add cache
bunx guren add notifications
bunx guren add storage
bunx guren add attachments
bunx guren add session
bunx guren add broadcasting
bunx guren add schedule
bunx guren add lint
bunx guren add prototype
```
--------------------------------
### Scaffold an API project with create-guren-app
Source: https://guren.dev/docs/guides/ship-api
Scaffolds a new Guren API-only project named my-api with the api blueprint and Postgres database, then installs dependencies.
```bash
bunx create-guren-app my-api --blueprint api --db postgres
cd my-api
bun install
```
--------------------------------
### Test Endpoints with curl
Source: https://guren.dev/docs/guides/ship-api
Example curl commands for CRUD operations on the /api/tasks endpoint. Use these to create, list, show, update, and delete tasks after starting the dev server.
```bash
# Create a task
curl -X POST http://localhost:3333/api/tasks \
-H "Content-Type: application/json" \
-d '{"title": "Write docs"}'
# List tasks
curl http://localhost:3333/api/tasks
# Show a task
curl http://localhost:3333/api/tasks/1
# Update a task
curl -X PUT http://localhost:3333/api/tasks/1 \
-H "Content-Type: application/json" \
-d '{"completed": true}'
# Delete a task
curl -X DELETE http://localhost:3333/api/tasks/1
```
--------------------------------
### Example Response Headers
Source: https://guren.dev/docs/guides/rate-limiting
Shows the rate limit headers returned when the limit is exceeded.
```http
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1705312800
```
--------------------------------
### Quick Start with LogManager facade
Source: https://guren.dev/docs/guides/logging
Use app.container.make('log') to resolve the default logger. Supports info, error, and channel-specific logging.
```ts
// Resolve the logger from the container
const Log = app.container.make('log')
Log.info('Application started')
Log.error('Something went wrong', { error: 'Connection failed' })
Log.channel('daily').warning('Disk space low')
```
--------------------------------
### Running commands with bun run console
Source: https://guren.dev/docs/guides/console
Scaffolded apps expose the console as a `console` script. Examples show running a custom command and a command with arguments and options.
```bash
bun run console send-digest
bun run console users:create ada@example.com --admin
```
--------------------------------
### Create Cache Facades from Container
Source: https://guren.dev/docs/guides/cache
Creates cache facades from an application container, enabling direct access to cache operations without passing a manager. Use this when you have an app container and want a convenient global cache interface. The example shows setting, getting, checking, and deleting a value with a TTL of 3600 seconds.
```ts
import { createFacades } from '@guren/core'
const { Cache } = createFacades(app.container)
// Store a value (TTL in seconds)
await Cache.store().set('user:1', { name: 'John' }, 3600)
// Retrieve a value
const user = await Cache.store().get<{ name: string }>('user:1')
// Check if key exists
const exists = await Cache.store().has('user:1')
// Delete a value
await Cache.store().delete('user:1')
```
--------------------------------
### Create app and listen with port fallback
Source: https://guren.dev/docs/guides/architecture
Bootstraps the application by creating the app instance with routes and providers, then starts the HTTP server. The listen() call resolves to the actual bound address, which may differ from the requested port (e.g., when port 0 is used or a busy port triggers fallback). Read the returned port rather than assuming the requested one.
```ts
const app = createApp({
routes: registerWebRoutes,
providers: [DatabaseProvider, AuthProvider, EventServiceProvider],
})
```
```ts
const { url, port } = await app.listen({ port: 3333 })
console.log(`listening on ${url}`) // the port that is actually bound
```
--------------------------------
### Production build and preview with bun run build and bun run preview
Source: https://guren.dev/docs/guides/getting-started
Builds the production bundle (emitting hashed client and server assets under public/assets/ plus manifests) and starts the production server locally to verify the build.
```bash
bun run build
bun run preview
```
--------------------------------
### Install React Email dependencies
Source: https://guren.dev/docs/guides/mail
Install the required packages for using React Email with Guren.
```bash
bun add @react-email/render react
```
--------------------------------
### Install AWS SDK for Data API
Source: https://guren.dev/docs/guides/database
Adds the required driver package for the AWS Data API adapter. Run this when using the Aurora Serverless adapter.
```bash
bun add @aws-sdk/client-rds-data
```
--------------------------------
### Manual boot and fromFetch alternative
Source: https://guren.dev/docs/guides/testing
Shows the longer form of booting and using fromFetch. The arrow function is required because fetch reads instance state; unbound app.fetch throws.
```ts
await app.boot()
http = TestApp.fromFetch((request) => app.fetch(request))
```
--------------------------------
### Scaffold a new Guren app with create-guren-app
Source: https://guren.dev/docs/guides/build-auth-app
Scaffolds a new Guren application named my-auth-app with SSR mode and Postgres database, then installs dependencies.
```bash
bunx create-guren-app my-auth-app --mode ssr --db postgres
cd my-auth-app
bun install
```
--------------------------------
### Apply D1 migrations and run wrangler dev
Source: https://guren.dev/docs/guides/cloudflare
Run these commands to apply local D1 migrations and start the wrangler dev server. This catches runtime differences that a Bun dev server cannot.
```bash
bunx wrangler d1 migrations apply my-app --local
bunx wrangler dev
```
--------------------------------
### Show what prototyping changed: git status --short
Source: https://guren.dev/docs/tutorials/15-prototype-first
Typical next step after installing prototype mode. It lists the new resources/js/prototype/index.ts fixture and the three patched files.
```bash
git status --short
```
--------------------------------
### Set up shiki code highlighting
Source: https://guren.dev/docs/guides/markdown
Install shiki as an optional peer dependency and configure it for code highlighting. Builds a fine-grained shiki/core highlighter with only the listed grammars and emits dual-theme output. Fences in unloaded languages fall back to plain text instead of throwing.
```bash
bun add shiki
```
```ts
import { createMarkdownRenderer } from '@guren/plugin-markdown'
import { createShikiHighlight } from '@guren/plugin-markdown/shiki'
const renderer = createMarkdownRenderer({
highlight: createShikiHighlight({
themes: { light: 'github-light', dark: 'github-dark' },
langs: ['typescript', 'tsx', 'bash', 'json'],
}),
})
```
--------------------------------
### Log levels RFC 5424 example
Source: https://guren.dev/docs/guides/logging
Examples of all severity levels from emergency to debug, with warning also available as warn().
```ts
log.emergency('System is unusable')
log.alert('Action must be taken immediately')
log.critical('Critical conditions')
log.error('Error conditions')
log.warning('Warning conditions') // or log.warn()
log.notice('Normal but significant conditions')
log.info('Informational messages')
log.debug('Debug-level messages')
```
--------------------------------
### Scaffold a Guren app with create-guren-app
Source: https://guren.dev/docs/tutorials/01-zero-to-deployed
Run this command to scaffold a new Guren app named guren-blog with SSR mode, SQLite database, Claude agent harness, and Git initialization. The --mode ssr flag renders pages on the server first; --db sqlite creates a file under ./data/ on first open; --agents claude installs the harness for Claude Code; --git initializes a repository and makes the first commit.
```bash
bunx create-guren-app guren-blog --mode ssr --db sqlite --agents claude --git
```
--------------------------------
### Wrap real application with TestApp.fromApp
Source: https://guren.dev/docs/guides/testing
Boots the actual app exported from src/app.js, exercising real configuration. fromApp() is idempotent and reuses the first boot.
```ts
import { TestApp } from '@guren/testing'
import app from '../src/app.js'
let http: TestApp
beforeAll(async () => {
http = await TestApp.fromApp(app)
})
test('serves the home page', async () => {
await http.get('/').assertOk()
})
```
--------------------------------
### JSON log format example
Source: https://guren.dev/docs/guides/logging
Shows the JSON log format with structured fields. The example includes an info and an error log entry.
```json
{"timestamp":"2024-01-15T10:30:00.000Z","level":"info","message":"User logged in","userId":123,"ip":"192.168.1.1"}
{"timestamp":"2024-01-15T10:30:01.000Z","level":"error","message":"Database connection failed","error":"ECONNREFUSED"}
```
--------------------------------
### Russian plural forms example (lang/ru/messages.json)
Source: https://guren.dev/docs/guides/i18n
JSON example for a language with three plural forms (one, few, many). Forms are listed in rule order.
```json
// lang/ru/messages.json — one | few | many
{
"apple": "яблоко|яблока|яблок"
}
```
--------------------------------
### Text log format example
Source: https://guren.dev/docs/guides/logging
Shows the text log format with timestamp, level, message, and context. The example includes an INFO and an ERROR log line.
```text
[2024-01-15T10:30:00.000Z] INFO User logged in {"userId":123,"ip":"192.168.1.1"}
[2024-01-15T10:30:01.000Z] ERROR Database connection failed {"error":"ECONNREFUSED"}
```
--------------------------------
### URLs: Get public URL and temporary signed URL
Source: https://guren.dev/docs/guides/storage
Shows how to get a public URL for a file and a temporary signed URL (S3 only) with an expiration date.
```TypeScript
const disk = storage.disk()
// Get public URL
const url = disk.url('avatars/user-1.jpg')
// e.g., '/storage/avatars/user-1.jpg' (local)
// e.g., 'https://bucket.s3.region.amazonaws.com/avatars/user-1.jpg' (S3)
// Get temporary signed URL (S3 only)
const expiration = new Date(Date.now() + 3600 * 1000) // 1 hour
const signedUrl = await disk.temporaryUrl('private/report.pdf', expiration)
```
--------------------------------
### GitHub OAuth controller with start and callback actions
Source: https://guren.dev/docs/guides/oauth
Controller with start and callback actions for GitHub OAuth. The start action initiates authorization, passing the session to bind the flow to the browser. The callback validates the code and state, fetches the profile, finds or creates the user, logs them in, and redirects to the original redirect_to or '/dashboard'.
```ts
import { Controller } from '@guren/core'
import { z } from 'zod'
import { oauth } from '@/config/oauth'
import { User } from '@/app/Models/User'
const CallbackQuerySchema = z.object({
code: z.string(),
state: z.string(),
})
export default class GitHubOAuthController extends Controller {
async start() {
// Passing the session ties the flow to this browser — see
// "Binding State to the Browser" below.
const { url } = await oauth.authorize('github', {
redirectTo: this.query('redirect_to'),
session: this.auth.session(),
})
return this.redirect(url)
}
async callback() {
const { code, state } = this.validateQuery(CallbackQuerySchema)
const { profile, redirectTo } = await oauth.handleCallback('github', {
code,
state,
session: this.auth.session(),
})
let user = await User.where('githubId', profile.id).first()
if (!user) {
user = await User.create({ email: profile.email, name: profile.name, githubId: profile.id })
}
await this.auth.login(user)
return this.redirect(redirectTo ?? '/dashboard')
}
}
```
--------------------------------
### Update dependencies and regenerate artifacts with bun install and bunx guren codegen
Source: https://guren.dev/docs/guides/upgrading
Run these commands to install dependencies and regenerate code artifacts as part of the upgrade workflow.
```bash
bun install
bunx guren codegen
```
--------------------------------
### Call an agent tool with arguments, preflight, and user authentication
Source: https://guren.dev/docs/guides/cli
Shows how to invoke a tool with `bunx guren tool:call`, including passing arguments, using `--preflight` to stop before the handler, and authenticating as a user with `--as`.
```bash
# Call a tool with arguments
bunx guren tool:call posts.store --input '{"title":"Hello agents"}'
# Rehearse it: run the middleware and validate the contract, stop before the handler
bunx guren tool:call posts.store --input '{"title":"Hello"}' --preflight
# Call as a user, and read the result as JSON
bunx guren tool:call posts.index --as user:42 --json
```
--------------------------------
### Run specific checks and get single check result
Source: https://guren.dev/docs/guides/health-checks
Shows how to run only specific checks by name using checkOnly, and how to get a single check result with getCheck.
```typescript
// Run only specific checks
const report = await health.checkOnly(['database', 'redis'])
// Get a single check result
const dbResult = await health.getCheck('database')
```
--------------------------------
### Example translation file (lang/en/messages.json)
Source: https://guren.dev/docs/guides/i18n
Example JSON catalog with nested objects that become dot-notation keys. Dots in property names are not allowed and are reported by 'guren check --i18n'.
```json
// lang/en/messages.json
{
"hello": "Hello",
"user": {
"profile": "Profile",
"settings": "Settings"
}
}
```
--------------------------------
### Generate project guidelines with guren guidelines
Source: https://guren.dev/docs/tutorials/08-teach-the-agent
Generates project guidelines from the codebase and writes them to `.claude/rules/project-guidelines.md`. The file lists models, relationships, validators, policies, security rules, and feature steps, all derived from reading the app.
```bash
bunx guren guidelines -o .claude/rules/project-guidelines.md
```
--------------------------------
### Verify upgrade with bun run typecheck and test
Source: https://guren.dev/docs/guides/upgrading
Run these commands to verify the upgrade after applying migration notes.
```bash
bun run typecheck && bun run test
```
--------------------------------
### Add auth and resource with bunx guren add
Source: https://guren.dev/docs/guides/getting-started
Scaffolds authentication (registration, login, logout, session middleware) and a full resource (model, migration, controller, validator, resource, Inertia pages) for the given fields. Run `bunx guren add --help` for all generators.
```bash
bunx guren add auth
bunx guren add resource posts --fields "title:string,body:text,published:boolean"
```
--------------------------------
### Console entry point (bin/console.ts)
Source: https://guren.dev/docs/guides/console
Boots the application and hands `argv` to the kernel. `kernel.handle()` resolves to the exit code rather than terminating the process, making it testable.
```ts
import { ready } from '../src/main.js'
import { kernel } from '../src/console.js'
await ready
process.exit(await kernel.handle(process.argv.slice(2)))
```
--------------------------------
### Zod Schema Validation in a Controller
Source: https://guren.dev/docs/guides/controllers
Complete controller example using validateBody, validateQuery, and validateParams with Zod schemas. These helpers throw ValidationException (422) on failure, and the example shows handling pagination, finding records, and creating posts.
```typescript
import { Controller } from '@guren/core'
import { z } from 'zod'
import { Post } from '@/app/Models/Post'
const PostIdParamSchema = z.object({ id: z.coerce.number().int().positive() })
const StorePostSchema = z.object({ title: z.string().min(1), content: z.string().min(10) })
const PageQuerySchema = z.object({ page: z.coerce.number().int().min(1).default(1) })
export default class PostsController extends Controller {
async index() {
const { page } = this.validateQuery(PageQuerySchema) // throws 422
const result = await Post.paginate({ page, perPage: 10 })
const paginator = paginate(result, { path: this.request.path ?? '/posts' })
return this.inertia(pages.posts.Index, {
data: result.data.map((post) => new PostResource(post).toJSON()),
pagination: {
meta: paginator.meta(),
links: paginator.links(),
},
})
}
async show() {
const { id } = this.validateParams(PostIdParamSchema) // throws 422
const post = await Post.findOrFail(id) // throws 404
return this.inertia(pages.posts.Show, { post: new PostResource(post).toJSON() })
}
async store() {
const data = await this.validateBody(StorePostSchema) // throws 422
const user = await this.auth.userOrFail() // throws 401
const post = await Post.create({ ...data, authorId: user.id })
return this.redirect('/posts')
}
}
```
--------------------------------
### Attach file, inline content, and inline image
Source: https://guren.dev/docs/guides/mail
Three examples showing how to attach a file from a path, attach inline content with a content type, and attach an inline image using a CID reference in HTML.
```ts
// File attachment
await mail(mailManager)
.to('user@example.com')
.subject('Your Report')
.text('Please find your report attached.')
.attach({
filename: 'report.pdf',
path: './storage/reports/monthly.pdf',
})
.send()
// Inline content
await mail(mailManager)
.to('user@example.com')
.subject('Data Export')
.text('Your data export is ready.')
.attach({
filename: 'data.json',
content: JSON.stringify(exportData, null, 2),
contentType: 'application/json',
})
.send()
// Inline images (CID)
await mail(mailManager)
.to('user@example.com')
.subject('Newsletter')
.html('
Welcome!
') .attach({ filename: 'logo.png', path: './public/logo.png', cid: 'logo', }) .send() ``` -------------------------------- ### TestApp basic test suite with bun:test Source: https://guren.dev/docs/guides/testing Boots a lightweight TestApp instance and uses fluent assertions to test list, create, and 404 responses. Requires bun:test and @guren/testing. ```ts import { describe, test, beforeAll } from 'bun:test' import { TestApp } from '@guren/testing' describe('Posts', () => { let app: TestApp beforeAll(async () => { app = await TestApp.create() }) test('lists all posts', async () => { await app.get('/posts').assertOk() }) test('creates a post', async () => { await app .post('/posts', { title: 'Hello', content: 'World' }) .assertStatus(201) .assertJsonPath('post.title', 'Hello') }) test('returns 404 for missing post', async () => { await app.get('/posts/999').assertNotFound() }) }) ``` -------------------------------- ### Request flow diagram for GET /posts Source: https://guren.dev/docs/guides/first-steps Mermaid flowchart showing the order of layers a GET /posts request passes through: route, controller, validation, model, database, resource, and Inertia page. The diagram is provided as an overview before the step-by-step tour. ```mermaid flowchart TD Browser["Browser