一键导入
kagaribi-development
Create packages, generate models, and develop Kagaribi applications locally
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Create packages, generate models, and develop Kagaribi applications locally
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | kagaribi-development |
| description | Create packages, generate models, and develop Kagaribi applications locally |
Guide Claude through package creation, model generation, local development, and inter-package communication.
Kagaribi is designed as a framework for the AI coding agent era.
Context Minimization
Separation of Concerns
Type Safety
getClient<T>()Each package is independent in these aspects:
ABSOLUTE RULE: .ts files MUST NOT contain HTML template literals. ALWAYS use .tsx files with React/JSX components for views.
❌ ABSOLUTELY FORBIDDEN:
// ❌ NEVER DO THIS - HTML template literals in .ts files
import { html } from 'hono/html';
app.get('/', (c) => {
return c.html(html`<html><body>...</body></html>`);
});
// ❌ ALSO FORBIDDEN - Any HTML strings in .ts files
app.get('/page', (c) => {
return c.html(`
<html>
<body><h1>Title</h1></body>
</html>
`);
});
✅ CORRECT APPROACHES:
For APIs - Return JSON in .ts files:
// ✅ .ts files for JSON APIs
app.get('/api/users', (c) => {
return c.json({ users: [] });
});
For Views - Use .tsx files with React/JSX:
// ✅ Create views/HomePage.tsx
import { FC } from 'hono/jsx';
export const HomePage: FC = () => {
return (
<html>
<body>
<h1>Welcome</h1>
</body>
</html>
);
};
// ✅ Use .tsx for routes that render views
// src/index.tsx (note: .tsx extension)
import { Hono } from 'hono';
import { HomePage } from '../views/HomePage';
const app = new Hono()
.get('/', (c) => c.html(<HomePage />));
export default app;
Why This Rule Exists:
See: Views Guide for detailed documentation.
npx kagaribi new <name> [--node|--cloudflare|--lambda|--cloudrun|--deno]
Examples:
# Co-located package (runs with root by default)
npx kagaribi new users
# Package targeting Cloudflare Workers
npx kagaribi new payments --cloudflare
# Package targeting AWS Lambda
npx kagaribi new analytics --lambda
What gets created:
packages/<name>/kagaribi.package.ts - Package manifestpackages/<name>/src/index.ts - Hono app templatekagaribi.config.ts with new package entrynpx kagaribi dev [port]
Examples:
npx kagaribi dev # http://localhost:3000 (default)
npx kagaribi dev 8080 # http://localhost:8080
All packages run in a single process with automatic routing.
npx kagaribi model new <table> <field:type>... [--db postgresql|mysql|sqlite] [--scope <packagePath>]
Supported field types: string, integer, boolean, timestamp, text
Examples:
# Generate posts table with title and content
npx kagaribi model new posts title:string content:text --db postgresql
# Generate products table
npx kagaribi model new products name:string price:integer stock:integer
# Auto-detect database dialect from config
npx kagaribi model new comments postId:integer userId:integer body:text
# Generate model in specific package's db directory (scoped database)
npx kagaribi model new users name:string email:string --scope packages/auth
What gets created (root db directory):
db/schema.tsdb/models/<table>.ts with helper functionsdb/models/index.ts to export the modelWith --scope flag (per-package db directory):
<scope>/db/schema.ts<scope>/db/models/<table>.ts with helper functions<scope>/db/models/index.ts to export the modelAfter generation:
npx drizzle-kit generate # Create migration files
npx drizzle-kit push # Apply to database
Database Access Patterns:
Kagaribi supports two ways to access database:
Shared Database with Model Helpers (default when using kagaribi model new)
findAll(), findById(), create(), remove()import * as Posts from '../../../db/models/posts.js'Per-Package Database Access (direct Drizzle ORM)
getDb() and schema directly in package codeconst db = getDb(); await db.select().from(schema.users)See Database Integration Guide for detailed comparison and best practices.
Each package is a self-contained Hono application:
app instancepackages/
users/
kagaribi.package.ts # Manifest (dependencies, routes, runtime)
src/
index.ts # Hono app with routes
Example decision:
auth) - independent concernusers package - tightly coupled to user datapayments) - separate domainpayments or be separate based on deployment needsEdit packages/<name>/kagaribi.package.ts to define dependencies and routes:
import { definePackage } from '@kagaribi/core';
export default definePackage({
name: 'articles',
dependencies: ['users', 'auth'], // Required packages
routes: [
'/users/:userId/articles', // Nested routing pattern
],
runtime: ['node', 'cloudflare-workers', 'deno'],
});
Key fields:
name - Package identifier (must match directory name)dependencies - Other Kagaribi packages this package calls via RPCroutes - Custom nested route patterns (optional)runtime - Compatible deployment targetsimport { Hono } from 'hono';
const app = new Hono()
.get('/api/items', async (c) => {
return c.json({ items: [] });
})
.get('/api/items/:id', async (c) => {
const id = c.req.param('id');
return c.json({ id, name: 'Item' });
})
.post('/api/items', async (c) => {
const body = await c.req.json();
// Create item logic
return c.json({ id: 1, ...body }, 201);
});
// IMPORTANT: Export type for RPC clients
export type ItemsApp = typeof app;
export default app;
import { Hono } from 'hono';
import { createDb, createDbMiddleware } from '@kagaribi/core';
import * as schema from '../../../db/schema.js';
const { initDb, getDb } = createDb('postgresql', schema);
const app = new Hono()
// Initialize database connection
.use('*', createDbMiddleware({ initFn: initDb }))
.get('/api/users', async (c) => {
const db = getDb();
const users = await db.select().from(schema.users);
return c.json(users);
})
.post('/api/users', async (c) => {
const db = getDb();
const { name, email } = await c.req.json();
const [user] = await db.insert(schema.users)
.values({ name, email })
.returning();
return c.json(user, 201);
});
export type UsersApp = typeof app;
export default app;
createDbMiddleware() features:
process.env.DATABASE_URL) or Cloudflare Workers (c.env.DATABASE_URL)initDb() with connection stringD1 uses a binding object instead of a URL connection string, so set isBinding: true.
import { Hono } from 'hono';
import { createDb, createDbMiddleware } from '@kagaribi/core';
import * as schema from '../../../db/schema.js';
// Bindings type definition
type Env = { Bindings: { DB: D1Database } };
const { initDb, getDb } = createDb('sqlite', schema, { driver: 'd1' });
const app = new Hono<Env>()
.use('*', createDbMiddleware<D1Database>({
initFn: initDb,
envVarName: 'DB', // Binding name from wrangler.toml
isBinding: true, // Pass binding object directly to initFn (for D1)
}))
.get('/api/users', async (c) => {
const db = getDb();
const users = await db.select().from(schema.users);
return c.json(users);
});
export type UsersApp = typeof app;
export default app;
createDbMiddleware options:
initFn - Database initialization functionenvVarName - Environment variable or binding name (default: 'DATABASE_URL')isBinding - When true, passes binding object directly to initFn (for D1)Absolute Rule: Direct inter-package communication is prohibited. Always go through the root package.
Centralized Authentication & Authorization
Centralized Orchestration
Clear Dependency Management
kagaribi.package.ts dependenciesClient Request → Root Package → Package A
↓
→ Package B
↓
← Response
Warning: Direct calls from Package A to Package B is a design mistake. Root package should aggregate necessary data before passing to each package.
Each package exports type definitions to be referenced by other packages.
Improved AI Agent Accuracy
Implementation Separation
// packages/users/src/index.ts
import { Hono } from 'hono';
const app = new Hono()
.get('/api/users/:id', async (c) => {
// implementation...
});
// ✅ REQUIRED: Export type definition
export type UsersApp = typeof app;
export default app;
Without export type UsersApp = typeof app, other packages cannot call it type-safely.
Views must be written in TSX. Direct HTML string literals in code are prohibited.
Type Safety
html tag literals don't have type checkingReusability
Maintainability
import { html } from 'hono/html';
app.get('/', (c) => {
return c.html(html`
<html>
<body>
<h1>Hello</h1>
</body>
</html>
`);
});
import { jsx } from 'hono/jsx';
const Layout = ({ children }: { children: any }) => (
<html>
<body>{children}</body>
</html>
);
const HomePage = () => (
<Layout>
<h1>Hello</h1>
</Layout>
);
app.get('/', (c) => {
return c.html(<HomePage />);
});
Use getClient<T>() for type-safe calls between packages:
Important: This feature is primarily used for calling packages from the root package. Do not use for direct inter-package communication (see "Inter-Package Communication Rules" above).
import { Hono } from 'hono';
import { getClient } from '@kagaribi/core';
import type { UsersApp } from '../../users/src/index.js';
import type { AuthApp } from '../../auth/src/index.js';
const users = getClient<UsersApp>('users');
const auth = getClient<AuthApp>('auth');
const app = new Hono()
.get('/api/profile', async (c) => {
// Call users package
const res = await users.api.users[':id'].$get({
param: { id: '123' },
});
const user = await res.json();
return c.json(user);
})
.post('/api/verify', async (c) => {
// Call auth package
const token = c.req.header('Authorization');
const res = await auth.api.verify.$post({
json: { token },
});
const result = await res.json();
return c.json(result);
});
export type ProfileApp = typeof app;
export default app;
Key points:
// packages/articles/kagaribi.package.ts
export default definePackage({
name: 'articles',
dependencies: ['users'],
routes: ['/users/:userId/articles'], // Handle user-specific articles
});
import { Hono } from 'hono';
import { kagaribiParamsMiddleware } from '@kagaribi/core';
const app = new Hono();
// Apply middleware to extract params from X-Kagaribi-Params header
app.use('*', kagaribiParamsMiddleware());
app.get('/', (c) => {
// Access extracted parameters
const userId = c.get('userId' as never) as string;
return c.json({ userId, articles: [] });
});
app.get('/:articleId', (c) => {
const userId = c.get('userId' as never) as string;
const articleId = c.req.param('articleId');
return c.json({ userId, articleId, title: 'Article Title' });
});
export type ArticlesApp = typeof app;
export default app;
npx kagaribi new orders --node
Edit packages/orders/kagaribi.package.ts:
export default definePackage({
name: 'orders',
dependencies: ['users', 'payments'],
runtime: ['node', 'cloudflare-workers'],
});
npx kagaribi model new orders userId:integer productId:integer quantity:integer
pnpm run db:generate
pnpm run db:migrate
Edit packages/orders/src/index.ts with routes and logic.
npx kagaribi dev
curl http://localhost:3000/api/orders
curl -X POST http://localhost:3000/api/orders \
-H "Content-Type: application/json" \
-d '{"userId":1,"productId":42,"quantity":2}'
export type XxxApp = typeof appcreateDbMiddleware() for consistent DB accesskagaribi.package.tsIssue: RPC call fails with "Package not found"
dependencies array in kagaribi.package.tsIssue: Database queries fail
createDbMiddleware({ initFn: initDb }) is applied before routesIssue: TypeScript error on getClient<T>()
export type XxxApp = typeof app)Issue: Model generation fails
npx kagaribi init --db <dialect> first to set up database supportIssue: Changes not reflected
npx kagaribi dev server (hot reload not yet supported)After development: